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