1use core::ops::Index;
2
3pub const MAX_SUITES_LEN: usize = 9;
6
7#[derive(PartialEq, Debug)]
8#[repr(C)]
9pub enum EdhocBufferError {
10 BufferAlreadyFull,
11 SliceTooLong,
12}
13
14#[derive(PartialEq, Debug, Copy, Clone)]
21#[repr(C)]
22pub struct EdhocBuffer<const N: usize> {
23 pub content: [u8; N],
24 pub len: usize,
25}
26
27impl<const N: usize> Default for EdhocBuffer<N> {
28 fn default() -> Self {
29 EdhocBuffer {
30 content: [0; N],
31 len: 0,
32 }
33 }
34}
35
36impl<const N: usize> EdhocBuffer<N> {
37 pub const fn new() -> Self {
38 EdhocBuffer {
39 content: [0u8; N],
40 len: 0,
41 }
42 }
43
44 pub fn len(&self) -> usize {
45 self.len
46 }
47
48 pub fn capacity(&self) -> usize {
49 N
50 }
51
52 pub fn new_from_slice(slice: &[u8]) -> Result<Self, EdhocBufferError> {
53 let mut buffer = Self::new();
54 if buffer.fill_with_slice(slice).is_ok() {
55 Ok(buffer)
56 } else {
57 Err(EdhocBufferError::SliceTooLong)
58 }
59 }
60
61 pub fn get(self, index: usize) -> Option<u8> {
62 self.content.get(index).copied()
63 }
64
65 pub fn contains(&self, item: &u8) -> bool {
66 self.content.contains(item)
67 }
68
69 pub fn push(&mut self, item: u8) -> Result<(), EdhocBufferError> {
70 if self.len < self.content.len() {
71 self.content[self.len] = item;
72 self.len += 1;
73 Ok(())
74 } else {
75 Err(EdhocBufferError::BufferAlreadyFull)
76 }
77 }
78
79 pub fn get_slice(&self, start: usize, len: usize) -> Option<&[u8]> {
80 self.content.get(start..start + len)
81 }
82
83 pub fn as_slice(&self) -> &[u8] {
84 &self.content[0..self.len]
85 }
86
87 pub fn fill_with_slice(&mut self, slice: &[u8]) -> Result<(), EdhocBufferError> {
88 if slice.len() <= self.content.len() {
89 self.len = slice.len();
90 self.content[..self.len].copy_from_slice(slice);
91 Ok(())
92 } else {
93 Err(EdhocBufferError::SliceTooLong)
94 }
95 }
96
97 pub fn extend_from_slice(&mut self, slice: &[u8]) -> Result<(), EdhocBufferError> {
98 if self.len + slice.len() <= self.content.len() {
99 self.content[self.len..self.len + slice.len()].copy_from_slice(slice);
100 self.len += slice.len();
101 Ok(())
102 } else {
103 Err(EdhocBufferError::SliceTooLong)
104 }
105 }
106
107 pub fn from_hex(hex: &str) -> Self {
109 let mut buffer = EdhocBuffer::new();
110 buffer.len = hex.len() / 2;
111 for (i, chunk) in hex.as_bytes().chunks(2).enumerate() {
112 let chunk_str = core::str::from_utf8(chunk).unwrap();
113 buffer.content[i] = u8::from_str_radix(chunk_str, 16).unwrap();
114 }
115 buffer
116 }
117}
118
119impl<const N: usize> Index<usize> for EdhocBuffer<N> {
120 type Output = u8;
121 fn index(&self, item: usize) -> &Self::Output {
122 &self.content[item]
123 }
124}
125
126impl<const N: usize> TryInto<EdhocBuffer<N>> for &[u8] {
127 type Error = ();
128
129 fn try_into(self) -> Result<EdhocBuffer<N>, Self::Error> {
130 let mut buffer = [0u8; N];
131 if self.len() <= buffer.len() {
132 buffer[..self.len()].copy_from_slice(self);
133
134 Ok(EdhocBuffer {
135 content: buffer,
136 len: self.len(),
137 })
138 } else {
139 Err(())
140 }
141 }
142}
143
144mod test {
145
146 #[test]
147 fn test_edhoc_buffer() {
148 let mut buffer = crate::EdhocBuffer::<5>::new();
149 assert_eq!(buffer.len, 0);
150 assert_eq!(buffer.content, [0; 5]);
151
152 buffer.push(1).unwrap();
153 assert_eq!(buffer.len, 1);
154 assert_eq!(buffer.content, [1, 0, 0, 0, 0]);
155 }
156
157 #[test]
158 fn test_new_from_slice() {
159 let buffer = crate::EdhocBuffer::<5>::new_from_slice(&[1, 2, 3]).unwrap();
160 assert_eq!(buffer.len, 3);
161 assert_eq!(buffer.content, [1, 2, 3, 0, 0]);
162 }
163}