commonware_utils/array/
u64.rs

1use crate::{Array, SizedSerialize};
2use std::{
3    cmp::{Ord, PartialOrd},
4    fmt::{Debug, Display},
5    hash::Hash,
6    ops::Deref,
7};
8use thiserror::Error;
9
10// Errors returned by `U64` functions.
11#[derive(Error, Debug, PartialEq)]
12pub enum Error {
13    #[error("invalid length")]
14    InvalidLength,
15}
16
17/// An `Array` implementation for `u64`.
18#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Default)]
19#[repr(transparent)]
20pub struct U64([u8; U64::SERIALIZED_LEN]);
21
22impl U64 {
23    pub fn new(value: u64) -> Self {
24        Self(value.to_be_bytes())
25    }
26
27    pub fn to_u64(&self) -> u64 {
28        u64::from_be_bytes(self.0)
29    }
30}
31
32impl Array for U64 {
33    type Error = Error;
34}
35
36impl SizedSerialize for U64 {
37    const SERIALIZED_LEN: usize = u64::SERIALIZED_LEN;
38}
39
40impl From<[u8; U64::SERIALIZED_LEN]> for U64 {
41    fn from(value: [u8; U64::SERIALIZED_LEN]) -> Self {
42        Self(value)
43    }
44}
45
46impl TryFrom<&[u8]> for U64 {
47    type Error = Error;
48
49    fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
50        if value.len() != U64::SERIALIZED_LEN {
51            return Err(Error::InvalidLength);
52        }
53        let array: [u8; U64::SERIALIZED_LEN] =
54            value.try_into().map_err(|_| Error::InvalidLength)?;
55        Ok(Self(array))
56    }
57}
58
59impl TryFrom<&Vec<u8>> for U64 {
60    type Error = Error;
61
62    fn try_from(value: &Vec<u8>) -> Result<Self, Self::Error> {
63        Self::try_from(value.as_slice())
64    }
65}
66
67impl TryFrom<Vec<u8>> for U64 {
68    type Error = Error;
69
70    fn try_from(value: Vec<u8>) -> Result<Self, Self::Error> {
71        if value.len() != U64::SERIALIZED_LEN {
72            return Err(Error::InvalidLength);
73        }
74
75        // If the length is correct, we can safely convert the vector into a boxed slice without any
76        // copies.
77        let boxed_slice = value.into_boxed_slice();
78        let boxed_array: Box<[u8; U64::SERIALIZED_LEN]> =
79            boxed_slice.try_into().map_err(|_| Error::InvalidLength)?;
80        Ok(Self(*boxed_array))
81    }
82}
83
84impl AsRef<[u8]> for U64 {
85    fn as_ref(&self) -> &[u8] {
86        &self.0
87    }
88}
89
90impl Deref for U64 {
91    type Target = [u8];
92    fn deref(&self) -> &[u8] {
93        &self.0
94    }
95}
96
97impl Debug for U64 {
98    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
99        write!(f, "{}", u64::from_be_bytes(self.0))
100    }
101}
102
103impl Display for U64 {
104    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
105        write!(f, "{}", u64::from_be_bytes(self.0))
106    }
107}
108
109#[cfg(test)]
110mod tests {
111    use super::*;
112
113    #[test]
114    fn test_u64() {
115        let value = 42u64;
116        let array = U64::new(value);
117        assert_eq!(value, U64::try_from(array.as_ref()).unwrap().to_u64());
118        assert_eq!(value, U64::from(array.0).to_u64());
119
120        let vec = array.to_vec();
121        assert_eq!(value, U64::try_from(&vec).unwrap().to_u64());
122        assert_eq!(value, U64::try_from(vec).unwrap().to_u64());
123    }
124}