1use crate::{Buf, Copying, Input, error::Error};
4#[cfg(not(feature = "std"))]
5use alloc::{sync::Arc, vec::Vec};
6use bytes::{Buf as _, BufMut, Bytes, BytesMut};
7#[cfg(feature = "std")]
8use std::{sync::Arc, vec::Vec};
9
10pub trait FixedSize {
17 const SIZE: usize;
19}
20
21pub trait MaxEncodeSize {
25 const MAX_ENCODE_SIZE: usize;
27}
28
29impl<T: FixedSize> MaxEncodeSize for T {
30 const MAX_ENCODE_SIZE: usize = T::SIZE;
31}
32
33pub trait EncodeSize {
39 fn encode_size(&self) -> usize;
41
42 #[doc(hidden)]
57 #[inline]
58 fn encode_size_slice(values: &[Self]) -> usize
59 where
60 Self: Sized,
61 {
62 values.iter().map(EncodeSize::encode_size).sum()
63 }
64
65 #[inline]
71 fn encode_inline_size(&self) -> usize {
72 self.encode_size()
73 }
74
75 #[doc(hidden)]
89 #[inline]
90 fn encode_inline_size_slice(values: &[Self]) -> usize
91 where
92 Self: Sized,
93 {
94 values
95 .iter()
96 .map(EncodeSize::encode_inline_size)
97 .sum::<usize>()
98 }
99}
100
101impl<T: FixedSize> EncodeSize for T {
103 #[inline]
104 fn encode_size(&self) -> usize {
105 Self::SIZE
106 }
107
108 #[inline]
109 fn encode_size_slice(values: &[Self]) -> usize
110 where
111 Self: Sized,
112 {
113 Self::SIZE * values.len()
114 }
115
116 #[inline]
117 fn encode_inline_size_slice(values: &[Self]) -> usize
118 where
119 Self: Sized,
120 {
121 Self::encode_size_slice(values)
122 }
123}
124
125pub trait Write {
127 fn write(&self, buf: &mut impl BufMut);
131
132 #[doc(hidden)]
145 #[inline]
146 fn write_slice(values: &[Self], buf: &mut impl BufMut)
147 where
148 Self: Sized,
149 {
150 for item in values {
151 item.write(buf);
152 }
153 }
154
155 #[inline]
159 fn write_bufs(&self, buf: &mut impl BufsMut) {
160 self.write(buf);
161 }
162
163 #[doc(hidden)]
174 #[inline]
175 fn write_slice_bufs(values: &[Self], buf: &mut impl BufsMut)
176 where
177 Self: Sized,
178 {
179 for item in values {
180 item.write_bufs(buf);
181 }
182 }
183}
184
185impl<T: EncodeSize + ?Sized> EncodeSize for Arc<T> {
186 #[inline]
187 fn encode_size(&self) -> usize {
188 self.as_ref().encode_size()
189 }
190
191 #[inline]
192 fn encode_inline_size(&self) -> usize {
193 self.as_ref().encode_inline_size()
194 }
195}
196
197impl<T: Write + ?Sized> Write for Arc<T> {
198 #[inline]
199 fn write(&self, buf: &mut impl BufMut) {
200 self.as_ref().write(buf);
201 }
202
203 #[inline]
204 fn write_bufs(&self, buf: &mut impl BufsMut) {
205 self.as_ref().write_bufs(buf);
206 }
207}
208
209pub trait Read: Sized {
211 type Cfg: Clone + Send + Sync + 'static;
217
218 fn read_cfg(buf: &mut impl Buf, cfg: &Self::Cfg) -> Result<Self, Error>;
230
231 #[doc(hidden)]
243 #[inline]
244 fn read_vec(buf: &mut impl Buf, len: usize, cfg: &Self::Cfg) -> Result<Vec<Self>, Error> {
245 let mut values = Vec::with_capacity(len.min(buf.remaining()));
246 for _ in 0..len {
247 values.push(Self::read_cfg(buf, cfg)?);
248 }
249 Ok(values)
250 }
251
252 #[doc(hidden)]
262 #[inline]
263 fn read_array<const N: usize>(buf: &mut impl Buf, cfg: &Self::Cfg) -> Result<[Self; N], Error> {
264 Ok(Self::read_vec(buf, N, cfg)?
265 .try_into()
266 .unwrap_or_else(|_| unreachable!("array length should match capacity")))
267 }
268}
269
270impl<T: Read> Read for Arc<T> {
271 type Cfg = T::Cfg;
272
273 #[inline]
274 fn read_cfg(buf: &mut impl Buf, cfg: &Self::Cfg) -> Result<Self, Error> {
275 T::read_cfg(buf, cfg).map(Self::new)
276 }
277}
278
279pub trait Encode: Write + EncodeSize {
284 fn encode(&self) -> Bytes {
295 self.encode_mut().freeze()
296 }
297
298 fn encode_mut(&self) -> BytesMut {
309 let len = self.encode_size();
310 let mut buffer = BytesMut::with_capacity(len);
311 self.write(&mut buffer);
312 assert_eq!(buffer.len(), len, "write() did not write expected bytes");
313 buffer
314 }
315}
316
317impl<T: Write + EncodeSize> Encode for T {}
319
320pub trait EncodeShared: Encode + Send + Sync {}
324
325impl<T: Encode + Send + Sync> EncodeShared for T {}
327
328pub trait Decode: Read {
332 fn decode_cfg(buf: impl Input, cfg: &Self::Cfg) -> Result<Self, Error> {
340 let mut buf = buf.into();
341 let result = Self::read_cfg(&mut buf, cfg)?;
342
343 let remaining = buf.remaining();
345 if remaining > 0 {
346 return Err(Error::ExtraData(remaining));
347 }
348
349 Ok(result)
350 }
351}
352
353impl<T: Read> Decode for T {}
355
356pub trait Codec: Encode + Decode {}
360
361impl<T: Encode + Decode> Codec for T {}
363
364pub trait EncodeFixed: Write + FixedSize {
366 fn encode_fixed<const N: usize>(&self) -> [u8; N] {
373 assert_eq!(
376 N,
377 Self::SIZE,
378 "Can't encode {} bytes into {} bytes",
379 Self::SIZE,
380 N
381 );
382
383 let mut array = [0u8; N];
384 let mut buf = &mut array[..];
385 self.write(&mut buf);
386 assert_eq!(buf.len(), 0);
387 array
388 }
389}
390
391impl<T: Write + FixedSize> EncodeFixed for T {}
393
394pub trait DecodeFixed: Read<Cfg = ()> + FixedSize {
396 fn decode_fixed<const N: usize>(bytes: [u8; N]) -> Result<Self, Error> {
402 assert_eq!(
403 N,
404 Self::SIZE,
405 "Can't decode {} bytes into {} bytes",
406 N,
407 Self::SIZE
408 );
409
410 Self::decode_cfg(Copying(&bytes), &())
411 }
412}
413
414impl<T: Read<Cfg = ()> + FixedSize> DecodeFixed for T {}
416
417pub trait CodecFixed: Codec + FixedSize {}
421
422impl<T: Codec + FixedSize> CodecFixed for T {}
424
425pub trait CodecShared: Codec + Send + Sync {}
429
430impl<T: Codec + Send + Sync> CodecShared for T {}
432
433pub trait CodecFixedShared: CodecFixed<Cfg = ()> + Send + Sync {}
438
439impl<T: CodecFixed<Cfg = ()> + Send + Sync> CodecFixedShared for T {}
441
442pub trait BufsMut: BufMut {
444 fn push(&mut self, chunk: impl Into<Bytes> + 'static);
447}
448
449#[cfg(test)]
450mod tests {
451 use super::*;
452 use crate::{
453 Error, FixedArray,
454 extensions::{DecodeExt, ReadExt},
455 };
456 use bytes::Bytes;
457 use core::marker::PhantomData;
458
459 #[test]
460 fn test_insufficient_buffer() {
461 let mut reader = Bytes::from_static(&[0x01, 0x02]);
462 assert!(matches!(u32::read(&mut reader), Err(Error::EndOfBuffer)));
463 }
464
465 #[test]
466 fn test_extra_data() {
467 let encoded = Bytes::from_static(&[0x01, 0x02]);
468 assert!(matches!(u8::decode(encoded), Err(Error::ExtraData(1))));
469 }
470
471 #[test]
472 fn test_encode_fixed() {
473 let value = 42u32;
474 let encoded: [u8; 4] = value.encode_fixed();
475 let decoded = <u32>::decode(Copying(&encoded)).unwrap();
476 assert_eq!(value, decoded);
477 }
478
479 #[test]
480 fn test_arc_codec() {
481 let value = Arc::new(vec![1u8, 2, 3]);
482 let encoded = value.encode();
483 let cfg = ((..=3).into(), ());
484
485 assert_eq!(encoded, value.as_ref().encode());
486 assert_eq!(value.encode_size(), value.as_ref().encode_size());
487 assert_eq!(
488 Arc::<Vec<u8>>::decode_cfg(encoded.clone(), &cfg).unwrap(),
489 value
490 );
491
492 assert!(matches!(
494 Arc::<Vec<u8>>::decode_cfg(encoded.clone(), &((..=2).into(), ())),
495 Err(Error::InvalidLength(3))
496 ));
497 assert!(matches!(
498 Arc::<Vec<u8>>::decode_cfg(encoded.slice(..encoded.len() - 1), &cfg),
499 Err(Error::EndOfBuffer)
500 ));
501 }
502
503 #[test]
504 #[should_panic(expected = "Can't encode 4 bytes into 5 bytes")]
505 fn test_encode_fixed_panic() {
506 let _: [u8; 5] = 42u32.encode_fixed();
507 }
508
509 #[derive(Debug, Eq, PartialEq, FixedArray)]
510 struct FixedBytes([u8; 2]);
511
512 impl Write for FixedBytes {
513 fn write(&self, buf: &mut impl BufMut) {
514 self.0.write(buf);
515 }
516 }
517
518 impl Read for FixedBytes {
519 type Cfg = ();
520
521 fn read_cfg(buf: &mut impl Buf, _: &()) -> Result<Self, Error> {
522 Ok(Self(<[u8; Self::SIZE]>::read(buf)?))
523 }
524 }
525
526 impl FixedSize for FixedBytes {
527 const SIZE: usize = 2;
528 }
529
530 #[test]
531 fn test_fixed_array() {
532 let value = FixedBytes([1, 2]);
533 let encoded: [u8; FixedBytes::SIZE] = (&value).into();
534 assert_eq!(encoded, [1, 2]);
535 assert_eq!(<[u8; FixedBytes::SIZE]>::from(value), encoded);
536 assert_eq!(FixedBytes::try_from(encoded).unwrap(), FixedBytes([1, 2]));
537 assert_eq!(FixedBytes::try_from(&encoded).unwrap(), FixedBytes([1, 2]));
538 assert_eq!(
539 FixedBytes::try_from([1u8, 2].as_slice()).unwrap(),
540 FixedBytes([1, 2])
541 );
542 assert!(matches!(
543 FixedBytes::try_from([1u8].as_slice()),
544 Err(Error::EndOfBuffer)
545 ));
546 assert!(matches!(
547 FixedBytes::try_from([1u8, 2, 3].as_slice()),
548 Err(Error::ExtraData(1))
549 ));
550 }
551
552 #[test]
553 fn test_decode_fixed() {
554 assert_eq!(
555 FixedBytes::decode_fixed([1, 2]).unwrap(),
556 FixedBytes([1, 2])
557 );
558 }
559
560 #[test]
561 #[should_panic(expected = "Can't decode 3 bytes into 2 bytes")]
562 fn test_decode_fixed_panic() {
563 let _ = FixedBytes::decode_fixed([1, 2, 3]);
564 }
565
566 #[derive(Debug, Eq, PartialEq, FixedArray)]
567 #[fixed_array(infallible)]
568 struct InfallibleFixedBytes([u8; 2]);
569
570 impl Write for InfallibleFixedBytes {
571 fn write(&self, buf: &mut impl BufMut) {
572 self.0.write(buf);
573 }
574 }
575
576 impl Read for InfallibleFixedBytes {
577 type Cfg = ();
578
579 fn read_cfg(buf: &mut impl Buf, _: &()) -> Result<Self, Error> {
580 Ok(Self(<[u8; Self::SIZE]>::read(buf)?))
581 }
582 }
583
584 impl FixedSize for InfallibleFixedBytes {
585 const SIZE: usize = 2;
586 }
587
588 #[test]
589 fn test_fixed_array_infallible() {
590 let value = InfallibleFixedBytes([1, 2]);
591 let encoded: [u8; InfallibleFixedBytes::SIZE] = (&value).into();
592 assert_eq!(encoded, [1, 2]);
593 assert_eq!(<[u8; InfallibleFixedBytes::SIZE]>::from(value), encoded);
594 assert_eq!(
595 InfallibleFixedBytes::from(encoded),
596 InfallibleFixedBytes([1, 2])
597 );
598 assert_eq!(
599 InfallibleFixedBytes::from(&encoded),
600 InfallibleFixedBytes([1, 2])
601 );
602 assert_eq!(
603 InfallibleFixedBytes::try_from([1u8, 2].as_slice()).unwrap(),
604 InfallibleFixedBytes([1, 2])
605 );
606 assert!(matches!(
607 InfallibleFixedBytes::try_from([1u8, 2, 3].as_slice()),
608 Err(Error::ExtraData(1))
609 ));
610 }
611
612 #[derive(Debug, Eq, PartialEq, FixedArray)]
613 #[fixed_array(bytes([u8; N]))]
614 struct GenericFixed<const N: usize>([u8; N]);
615
616 impl<const N: usize> Write for GenericFixed<N> {
617 fn write(&self, buf: &mut impl BufMut) {
618 self.0.write(buf);
619 }
620 }
621
622 impl<const N: usize> Read for GenericFixed<N> {
623 type Cfg = ();
624
625 fn read_cfg(buf: &mut impl Buf, _: &()) -> Result<Self, Error> {
626 Ok(Self(<[u8; N]>::read(buf)?))
627 }
628 }
629
630 impl<const N: usize> FixedSize for GenericFixed<N> {
631 const SIZE: usize = N;
632 }
633
634 #[test]
635 fn test_fixed_array_generic() {
636 let value = GenericFixed::<3>([1, 2, 3]);
637 let encoded: [u8; 3] = (&value).into();
638 assert_eq!(encoded, [1, 2, 3]);
639 assert_eq!(<[u8; 3]>::from(value), encoded);
640 assert_eq!(
641 GenericFixed::<3>::try_from(encoded).unwrap(),
642 GenericFixed([1, 2, 3])
643 );
644 assert_eq!(
645 GenericFixed::<3>::try_from(&encoded).unwrap(),
646 GenericFixed([1, 2, 3])
647 );
648 assert_eq!(
649 GenericFixed::<3>::try_from([1u8, 2, 3].as_slice()).unwrap(),
650 GenericFixed([1, 2, 3])
651 );
652 }
653
654 #[derive(Debug, Eq, PartialEq, FixedArray)]
655 #[fixed_array(infallible, bytes([u8; N]))]
656 struct GenericInfallible<const N: usize>([u8; N]);
657
658 impl<const N: usize> Write for GenericInfallible<N> {
659 fn write(&self, buf: &mut impl BufMut) {
660 self.0.write(buf);
661 }
662 }
663
664 impl<const N: usize> Read for GenericInfallible<N> {
665 type Cfg = ();
666
667 fn read_cfg(buf: &mut impl Buf, _: &()) -> Result<Self, Error> {
668 Ok(Self(<[u8; N]>::read(buf)?))
669 }
670 }
671
672 impl<const N: usize> FixedSize for GenericInfallible<N> {
673 const SIZE: usize = N;
674 }
675
676 #[test]
677 fn test_fixed_array_generic_infallible() {
678 let value = GenericInfallible::<3>([1, 2, 3]);
679 let encoded: [u8; 3] = (&value).into();
680 assert_eq!(encoded, [1, 2, 3]);
681 assert_eq!(<[u8; 3]>::from(value), encoded);
682 assert_eq!(
683 GenericInfallible::<3>::from(encoded),
684 GenericInfallible([1, 2, 3])
685 );
686 assert_eq!(
687 GenericInfallible::<3>::from(&encoded),
688 GenericInfallible([1, 2, 3])
689 );
690 assert_eq!(
691 GenericInfallible::<3>::try_from([1u8, 2, 3].as_slice()).unwrap(),
692 GenericInfallible([1, 2, 3])
693 );
694 }
695
696 trait FixedArrayBound {}
697
698 #[derive(Debug, Eq, PartialEq)]
699 struct Bounded;
700
701 impl FixedArrayBound for Bounded {}
702
703 #[derive(Debug, Eq, PartialEq, FixedArray)]
704 #[fixed_array(bytes([u8; 2]))]
705 struct BoundedGeneric<T> {
706 marker: PhantomData<T>,
707 raw: [u8; 2],
708 }
709
710 impl<T: FixedArrayBound> Write for BoundedGeneric<T> {
711 fn write(&self, buf: &mut impl BufMut) {
712 self.raw.write(buf);
713 }
714 }
715
716 impl<T: FixedArrayBound> Read for BoundedGeneric<T> {
717 type Cfg = ();
718
719 fn read_cfg(buf: &mut impl Buf, _: &()) -> Result<Self, Error> {
720 Ok(Self {
721 marker: PhantomData,
722 raw: <[u8; 2]>::read(buf)?,
723 })
724 }
725 }
726
727 impl<T: FixedArrayBound> FixedSize for BoundedGeneric<T> {
728 const SIZE: usize = 2;
729 }
730
731 #[test]
732 fn test_fixed_array_bounded_generic() {
733 let value = BoundedGeneric::<Bounded> {
734 marker: PhantomData,
735 raw: [1, 2],
736 };
737 let encoded: [u8; 2] = (&value).into();
738 assert_eq!(encoded, [1, 2]);
739 assert_eq!(<[u8; 2]>::from(value).as_ref(), &[1, 2]);
740 assert_eq!(
741 BoundedGeneric::<Bounded>::try_from(encoded).unwrap().raw,
742 [1, 2]
743 );
744 assert_eq!(
745 BoundedGeneric::<Bounded>::try_from(&encoded).unwrap().raw,
746 [1, 2]
747 );
748 assert_eq!(
749 BoundedGeneric::<Bounded>::try_from([1u8, 2].as_slice())
750 .unwrap()
751 .raw,
752 [1, 2]
753 );
754 }
755
756 #[derive(Debug, Eq, PartialEq, FixedArray)]
757 #[fixed_array(bytes([u8; 2]))]
758 struct LifetimeFixed<'a> {
759 marker: PhantomData<&'a ()>,
760 raw: [u8; 2],
761 }
762
763 impl Write for LifetimeFixed<'_> {
764 fn write(&self, buf: &mut impl BufMut) {
765 self.raw.write(buf);
766 }
767 }
768
769 impl Read for LifetimeFixed<'_> {
770 type Cfg = ();
771
772 fn read_cfg(buf: &mut impl Buf, _: &()) -> Result<Self, Error> {
773 Ok(Self {
774 marker: PhantomData,
775 raw: <[u8; 2]>::read(buf)?,
776 })
777 }
778 }
779
780 impl FixedSize for LifetimeFixed<'_> {
781 const SIZE: usize = 2;
782 }
783
784 #[test]
785 fn test_fixed_array_lifetime() {
786 let value = LifetimeFixed {
787 marker: PhantomData,
788 raw: [1, 2],
789 };
790 let encoded: [u8; LifetimeFixed::SIZE] = (&value).into();
791 assert_eq!(encoded, [1, 2]);
792 assert_eq!(<[u8; LifetimeFixed::SIZE]>::from(value).as_ref(), &[1, 2]);
793 assert_eq!(LifetimeFixed::try_from(encoded).unwrap().raw, [1, 2]);
794 assert_eq!(LifetimeFixed::try_from(&encoded).unwrap().raw, [1, 2]);
795 assert_eq!(
796 LifetimeFixed::try_from([1u8, 2].as_slice()).unwrap().raw,
797 [1, 2]
798 );
799 }
800
801 #[cfg(feature = "arbitrary")]
802 mod conformance {
803 use super::Arc;
804 use crate::conformance::CodecConformance;
805
806 commonware_conformance::conformance_tests! {
807 CodecConformance<Arc<u64>>,
808 CodecConformance<Arc<Vec<u8>>>,
809 }
810 }
811}