Skip to main content

commonware_utils/sequence/
u32.rs

1use crate::{Array, Span};
2use bytes::{Buf, BufMut};
3use commonware_codec::{Error as CodecError, FixedArray, FixedSize, Read, ReadExt, Write};
4use core::{
5    cmp::{Ord, PartialOrd},
6    fmt::{Debug, Display, Formatter},
7    hash::Hash,
8    ops::Deref,
9};
10use thiserror::Error;
11
12// Errors returned by [U32] functions.
13#[derive(Error, Debug, PartialEq)]
14pub enum Error {
15    #[error("invalid length")]
16    InvalidLength,
17}
18
19/// An [Array] implementation for u32.
20#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Default, FixedArray)]
21#[fixed_array(infallible)]
22#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
23#[repr(transparent)]
24pub struct U32([u8; u32::SIZE]);
25
26impl U32 {
27    pub const fn new(value: u32) -> Self {
28        Self(value.to_be_bytes())
29    }
30}
31
32impl Write for U32 {
33    fn write(&self, buf: &mut impl BufMut) {
34        self.0.write(buf);
35    }
36}
37
38impl Read for U32 {
39    type Cfg = ();
40
41    fn read_cfg(buf: &mut impl Buf, _: &()) -> Result<Self, CodecError> {
42        <[u8; Self::SIZE]>::read(buf).map(Self)
43    }
44}
45
46impl FixedSize for U32 {
47    const SIZE: usize = u32::SIZE;
48}
49
50impl Span for U32 {}
51
52impl Array for U32 {}
53
54impl From<u32> for U32 {
55    fn from(value: u32) -> Self {
56        Self(value.to_be_bytes())
57    }
58}
59
60impl From<U32> for u32 {
61    fn from(value: U32) -> Self {
62        Self::from_be_bytes(value.0)
63    }
64}
65
66impl From<&U32> for u32 {
67    fn from(value: &U32) -> Self {
68        Self::from_be_bytes(value.0)
69    }
70}
71
72impl AsRef<[u8]> for U32 {
73    fn as_ref(&self) -> &[u8] {
74        &self.0
75    }
76}
77
78impl Deref for U32 {
79    type Target = [u8];
80    fn deref(&self) -> &[u8] {
81        &self.0
82    }
83}
84
85impl Debug for U32 {
86    fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
87        write!(f, "{}", u32::from_be_bytes(self.0))
88    }
89}
90
91impl Display for U32 {
92    fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
93        write!(f, "{}", u32::from_be_bytes(self.0))
94    }
95}
96
97#[cfg(test)]
98mod tests {
99    use super::*;
100    use commonware_codec::{DecodeExt, Encode};
101
102    #[test]
103    fn test_u32() {
104        let value = 42u32;
105        let array = U32::new(value);
106        assert_eq!(value, u32::from(U32::decode(array.as_ref()).unwrap()));
107        assert_eq!(value, u32::from(U32::from(array.0)));
108
109        let vec = array.to_vec();
110        assert_eq!(value, u32::from(U32::decode(vec.as_ref()).unwrap()));
111    }
112
113    #[test]
114    fn test_codec() {
115        let original = U32::new(42u32);
116
117        let encoded = original.encode();
118        assert_eq!(encoded.len(), U32::SIZE);
119        assert_eq!(encoded, original.as_ref());
120
121        let decoded = U32::decode(encoded).unwrap();
122        assert_eq!(original, decoded);
123    }
124
125    #[cfg(feature = "arbitrary")]
126    mod conformance {
127        use super::*;
128        use commonware_codec::conformance::CodecConformance;
129
130        commonware_conformance::conformance_tests! {
131            CodecConformance<U32>,
132        }
133    }
134}