1#[cfg(test)]
2#[path = "../../tests/bytes/fixed.rs"]
3mod tests;
4
5use std::fmt::{Debug, Display, Formatter, Result as FmtResult};
8use std::hash::{Hash, Hasher};
9
10use crate::bytes::common::ByteBuffer;
11
12#[derive(Clone, Copy)]
16pub struct FixedByteBuffer<const N: usize> {
17 data: [u8; N],
18}
19
20impl<const N: usize> FixedByteBuffer<N> {
21 #[inline]
23 pub fn zeroed() -> Self {
24 Self {
25 data: [0u8; N],
26 }
27 }
28
29 #[inline]
31 pub fn from_array(arr: [u8; N]) -> Self {
32 Self {
33 data: arr,
34 }
35 }
36
37 #[inline]
39 pub fn as_array(&self) -> &[u8; N] {
40 &self.data
41 }
42}
43
44impl<const N: usize> ByteBuffer for FixedByteBuffer<N> {
45 #[inline]
46 fn len(&self) -> usize {
47 N
48 }
49
50 #[inline]
51 fn get(&self, at: usize) -> &u8 {
52 assert!(at < N, "index out of bounds: {at} >= {N}");
53 &self.data[at]
54 }
55
56 #[inline]
57 fn slice(&self) -> &[u8] {
58 &self.data
59 }
60
61 #[inline]
62 fn slice_start(&self, start: usize) -> &[u8] {
63 assert!(start <= N, "start out of bounds");
64 &self.data[start..]
65 }
66
67 #[inline]
68 fn slice_end(&self, end: usize) -> &[u8] {
69 assert!(end <= N, "end out of bounds");
70 &self.data[..end]
71 }
72
73 #[inline]
74 fn slice_both(&self, start: usize, end: usize) -> &[u8] {
75 assert!(start <= end && end <= N, "invalid slice bounds");
76 &self.data[start..end]
77 }
78
79 #[inline]
80 fn split(&self, divide: usize) -> (&[u8], &[u8]) {
81 assert!(divide <= N, "divide point out of bounds");
82 (&self.data[..divide], &self.data[divide..])
83 }
84}
85
86impl<const N: usize> AsRef<[u8]> for FixedByteBuffer<N> {
87 #[inline]
88 fn as_ref(&self) -> &[u8] {
89 &self.data
90 }
91}
92
93impl<const N: usize> From<[u8; N]> for FixedByteBuffer<N> {
94 #[inline]
95 fn from(arr: [u8; N]) -> Self {
96 Self {
97 data: arr,
98 }
99 }
100}
101
102impl<const N: usize> From<&[u8; N]> for FixedByteBuffer<N> {
103 #[inline]
104 fn from(arr: &[u8; N]) -> Self {
105 Self {
106 data: *arr,
107 }
108 }
109}
110
111impl<const N: usize> From<FixedByteBuffer<N>> for [u8; N] {
112 #[inline]
113 fn from(buf: FixedByteBuffer<N>) -> [u8; N] {
114 buf.data
115 }
116}
117
118impl<const N: usize> Default for FixedByteBuffer<N> {
119 #[inline]
120 fn default() -> Self {
121 Self::zeroed()
122 }
123}
124
125impl<const N: usize> PartialEq for FixedByteBuffer<N> {
126 #[inline]
127 fn eq(&self, other: &Self) -> bool {
128 self.data == other.data
129 }
130}
131
132impl<const N: usize> Eq for FixedByteBuffer<N> {}
133
134impl<const N: usize> Hash for FixedByteBuffer<N> {
135 #[inline]
136 fn hash<H: Hasher>(&self, state: &mut H) {
137 self.data.hash(state);
138 }
139}
140
141impl<const N: usize> Display for FixedByteBuffer<N> {
142 fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
143 for byte in &self.data {
144 write!(f, "{byte:02x}")?;
145 }
146 Ok(())
147 }
148}
149
150impl<const N: usize> Debug for FixedByteBuffer<N> {
151 fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
152 f.debug_struct("FixedByteBuffer").field("length", &N).field("data", &self.data).finish()
153 }
154}