1#[cfg(test)]
24mod tests;
25
26use std::convert::TryInto;
27use std::{cmp, mem};
28use thiserror::Error;
29
30#[derive(Debug, Error)]
32pub enum BufferError {
33 #[error("unexpected eof")]
34 UnexpectedEof,
35
36 #[error("write zero")]
37 WriteZero,
38
39 #[error("vector too large")]
40 VecTooLarge,
41
42 #[error("no {0} at {1}")]
43 InvalidIndex(String, u32),
44}
45
46macro_rules! get_func {
47 ($name:ident, $ty:ty) => {
48 fn $name(&mut self) -> Result<$ty, BufferError> {
49 self.get_array().map(|bytes| <$ty>::from_be_bytes(bytes))
50 }
51 };
52}
53
54fn safe_shl(n: usize, nshift: u8) -> Option<usize> {
55 const NBITS: u8 = mem::size_of::<usize>() as u8 * 8;
56
57 if n >> (NBITS - nshift) == 0 {
58 Some(n << nshift)
59 } else {
60 None }
62}
63
64pub trait Buffer: Sized {
65 fn get_chunk(&mut self, len: usize) -> Result<&[u8], BufferError>;
66
67 fn get_array<const N: usize>(&mut self) -> Result<[u8; N], BufferError> {
68 let buf = self.get_chunk(N)?;
69
70 buf.try_into().map_err(|_| {
71 BufferError::UnexpectedEof
73 })
74 }
75
76 get_func!(get_u8, u8);
77 get_func!(get_u16, u16);
78 get_func!(get_u32, u32);
79 get_func!(get_u64, u64);
80
81 fn get_vec<const L: usize>(&mut self) -> Result<Vec<u8>, BufferError> {
82 let mut len = 0usize;
83
84 for n in self.get_array::<L>()? {
85 match safe_shl(len, 8) {
87 Some(result) => len = result | n as usize,
88 None => return Err(BufferError::VecTooLarge),
89 }
90 }
91
92 self.get_chunk(len).map(|buf| buf.to_vec())
93 }
94}
95
96pub trait BufferMut: Sized {
97 fn put_chunk(&mut self, buf: &[u8]) -> Result<(), BufferError>;
98
99 fn put_u8(&mut self, value: u8) -> Result<(), BufferError> {
100 self.put_chunk(&value.to_be_bytes())
101 }
102
103 fn put_u16(&mut self, value: u16) -> Result<(), BufferError> {
104 self.put_chunk(&value.to_be_bytes())
105 }
106
107 fn put_u32(&mut self, value: u32) -> Result<(), BufferError> {
108 self.put_chunk(&value.to_be_bytes())
109 }
110
111 fn put_u64(&mut self, value: u64) -> Result<(), BufferError> {
112 self.put_chunk(&value.to_be_bytes())
113 }
114
115 fn put_vec<const L: usize>(&mut self, buf: &[u8]) -> Result<(), BufferError> {
116 const U64_LEN: usize = mem::size_of::<u64>();
117
118 let mut len_bytes = [0; L];
119 let buf_len_bytes = (buf.len() as u64).to_be_bytes();
120
121 let n = cmp::min(L, U64_LEN);
122 let (unwritten, source) = buf_len_bytes.split_at(U64_LEN - n);
123 let target = &mut len_bytes[L - n..];
124
125 if unwritten.iter().any(|n| *n > 0) {
126 return Err(BufferError::VecTooLarge);
127 }
128
129 target.copy_from_slice(source);
130
131 self.put_chunk(&len_bytes)
132 .and_then(|()| self.put_chunk(buf))
133 }
134}
135
136impl Buffer for &[u8] {
137 fn get_chunk(&mut self, len: usize) -> Result<&[u8], BufferError> {
138 if self.len() >= len {
139 let buf = &self[..len];
140
141 *self = &self[len..];
142
143 Ok(buf)
144 } else {
145 Err(BufferError::UnexpectedEof)
146 }
147 }
148}
149
150impl BufferMut for Vec<u8> {
151 fn put_chunk(&mut self, buf: &[u8]) -> Result<(), BufferError> {
152 self.extend_from_slice(buf);
153 Ok(())
154 }
155}
156
157impl BufferMut for &mut [u8] {
158 fn put_chunk(&mut self, buf: &[u8]) -> Result<(), BufferError> {
159 if self.len() >= buf.len() {
160 let target = &mut self[..buf.len()];
161
162 target.copy_from_slice(buf);
163
164 let (_, b) = mem::take(self).split_at_mut(buf.len());
166
167 *self = b;
168
169 Ok(())
170 } else {
171 Err(BufferError::WriteZero)
172 }
173 }
174}
175
176pub trait FromBuffer: Sized {
177 type Error: From<BufferError>;
178
179 fn from_buffer<T: Buffer>(buf: &mut T) -> Result<Self, Self::Error>;
180}
181
182pub trait ToBuffer {
183 fn to_buffer<T: BufferMut>(&self, buf: &mut T) -> Result<(), BufferError>;
184}