commonware_utils/array/
prefixed_u64.rs1use crate::Array;
4use bytes::{Buf, BufMut};
5use commonware_codec::{Codec, Error as CodecError, SizedCodec};
6use std::{
7 cmp::{Ord, PartialOrd},
8 fmt::{Debug, Display},
9 hash::Hash,
10 ops::Deref,
11};
12use thiserror::Error;
13
14#[derive(Error, Debug, PartialEq)]
16pub enum Error {
17 #[error("invalid length")]
18 InvalidLength,
19}
20
21#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Default)]
23#[repr(transparent)]
24pub struct U64([u8; u64::LEN_ENCODED + 1]);
25
26impl U64 {
27 pub fn new(prefix: u8, value: u64) -> Self {
28 let mut arr = [0; u64::LEN_ENCODED + 1];
29 arr[0] = prefix;
30 arr[1..].copy_from_slice(&u64::to_be_bytes(value));
31
32 Self(arr)
33 }
34
35 pub fn to_u64(&self) -> u64 {
36 u64::from_be_bytes(self.0[1..].try_into().unwrap())
37 }
38
39 pub fn prefix(&self) -> u8 {
40 self.0[0]
41 }
42}
43
44impl Codec for U64 {
45 fn write(&self, buf: &mut impl BufMut) {
46 self.0.write(buf);
47 }
48
49 fn read(buf: &mut impl Buf) -> Result<Self, CodecError> {
50 <[u8; Self::LEN_ENCODED]>::read(buf).map(Self)
51 }
52
53 fn len_encoded(&self) -> usize {
54 Self::LEN_ENCODED
55 }
56}
57
58impl SizedCodec for U64 {
59 const LEN_ENCODED: usize = u64::LEN_ENCODED + 1;
60}
61
62impl Array for U64 {
63 type Error = Error;
64}
65
66impl From<[u8; U64::LEN_ENCODED]> for U64 {
67 fn from(value: [u8; U64::LEN_ENCODED]) -> Self {
68 Self(value)
69 }
70}
71
72impl TryFrom<&[u8]> for U64 {
73 type Error = Error;
74
75 fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
76 if value.len() != U64::LEN_ENCODED {
77 return Err(Error::InvalidLength);
78 }
79 let array: [u8; U64::LEN_ENCODED] = value.try_into().map_err(|_| Error::InvalidLength)?;
80 Ok(Self(array))
81 }
82}
83
84impl TryFrom<&Vec<u8>> for U64 {
85 type Error = Error;
86
87 fn try_from(value: &Vec<u8>) -> Result<Self, Self::Error> {
88 Self::try_from(value.as_slice())
89 }
90}
91
92impl TryFrom<Vec<u8>> for U64 {
93 type Error = Error;
94
95 fn try_from(value: Vec<u8>) -> Result<Self, Self::Error> {
96 if value.len() != U64::LEN_ENCODED {
97 return Err(Error::InvalidLength);
98 }
99
100 let boxed_slice = value.into_boxed_slice();
103 let boxed_array: Box<[u8; U64::LEN_ENCODED]> =
104 boxed_slice.try_into().map_err(|_| Error::InvalidLength)?;
105 Ok(Self(*boxed_array))
106 }
107}
108
109impl AsRef<[u8]> for U64 {
110 fn as_ref(&self) -> &[u8] {
111 &self.0
112 }
113}
114
115impl Deref for U64 {
116 type Target = [u8];
117 fn deref(&self) -> &[u8] {
118 &self.0
119 }
120}
121
122impl Debug for U64 {
123 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
124 write!(
125 f,
126 "{}:{}",
127 self.0[0],
128 u64::from_be_bytes(self.0[1..].try_into().unwrap())
129 )
130 }
131}
132
133impl Display for U64 {
134 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
135 Debug::fmt(self, f)
136 }
137}
138
139#[cfg(test)]
140mod tests {
141 use super::*;
142
143 #[test]
144 fn test_prefixed_u64() {
145 let prefix = 69u8;
146 let value = 42u64;
147 let array = U64::new(prefix, value);
148 let try_from = U64::try_from(array.as_ref()).unwrap();
149 assert_eq!(value, try_from.to_u64());
150 assert_eq!(prefix, try_from.prefix());
151 let from = U64::from(array.0);
152 assert_eq!(value, from.to_u64());
153 assert_eq!(prefix, from.prefix());
154
155 let vec = array.to_vec();
156 let from_vec = U64::try_from(&vec).unwrap();
157 assert_eq!(value, from_vec.to_u64());
158 assert_eq!(prefix, from_vec.prefix());
159 let from_vec = U64::try_from(vec).unwrap();
160 assert_eq!(value, from_vec.to_u64());
161 assert_eq!(prefix, from_vec.prefix());
162 }
163
164 #[test]
165 fn test_prefixed_u64_codec() {
166 let original = U64::new(69, 42u64);
167
168 let encoded = original.encode();
169 assert_eq!(encoded.len(), U64::LEN_ENCODED);
170 assert_eq!(encoded, original.as_ref());
171
172 let decoded = U64::decode(encoded).unwrap();
173 assert_eq!(original, decoded);
174 }
175}