1mod builder_buffer;
2
3use crate::owned::builder_buffer::BuilderBuffer;
4use crate::{Transaction, TransactionHeader, TransactionSlot};
5use ab_aligned_buffer::SharedAlignedBuffer;
6use ab_contracts_io_type::trivial_type::TrivialType;
7use core::slice;
8
9#[derive(Debug, Default, Copy, Clone, TrivialType)]
10#[repr(C)]
11pub struct OwnedTransactionLengths {
12 pub read_slots: u16,
13 pub write_slots: u16,
14 pub payload: u32,
15 pub seal: u32,
16 pub padding: [u8; 12],
18}
19
20#[derive(Debug, thiserror::Error)]
22pub enum OwnedTransactionError {
23 #[error("Not enough bytes")]
25 NotEnoughBytes,
26 #[error("Payload is not a multiple of `u128`")]
28 PayloadIsNotMultipleOfU128,
29 #[error("Expected number of bytes: {actual} != {expected}")]
31 UnexpectedNumberOfBytes { actual: u32, expected: u32 },
32}
33
34#[derive(Debug, Clone)]
48pub struct OwnedTransaction {
49 buffer: SharedAlignedBuffer,
50}
51
52impl OwnedTransaction {
53 pub fn build(header: &TransactionHeader) -> OwnedTransactionBuilder {
54 OwnedTransactionBuilder {
55 buffer: BuilderBuffer::new(header),
56 }
57 }
58
59 pub fn from_buffer(buffer: SharedAlignedBuffer) -> Result<Self, OwnedTransactionError> {
61 if (buffer.len() as usize)
62 < size_of::<TransactionHeader>() + size_of::<OwnedTransactionLengths>()
63 {
64 return Err(OwnedTransactionError::NotEnoughBytes);
65 }
66
67 let lengths = unsafe {
69 buffer
70 .as_ptr()
71 .add(size_of::<TransactionHeader>())
72 .cast::<OwnedTransactionLengths>()
73 .read()
74 };
75 let OwnedTransactionLengths {
76 read_slots,
77 write_slots,
78 payload,
79 seal,
80 padding: _,
81 } = lengths;
82
83 if payload % u128::SIZE != 0 {
84 return Err(OwnedTransactionError::PayloadIsNotMultipleOfU128);
85 }
86
87 let expected = (size_of::<TransactionHeader>() as u32
88 + size_of::<OwnedTransactionLengths>() as u32)
89 .saturating_add(u32::from(read_slots))
90 .saturating_add(u32::from(write_slots))
91 .saturating_add(payload)
92 .saturating_add(seal);
93
94 if buffer.len() != expected {
95 return Err(OwnedTransactionError::UnexpectedNumberOfBytes {
96 actual: buffer.len(),
97 expected,
98 });
99 }
100
101 Ok(Self { buffer })
102 }
103
104 pub fn buffer(&self) -> &SharedAlignedBuffer {
111 &self.buffer
112 }
113
114 pub fn transaction(&self) -> Transaction<'_> {
115 let lengths = unsafe {
117 self.buffer
118 .as_ptr()
119 .add(size_of::<TransactionHeader>())
120 .cast::<OwnedTransactionLengths>()
121 .read()
122 };
123 let OwnedTransactionLengths {
124 read_slots,
125 write_slots,
126 payload,
127 seal,
128 padding: _,
129 } = lengths;
130
131 Transaction {
132 header: unsafe {
135 self.buffer
136 .as_ptr()
137 .cast::<TransactionHeader>()
138 .as_ref_unchecked()
139 },
140 read_slots: unsafe {
143 slice::from_raw_parts(
144 self.buffer
145 .as_ptr()
146 .add(size_of::<TransactionHeader>())
147 .add(size_of::<OwnedTransactionLengths>())
148 .cast::<TransactionSlot>(),
149 usize::from(read_slots),
150 )
151 },
152 write_slots: unsafe {
155 slice::from_raw_parts(
156 self.buffer
157 .as_ptr()
158 .add(size_of::<TransactionHeader>())
159 .add(size_of::<OwnedTransactionLengths>())
160 .cast::<TransactionSlot>()
161 .add(usize::from(read_slots)),
162 usize::from(write_slots),
163 )
164 },
165 payload: unsafe {
168 slice::from_raw_parts(
169 self.buffer
170 .as_ptr()
171 .add(size_of::<TransactionHeader>())
172 .add(size_of::<OwnedTransactionLengths>())
173 .add(
174 size_of::<TransactionSlot>()
175 * (usize::from(read_slots) + usize::from(write_slots)),
176 )
177 .cast::<u128>(),
178 payload as usize,
179 )
180 },
181 seal: unsafe {
184 slice::from_raw_parts(
185 self.buffer
186 .as_ptr()
187 .add(size_of::<TransactionHeader>())
188 .add(size_of::<OwnedTransactionLengths>())
189 .add(
190 size_of::<TransactionSlot>()
191 * (usize::from(read_slots) + usize::from(write_slots))
192 + payload as usize,
193 ),
194 seal as usize,
195 )
196 },
197 }
198 }
199}
200
201#[derive(Debug, thiserror::Error)]
203pub enum OwnedTransactionBuilderError {
204 #[error("Too many read slots")]
206 TooManyReadSlots,
207 #[error("Too many write slots")]
209 TooManyWriteSlots,
210 #[error("Payload too large")]
212 PayloadTooLarge,
213 #[error("Payload is not a multiple of `u128`")]
215 PayloadIsNotMultipleOfU128,
216 #[error("Seal too large")]
218 SealTooLarge,
219 #[error("Transaction too large")]
221 TransactionTooLarge,
222}
223
224#[derive(Debug, Clone)]
225pub struct OwnedTransactionBuilder {
226 buffer: BuilderBuffer,
227}
228
229impl OwnedTransactionBuilder {
230 pub fn with_read_slot(
231 mut self,
232 slot: &TransactionSlot,
233 ) -> Result<OwnedTransactionBuilderWithReadSlot, OwnedTransactionBuilderError> {
234 self.buffer.append_read_slots(slice::from_ref(slot))?;
235 Ok(OwnedTransactionBuilderWithReadSlot {
236 buffer: self.buffer,
237 })
238 }
239
240 pub fn with_read_slots(
241 mut self,
242 slots: &[TransactionSlot],
243 ) -> Result<OwnedTransactionBuilderWithReadSlot, OwnedTransactionBuilderError> {
244 self.buffer.append_read_slots(slots)?;
245 Ok(OwnedTransactionBuilderWithReadSlot {
246 buffer: self.buffer,
247 })
248 }
249
250 pub fn with_write_slot(
251 mut self,
252 slot: &TransactionSlot,
253 ) -> Result<OwnedTransactionBuilderWithWriteSlot, OwnedTransactionBuilderError> {
254 self.buffer.append_write_slots(slice::from_ref(slot))?;
255 Ok(OwnedTransactionBuilderWithWriteSlot {
256 buffer: self.buffer,
257 })
258 }
259
260 pub fn with_write_slots(
261 mut self,
262 slots: &[TransactionSlot],
263 ) -> Result<OwnedTransactionBuilderWithWriteSlot, OwnedTransactionBuilderError> {
264 self.buffer.append_write_slots(slots)?;
265 Ok(OwnedTransactionBuilderWithWriteSlot {
266 buffer: self.buffer,
267 })
268 }
269
270 pub fn with_payload(
271 mut self,
272 payload: &[u8],
273 ) -> Result<OwnedTransactionBuilderWithPayload, OwnedTransactionBuilderError> {
274 self.buffer.append_payload(payload)?;
275 Ok(OwnedTransactionBuilderWithPayload {
276 buffer: self.buffer,
277 })
278 }
279
280 pub fn with_seal(
281 mut self,
282 seal: &[u8],
283 ) -> Result<OwnedTransaction, OwnedTransactionBuilderError> {
284 self.buffer.append_seal(seal)?;
285 self.finish()
286 }
287
288 pub fn finish(self) -> Result<OwnedTransaction, OwnedTransactionBuilderError> {
289 let buffer = self.buffer.finish()?.into_shared();
290 Ok(OwnedTransaction { buffer })
291 }
292}
293
294#[derive(Debug, Clone)]
295pub struct OwnedTransactionBuilderWithReadSlot {
296 buffer: BuilderBuffer,
297}
298
299impl OwnedTransactionBuilderWithReadSlot {
300 pub fn with_read_slot(
301 mut self,
302 slot: &TransactionSlot,
303 ) -> Result<Self, OwnedTransactionBuilderError> {
304 self.buffer.append_read_slots(slice::from_ref(slot))?;
305 Ok(Self {
306 buffer: self.buffer,
307 })
308 }
309
310 pub fn with_read_slots(
311 mut self,
312 slots: &[TransactionSlot],
313 ) -> Result<Self, OwnedTransactionBuilderError> {
314 self.buffer.append_read_slots(slots)?;
315 Ok(Self {
316 buffer: self.buffer,
317 })
318 }
319
320 pub fn with_write_slot(
321 mut self,
322 slot: &TransactionSlot,
323 ) -> Result<OwnedTransactionBuilderWithWriteSlot, OwnedTransactionBuilderError> {
324 self.buffer.append_write_slots(slice::from_ref(slot))?;
325 Ok(OwnedTransactionBuilderWithWriteSlot {
326 buffer: self.buffer,
327 })
328 }
329
330 pub fn with_write_slots(
331 mut self,
332 slots: &[TransactionSlot],
333 ) -> Result<OwnedTransactionBuilderWithWriteSlot, OwnedTransactionBuilderError> {
334 self.buffer.append_write_slots(slots)?;
335 Ok(OwnedTransactionBuilderWithWriteSlot {
336 buffer: self.buffer,
337 })
338 }
339
340 pub fn with_payload(
341 mut self,
342 payload: &[u8],
343 ) -> Result<OwnedTransactionBuilderWithPayload, OwnedTransactionBuilderError> {
344 self.buffer.append_payload(payload)?;
345 Ok(OwnedTransactionBuilderWithPayload {
346 buffer: self.buffer,
347 })
348 }
349
350 pub fn with_seal(
351 mut self,
352 seal: &[u8],
353 ) -> Result<OwnedTransaction, OwnedTransactionBuilderError> {
354 self.buffer.append_seal(seal)?;
355 self.finish()
356 }
357
358 pub fn finish(self) -> Result<OwnedTransaction, OwnedTransactionBuilderError> {
359 let buffer = self.buffer.finish()?.into_shared();
360 Ok(OwnedTransaction { buffer })
361 }
362}
363
364#[derive(Debug, Clone)]
365pub struct OwnedTransactionBuilderWithWriteSlot {
366 buffer: BuilderBuffer,
367}
368
369impl OwnedTransactionBuilderWithWriteSlot {
370 pub fn with_write_slot(
371 mut self,
372 slot: &TransactionSlot,
373 ) -> Result<Self, OwnedTransactionBuilderError> {
374 self.buffer.append_write_slots(slice::from_ref(slot))?;
375 Ok(Self {
376 buffer: self.buffer,
377 })
378 }
379
380 pub fn with_write_slots(
381 mut self,
382 slots: &[TransactionSlot],
383 ) -> Result<Self, OwnedTransactionBuilderError> {
384 self.buffer.append_write_slots(slots)?;
385 Ok(Self {
386 buffer: self.buffer,
387 })
388 }
389
390 pub fn with_payload(
391 mut self,
392 payload: &[u8],
393 ) -> Result<OwnedTransactionBuilderWithPayload, OwnedTransactionBuilderError> {
394 self.buffer.append_payload(payload)?;
395 Ok(OwnedTransactionBuilderWithPayload {
396 buffer: self.buffer,
397 })
398 }
399
400 pub fn with_seal(
401 mut self,
402 seal: &[u8],
403 ) -> Result<OwnedTransaction, OwnedTransactionBuilderError> {
404 self.buffer.append_seal(seal)?;
405 self.finish()
406 }
407
408 pub fn finish(self) -> Result<OwnedTransaction, OwnedTransactionBuilderError> {
409 let buffer = self.buffer.finish()?.into_shared();
410 Ok(OwnedTransaction { buffer })
411 }
412}
413
414#[derive(Debug, Clone)]
415pub struct OwnedTransactionBuilderWithPayload {
416 buffer: BuilderBuffer,
417}
418
419impl OwnedTransactionBuilderWithPayload {
420 pub fn with_payload(mut self, payload: &[u8]) -> Result<Self, OwnedTransactionBuilderError> {
421 self.buffer.append_payload(payload)?;
422 Ok(Self {
423 buffer: self.buffer,
424 })
425 }
426
427 pub fn with_seal(
428 mut self,
429 seal: &[u8],
430 ) -> Result<OwnedTransaction, OwnedTransactionBuilderError> {
431 self.buffer.append_seal(seal)?;
432 self.finish()
433 }
434
435 pub fn finish(self) -> Result<OwnedTransaction, OwnedTransactionBuilderError> {
436 let buffer = self.buffer.finish()?.into_shared();
437 Ok(OwnedTransaction { buffer })
438 }
439}