summaryrefslogtreecommitdiff
path: root/src/serialise/mod.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/serialise/mod.rs')
-rw-r--r--src/serialise/mod.rs121
1 files changed, 115 insertions, 6 deletions
diff --git a/src/serialise/mod.rs b/src/serialise/mod.rs
index 9fb56e3..1a63080 100644
--- a/src/serialise/mod.rs
+++ b/src/serialise/mod.rs
@@ -19,11 +19,120 @@
// er General Public License along with bzipper. If
// not, see <https://www.gnu.org/licenses/>.
-//! Serialisation utilities.
-
-use crate::use_mod;
-use_mod!(pub s_stream);
-use_mod!(pub serialise);
-
#[cfg(test)]
mod test;
+
+use crate::SStream;
+
+use std::convert::Infallible;
+use std::mem::size_of;
+use std::num::NonZero;
+
+/// Denotes a type capable of being serialised.
+pub trait Serialise: Sized {
+ /// Serialises `self` into a byte stream.
+ ///
+ /// One may assume that the resulting stream has at most the same ammount of bytes as before serialisation.
+ /// Therefore, not observing this rule is a logic error.
+ fn serialise(&self, stream: &mut SStream);
+}
+
+macro_rules! impl_float {
+ ($type:ty) => {
+ impl Serialise for $type {
+ fn serialise(&self, stream: &mut SStream) {
+ stream.append(&self.to_be_bytes())
+ }
+ }
+ };
+}
+
+macro_rules! impl_int {
+ ($type:ty) => {
+ impl Serialise for $type {
+ fn serialise(&self, stream: &mut SStream) {
+ stream.append(&self.to_be_bytes())
+ }
+ }
+
+ impl Serialise for NonZero<$type> {
+ fn serialise(&self, stream: &mut SStream) {
+ self.get().serialise(stream)
+ }
+ }
+ };
+}
+
+impl<T: Serialise, const N: usize> Serialise for [T; N] {
+ fn serialise(&self, stream: &mut SStream) {
+ u64::try_from(self.len()).unwrap().serialise(stream);
+
+ for v in self { v.serialise(stream) }
+ }
+}
+
+impl Serialise for () {
+ fn serialise(&self, _stream: &mut SStream) { }
+}
+
+impl Serialise for bool {
+ fn serialise(&self, stream: &mut SStream) {
+ u8::from(*self).serialise(stream)
+ }
+}
+
+impl Serialise for char {
+ fn serialise(&self, stream: &mut SStream) {
+ u32::from(*self).serialise(stream)
+ }
+}
+
+impl Serialise for Infallible {
+ fn serialise(&self, _stream: &mut SStream) { unreachable!() }
+}
+
+impl<T: Serialise> Serialise for Option<T> {
+ fn serialise(&self, stream: &mut SStream) {
+ match *self {
+ None => {
+ stream.append(&[0x00]);
+ stream.append(&vec![0x00; size_of::<T>()]);
+ },
+
+ Some(ref v) => {
+ stream.append(&[0x01]);
+ v.serialise(stream);
+ },
+ };
+ }
+}
+
+impl<T: Serialise, E: Serialise> Serialise for Result<T, E> {
+ fn serialise(&self, stream: &mut SStream) {
+ match *self {
+ Ok(ref v) => {
+ stream.append(&[0x00]);
+ v.serialise(stream);
+ },
+
+ Err(ref e) => {
+ stream.append(&[0x01]);
+ e.serialise(stream);
+ },
+ };
+ }
+}
+
+impl_float!(f32);
+impl_float!(f64);
+
+impl_int!(i128);
+impl_int!(i16);
+impl_int!(i32);
+impl_int!(i64);
+impl_int!(i8);
+impl_int!(u128);
+impl_int!(u16);
+impl_int!(u32);
+impl_int!(u64);
+impl_int!(u8);