flood_rs/
lib.rs

1/*
2 * Copyright (c) Peter Bjorklund. All rights reserved. https://github.com/piot/flood-rs
3 * Licensed under the MIT License. See LICENSE in the project root for license information.
4 */
5use std::io::{self, Read, Result, Seek, SeekFrom, Write};
6
7pub mod in_borrowed;
8pub mod in_stream;
9pub mod out_borrowed;
10pub mod out_stream;
11pub mod prelude;
12
13pub trait WriteOctetStream {
14    fn write(&mut self, v: &[u8]) -> Result<()>;
15    fn write_u64(&mut self, v: u64) -> Result<()>;
16    fn write_i64(&mut self, v: i64) -> Result<()>;
17    fn write_u32(&mut self, v: u32) -> Result<()>;
18    fn write_i32(&mut self, v: i32) -> Result<()>;
19    fn write_u16(&mut self, v: u16) -> Result<()>;
20    fn write_i16(&mut self, v: i16) -> Result<()>;
21    fn write_u8(&mut self, v: u8) -> Result<()>;
22    fn write_i8(&mut self, v: i8) -> Result<()>;
23}
24
25impl<W: Write> WriteOctetStream for W {
26    /// Writes a octet slice to the stream.
27    fn write(&mut self, v: &[u8]) -> io::Result<()> {
28        self.write_all(v)
29    }
30
31    /// Writes a `u64` in big-endian octet order.
32    fn write_u64(&mut self, v: u64) -> io::Result<()> {
33        self.write_all(&v.to_be_bytes())
34    }
35
36    /// Writes an `i64` in big-endian octet order.
37    fn write_i64(&mut self, v: i64) -> io::Result<()> {
38        self.write_all(&v.to_be_bytes())
39    }
40
41    /// Writes a `u32` in big-endian octet order.
42    fn write_u32(&mut self, v: u32) -> io::Result<()> {
43        self.write_all(&v.to_be_bytes())
44    }
45
46    /// Writes an `i32` in big-endian octet order.
47    fn write_i32(&mut self, v: i32) -> io::Result<()> {
48        self.write_all(&v.to_be_bytes())
49    }
50
51    /// Writes a `u16` in big-endian octet order.
52    fn write_u16(&mut self, v: u16) -> io::Result<()> {
53        self.write_all(&v.to_be_bytes())
54    }
55
56    /// Writes an `i16` in big-endian octet order.
57    fn write_i16(&mut self, v: i16) -> io::Result<()> {
58        self.write_all(&v.to_be_bytes())
59    }
60
61    /// Writes a `u8` directly to the stream.
62    fn write_u8(&mut self, v: u8) -> io::Result<()> {
63        self.write_all(&[v])
64    }
65
66    /// Writes an `i8` directly to the stream.
67    fn write_i8(&mut self, v: i8) -> io::Result<()> {
68        self.write_all(&[v as u8])
69    }
70}
71
72pub trait ReadOctetStream {
73    fn read(&mut self, v: &mut [u8]) -> Result<()>;
74    fn read_u64(&mut self) -> Result<u64>;
75    fn read_i64(&mut self) -> Result<i64>;
76    fn read_u32(&mut self) -> Result<u32>;
77    fn read_i32(&mut self) -> Result<i32>;
78    fn read_u16(&mut self) -> Result<u16>;
79    fn read_i16(&mut self) -> Result<i16>;
80    fn read_u8(&mut self) -> Result<u8>;
81    fn read_i8(&mut self) -> Result<i8>;
82    #[must_use]
83    fn has_reached_end(&mut self) -> bool;
84}
85
86/// Blanket implementation of `ReadOctetStream` for all types that implement `Read` and `Seek`.
87impl<R: Read + Seek> ReadOctetStream for R {
88    /// Reads a octet slice from the stream.
89    fn read(&mut self, v: &mut [u8]) -> io::Result<()> {
90        self.read_exact(v)
91    }
92
93    /// Reads a `u64` in big-endian octet order.
94    fn read_u64(&mut self) -> io::Result<u64> {
95        let mut buf = [0u8; 8];
96        self.read_exact(&mut buf)?;
97        Ok(u64::from_be_bytes(buf))
98    }
99
100    /// Reads an `i64` in big-endian octet order.
101    fn read_i64(&mut self) -> io::Result<i64> {
102        let mut buf = [0u8; 8];
103        self.read_exact(&mut buf)?;
104        Ok(i64::from_be_bytes(buf))
105    }
106
107    /// Reads a `u32` in big-endian octet order.
108    fn read_u32(&mut self) -> io::Result<u32> {
109        let mut buf = [0u8; 4];
110        self.read_exact(&mut buf)?;
111        Ok(u32::from_be_bytes(buf))
112    }
113
114    /// Reads an `i32` in big-endian octet order.
115    fn read_i32(&mut self) -> io::Result<i32> {
116        let mut buf = [0u8; 4];
117        self.read_exact(&mut buf)?;
118        Ok(i32::from_be_bytes(buf))
119    }
120
121    /// Reads a `u16` in big-endian octet order.
122    fn read_u16(&mut self) -> io::Result<u16> {
123        let mut buf = [0u8; 2];
124        self.read_exact(&mut buf)?;
125        Ok(u16::from_be_bytes(buf))
126    }
127
128    /// Reads an `i16` in big-endian octet order.
129    fn read_i16(&mut self) -> io::Result<i16> {
130        let mut buf = [0u8; 2];
131        self.read_exact(&mut buf)?;
132        Ok(i16::from_be_bytes(buf))
133    }
134
135    /// Reads a `u8` directly from the stream.
136    fn read_u8(&mut self) -> io::Result<u8> {
137        let mut buf = [0u8; 1];
138        self.read_exact(&mut buf)?;
139        Ok(buf[0])
140    }
141
142    /// Reads an `i8` directly from the stream.
143    fn read_i8(&mut self) -> io::Result<i8> {
144        let octet = self.read_u8()?;
145        Ok(octet as i8)
146    }
147
148    /// Checks if the stream has reached the end.
149    ///
150    /// This method attempts to peek one octet without consuming it. If no octet is available,
151    /// it indicates that the end of the stream has been reached.
152    /// It is a really hacky way to do it, wished there was another way.
153    fn has_reached_end(&mut self) -> bool {
154        let current_pos = match self.stream_position() {
155            Ok(pos) => pos,
156            Err(_) => return false, // Unable to seek, assume not at end
157        };
158
159        let mut buffer = [0u8; 1];
160        let result = self.read_exact(&mut buffer);
161
162        match result {
163            Ok(_) => {
164                let _ = self.seek(SeekFrom::Start(current_pos));
165                false
166            }
167            Err(ref e) if e.kind() == io::ErrorKind::UnexpectedEof => true,
168            Err(_) => false,
169        }
170    }
171}
172
173/// Custom trait for seeking within an octet stream.
174pub trait SeekOctetStream {
175    /// Moves the cursor to the specified octet position from the start of the stream.
176    ///
177    /// # Arguments
178    ///
179    /// * `pos` - The octet position to seek to.
180    ///
181    /// # Returns
182    ///
183    /// * `Ok(())` if the operation is successful.
184    /// * `Err(io::Error)` if an I/O error occurs.
185    fn seek(&mut self, pos: u64) -> io::Result<()>;
186
187    /// Retrieves the current octet position of the cursor in the stream.
188    ///
189    /// # Returns
190    ///
191    /// * `Ok(u64)` representing the current octet position.
192    /// * `Err(io::Error)` if an I/O error occurs.
193    fn stream_position(&mut self) -> io::Result<u64>;
194}
195
196/// Blanket implementation of `SeekOctetStream` for all types that implement `Seek`.
197impl<S: Seek> SeekOctetStream for S {
198    /// Moves the cursor to the specified octet position from the start.
199    fn seek(&mut self, pos: u64) -> io::Result<()> {
200        self.seek(SeekFrom::Start(pos)).map(|_| ())
201    }
202
203    /// Retrieves the current cursor position.
204    fn stream_position(&mut self) -> io::Result<u64> {
205        self.stream_position()
206    }
207}
208
209pub trait Deserialize: Sized {
210    fn deserialize(stream: &mut impl ReadOctetStream) -> Result<Self>;
211}
212
213pub trait Serialize: Sized {
214    fn serialize(&self, stream: &mut impl WriteOctetStream) -> Result<()>;
215}
216
217/// A trait for deserializing objects from a octet buffer.
218pub trait BufferDeserializer: Sized {
219    /// Deserializes an instance of `Self` from the given octet buffer.
220    ///
221    /// # Parameters
222    ///
223    /// * `buf`: A octet slice that contains the serialized data.
224    ///
225    /// # Returns
226    ///
227    /// This method returns a `Result<Self>`, which is:
228    /// - `Ok((Self, usize))` on successful deserialization, where the `usize` indicates the number of octets consumed.
229    /// - `Err(io::Error)` if deserialization fails, which could be due to invalid data or unexpected format.
230    fn deserialize(buf: &[u8]) -> Result<(Self, usize)>;
231}
232
233/// A trait for serializing objects to an octet buffer.
234pub trait BufferSerializer: Sized {
235    /// Serializes `self` into the given mutable octet buffer.
236    ///
237    /// # Parameters
238    ///
239    /// * `buf`: A mutable reference to a octet slice that will be populated with serialized data.
240    ///
241    /// # Returns
242    ///
243    /// This method returns a `Result<usize>`, which is:
244    /// - `Ok(usize)` representing the number of octets written to the buffer on success.
245    /// - `Err(io::Error)` if serialization fails, which could occur due to issues with writing to the buffer.
246    fn serialize(&self, buf: &mut &[u8]) -> Result<usize>;
247}