1#![allow(unsafe_code)]
7
8#[cfg(feature = "alloc")]
9use alloc::vec::Vec;
10use core::fmt;
11
12use core::mem::MaybeUninit;
13pub use fuel_derive::{
14 Deserialize,
15 Serialize,
16};
17
18#[derive(Debug, Eq, PartialEq)]
20#[non_exhaustive]
21pub enum Error {
22 BufferIsTooShort,
24 UnknownDiscriminant,
26 InvalidPrefix,
28 AllocationLimit,
30 Unknown(&'static str),
32}
33
34impl Error {
35 pub(crate) fn as_str(&self) -> &'static str {
36 match self {
37 Error::BufferIsTooShort => "buffer is too short",
38 Error::UnknownDiscriminant => "unknown discriminant",
39 Error::InvalidPrefix => {
40 "prefix set with #[canonical(prefix = ...)] was invalid"
41 }
42 Error::AllocationLimit => "allocation too large",
43 Error::Unknown(str) => str,
44 }
45 }
46}
47
48impl fmt::Display for Error {
49 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
51 fmt.write_str(self.as_str())
52 }
53}
54
55pub trait Output {
57 fn write(&mut self, bytes: &[u8]) -> Result<(), Error>;
59
60 fn push_byte(&mut self, byte: u8) -> Result<(), Error> {
62 self.write(&[byte])
63 }
64}
65
66pub trait Serialize {
69 #[doc(hidden)]
72 const UNALIGNED_BYTES: bool = false;
73
74 fn size_static(&self) -> usize;
77
78 fn size_dynamic(&self) -> usize;
81
82 fn size(&self) -> usize {
85 self.size_static().saturating_add(self.size_dynamic())
86 }
87
88 fn encode<O: Output + ?Sized>(&self, buffer: &mut O) -> Result<(), Error> {
93 self.encode_static(buffer)?;
94 self.encode_dynamic(buffer)
95 }
96
97 fn encode_static<O: Output + ?Sized>(&self, buffer: &mut O) -> Result<(), Error>;
99
100 fn encode_dynamic<O: Output + ?Sized>(&self, _buffer: &mut O) -> Result<(), Error> {
104 Ok(())
105 }
106
107 #[cfg(feature = "alloc")]
109 fn to_bytes(&self) -> Vec<u8> {
110 let mut vec = Vec::with_capacity(self.size());
111 self.encode(&mut vec).expect("Unable to encode self");
112 vec
113 }
114}
115
116pub trait Input {
118 fn remaining(&mut self) -> usize;
120
121 fn peek(&self, buf: &mut [u8]) -> Result<(), Error>;
123
124 fn read(&mut self, buf: &mut [u8]) -> Result<(), Error>;
126
127 fn peek_byte(&mut self) -> Result<u8, Error> {
129 let mut buf = [0u8];
130 self.peek(&mut buf[..])?;
131 Ok(buf[0])
132 }
133
134 fn read_byte(&mut self) -> Result<u8, Error> {
136 let mut buf = [0u8];
137 self.read(&mut buf[..])?;
138 Ok(buf[0])
139 }
140
141 fn skip(&mut self, n: usize) -> Result<(), Error>;
143}
144
145pub trait Deserialize: Sized {
148 #[doc(hidden)]
151 const UNALIGNED_BYTES: bool = false;
152
153 fn decode<I: Input + ?Sized>(buffer: &mut I) -> Result<Self, Error> {
158 let mut object = Self::decode_static(buffer)?;
159 object.decode_dynamic(buffer)?;
160 Ok(object)
161 }
162
163 fn decode_static<I: Input + ?Sized>(buffer: &mut I) -> Result<Self, Error>;
165
166 fn decode_dynamic<I: Input + ?Sized>(
170 &mut self,
171 _buffer: &mut I,
172 ) -> Result<(), Error> {
173 Ok(())
174 }
175
176 fn from_bytes(mut buffer: &[u8]) -> Result<Self, Error> {
178 Self::decode(&mut buffer)
179 }
180}
181
182pub const ALIGN: usize = 8;
184
185#[allow(clippy::arithmetic_side_effects)] const fn alignment_bytes(len: usize) -> usize {
188 let modulo = len % ALIGN;
189 if modulo == 0 {
190 0
191 } else {
192 ALIGN - modulo
193 }
194}
195
196pub const fn aligned_size(len: usize) -> usize {
198 len.saturating_add(alignment_bytes(len))
199}
200
201macro_rules! impl_for_primitives {
202 ($t:ident, $unpadded:literal) => {
203 impl Serialize for $t {
204 const UNALIGNED_BYTES: bool = $unpadded;
205
206 #[inline(always)]
207 fn size_static(&self) -> usize {
208 aligned_size(::core::mem::size_of::<$t>())
209 }
210
211 #[inline(always)]
212 fn size_dynamic(&self) -> usize {
213 0
214 }
215
216 #[inline(always)]
217 fn encode_static<O: Output + ?Sized>(
218 &self,
219 buffer: &mut O,
220 ) -> Result<(), Error> {
221 let bytes = <$t>::to_be_bytes(*self);
224 for _ in 0..alignment_bytes(bytes.len()) {
225 buffer.push_byte(0)?;
227 }
228 buffer.write(bytes.as_ref())?;
229 Ok(())
230 }
231 }
232
233 impl Deserialize for $t {
234 const UNALIGNED_BYTES: bool = $unpadded;
235
236 fn decode_static<I: Input + ?Sized>(buffer: &mut I) -> Result<Self, Error> {
237 let mut asset = [0u8; ::core::mem::size_of::<$t>()];
238 buffer.skip(alignment_bytes(asset.len()))?; buffer.read(asset.as_mut())?;
240 Ok(<$t>::from_be_bytes(asset))
241 }
242 }
243 };
244}
245
246impl_for_primitives!(u8, true);
247impl_for_primitives!(u16, false);
248impl_for_primitives!(u32, false);
249impl_for_primitives!(usize, false);
250impl_for_primitives!(u64, false);
251impl_for_primitives!(u128, false);
252
253impl Serialize for () {
255 fn size_static(&self) -> usize {
256 0
257 }
258
259 #[inline(always)]
260 fn size_dynamic(&self) -> usize {
261 0
262 }
263
264 #[inline(always)]
265 fn encode_static<O: Output + ?Sized>(&self, _buffer: &mut O) -> Result<(), Error> {
266 Ok(())
267 }
268}
269
270impl Deserialize for () {
271 fn decode_static<I: Input + ?Sized>(_buffer: &mut I) -> Result<Self, Error> {
272 Ok(())
273 }
274}
275
276pub const VEC_DECODE_LIMIT: usize = 100 * (1 << 20); #[cfg(feature = "alloc")]
280impl<T: Serialize> Serialize for Vec<T> {
281 fn size_static(&self) -> usize {
282 8
283 }
284
285 #[inline(always)]
286 fn size_dynamic(&self) -> usize {
287 if T::UNALIGNED_BYTES {
288 aligned_size(self.len())
289 } else {
290 aligned_size(
291 self.iter()
292 .map(|e| e.size())
293 .reduce(usize::saturating_add)
294 .unwrap_or_default(),
295 )
296 }
297 }
298
299 #[inline(always)]
300 fn encode_static<O: Output + ?Sized>(&self, buffer: &mut O) -> Result<(), Error> {
303 if self.len() > VEC_DECODE_LIMIT {
304 return Err(Error::AllocationLimit)
305 }
306 let len: u64 = self.len().try_into().expect("msg.len() > u64::MAX");
307 len.encode(buffer)
308 }
309
310 fn encode_dynamic<O: Output + ?Sized>(&self, buffer: &mut O) -> Result<(), Error> {
311 if T::UNALIGNED_BYTES {
314 let bytes = unsafe { ::core::mem::transmute::<&Vec<T>, &Vec<u8>>(self) };
316 buffer.write(bytes.as_slice())?;
317 for _ in 0..alignment_bytes(self.len()) {
318 buffer.push_byte(0)?;
319 }
320 } else {
321 for e in self.iter() {
322 e.encode(buffer)?;
323 }
324 }
325 Ok(())
326 }
327}
328
329#[cfg(feature = "alloc")]
330impl<T: Deserialize> Deserialize for Vec<T> {
331 fn decode_static<I: Input + ?Sized>(buffer: &mut I) -> Result<Self, Error> {
334 let cap = u64::decode(buffer)?;
335 let cap: usize = cap.try_into().map_err(|_| Error::AllocationLimit)?;
336 if cap > VEC_DECODE_LIMIT {
337 return Err(Error::AllocationLimit)
338 }
339 Ok(Vec::with_capacity(cap))
340 }
341
342 fn decode_dynamic<I: Input + ?Sized>(&mut self, buffer: &mut I) -> Result<(), Error> {
343 for _ in 0..self.capacity() {
344 if T::UNALIGNED_BYTES {
347 let byte = buffer.read_byte()?;
348 let _self =
350 unsafe { ::core::mem::transmute::<&mut Vec<T>, &mut Vec<u8>>(self) };
351 _self.push(byte);
352 } else {
353 self.push(T::decode(buffer)?);
354 }
355 }
356
357 if T::UNALIGNED_BYTES {
358 buffer.skip(alignment_bytes(self.capacity()))?;
359 }
360
361 Ok(())
362 }
363}
364
365impl<const N: usize, T: Serialize> Serialize for [T; N] {
366 fn size_static(&self) -> usize {
367 if T::UNALIGNED_BYTES {
368 aligned_size(N)
369 } else {
370 aligned_size(
371 self.iter()
372 .map(|e| e.size_static())
373 .reduce(usize::saturating_add)
374 .unwrap_or_default(),
375 )
376 }
377 }
378
379 #[inline(always)]
380 fn size_dynamic(&self) -> usize {
381 if T::UNALIGNED_BYTES {
382 0
383 } else {
384 aligned_size(
385 self.iter()
386 .map(|e| e.size_dynamic())
387 .reduce(usize::saturating_add)
388 .unwrap_or_default(),
389 )
390 }
391 }
392
393 #[inline(always)]
394 fn encode_static<O: Output + ?Sized>(&self, buffer: &mut O) -> Result<(), Error> {
395 if T::UNALIGNED_BYTES {
398 let bytes = unsafe { ::core::mem::transmute::<&[T; N], &[u8; N]>(self) };
400 buffer.write(bytes.as_slice())?;
401 for _ in 0..alignment_bytes(N) {
402 buffer.push_byte(0)?;
403 }
404 } else {
405 for e in self.iter() {
406 e.encode_static(buffer)?;
407 }
408 }
409 Ok(())
410 }
411
412 fn encode_dynamic<O: Output + ?Sized>(&self, buffer: &mut O) -> Result<(), Error> {
413 for e in self.iter() {
414 e.encode_dynamic(buffer)?;
415 }
416
417 Ok(())
418 }
419}
420
421impl<const N: usize, T: Deserialize> Deserialize for [T; N] {
422 fn decode_static<I: Input + ?Sized>(buffer: &mut I) -> Result<Self, Error> {
423 if T::UNALIGNED_BYTES {
424 let mut bytes: [u8; N] = [0; N];
425 buffer.read(bytes.as_mut())?;
426 buffer.skip(alignment_bytes(N))?;
427 let ref_typed: &[T; N] = unsafe { core::mem::transmute(&bytes) };
428 let typed: [T; N] = unsafe { core::ptr::read(ref_typed) };
429 Ok(typed)
430 } else {
431 let mut uninit: [MaybeUninit<T>; N] =
436 unsafe { MaybeUninit::uninit().assume_init() };
437 for i in 0..N {
440 match T::decode_static(buffer) {
441 Err(e) => {
442 for item in uninit.iter_mut().take(i) {
443 unsafe {
446 item.assume_init_drop();
447 }
448 }
449 return Err(e)
450 }
451 Ok(decoded) => {
452 uninit[i].write(decoded);
455
456 }
459 }
460 }
461
462 let init = uninit.map(|v| unsafe { v.assume_init() });
464 Ok(init)
465 }
466 }
467
468 fn decode_dynamic<I: Input + ?Sized>(&mut self, buffer: &mut I) -> Result<(), Error> {
469 for e in self.iter_mut() {
470 e.decode_dynamic(buffer)?;
471 }
472 Ok(())
473 }
474}
475
476#[cfg(feature = "alloc")]
477impl Output for Vec<u8> {
478 fn write(&mut self, bytes: &[u8]) -> Result<(), Error> {
479 self.extend_from_slice(bytes);
480 Ok(())
481 }
482}
483
484impl Output for &'_ mut [u8] {
485 fn write(&mut self, from: &[u8]) -> Result<(), Error> {
486 if from.len() > self.len() {
487 return Err(Error::BufferIsTooShort)
488 }
489 let len = from.len();
490 self[..len].copy_from_slice(from);
491 let reduced = &mut self[len..];
493
494 *self = unsafe { &mut *(reduced as *mut [u8]) };
497 Ok(())
498 }
499}
500
501impl Input for &'_ [u8] {
502 fn remaining(&mut self) -> usize {
503 self.len()
504 }
505
506 fn peek(&self, into: &mut [u8]) -> Result<(), Error> {
507 if into.len() > self.len() {
508 return Err(Error::BufferIsTooShort)
509 }
510
511 let len = into.len();
512 into.copy_from_slice(&self[..len]);
513 Ok(())
514 }
515
516 fn read(&mut self, into: &mut [u8]) -> Result<(), Error> {
517 if into.len() > self.len() {
518 return Err(Error::BufferIsTooShort)
519 }
520
521 let len = into.len();
522 into.copy_from_slice(&self[..len]);
523 *self = &self[len..];
524 Ok(())
525 }
526
527 fn skip(&mut self, n: usize) -> Result<(), Error> {
528 if n > self.len() {
529 return Err(Error::BufferIsTooShort)
530 }
531
532 *self = &self[n..];
533 Ok(())
534 }
535}
536
537#[cfg(test)]
538mod tests {
539 use super::*;
540
541 fn validate<T: Serialize + Deserialize + Eq + core::fmt::Debug>(t: T) {
542 let bytes = t.to_bytes();
543 let t2 = T::from_bytes(&bytes).expect("Roundtrip failed");
544 assert_eq!(t, t2);
545 assert_eq!(t.to_bytes(), t2.to_bytes());
546
547 let mut vec = Vec::new();
548 t.encode_static(&mut vec).expect("Encode failed");
549 assert_eq!(vec.len(), t.size_static());
550 }
551
552 fn validate_enum<T: Serialize + Deserialize + Eq + fmt::Debug>(t: T) {
553 let bytes = t.to_bytes();
554 let t2 = T::from_bytes(&bytes).expect("Roundtrip failed");
555 assert_eq!(t, t2);
556 assert_eq!(t.to_bytes(), t2.to_bytes());
557
558 let mut vec = Vec::new();
559 t.encode_static(&mut vec).expect("Encode failed");
560 assert_eq!(vec.len(), t.size_static());
561 t.encode_dynamic(&mut vec).expect("Encode failed");
562 assert_eq!(vec.len(), t.size());
563
564 let mut vec2 = Vec::new();
565 t.encode_dynamic(&mut vec2).expect("Encode failed");
566 assert_eq!(vec2.len(), t.size_dynamic());
567 }
568
569 #[test]
570 fn test_canonical_encode_decode() {
571 validate(());
572 validate(123u8);
573 validate(u8::MAX);
574 validate(123u16);
575 validate(u16::MAX);
576 validate(123u32);
577 validate(u32::MAX);
578 validate(123u64);
579 validate(u64::MAX);
580 validate(123u128);
581 validate(u128::MAX);
582 validate(Vec::<u8>::new());
583 validate(Vec::<u16>::new());
584 validate(Vec::<u32>::new());
585 validate(Vec::<u64>::new());
586 validate(Vec::<u128>::new());
587 validate(vec![1u8]);
588 validate(vec![1u16]);
589 validate(vec![1u32]);
590 validate(vec![1u64]);
591 validate(vec![1u128]);
592 validate(vec![1u8, 2u8]);
593 validate(vec![1u16, 2u16]);
594 validate(vec![1u32, 2u32]);
595 validate(vec![1u64, 2u64]);
596 validate(vec![1u128, 2u128]);
597
598 #[derive(Serialize, Deserialize, Debug, PartialEq, Eq)]
599 struct TestStruct1 {
600 a: u8,
601 b: u16,
602 }
603
604 let t = TestStruct1 { a: 123, b: 456 };
605 assert_eq!(t.size_static(), 16);
606 assert_eq!(t.size(), 16);
607 validate(t);
608
609 #[derive(Serialize, Deserialize, Debug, PartialEq, Eq)]
610 struct TestStruct2 {
611 a: u8,
612 v: Vec<u8>,
613 b: u16,
614 arr0: [u8; 0],
615 arr1: [u8; 2],
616 arr2: [u16; 3],
617 arr3: [u64; 4],
618 }
619
620 validate(TestStruct2 {
621 a: 123,
622 v: vec![1, 2, 3],
623 b: 456,
624 arr0: [],
625 arr1: [1, 2],
626 arr2: [1, 2, u16::MAX],
627 arr3: [0, 3, 1111, u64::MAX],
628 });
629
630 #[derive(Serialize, Deserialize, Debug, PartialEq, Eq)]
631 #[repr(transparent)]
632 struct TestStruct3([u8; 64]);
633
634 let t = TestStruct3([1; 64]);
635 assert_eq!(t.size_static(), 64);
636 assert_eq!(t.size(), 64);
637 validate(t);
638
639 #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
640 #[canonical(prefix = 1u64)]
641 struct Prefixed1 {
642 a: [u8; 3],
643 b: Vec<u8>,
644 }
645 validate(Prefixed1 {
646 a: [1, 2, 3],
647 b: vec![4, 5, 6],
648 });
649
650 #[derive(Serialize, Deserialize, Debug, PartialEq, Eq)]
651 #[repr(u8)]
652 enum TestEnum1 {
653 A,
654 B,
655 C = 0x13,
656 D,
657 }
658
659 validate(TestEnum1::A);
660 validate(TestEnum1::B);
661 validate(TestEnum1::C);
662 validate(TestEnum1::D);
663
664 #[derive(Serialize, Deserialize, Debug, PartialEq, Eq)]
665 enum TestEnum2 {
666 A(u8),
667 B([u8; 3]),
668 C(Vec<u8>),
669 }
670
671 validate_enum(TestEnum2::A(2));
672 validate_enum(TestEnum2::B([1, 2, 3]));
673 validate_enum(TestEnum2::C(vec![1, 2, 3]));
674
675 #[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq)]
676 #[canonical(prefix = 2u64)]
677 struct Prefixed2(u16);
678 validate(Prefixed2(u16::MAX));
679
680 assert_eq!(
681 &Prefixed1 {
682 a: [1, 2, 3],
683 b: vec![4, 5]
684 }
685 .to_bytes()[..8],
686 &[0u8, 0, 0, 0, 0, 0, 0, 1]
687 );
688 assert_eq!(
689 Prefixed2(u16::MAX).to_bytes(),
690 [0u8, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0xff, 0xff]
691 );
692 }
693}