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 { 0 } else { ALIGN - modulo }
190}
191
192pub const fn aligned_size(len: usize) -> usize {
194 len.saturating_add(alignment_bytes(len))
195}
196
197macro_rules! impl_for_primitives {
198 ($t:ident, $unpadded:literal) => {
199 impl Serialize for $t {
200 const UNALIGNED_BYTES: bool = $unpadded;
201
202 #[inline(always)]
203 fn size_static(&self) -> usize {
204 aligned_size(::core::mem::size_of::<$t>())
205 }
206
207 #[inline(always)]
208 fn size_dynamic(&self) -> usize {
209 0
210 }
211
212 #[inline(always)]
213 fn encode_static<O: Output + ?Sized>(
214 &self,
215 buffer: &mut O,
216 ) -> Result<(), Error> {
217 let bytes = <$t>::to_be_bytes(*self);
220 for _ in 0..alignment_bytes(bytes.len()) {
221 buffer.push_byte(0)?;
223 }
224 buffer.write(bytes.as_ref())?;
225 Ok(())
226 }
227 }
228
229 impl Deserialize for $t {
230 const UNALIGNED_BYTES: bool = $unpadded;
231
232 fn decode_static<I: Input + ?Sized>(buffer: &mut I) -> Result<Self, Error> {
233 let mut asset = [0u8; ::core::mem::size_of::<$t>()];
234 buffer.skip(alignment_bytes(asset.len()))?; buffer.read(asset.as_mut())?;
236 Ok(<$t>::from_be_bytes(asset))
237 }
238 }
239 };
240}
241
242impl_for_primitives!(u8, true);
243impl_for_primitives!(u16, false);
244impl_for_primitives!(u32, false);
245impl_for_primitives!(usize, false);
246impl_for_primitives!(u64, false);
247impl_for_primitives!(u128, false);
248
249impl Serialize for () {
251 fn size_static(&self) -> usize {
252 0
253 }
254
255 #[inline(always)]
256 fn size_dynamic(&self) -> usize {
257 0
258 }
259
260 #[inline(always)]
261 fn encode_static<O: Output + ?Sized>(&self, _buffer: &mut O) -> Result<(), Error> {
262 Ok(())
263 }
264}
265
266impl Deserialize for () {
267 fn decode_static<I: Input + ?Sized>(_buffer: &mut I) -> Result<Self, Error> {
268 Ok(())
269 }
270}
271
272pub const VEC_DECODE_LIMIT: usize = 100 * (1 << 20); #[cfg(feature = "alloc")]
276impl<T: Serialize> Serialize for Vec<T> {
277 fn size_static(&self) -> usize {
278 8
279 }
280
281 #[inline(always)]
282 fn size_dynamic(&self) -> usize {
283 if T::UNALIGNED_BYTES {
284 aligned_size(self.len())
285 } else {
286 aligned_size(
287 self.iter()
288 .map(|e| e.size())
289 .reduce(usize::saturating_add)
290 .unwrap_or_default(),
291 )
292 }
293 }
294
295 #[inline(always)]
296 fn encode_static<O: Output + ?Sized>(&self, buffer: &mut O) -> Result<(), Error> {
299 if self.len() > VEC_DECODE_LIMIT {
300 return Err(Error::AllocationLimit)
301 }
302 let len: u64 = self.len().try_into().expect("msg.len() > u64::MAX");
303 len.encode(buffer)
304 }
305
306 fn encode_dynamic<O: Output + ?Sized>(&self, buffer: &mut O) -> Result<(), Error> {
307 if T::UNALIGNED_BYTES {
310 let bytes = unsafe { ::core::mem::transmute::<&Vec<T>, &Vec<u8>>(self) };
312 buffer.write(bytes.as_slice())?;
313 for _ in 0..alignment_bytes(self.len()) {
314 buffer.push_byte(0)?;
315 }
316 } else {
317 for e in self.iter() {
318 e.encode(buffer)?;
319 }
320 }
321 Ok(())
322 }
323}
324
325#[cfg(feature = "alloc")]
326impl<T: Deserialize> Deserialize for Vec<T> {
327 fn decode_static<I: Input + ?Sized>(buffer: &mut I) -> Result<Self, Error> {
330 let cap = u64::decode(buffer)?;
331 let cap: usize = cap.try_into().map_err(|_| Error::AllocationLimit)?;
332 if cap > VEC_DECODE_LIMIT {
333 return Err(Error::AllocationLimit)
334 }
335 Ok(Vec::with_capacity(cap))
336 }
337
338 fn decode_dynamic<I: Input + ?Sized>(&mut self, buffer: &mut I) -> Result<(), Error> {
339 for _ in 0..self.capacity() {
340 if T::UNALIGNED_BYTES {
343 let byte = buffer.read_byte()?;
344 let _self =
346 unsafe { ::core::mem::transmute::<&mut Vec<T>, &mut Vec<u8>>(self) };
347 _self.push(byte);
348 } else {
349 self.push(T::decode(buffer)?);
350 }
351 }
352
353 if T::UNALIGNED_BYTES {
354 buffer.skip(alignment_bytes(self.capacity()))?;
355 }
356
357 Ok(())
358 }
359}
360
361impl<const N: usize, T: Serialize> Serialize for [T; N] {
362 fn size_static(&self) -> usize {
363 if T::UNALIGNED_BYTES {
364 aligned_size(N)
365 } else {
366 aligned_size(
367 self.iter()
368 .map(|e| e.size_static())
369 .reduce(usize::saturating_add)
370 .unwrap_or_default(),
371 )
372 }
373 }
374
375 #[inline(always)]
376 fn size_dynamic(&self) -> usize {
377 if T::UNALIGNED_BYTES {
378 0
379 } else {
380 aligned_size(
381 self.iter()
382 .map(|e| e.size_dynamic())
383 .reduce(usize::saturating_add)
384 .unwrap_or_default(),
385 )
386 }
387 }
388
389 #[inline(always)]
390 fn encode_static<O: Output + ?Sized>(&self, buffer: &mut O) -> Result<(), Error> {
391 if T::UNALIGNED_BYTES {
394 let bytes = unsafe { ::core::mem::transmute::<&[T; N], &[u8; N]>(self) };
396 buffer.write(bytes.as_slice())?;
397 for _ in 0..alignment_bytes(N) {
398 buffer.push_byte(0)?;
399 }
400 } else {
401 for e in self.iter() {
402 e.encode_static(buffer)?;
403 }
404 }
405 Ok(())
406 }
407
408 fn encode_dynamic<O: Output + ?Sized>(&self, buffer: &mut O) -> Result<(), Error> {
409 for e in self.iter() {
410 e.encode_dynamic(buffer)?;
411 }
412
413 Ok(())
414 }
415}
416
417impl<const N: usize, T: Deserialize> Deserialize for [T; N] {
418 fn decode_static<I: Input + ?Sized>(buffer: &mut I) -> Result<Self, Error> {
419 if T::UNALIGNED_BYTES {
420 let mut bytes: [u8; N] = [0; N];
421 buffer.read(bytes.as_mut())?;
422 buffer.skip(alignment_bytes(N))?;
423 let ref_typed: &[T; N] = unsafe { core::mem::transmute(&bytes) };
424 let typed: [T; N] = unsafe { core::ptr::read(ref_typed) };
425 Ok(typed)
426 } else {
427 let mut uninit: [MaybeUninit<T>; N] =
432 unsafe { MaybeUninit::uninit().assume_init() };
433 for i in 0..N {
436 match T::decode_static(buffer) {
437 Err(e) => {
438 for item in uninit.iter_mut().take(i) {
439 unsafe {
442 item.assume_init_drop();
443 }
444 }
445 return Err(e)
446 }
447 Ok(decoded) => {
448 uninit[i].write(decoded);
451
452 }
455 }
456 }
457
458 let init = uninit.map(|v| unsafe { v.assume_init() });
460 Ok(init)
461 }
462 }
463
464 fn decode_dynamic<I: Input + ?Sized>(&mut self, buffer: &mut I) -> Result<(), Error> {
465 for e in self.iter_mut() {
466 e.decode_dynamic(buffer)?;
467 }
468 Ok(())
469 }
470}
471
472#[cfg(feature = "alloc")]
473impl Output for Vec<u8> {
474 fn write(&mut self, bytes: &[u8]) -> Result<(), Error> {
475 self.extend_from_slice(bytes);
476 Ok(())
477 }
478}
479
480impl Output for &'_ mut [u8] {
481 fn write(&mut self, from: &[u8]) -> Result<(), Error> {
482 if from.len() > self.len() {
483 return Err(Error::BufferIsTooShort)
484 }
485 let len = from.len();
486 self[..len].copy_from_slice(from);
487 let reduced = &mut self[len..];
489
490 *self = unsafe { &mut *(reduced as *mut [u8]) };
493 Ok(())
494 }
495}
496
497impl Input for &'_ [u8] {
498 fn remaining(&mut self) -> usize {
499 self.len()
500 }
501
502 fn peek(&self, into: &mut [u8]) -> Result<(), Error> {
503 if into.len() > self.len() {
504 return Err(Error::BufferIsTooShort)
505 }
506
507 let len = into.len();
508 into.copy_from_slice(&self[..len]);
509 Ok(())
510 }
511
512 fn read(&mut self, into: &mut [u8]) -> Result<(), Error> {
513 if into.len() > self.len() {
514 return Err(Error::BufferIsTooShort)
515 }
516
517 let len = into.len();
518 into.copy_from_slice(&self[..len]);
519 *self = &self[len..];
520 Ok(())
521 }
522
523 fn skip(&mut self, n: usize) -> Result<(), Error> {
524 if n > self.len() {
525 return Err(Error::BufferIsTooShort)
526 }
527
528 *self = &self[n..];
529 Ok(())
530 }
531}
532
533#[cfg(test)]
534mod tests {
535 use super::*;
536
537 fn validate<T: Serialize + Deserialize + Eq + core::fmt::Debug>(t: T) {
538 let bytes = t.to_bytes();
539 let t2 = T::from_bytes(&bytes).expect("Roundtrip failed");
540 assert_eq!(t, t2);
541 assert_eq!(t.to_bytes(), t2.to_bytes());
542
543 let mut vec = Vec::new();
544 t.encode_static(&mut vec).expect("Encode failed");
545 assert_eq!(vec.len(), t.size_static());
546 }
547
548 fn validate_enum<T: Serialize + Deserialize + Eq + fmt::Debug>(t: T) {
549 let bytes = t.to_bytes();
550 let t2 = T::from_bytes(&bytes).expect("Roundtrip failed");
551 assert_eq!(t, t2);
552 assert_eq!(t.to_bytes(), t2.to_bytes());
553
554 let mut vec = Vec::new();
555 t.encode_static(&mut vec).expect("Encode failed");
556 assert_eq!(vec.len(), t.size_static());
557 t.encode_dynamic(&mut vec).expect("Encode failed");
558 assert_eq!(vec.len(), t.size());
559
560 let mut vec2 = Vec::new();
561 t.encode_dynamic(&mut vec2).expect("Encode failed");
562 assert_eq!(vec2.len(), t.size_dynamic());
563 }
564
565 #[test]
566 fn test_canonical_encode_decode() {
567 validate(());
568 validate(123u8);
569 validate(u8::MAX);
570 validate(123u16);
571 validate(u16::MAX);
572 validate(123u32);
573 validate(u32::MAX);
574 validate(123u64);
575 validate(u64::MAX);
576 validate(123u128);
577 validate(u128::MAX);
578 validate(Vec::<u8>::new());
579 validate(Vec::<u16>::new());
580 validate(Vec::<u32>::new());
581 validate(Vec::<u64>::new());
582 validate(Vec::<u128>::new());
583 validate(vec![1u8]);
584 validate(vec![1u16]);
585 validate(vec![1u32]);
586 validate(vec![1u64]);
587 validate(vec![1u128]);
588 validate(vec![1u8, 2u8]);
589 validate(vec![1u16, 2u16]);
590 validate(vec![1u32, 2u32]);
591 validate(vec![1u64, 2u64]);
592 validate(vec![1u128, 2u128]);
593
594 #[derive(Serialize, Deserialize, Debug, PartialEq, Eq)]
595 struct TestStruct1 {
596 a: u8,
597 b: u16,
598 }
599
600 let t = TestStruct1 { a: 123, b: 456 };
601 assert_eq!(t.size_static(), 16);
602 assert_eq!(t.size(), 16);
603 validate(t);
604
605 #[derive(Serialize, Deserialize, Debug, PartialEq, Eq)]
606 struct TestStruct2 {
607 a: u8,
608 v: Vec<u8>,
609 b: u16,
610 arr0: [u8; 0],
611 arr1: [u8; 2],
612 arr2: [u16; 3],
613 arr3: [u64; 4],
614 }
615
616 validate(TestStruct2 {
617 a: 123,
618 v: vec![1, 2, 3],
619 b: 456,
620 arr0: [],
621 arr1: [1, 2],
622 arr2: [1, 2, u16::MAX],
623 arr3: [0, 3, 1111, u64::MAX],
624 });
625
626 #[derive(Serialize, Deserialize, Debug, PartialEq, Eq)]
627 #[repr(transparent)]
628 struct TestStruct3([u8; 64]);
629
630 let t = TestStruct3([1; 64]);
631 assert_eq!(t.size_static(), 64);
632 assert_eq!(t.size(), 64);
633 validate(t);
634
635 #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
636 #[canonical(prefix = 1u64)]
637 struct Prefixed1 {
638 a: [u8; 3],
639 b: Vec<u8>,
640 }
641 validate(Prefixed1 {
642 a: [1, 2, 3],
643 b: vec![4, 5, 6],
644 });
645
646 #[derive(Serialize, Deserialize, Debug, PartialEq, Eq)]
647 #[repr(u8)]
648 enum TestEnum1 {
649 A,
650 B,
651 C = 0x13,
652 D,
653 }
654
655 validate(TestEnum1::A);
656 validate(TestEnum1::B);
657 validate(TestEnum1::C);
658 validate(TestEnum1::D);
659
660 #[derive(Serialize, Deserialize, Debug, PartialEq, Eq)]
661 enum TestEnum2 {
662 A(u8),
663 B([u8; 3]),
664 C(Vec<u8>),
665 }
666
667 validate_enum(TestEnum2::A(2));
668 validate_enum(TestEnum2::B([1, 2, 3]));
669 validate_enum(TestEnum2::C(vec![1, 2, 3]));
670
671 #[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq)]
672 #[canonical(prefix = 2u64)]
673 struct Prefixed2(u16);
674 validate(Prefixed2(u16::MAX));
675
676 assert_eq!(
677 &Prefixed1 {
678 a: [1, 2, 3],
679 b: vec![4, 5]
680 }
681 .to_bytes()[..8],
682 &[0u8, 0, 0, 0, 0, 0, 0, 1]
683 );
684 assert_eq!(
685 Prefixed2(u16::MAX).to_bytes(),
686 [0u8, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0xff, 0xff]
687 );
688 }
689}