Skip to main content

commonware_utils/sequence/
u64.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 `U64` functions.
13#[derive(Error, Debug, PartialEq)]
14pub enum Error {
15    #[error("invalid length")]
16    InvalidLength,
17}
18
19/// An `Array` implementation for `u64`.
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 U64([u8; u64::SIZE]);
25
26impl U64 {
27    pub const fn new(value: u64) -> Self {
28        Self(value.to_be_bytes())
29    }
30}
31
32impl Write for U64 {
33    fn write(&self, buf: &mut impl BufMut) {
34        self.0.write(buf);
35    }
36}
37
38impl Read for U64 {
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 U64 {
47    const SIZE: usize = u64::SIZE;
48}
49
50impl Span for U64 {}
51
52impl Array for U64 {}
53
54impl From<u64> for U64 {
55    fn from(value: u64) -> Self {
56        Self(value.to_be_bytes())
57    }
58}
59
60impl From<U64> for u64 {
61    fn from(value: U64) -> Self {
62        Self::from_be_bytes(value.0)
63    }
64}
65
66impl From<&U64> for u64 {
67    fn from(value: &U64) -> Self {
68        Self::from_be_bytes(value.0)
69    }
70}
71
72impl AsRef<[u8]> for U64 {
73    fn as_ref(&self) -> &[u8] {
74        &self.0
75    }
76}
77
78impl Deref for U64 {
79    type Target = [u8];
80    fn deref(&self) -> &[u8] {
81        &self.0
82    }
83}
84
85impl Debug for U64 {
86    fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
87        write!(f, "{}", u64::from_be_bytes(self.0))
88    }
89}
90
91impl Display for U64 {
92    fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
93        write!(f, "{}", u64::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_u64() {
104        let value = 42u64;
105        let array = U64::new(value);
106        assert_eq!(value, u64::from(U64::decode(array.as_ref()).unwrap()));
107        assert_eq!(value, u64::from(U64::from(array.0)));
108
109        let vec = array.to_vec();
110        assert_eq!(value, u64::from(U64::decode(vec.as_ref()).unwrap()));
111    }
112
113    #[test]
114    fn test_codec() {
115        let original = U64::new(42u64);
116
117        let encoded = original.encode();
118        assert_eq!(encoded.len(), U64::SIZE);
119        assert_eq!(encoded, original.as_ref());
120
121        let decoded = U64::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<U64>,
132        }
133    }
134}