xtea_cipher/
bytes.rs

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    /// Constructs a new byte buffer using the provided vector as the initial contents.
41    pub fn new(contents: Vec<u8>) -> Self {
42        Self {
43            buffer: contents,
44            read_pos: 0,
45            write_pos: 0,
46        }
47    }
48
49    /// Constructs a new byte buffer with the allocated capacity specified by the passed-in `capacity` value.
50    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    /// Constructs a new byte buffer with the allocated capacity specified by the `SIZE` type parameter. The contents of the buffer is filled with default
59    /// values.
60    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    /// Attempts to return an unsigned byte from the reader, incrementing the position by `1` if successful. Otherwise
69    /// an error is returned if not enough bytes remain.
70    pub fn get_u8(&mut self) -> io::Result<u8> {
71        impl_get_bytes!(self, u8, u8::from_be_bytes)
72    }
73
74    /// Attempts to return a signed byte from the reader, incrementing the position by `1` if successful. Otherwise
75    /// an error is returned if not enough bytes remain.
76    pub fn get_i8(&mut self) -> io::Result<i8> {
77        impl_get_bytes!(self, i8, i8::from_be_bytes)
78    }
79
80    /// Attempts to return a signed short from the reader, incrementing the position by `2` if successful. Otherwise
81    /// an error is returned if not enough bytes remain.
82    pub fn get_i16(&mut self) -> io::Result<i16> {
83        impl_get_bytes!(self, i16, i16::from_be_bytes)
84    }
85
86    /// Attempts to return an unsigned short from the reader, incrementing the position by `2` if successful. Otherwise
87    /// an error is returned if not enough bytes remain.
88    pub fn get_u16(&mut self) -> io::Result<u16> {
89        impl_get_bytes!(self, u16, u16::from_be_bytes)
90    }
91
92    /// Attempts to return a signed integer from the reader, incrementing the position by `4` if successful. Otherwise
93    /// an error is returned if not enough bytes remain.
94    pub fn get_i32(&mut self) -> io::Result<i32> {
95        impl_get_bytes!(self, i32, i32::from_be_bytes)
96    }
97
98    /// Attempts to return an unsigned integer from the reader, incrementing the position by `4` if successful. Otherwise
99    /// an error is returned if not enough bytes remain.
100    pub fn get_u32(&mut self) -> io::Result<u32> {
101        impl_get_bytes!(self, u32, u32::from_be_bytes)
102    }
103
104    /// Attempts to return a signed long from the reader, incrementing the position by `8` if successful. Otherwise
105    /// an error is returned if not enough bytes remain.
106    pub fn get_i64(&mut self) -> io::Result<i64> {
107        impl_get_bytes!(self, i64, i64::from_be_bytes)
108    }
109
110    /// Attempts to return an unsigned long from the reader, incrementing the position by `8` if successful. Otherwise
111    /// an error is returned if not enough bytes remain.
112    pub fn get_u64(&mut self) -> io::Result<u64> {
113        impl_get_bytes!(self, u64, u64::from_be_bytes)
114    }
115
116    /// Writes an unsigned byte value into the buffer, incrementing the position by `1`.
117    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    /// Writes a signed byte value into the buffer, incrementing the position by `1`.
123    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    /// Writes a signed short value into the buffer, incrementing the position by `2`.
129    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    /// Writes an unsigned short value into the buffer, incrementing the position by `2`.
135    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    /// Writes a signed int value into the buffer, incrementing the position by `4`.
141    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    /// Writes an unsigned int value into the buffer, incrementing the position by `4`.
147    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    /// Writes an unsigned int value into the buffer, incrementing the position by `8`.
153    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}