lbytes/
lib.rs

1mod macros;
2
3use std::{
4	io::{Read, Seek, Write},
5	string::FromUtf8Error,
6};
7
8use thiserror::Error;
9
10#[derive(Debug, Error)]
11pub enum Error {
12	#[error("IO Error: {0}")]
13	IO(#[from] std::io::Error),
14	#[error("Utf8: {0}")]
15	FromUtf8(#[from] FromUtf8Error),
16}
17
18pub trait BytesReadExt: Read + Seek {
19	define_integral_r!(i8, 1);
20	define_integral_r!(u8, 1);
21
22	define_integral_r!(i16, 2);
23	define_integral_r!(u16, 2);
24
25	define_integral_r!(i32, 4);
26	define_integral_r!(u32, 4);
27
28	define_integral_r!(i64, 8);
29	define_integral_r!(u64, 8);
30
31	define_integral_r!(i128, 16);
32	define_integral_r!(u128, 16);
33
34	fn read_to_vec(&mut self) -> Result<Vec<u8>, Error> {
35		let mut buf = Vec::new();
36		self.read_to_end(&mut buf)?;
37		Ok(buf)
38	}
39
40	fn read_n_bytes<const N: usize>(&mut self) -> Result<[u8; N], Error> {
41		let mut bytes = [0u8; N];
42		self.read_exact(&mut bytes)?;
43		Ok(bytes)
44	}
45
46	fn read_n_bytes_vec(&mut self, amount: usize) -> Result<Vec<u8>, Error> {
47		let mut bytes = vec![0; amount];
48		self.read_exact(&mut bytes)?;
49		Ok(bytes)
50	}
51
52	fn read_f32(&mut self) -> Result<f32, Error> {
53		let v = self.read_u32()?;
54		Ok(f32::from_bits(v))
55	}
56
57	fn read_f64(&mut self) -> Result<f64, Error> {
58		let v = self.read_u64()?;
59		Ok(f64::from_bits(v))
60	}
61
62	fn read_string(&mut self) -> Result<String, Error> {
63		let len = self.read_u64()?;
64		Ok(String::from_utf8(self.read_n_bytes_vec(len as usize)?)?)
65	}
66}
67
68pub trait BytesWriteExt: Write {
69	define_write!(i8);
70	define_write!(u8);
71
72	define_write!(i16);
73	define_write!(u16);
74
75	define_write!(i32);
76	define_write!(u32);
77
78	define_write!(i64);
79	define_write!(u64);
80
81	define_write!(i128);
82	define_write!(u128);
83
84	define_write!(f32);
85	define_write!(f64);
86
87	fn write_string<S: AsRef<str>>(&mut self, value: S) -> Result<(), Error> {
88		let value = value.as_ref();
89		self.write_u64(value.len() as u64)?;
90		self.write_all(value.as_bytes())?;
91		Ok(())
92	}
93}
94
95impl<R: Read + Seek> BytesReadExt for R {}
96impl<R: Write> BytesWriteExt for R {}
97
98#[cfg(test)]
99mod tests {
100	use std::io::Cursor;
101
102	use super::*;
103
104	#[test]
105	fn string() {
106		const CONTENTS: &str = "Hello World. Trans Rights 🏳️‍⚧️ 🏳️‍⚧️ 🏳️‍⚧️ 🦀 🦀 🦀";
107		let mut buffer: Cursor<Vec<u8>> = Cursor::new(Vec::new());
108		buffer.write_string(CONTENTS.to_string()).expect("Error when writing");
109		buffer.set_position(0);
110		assert_eq!(CONTENTS, buffer.read_string().expect("Error when reading"));
111	}
112
113	macro_rules! define_test {
114		($ty:ty) => {
115			paste::item! {
116				#[test]
117				fn [<$ty>]() {
118					const VALUES: [$ty; 2] = [$ty::MAX, $ty::MIN];
119
120					for v in VALUES {
121						let mut buffer: Cursor<Vec<u8>> =
122							Cursor::new(Vec::new());
123						buffer.[<write_$ty>](v).expect("Error when writing");
124						buffer.set_position(0);
125						assert_eq!(
126							v,
127							buffer.[<read_$ty>]().expect("Error when reading")
128						);
129					}
130				}
131			}
132		};
133	}
134
135	define_test!(i8);
136	define_test!(u8);
137	define_test!(i16);
138	define_test!(u16);
139	define_test!(i32);
140	define_test!(u32);
141	define_test!(i64);
142	define_test!(u64);
143	define_test!(i128);
144	define_test!(u128);
145	define_test!(f32);
146	define_test!(f64);
147}