commonware_utils/array/
u64.rs1use 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#[derive(Error, Debug, PartialEq)]
14pub enum Error {
15 #[error("invalid length")]
16 InvalidLength,
17}
18
19#[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 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}