commonware_utils/array/
prefixed_u64.rs1use crate::Array;
4use bytes::{Buf, BufMut};
5use commonware_codec::{Error as CodecError, FixedSize, Read, ReadExt, Write};
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::SIZE + 1]);
25
26impl U64 {
27 pub fn new(prefix: u8, value: u64) -> Self {
28 let mut arr = [0; u64::SIZE + 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 Write for U64 {
45 fn write(&self, buf: &mut impl BufMut) {
46 self.0.write(buf);
47 }
48}
49
50impl Read for U64 {
51 type Cfg = ();
52
53 fn read_cfg(buf: &mut impl Buf, _: &()) -> Result<Self, CodecError> {
54 <[u8; Self::SIZE]>::read(buf).map(Self)
55 }
56}
57
58impl FixedSize for U64 {
59 const SIZE: usize = u64::SIZE + 1;
60}
61
62impl Array for U64 {}
63
64impl From<[u8; U64::SIZE]> for U64 {
65 fn from(value: [u8; U64::SIZE]) -> Self {
66 Self(value)
67 }
68}
69
70impl AsRef<[u8]> for U64 {
71 fn as_ref(&self) -> &[u8] {
72 &self.0
73 }
74}
75
76impl Deref for U64 {
77 type Target = [u8];
78 fn deref(&self) -> &[u8] {
79 &self.0
80 }
81}
82
83impl Debug for U64 {
84 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
85 write!(
86 f,
87 "{}:{}",
88 self.0[0],
89 u64::from_be_bytes(self.0[1..].try_into().unwrap())
90 )
91 }
92}
93
94impl Display for U64 {
95 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
96 Debug::fmt(self, f)
97 }
98}
99
100#[cfg(test)]
101mod tests {
102 use super::*;
103 use commonware_codec::{DecodeExt, Encode};
104
105 #[test]
106 fn test_prefixed_u64() {
107 let prefix = 69u8;
108 let value = 42u64;
109 let array = U64::new(prefix, value);
110 let decoded = U64::decode(array.as_ref()).unwrap();
111 assert_eq!(value, decoded.to_u64());
112 assert_eq!(prefix, decoded.prefix());
113 let from = U64::from(array.0);
114 assert_eq!(value, from.to_u64());
115 assert_eq!(prefix, from.prefix());
116
117 let vec = array.to_vec();
118 let from_vec = U64::decode(vec.as_ref()).unwrap();
119 assert_eq!(value, from_vec.to_u64());
120 assert_eq!(prefix, from_vec.prefix());
121 }
122
123 #[test]
124 fn test_prefixed_u64_codec() {
125 let original = U64::new(69, 42u64);
126
127 let encoded = original.encode();
128 assert_eq!(encoded.len(), U64::SIZE);
129 assert_eq!(encoded, original.as_ref());
130
131 let decoded = U64::decode(encoded).unwrap();
132 assert_eq!(original, decoded);
133 }
134}