1use std::{cmp, io, ops::Deref};
2
3macro_rules! impl_get_bytes {
4 ($buf:ident, $byte_ty:ty, $conversion:expr) => {{
5 const SIZE: usize = std::mem::size_of::<$byte_ty>();
6 let limit = $buf.buffer.len();
7 let pos = $buf.read_pos;
8 if pos + SIZE > limit {
9 return Err(io::ErrorKind::UnexpectedEof.into());
10 }
11
12 let slice = unsafe { *($buf.buffer[pos..pos + SIZE].as_ptr() as *const [_; SIZE]) };
13 $buf.advance_read_pos(SIZE);
14 Ok($conversion(slice))
15 }};
16}
17
18macro_rules! impl_put_bytes {
19 ($this:tt, $value:tt) => {{
20 let pos = $this.write_pos;
21 let slice_len = $value.len();
22 let buf_len = $this.buffer.len();
23 if pos + slice_len >= buf_len {
24 $this.buffer.resize(buf_len * 2, 0u8);
25 }
26
27 $this.buffer[pos..pos + slice_len].copy_from_slice($value);
28 $this.advance_write_pos(slice_len);
29 }};
30}
31
32pub struct Bytes {
33 buffer: Vec<u8>,
34 read_pos: usize,
35 write_pos: usize,
36}
37
38impl Bytes {
39
40 pub fn new(contents: Vec<u8>) -> Self {
42 Self {
43 buffer: contents,
44 read_pos: 0,
45 write_pos: 0,
46 }
47 }
48
49 pub fn with_capacity(capacity: usize) -> Self {
51 Self {
52 buffer: Vec::with_capacity(capacity),
53 read_pos: 0,
54 write_pos: 0,
55 }
56 }
57
58 pub fn sized<const SIZE: usize>() -> Self {
61 Self {
62 buffer: vec![0u8; SIZE],
63 read_pos: 0,
64 write_pos: 0,
65 }
66 }
67
68 pub fn get_u8(&mut self) -> io::Result<u8> {
71 impl_get_bytes!(self, u8, u8::from_be_bytes)
72 }
73
74 pub fn get_i8(&mut self) -> io::Result<i8> {
77 impl_get_bytes!(self, i8, i8::from_be_bytes)
78 }
79
80 pub fn get_i16(&mut self) -> io::Result<i16> {
83 impl_get_bytes!(self, i16, i16::from_be_bytes)
84 }
85
86 pub fn get_u16(&mut self) -> io::Result<u16> {
89 impl_get_bytes!(self, u16, u16::from_be_bytes)
90 }
91
92 pub fn get_i32(&mut self) -> io::Result<i32> {
95 impl_get_bytes!(self, i32, i32::from_be_bytes)
96 }
97
98 pub fn get_u32(&mut self) -> io::Result<u32> {
101 impl_get_bytes!(self, u32, u32::from_be_bytes)
102 }
103
104 pub fn get_i64(&mut self) -> io::Result<i64> {
107 impl_get_bytes!(self, i64, i64::from_be_bytes)
108 }
109
110 pub fn get_u64(&mut self) -> io::Result<u64> {
113 impl_get_bytes!(self, u64, u64::from_be_bytes)
114 }
115
116 pub fn put_u8(&mut self, value: u8) {
118 let slice = &u8::to_be_bytes(value);
119 impl_put_bytes!(self, slice);
120 }
121
122 pub fn put_i8(&mut self, value: i8) {
124 let slice = &i8::to_be_bytes(value);
125 impl_put_bytes!(self, slice);
126 }
127
128 pub fn put_i16(&mut self, value: i16) {
130 let slice = &i16::to_be_bytes(value);
131 impl_put_bytes!(self, slice);
132 }
133
134 pub fn put_u16(&mut self, value: u16) {
136 let slice: &[u8; 2] = &u16::to_be_bytes(value);
137 impl_put_bytes!(self, slice);
138 }
139
140 pub fn put_i32(&mut self, value: i32) {
142 let slice = &i32::to_be_bytes(value);
143 impl_put_bytes!(self, slice);
144 }
145
146 pub fn put_u32(&mut self, value: u32) {
148 let slice = &u32::to_be_bytes(value);
149 impl_put_bytes!(self, slice);
150 }
151
152 pub fn put_u64(&mut self, value: u64) {
154 let slice = &u64::to_be_bytes(value);
155 impl_put_bytes!(self, slice);
156 }
157
158 pub fn len(&self) -> usize {
159 self.buffer.len()
160 }
161
162 pub fn readable(&self) -> usize {
163 self.buffer.len() - self.read_pos
164 }
165
166 pub fn writable(&self) -> usize {
167 self.buffer.len() - self.write_pos
168 }
169
170 pub fn advance_read_pos(&mut self, amount: usize) {
171 self.read_pos += cmp::min(amount, self.readable());
172 }
173
174 pub fn advance_write_pos(&mut self, amount: usize) {
175 self.write_pos += cmp::min(amount, self.writable());
176 }
177}
178
179impl Deref for Bytes {
180 type Target = [u8];
181
182 fn deref(&self) -> &Self::Target {
183 self.buffer.deref()
184 }
185}