koibumi_core/
io.rs

1//! Traits which provides the serializations
2//! into the byte sequences used by the Bitmessage network,
3//! and traits which provides the deserializations
4//! into the data types used by the Bitmessage protocol.
5
6use std::{
7    fmt,
8    io::{self, Cursor, Read, Write},
9    mem::size_of,
10};
11
12use koibumi_net::Port;
13
14pub use crate::error::TooLongError;
15
16/// Provides a method that writes this object as a Bitmessage entity to a writer.
17pub trait WriteTo {
18    /// Writes this object as a Bitmessage entity to a writer.
19    fn write_to(&self, w: &mut dyn Write) -> io::Result<()>;
20}
21
22/// Provides a method that reads this object as a Bitmessage entity from a reader.
23pub trait ReadFrom {
24    /// Reads this object as a Bitmessage entity from a reader.
25    fn read_from(r: &mut dyn Read) -> io::Result<Self>
26    where
27        Self: Sized;
28}
29
30impl WriteTo for u8 {
31    fn write_to(&self, w: &mut dyn Write) -> io::Result<()> {
32        let bytes = [*self];
33        w.write_all(&bytes)
34    }
35}
36
37impl ReadFrom for u8 {
38    fn read_from(r: &mut dyn Read) -> io::Result<Self>
39    where
40        Self: Sized,
41    {
42        let mut buf = [0; 1];
43        r.read_exact(&mut buf)?;
44        Ok(buf[0])
45    }
46}
47
48impl WriteTo for u16 {
49    fn write_to(&self, w: &mut dyn Write) -> io::Result<()> {
50        w.write_all(&self.to_be_bytes())
51    }
52}
53
54impl ReadFrom for u16 {
55    fn read_from(r: &mut dyn Read) -> io::Result<Self>
56    where
57        Self: Sized,
58    {
59        let mut buf = [0; 2];
60        r.read_exact(&mut buf)?;
61        Ok(Self::from_be_bytes(buf))
62    }
63}
64
65impl WriteTo for u32 {
66    fn write_to(&self, w: &mut dyn Write) -> io::Result<()> {
67        w.write_all(&self.to_be_bytes())
68    }
69}
70
71impl ReadFrom for u32 {
72    fn read_from(r: &mut dyn Read) -> io::Result<Self>
73    where
74        Self: Sized,
75    {
76        let mut buf = [0; 4];
77        r.read_exact(&mut buf)?;
78        Ok(Self::from_be_bytes(buf))
79    }
80}
81
82impl WriteTo for u64 {
83    fn write_to(&self, w: &mut dyn Write) -> io::Result<()> {
84        w.write_all(&self.to_be_bytes())
85    }
86}
87
88impl ReadFrom for u64 {
89    fn read_from(r: &mut dyn Read) -> io::Result<Self>
90    where
91        Self: Sized,
92    {
93        let mut buf = [0; 8];
94        r.read_exact(&mut buf)?;
95        Ok(Self::from_be_bytes(buf))
96    }
97}
98
99impl WriteTo for [u8] {
100    fn write_to(&self, w: &mut dyn Write) -> io::Result<()> {
101        w.write_all(self)
102    }
103}
104
105macro_rules! io_array {
106    ($len:expr) => {
107        impl ReadFrom for [u8; $len] {
108            fn read_from(r: &mut dyn Read) -> io::Result<Self>
109            where
110                Self: Sized,
111            {
112                let mut buf = [0; $len];
113                r.read_exact(&mut buf)?;
114                Ok(buf)
115            }
116        }
117    };
118}
119
120io_array!(4);
121io_array!(6);
122io_array!(10);
123io_array!(12);
124io_array!(16);
125io_array!(18);
126io_array!(20);
127io_array!(32);
128
129impl WriteTo for Vec<u8> {
130    fn write_to(&self, w: &mut dyn Write) -> io::Result<()> {
131        w.write_all(self)
132    }
133}
134
135impl WriteTo for Port {
136    fn write_to(&self, w: &mut dyn Write) -> io::Result<()> {
137        self.as_u16().write_to(w)
138    }
139}
140
141impl ReadFrom for Port {
142    fn read_from(r: &mut dyn Read) -> io::Result<Self>
143    where
144        Self: Sized,
145    {
146        Ok(Self::new(u16::read_from(r)?))
147    }
148}
149
150/// This error indicates
151/// that some trailing bytes remained after reading had finished.
152///
153/// The length of the trailing bytes is retrievable
154/// from the error object.
155#[derive(Clone, PartialEq, Eq, Debug)]
156pub struct TrailingBytesError(usize);
157
158impl fmt::Display for TrailingBytesError {
159    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
160        write!(f, "found trailing {} bytes", self.0)
161    }
162}
163
164impl std::error::Error for TrailingBytesError {}
165
166impl TrailingBytesError {
167    /// Constructs an error object from a length value.
168    pub fn new(trailing_len: usize) -> Self {
169        Self(trailing_len)
170    }
171
172    /// Returns the length of the trailing bytes.
173    pub fn trailing_len(&self) -> usize {
174        self.0
175    }
176}
177
178/// Provides a method that reads this object as a Bitmessage entity from a reader
179/// with a specified byte length.
180pub trait SizedReadFrom {
181    /// Reads this object as a Bitmessage entity from a reader
182    /// with a specified byte length.
183    fn sized_read_from(r: &mut dyn Read, len: usize) -> io::Result<Self>
184    where
185        Self: Sized;
186}
187
188impl SizedReadFrom for Vec<u8> {
189    fn sized_read_from(r: &mut dyn Read, len: usize) -> io::Result<Self>
190    where
191        Self: Sized,
192    {
193        let mut r = r.take(len as u64);
194        let mut bytes = Vec::with_capacity(len);
195        r.read_to_end(&mut bytes)?;
196        Ok(bytes)
197    }
198}
199
200/// Provides a method that reads this object as a Bitmessage entity from a reader
201/// with a limited item count.
202pub trait LimitedReadFrom {
203    /// Reads this object as a Bitmessage entity from a reader
204    /// with a limited item count.
205    fn limited_read_from(r: &mut dyn Read, max_len: usize) -> io::Result<Self>
206    where
207        Self: Sized;
208}
209
210/// Provides a method that reads this object as a Bitmessage entity
211/// from a byte array with an exact length.
212pub trait ReadFromExact {
213    /// Reads this object as a Bitmessage entity
214    /// from a byte array with an exact length.
215    fn read_from_exact(bytes: impl AsRef<[u8]>) -> io::Result<Self>
216    where
217        Self: Sized;
218}
219
220impl<T> ReadFromExact for T
221where
222    T: ReadFrom,
223{
224    fn read_from_exact(bytes: impl AsRef<[u8]>) -> io::Result<Self>
225    where
226        Self: Sized,
227    {
228        let bytes = bytes.as_ref();
229        let mut cur = Cursor::new(bytes);
230        let v = Self::read_from(&mut cur)?;
231        if cur.position() != bytes.len() as u64 {
232            return Err(io::Error::new(
233                io::ErrorKind::Other,
234                TrailingBytesError(bytes.len() - cur.position() as usize),
235            ));
236        }
237        Ok(v)
238    }
239}
240
241/// Provides a method that reads this object as a Bitmessage entity
242/// from a byte array with an exact length.
243pub trait SizedReadFromExact {
244    /// Reads this object as a Bitmessage entity
245    /// from a byte array with an exact length.
246    fn sized_read_from_exact(bytes: impl AsRef<[u8]>) -> io::Result<Self>
247    where
248        Self: Sized;
249}
250
251impl<T> SizedReadFromExact for T
252where
253    T: SizedReadFrom,
254{
255    fn sized_read_from_exact(bytes: impl AsRef<[u8]>) -> io::Result<Self>
256    where
257        Self: Sized,
258    {
259        let bytes = bytes.as_ref();
260        let mut cur = Cursor::new(bytes);
261        Self::sized_read_from(&mut cur, bytes.len())
262    }
263}
264
265/// Provides a method that returns the object's byte length
266/// when serialized as a Bitmessage entity.
267pub trait LenBm {
268    /// Returns the object's byte length
269    /// when serialized as a Bitmessage entity.
270    fn len_bm(&self) -> usize;
271}
272
273impl LenBm for u32 {
274    fn len_bm(&self) -> usize {
275        size_of::<u32>()
276    }
277}
278
279impl LenBm for u64 {
280    fn len_bm(&self) -> usize {
281        size_of::<u64>()
282    }
283}