commonware_utils/array/
u64.rs

1use crate::Array;
2use bytes::{Buf, BufMut};
3use commonware_codec::{Codec, Error as CodecError, SizedCodec};
4use std::{
5    cmp::{Ord, PartialOrd},
6    fmt::{Debug, Display},
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)]
21#[repr(transparent)]
22pub struct U64([u8; u64::LEN_ENCODED]);
23
24impl U64 {
25    pub fn new(value: u64) -> Self {
26        Self(value.to_be_bytes())
27    }
28
29    pub fn to_u64(&self) -> u64 {
30        u64::from_be_bytes(self.0)
31    }
32}
33
34impl Codec for U64 {
35    fn write(&self, buf: &mut impl BufMut) {
36        self.0.write(buf);
37    }
38
39    fn read(buf: &mut impl Buf) -> Result<Self, CodecError> {
40        <[u8; U64::LEN_ENCODED]>::read(buf).map(Self)
41    }
42
43    fn len_encoded(&self) -> usize {
44        Self::LEN_ENCODED
45    }
46}
47
48impl SizedCodec for U64 {
49    const LEN_ENCODED: usize = u64::LEN_ENCODED;
50}
51
52impl Array for U64 {
53    type Error = Error;
54}
55
56impl From<[u8; U64::LEN_ENCODED]> for U64 {
57    fn from(value: [u8; U64::LEN_ENCODED]) -> Self {
58        Self(value)
59    }
60}
61
62impl TryFrom<&[u8]> for U64 {
63    type Error = Error;
64
65    fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
66        if value.len() != U64::LEN_ENCODED {
67            return Err(Error::InvalidLength);
68        }
69        let array: [u8; U64::LEN_ENCODED] = value.try_into().map_err(|_| Error::InvalidLength)?;
70        Ok(Self(array))
71    }
72}
73
74impl TryFrom<&Vec<u8>> for U64 {
75    type Error = Error;
76
77    fn try_from(value: &Vec<u8>) -> Result<Self, Self::Error> {
78        Self::try_from(value.as_slice())
79    }
80}
81
82impl TryFrom<Vec<u8>> for U64 {
83    type Error = Error;
84
85    fn try_from(value: Vec<u8>) -> Result<Self, Self::Error> {
86        if value.len() != U64::LEN_ENCODED {
87            return Err(Error::InvalidLength);
88        }
89
90        // If the length is correct, we can safely convert the vector into a boxed slice without any
91        // copies.
92        let boxed_slice = value.into_boxed_slice();
93        let boxed_array: Box<[u8; U64::LEN_ENCODED]> =
94            boxed_slice.try_into().map_err(|_| Error::InvalidLength)?;
95        Ok(Self(*boxed_array))
96    }
97}
98
99impl AsRef<[u8]> for U64 {
100    fn as_ref(&self) -> &[u8] {
101        &self.0
102    }
103}
104
105impl Deref for U64 {
106    type Target = [u8];
107    fn deref(&self) -> &[u8] {
108        &self.0
109    }
110}
111
112impl Debug for U64 {
113    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
114        write!(f, "{}", u64::from_be_bytes(self.0))
115    }
116}
117
118impl Display for U64 {
119    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
120        write!(f, "{}", u64::from_be_bytes(self.0))
121    }
122}
123
124#[cfg(test)]
125mod tests {
126    use super::*;
127
128    #[test]
129    fn test_u64() {
130        let value = 42u64;
131        let array = U64::new(value);
132        assert_eq!(value, U64::try_from(array.as_ref()).unwrap().to_u64());
133        assert_eq!(value, U64::from(array.0).to_u64());
134
135        let vec = array.to_vec();
136        assert_eq!(value, U64::try_from(&vec).unwrap().to_u64());
137        assert_eq!(value, U64::try_from(vec).unwrap().to_u64());
138    }
139
140    #[test]
141    fn test_codec() {
142        let original = U64::new(42u64);
143
144        let encoded = original.encode();
145        assert_eq!(encoded.len(), U64::LEN_ENCODED);
146        assert_eq!(encoded, original.as_ref());
147
148        let decoded = U64::decode(encoded).unwrap();
149        assert_eq!(original, decoded);
150    }
151}