ab_transaction/owned/
builder_buffer.rs1use crate::owned::{OwnedTransactionBuilderError, OwnedTransactionLengths};
2use crate::{TransactionHeader, TransactionSlot};
3use ab_aligned_buffer::OwnedAlignedBuffer;
4use ab_contracts_io_type::trivial_type::TrivialType;
5use core::slice;
6
7#[derive(Debug, Clone)]
8pub(super) struct BuilderBuffer {
9 buffer: OwnedAlignedBuffer,
10}
11
12impl BuilderBuffer {
13 pub(super) fn new(header: &TransactionHeader) -> Self {
14 const _: () = {
15 assert!(size_of::<TransactionHeader>() % align_of::<OwnedTransactionLengths>() == 0);
17 };
18 let mut buffer = OwnedAlignedBuffer::with_capacity(
19 TransactionHeader::SIZE + OwnedTransactionLengths::SIZE,
20 );
21 let _: bool = buffer.append(header.as_bytes());
23 let _: bool = buffer.append(OwnedTransactionLengths::default().as_bytes());
25 Self { buffer }
26 }
27
28 fn get_lengths(&mut self) -> &mut OwnedTransactionLengths {
29 unsafe {
30 self.buffer
31 .as_mut_ptr()
32 .add(size_of::<TransactionHeader>())
33 .cast::<OwnedTransactionLengths>()
34 .as_mut_unchecked()
35 }
36 }
37
38 pub(super) fn append_read_slots(
39 &mut self,
40 slots: &[TransactionSlot],
41 ) -> Result<(), OwnedTransactionBuilderError> {
42 {
43 let lengths = self.get_lengths();
44 let Ok(slots_len) = u16::try_from(slots.len()) else {
45 return Err(OwnedTransactionBuilderError::TooManyReadSlots);
46 };
47 let Some(new_read_slots) = lengths.read_slots.checked_add(slots_len) else {
48 return Err(OwnedTransactionBuilderError::TooManyReadSlots);
49 };
50
51 lengths.read_slots = new_read_slots;
52 }
53
54 const _: () = {
55 assert!(
58 (size_of::<TransactionHeader>() + size_of::<OwnedTransactionLengths>())
59 % align_of::<TransactionSlot>()
60 == 0
61 );
62 };
63 if !self.buffer.append(unsafe {
66 slice::from_raw_parts(slots.as_ptr().cast::<u8>(), size_of_val(slots))
67 }) {
68 return Err(OwnedTransactionBuilderError::TransactionTooLarge);
69 }
70
71 Ok(())
72 }
73
74 pub(super) fn append_write_slots(
75 &mut self,
76 slots: &[TransactionSlot],
77 ) -> Result<(), OwnedTransactionBuilderError> {
78 {
79 let lengths = self.get_lengths();
80 let Ok(slots_len) = u16::try_from(slots.len()) else {
81 return Err(OwnedTransactionBuilderError::TooManyWriteSlots);
82 };
83 let Some(new_write_slots) = lengths.write_slots.checked_add(slots_len) else {
84 return Err(OwnedTransactionBuilderError::TooManyWriteSlots);
85 };
86
87 lengths.write_slots = new_write_slots;
88 }
89
90 const _: () = {
91 assert!(
94 (size_of::<TransactionHeader>() + size_of::<OwnedTransactionLengths>())
95 % align_of::<TransactionSlot>()
96 == 0
97 );
98 };
99 if !self.buffer.append(unsafe {
102 slice::from_raw_parts(slots.as_ptr().cast::<u8>(), size_of_val(slots))
103 }) {
104 return Err(OwnedTransactionBuilderError::TransactionTooLarge);
105 }
106
107 Ok(())
108 }
109
110 pub(super) fn append_payload(
111 &mut self,
112 payload: &[u8],
113 ) -> Result<(), OwnedTransactionBuilderError> {
114 {
115 let lengths = self.get_lengths();
116 let Ok(payload_len) = u32::try_from(payload.len()) else {
117 return Err(OwnedTransactionBuilderError::PayloadTooLarge);
118 };
119 let Some(new_payload_len) = lengths.payload.checked_add(payload_len) else {
120 return Err(OwnedTransactionBuilderError::PayloadTooLarge);
121 };
122
123 lengths.payload = new_payload_len;
124 }
125
126 const _: () = {
127 assert!(
130 (size_of::<TransactionHeader>() + size_of::<OwnedTransactionLengths>())
131 % align_of::<u128>()
132 == 0
133 );
134 assert!(
135 (size_of::<TransactionHeader>()
136 + size_of::<OwnedTransactionLengths>()
137 + size_of::<TransactionSlot>())
138 % align_of::<u128>()
139 == 0
140 );
141 };
142 if !self.buffer.append(payload) {
143 return Err(OwnedTransactionBuilderError::TransactionTooLarge);
144 }
145
146 Ok(())
147 }
148
149 pub(super) fn append_seal(&mut self, seal: &[u8]) -> Result<(), OwnedTransactionBuilderError> {
150 {
151 let lengths = self.get_lengths();
152 if lengths.payload % u128::SIZE != 0 {
153 return Err(OwnedTransactionBuilderError::PayloadIsNotMultipleOfU128);
154 }
155 let Ok(seal_len) = u32::try_from(seal.len()) else {
156 return Err(OwnedTransactionBuilderError::SealTooLarge);
157 };
158 let Some(new_seal_len) = lengths.seal.checked_add(seal_len) else {
159 return Err(OwnedTransactionBuilderError::SealTooLarge);
160 };
161
162 lengths.seal = new_seal_len;
163 }
164
165 const _: () = {
166 assert!(
169 (size_of::<TransactionHeader>() + size_of::<OwnedTransactionLengths>())
170 % align_of::<u128>()
171 == 0
172 );
173 assert!(
174 (size_of::<TransactionHeader>()
175 + size_of::<OwnedTransactionLengths>()
176 + size_of::<TransactionSlot>())
177 % align_of::<u128>()
178 == 0
179 );
180 };
181 if !self.buffer.append(seal) {
182 return Err(OwnedTransactionBuilderError::TransactionTooLarge);
183 }
184
185 Ok(())
186 }
187
188 pub(super) fn finish(mut self) -> Result<OwnedAlignedBuffer, OwnedTransactionBuilderError> {
189 let lengths = self.get_lengths();
190 if lengths.payload % u128::SIZE != 0 {
191 return Err(OwnedTransactionBuilderError::PayloadIsNotMultipleOfU128);
192 }
193 Ok(self.buffer)
194 }
195}