rustmeter_beacon_core/
buffer.rs1use core::mem::MaybeUninit;
2
3use crate::{tracing::ReadTracingError, varint::VarIntWritable};
4
5pub struct BufferWriter {
7 buffer: [MaybeUninit<u8>; 32],
8 position: usize,
9}
10
11impl BufferWriter {
12 pub fn new() -> Self {
13 BufferWriter {
14 buffer: [MaybeUninit::uninit(); 32],
15 position: 0,
16 }
17 }
18
19 pub fn write_byte(&mut self, byte: u8) {
20 self.buffer[self.position] = MaybeUninit::new(byte);
21 self.position += 1;
22 }
23
24 pub fn write_bytes(&mut self, data: &[u8]) {
26 let len = data.len();
27 self.buffer[self.position..self.position + len]
28 .copy_from_slice(unsafe { core::mem::transmute::<&[u8], &[MaybeUninit<u8>]>(data) });
29 self.position += len;
30 }
31
32 #[inline]
34 pub fn write_varint<T: VarIntWritable>(&mut self, mut value: T) {
35 loop {
36 let mut byte = value.low_7_bits();
37
38 value.shr_7();
39 if !value.is_zero() {
40 byte |= 0x80;
42 self.write_byte(byte);
43 } else {
44 self.write_byte(byte);
46 break;
47 }
48 }
49 }
50
51 pub fn as_slice(&self) -> &[u8] {
53 &unsafe { core::mem::transmute::<&[MaybeUninit<u8>], &[u8]>(&self.buffer[..self.position]) }
54 }
55
56 pub fn len(&self) -> usize {
57 self.position
58 }
59}
60
61pub struct BufferReader<'a> {
63 buffer: &'a [u8],
64 position: usize,
65}
66
67impl<'a> BufferReader<'a> {
68 pub fn new(buffer: &'a [u8]) -> Self {
69 BufferReader {
70 buffer,
71 position: 0,
72 }
73 }
74
75 pub fn len(&self) -> usize {
76 self.buffer.len()
77 }
78
79 pub fn read_byte(&mut self) -> Result<u8, ReadTracingError> {
81 if self.position >= self.buffer.len() {
82 return Err(ReadTracingError::InsufficientData);
83 }
84
85 let byte = self.buffer[self.position];
86 self.position += 1;
87 Ok(byte)
88 }
89
90 pub fn read_bytes(&mut self, length: usize) -> Result<&[u8], ReadTracingError> {
92 if self.position + length > self.buffer.len() {
93 return Err(ReadTracingError::InsufficientData);
94 }
95
96 let bytes = &self.buffer[self.position..self.position + length];
97 self.position += length;
98 Ok(bytes)
99 }
100
101 pub fn read_varint(&mut self) -> Result<u64, ReadTracingError> {
103 let mut result = 0u64;
104 let mut shift = 0;
105
106 loop {
107 let byte = self.read_byte()?;
108
109 result |= ((byte & 0x7F) as u64) << shift;
111
112 if (byte & 0x80) == 0 {
114 return Ok(result);
115 }
116
117 shift += 7;
118
119 if shift >= 70 {
121 return Err(ReadTracingError::VarIntOverflow);
122 }
123 }
124 }
125
126 pub fn read_u16(&mut self) -> Result<u16, ReadTracingError> {
128 let bytes = self.read_bytes(2)?;
129 Ok(u16::from_le_bytes(bytes.try_into().unwrap()))
130 }
131
132 pub fn read_u32(&mut self) -> Result<u32, ReadTracingError> {
134 let bytes = self.read_bytes(4)?;
135 Ok(u32::from_le_bytes(bytes.try_into().unwrap()))
136 }
137
138 pub fn read_u64(&mut self) -> Result<u64, ReadTracingError> {
140 let bytes = self.read_bytes(8)?;
141 Ok(u64::from_le_bytes(bytes.try_into().unwrap()))
142 }
143
144 pub fn get_position(&self) -> usize {
145 self.position
146 }
147}
148
149#[cfg(test)]
150mod tests {
151 use super::*;
152
153 #[test]
154 fn test_buffer_writer() {
155 let mut writer = BufferWriter::new();
156 writer.write_byte(0x12);
157 writer.write_bytes(&[0x34, 0x56, 0x78]);
158
159 let written = writer.as_slice();
160 assert_eq!(written, &[0x12, 0x34, 0x56, 0x78]);
161 }
162
163 #[test]
164 fn test_buffer_reader() {
165 let data = [0x9A, 0xBC, 0xDE, 0xF0];
166 let mut reader = BufferReader::new(&data);
167
168 assert_eq!(reader.read_byte(), Ok(0x9A));
169 assert_eq!(reader.read_bytes(2), Ok(&[0xBC, 0xDE][..]));
170 assert_eq!(reader.read_byte(), Ok(0xF0));
171 assert_eq!(reader.read_byte(), Err(ReadTracingError::InsufficientData));
172 }
173
174 #[test]
175 fn test_buffer_write_and_read() {
176 let mut writer = BufferWriter::new();
178 writer.write_bytes(&[0x01, 0x02, 0x03, 0x04, 0x05]);
179 writer.write_varint(1u8);
180 writer.write_varint(300u16);
181 writer.write_varint(70000u32);
182 writer.write_varint(123456789u64);
183 writer.write_bytes(&[0x01, 0x02, 0x03, 0x04, 0x05]);
184
185 let data = writer.as_slice();
187 let mut reader = BufferReader::new(data);
188 assert_eq!(
189 reader.read_bytes(5),
190 Ok(&[0x01, 0x02, 0x03, 0x04, 0x05][..])
191 );
192 assert_eq!(reader.read_varint(), Ok(1u64));
193 assert_eq!(reader.read_varint(), Ok(300u64));
194 assert_eq!(reader.read_varint(), Ok(70000u64));
195 assert_eq!(reader.read_varint(), Ok(123456789u64));
196 assert_eq!(
197 reader.read_bytes(5),
198 Ok(&[0x01, 0x02, 0x03, 0x04, 0x05][..])
199 );
200 }
201}