diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/deserialise/mod.rs | 264 | ||||
-rw-r--r-- | src/fixed_string/mod.rs | 99 | ||||
-rw-r--r-- | src/fixed_string/test.rs | 43 | ||||
-rw-r--r-- | src/serialise/mod.rs | 220 |
4 files changed, 610 insertions, 16 deletions
diff --git a/src/deserialise/mod.rs b/src/deserialise/mod.rs index 2678670..fff89e2 100644 --- a/src/deserialise/mod.rs +++ b/src/deserialise/mod.rs @@ -86,6 +86,270 @@ macro_rules! impl_int { }; } +impl<T0, T1> Deserialise for (T0, T1) +where + T0: Deserialise<Error: StdError + 'static>, + T1: Deserialise<Error: StdError + 'static>, { + type Error = Box<dyn StdError>; + + fn deserialise(stream: &mut DStream) -> Result<Self, Self::Error> { + Ok(( + Deserialise::deserialise(stream)?, + Deserialise::deserialise(stream)?, + )) + } +} + +impl<T0, T1, T2> Deserialise for (T0, T1, T2) +where + T0: Deserialise<Error: StdError + 'static>, + T1: Deserialise<Error: StdError + 'static>, + T2: Deserialise<Error: StdError + 'static>, { + type Error = Box<dyn StdError>; + + fn deserialise(stream: &mut DStream) -> Result<Self, Self::Error> { + Ok(( + Deserialise::deserialise(stream)?, + Deserialise::deserialise(stream)?, + Deserialise::deserialise(stream)?, + )) + } +} + +impl<T0, T1, T2, T3> Deserialise for (T0, T1, T2, T3) +where + T0: Deserialise<Error: StdError + 'static>, + T1: Deserialise<Error: StdError + 'static>, + T2: Deserialise<Error: StdError + 'static>, + T3: Deserialise<Error: StdError + 'static>, { + type Error = Box<dyn StdError>; + + fn deserialise(stream: &mut DStream) -> Result<Self, Self::Error> { + Ok(( + Deserialise::deserialise(stream)?, + Deserialise::deserialise(stream)?, + Deserialise::deserialise(stream)?, + Deserialise::deserialise(stream)?, + )) + } +} + +impl<T0, T1, T2, T3, T4> Deserialise for (T0, T1, T2, T3, T4) +where + T0: Deserialise<Error: StdError + 'static>, + T1: Deserialise<Error: StdError + 'static>, + T2: Deserialise<Error: StdError + 'static>, + T3: Deserialise<Error: StdError + 'static>, + T4: Deserialise<Error: StdError + 'static>, { + type Error = Box<dyn StdError>; + + fn deserialise(stream: &mut DStream) -> Result<Self, Self::Error> { + Ok(( + Deserialise::deserialise(stream)?, + Deserialise::deserialise(stream)?, + Deserialise::deserialise(stream)?, + Deserialise::deserialise(stream)?, + Deserialise::deserialise(stream)?, + )) + } +} + +impl<T0, T1, T2, T3, T4, T5> Deserialise for (T0, T1, T2, T3, T4, T5) +where + T0: Deserialise<Error: StdError + 'static>, + T1: Deserialise<Error: StdError + 'static>, + T2: Deserialise<Error: StdError + 'static>, + T3: Deserialise<Error: StdError + 'static>, + T4: Deserialise<Error: StdError + 'static>, + T5: Deserialise<Error: StdError + 'static>, { + type Error = Box<dyn StdError>; + + fn deserialise(stream: &mut DStream) -> Result<Self, Self::Error> { + Ok(( + Deserialise::deserialise(stream)?, + Deserialise::deserialise(stream)?, + Deserialise::deserialise(stream)?, + Deserialise::deserialise(stream)?, + Deserialise::deserialise(stream)?, + Deserialise::deserialise(stream)?, + )) + } +} + +impl<T0, T1, T2, T3, T4, T5, T6> Deserialise for (T0, T1, T2, T3, T4, T5, T6) +where + T0: Deserialise<Error: StdError + 'static>, + T1: Deserialise<Error: StdError + 'static>, + T2: Deserialise<Error: StdError + 'static>, + T3: Deserialise<Error: StdError + 'static>, + T4: Deserialise<Error: StdError + 'static>, + T5: Deserialise<Error: StdError + 'static>, + T6: Deserialise<Error: StdError + 'static>, { + type Error = Box<dyn StdError>; + + fn deserialise(stream: &mut DStream) -> Result<Self, Self::Error> { + Ok(( + Deserialise::deserialise(stream)?, + Deserialise::deserialise(stream)?, + Deserialise::deserialise(stream)?, + Deserialise::deserialise(stream)?, + Deserialise::deserialise(stream)?, + Deserialise::deserialise(stream)?, + Deserialise::deserialise(stream)?, + )) + } +} + +impl<T0, T1, T2, T3, T4, T5, T6, T7> Deserialise for (T0, T1, T2, T3, T4, T5, T6, T7) +where + T0: Deserialise<Error: StdError + 'static>, + T1: Deserialise<Error: StdError + 'static>, + T2: Deserialise<Error: StdError + 'static>, + T3: Deserialise<Error: StdError + 'static>, + T4: Deserialise<Error: StdError + 'static>, + T5: Deserialise<Error: StdError + 'static>, + T6: Deserialise<Error: StdError + 'static>, + T7: Deserialise<Error: StdError + 'static>, { + type Error = Box<dyn StdError>; + + fn deserialise(stream: &mut DStream) -> Result<Self, Self::Error> { + Ok(( + Deserialise::deserialise(stream)?, + Deserialise::deserialise(stream)?, + Deserialise::deserialise(stream)?, + Deserialise::deserialise(stream)?, + Deserialise::deserialise(stream)?, + Deserialise::deserialise(stream)?, + Deserialise::deserialise(stream)?, + Deserialise::deserialise(stream)?, + )) + } +} + +impl<T0, T1, T2, T3, T4, T5, T6, T7, T8> Deserialise for (T0, T1, T2, T3, T4, T5, T6, T7, T8) +where + T0: Deserialise<Error: StdError + 'static>, + T1: Deserialise<Error: StdError + 'static>, + T2: Deserialise<Error: StdError + 'static>, + T3: Deserialise<Error: StdError + 'static>, + T4: Deserialise<Error: StdError + 'static>, + T5: Deserialise<Error: StdError + 'static>, + T6: Deserialise<Error: StdError + 'static>, + T7: Deserialise<Error: StdError + 'static>, + T8: Deserialise<Error: StdError + 'static>, { + type Error = Box<dyn StdError>; + + fn deserialise(stream: &mut DStream) -> Result<Self, Self::Error> { + Ok(( + Deserialise::deserialise(stream)?, + Deserialise::deserialise(stream)?, + Deserialise::deserialise(stream)?, + Deserialise::deserialise(stream)?, + Deserialise::deserialise(stream)?, + Deserialise::deserialise(stream)?, + Deserialise::deserialise(stream)?, + Deserialise::deserialise(stream)?, + Deserialise::deserialise(stream)?, + )) + } +} + +impl<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9> Deserialise for (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9) +where + T0: Deserialise<Error: StdError + 'static>, + T1: Deserialise<Error: StdError + 'static>, + T2: Deserialise<Error: StdError + 'static>, + T3: Deserialise<Error: StdError + 'static>, + T4: Deserialise<Error: StdError + 'static>, + T5: Deserialise<Error: StdError + 'static>, + T6: Deserialise<Error: StdError + 'static>, + T7: Deserialise<Error: StdError + 'static>, + T8: Deserialise<Error: StdError + 'static>, + T9: Deserialise<Error: StdError + 'static>, { + type Error = Box<dyn StdError>; + + fn deserialise(stream: &mut DStream) -> Result<Self, Self::Error> { + Ok(( + Deserialise::deserialise(stream)?, + Deserialise::deserialise(stream)?, + Deserialise::deserialise(stream)?, + Deserialise::deserialise(stream)?, + Deserialise::deserialise(stream)?, + Deserialise::deserialise(stream)?, + Deserialise::deserialise(stream)?, + Deserialise::deserialise(stream)?, + Deserialise::deserialise(stream)?, + Deserialise::deserialise(stream)?, + )) + } +} + +impl<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> Deserialise for (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10) +where + T0: Deserialise<Error: StdError + 'static>, + T1: Deserialise<Error: StdError + 'static>, + T2: Deserialise<Error: StdError + 'static>, + T3: Deserialise<Error: StdError + 'static>, + T4: Deserialise<Error: StdError + 'static>, + T5: Deserialise<Error: StdError + 'static>, + T6: Deserialise<Error: StdError + 'static>, + T7: Deserialise<Error: StdError + 'static>, + T8: Deserialise<Error: StdError + 'static>, + T9: Deserialise<Error: StdError + 'static>, + T10: Deserialise<Error: StdError + 'static>, { + type Error = Box<dyn StdError>; + + fn deserialise(stream: &mut DStream) -> Result<Self, Self::Error> { + Ok(( + Deserialise::deserialise(stream)?, + Deserialise::deserialise(stream)?, + Deserialise::deserialise(stream)?, + Deserialise::deserialise(stream)?, + Deserialise::deserialise(stream)?, + Deserialise::deserialise(stream)?, + Deserialise::deserialise(stream)?, + Deserialise::deserialise(stream)?, + Deserialise::deserialise(stream)?, + Deserialise::deserialise(stream)?, + Deserialise::deserialise(stream)?, + )) + } +} + +impl<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11> Deserialise for (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11) +where + T0: Deserialise<Error: StdError + 'static>, + T1: Deserialise<Error: StdError + 'static>, + T2: Deserialise<Error: StdError + 'static>, + T3: Deserialise<Error: StdError + 'static>, + T4: Deserialise<Error: StdError + 'static>, + T5: Deserialise<Error: StdError + 'static>, + T6: Deserialise<Error: StdError + 'static>, + T7: Deserialise<Error: StdError + 'static>, + T8: Deserialise<Error: StdError + 'static>, + T9: Deserialise<Error: StdError + 'static>, + T10: Deserialise<Error: StdError + 'static>, + T11: Deserialise<Error: StdError + 'static>, { + type Error = Box<dyn StdError>; + + fn deserialise(stream: &mut DStream) -> Result<Self, Self::Error> { + Ok(( + Deserialise::deserialise(stream)?, + Deserialise::deserialise(stream)?, + Deserialise::deserialise(stream)?, + Deserialise::deserialise(stream)?, + Deserialise::deserialise(stream)?, + Deserialise::deserialise(stream)?, + Deserialise::deserialise(stream)?, + Deserialise::deserialise(stream)?, + Deserialise::deserialise(stream)?, + Deserialise::deserialise(stream)?, + Deserialise::deserialise(stream)?, + Deserialise::deserialise(stream)?, + )) + } +} + impl<T: Deserialise<Error: StdError + 'static>, const N: usize> Deserialise for [T; N] { type Error = Box<dyn StdError>; diff --git a/src/fixed_string/mod.rs b/src/fixed_string/mod.rs index ca369ce..e755c29 100644 --- a/src/fixed_string/mod.rs +++ b/src/fixed_string/mod.rs @@ -19,6 +19,9 @@ // er General Public License along with bzipper. If // not, see <https://www.gnu.org/licenses/>. +#[cfg(test)] +mod test; + use crate::{ Deserialise, DStream, @@ -28,7 +31,9 @@ use crate::{ SStream, }; -use std::fmt::{Display, Debug, Formatter}; +use std::cmp::Ordering; +use std::fmt::{Debug, Display, Formatter, Write}; +use std::ops::{Index, IndexMut}; use std::str::FromStr; /// Owned string with maximum size. @@ -74,6 +79,32 @@ impl<const N: usize> FixedString<N> { #[must_use] pub const fn is_empty(&self) -> bool { self.len == 0x0 } + /// Borrows the character at the specified index. + /// + /// If no element exists at that position, [`None`] is returned instead. + #[inline] + #[must_use] + pub const fn get(&self, index: usize) -> Option<&char> { + if index >= self.len { + None + } else { + Some(&self.buf[index]) + } + } + + /// Mutably borrows the character at the specified index. + /// + /// If no element exists at that position, [`None`] is returned instead. + #[inline] + #[must_use] + pub fn get_mut(&mut self, index: usize) -> Option<&mut char> { + if index >= self.len { + None + } else { + Some(&mut self.buf[index]) + } + } + /// Returns an iterator to the contained characters. #[inline(always)] pub fn iter(&self) -> std::slice::Iter<'_, char> { self.buf[0x0..self.len].iter() } @@ -85,19 +116,9 @@ impl<const N: usize> FixedString<N> { impl<const N: usize> Debug for FixedString<N> { fn fmt(&self, f: &mut Formatter) -> std::fmt::Result { - write!(f, "\"")?; - - for c in self { - if c.is_ascii_graphic() { - write!(f, "{c}")?; - } else if *c == '\0' { - write!(f, "\\0")?; - } else { - write!(f, "{c}")?; - } - } - - write!(f, "\"")?; + f.write_char('"')?; + for c in self { write!(f, "{}", c.escape_debug())? } + f.write_char('"')?; Ok(()) } @@ -145,12 +166,29 @@ impl<const N: usize> Display for FixedString<N> { impl<const N: usize> Eq for FixedString<N> { } +impl<const N: usize> From<[char; N]> for FixedString<N> { + fn from(value: [char; N]) -> Self { Self { + buf: value, + len: N, + } } +} + impl<const N: usize> FromStr for FixedString<N> { type Err = Error; fn from_str(s: &str) -> Result<Self, Error> { Self::new(s) } } +impl<const N: usize> Index<usize> for FixedString<N> { + type Output = char; + + fn index(&self, index: usize) -> &Self::Output { self.get(index).unwrap() } +} + +impl<const N: usize> IndexMut<usize> for FixedString<N> { + fn index_mut(&mut self, index: usize) -> &mut Self::Output { self.get_mut(index).unwrap() } +} + impl<const N: usize> IntoIterator for FixedString<N> { type Item = char; @@ -182,8 +220,12 @@ impl<'a, const N: usize> IntoIterator for &'a mut FixedString<N> { fn into_iter(self) -> Self::IntoIter { self.iter_mut() } } -impl<const N: usize> PartialEq for FixedString<N> { - fn eq(&self, other: &Self) -> bool { +impl<const N: usize> Ord for FixedString<N> { + fn cmp(&self, other: &Self) -> Ordering { self.partial_cmp(other).unwrap() } +} + +impl<const N: usize, const M: usize> PartialEq<FixedString<M>> for FixedString<N> { + fn eq(&self, other: &FixedString<M>) -> bool { if self.len() != other.len() { return false }; for i in 0x0..self.len() { @@ -204,6 +246,31 @@ impl<const N: usize> PartialEq<&str> for FixedString<N> { } } +impl<const N: usize, const M: usize> PartialOrd<FixedString<M>> for FixedString<N> { + fn partial_cmp(&self, other: &FixedString<M>) -> Option<Ordering> { + let len = self.len().max(other.len()); + + for i in 0x0..len { + let lc = self.get(i); + let rc = other.get(i); + + match (lc, rc) { + (None, None) => return Some(Ordering::Equal), + (Some(_), None) => return Some(Ordering::Greater), + (None, Some(_)) => return Some(Ordering::Less), + + (Some(lc), Some(rc)) => { + let ordering = lc.cmp(rc); + + if ordering != Ordering::Equal { return Some(ordering) }; + } + } + } + + Some(Ordering::Equal) + } +} + impl<const N: usize> Serialise for FixedString<N> { fn serialise(&self, stream: &mut SStream) { let s: String = self.iter().collect(); diff --git a/src/fixed_string/test.rs b/src/fixed_string/test.rs new file mode 100644 index 0000000..1e3be42 --- /dev/null +++ b/src/fixed_string/test.rs @@ -0,0 +1,43 @@ +// Copyright 2024 Gabriel Bjørnager Jensen. +// +// This file is part of bzipper. +// +// bzipper is free software: you can redistribute +// it and/or modify it under the terms of the GNU +// Lesser General Public License as published by +// the Free Software Foundation, either version 3 +// of the License, or (at your option) any later +// version. +// +// bzipper is distributed in the hope that it will +// be useful, but WITHOUT ANY WARRANTY; without +// even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Less- +// er General Public License along with bzipper. If +// not, see <https://www.gnu.org/licenses/>. + +use crate::FixedString; + +use std::cmp::Ordering; + +#[test] +fn test_fixed_string() { + let str0 = FixedString::<0xC>::new("Hello there!").unwrap(); + let str1 = FixedString::<0xE>::new("MEIN_GRO\u{1E9E}_GOTT").unwrap(); + let str2 = FixedString::<0x5>::new("Hello").unwrap(); + + assert_eq!(str0.partial_cmp(&str0), Some(Ordering::Equal)); + assert_eq!(str0.partial_cmp(&str1), Some(Ordering::Less)); + assert_eq!(str0.partial_cmp(&str2), Some(Ordering::Greater)); + + assert_eq!(str1.partial_cmp(&str0), Some(Ordering::Greater)); + assert_eq!(str1.partial_cmp(&str1), Some(Ordering::Equal)); + assert_eq!(str1.partial_cmp(&str2), Some(Ordering::Greater)); + + assert_eq!(str2.partial_cmp(&str0), Some(Ordering::Less)); + assert_eq!(str2.partial_cmp(&str1), Some(Ordering::Less)); + assert_eq!(str2.partial_cmp(&str2), Some(Ordering::Equal)); +} diff --git a/src/serialise/mod.rs b/src/serialise/mod.rs index 1a63080..b8f6dba 100644 --- a/src/serialise/mod.rs +++ b/src/serialise/mod.rs @@ -63,6 +63,226 @@ macro_rules! impl_int { }; } +impl<T0, T1> Serialise for (T0, T1) +where + T0: Serialise, + T1: Serialise, { + fn serialise(&self, stream: &mut SStream) { + self.0.serialise(stream); + self.1.serialise(stream); + } +} + +impl<T0, T1, T2> Serialise for (T0, T1, T2) +where + T0: Serialise, + T1: Serialise, + T2: Serialise, { + fn serialise(&self, stream: &mut SStream) { + self.0.serialise(stream); + self.1.serialise(stream); + self.2.serialise(stream); + } +} + +impl<T0, T1, T2, T3> Serialise for (T0, T1, T2, T3) +where + T0: Serialise, + T1: Serialise, + T2: Serialise, + T3: Serialise, { + fn serialise(&self, stream: &mut SStream) { + self.0.serialise(stream); + self.1.serialise(stream); + self.2.serialise(stream); + self.3.serialise(stream); + } +} + +impl<T0, T1, T2, T3, T4> Serialise for (T0, T1, T2, T3, T4) +where + T0: Serialise, + T1: Serialise, + T2: Serialise, + T3: Serialise, + T4: Serialise, { + fn serialise(&self, stream: &mut SStream) { + self.0.serialise(stream); + self.1.serialise(stream); + self.2.serialise(stream); + self.3.serialise(stream); + self.4.serialise(stream); + } +} + +impl<T0, T1, T2, T3, T4, T5> Serialise for (T0, T1, T2, T3, T4, T5) +where + T0: Serialise, + T1: Serialise, + T2: Serialise, + T3: Serialise, + T4: Serialise, + T5: Serialise, { + fn serialise(&self, stream: &mut SStream) { + self.0.serialise(stream); + self.1.serialise(stream); + self.2.serialise(stream); + self.3.serialise(stream); + self.4.serialise(stream); + self.5.serialise(stream); + } +} + +impl<T0, T1, T2, T3, T4, T5, T6> Serialise for (T0, T1, T2, T3, T4, T5, T6) +where + T0: Serialise, + T1: Serialise, + T2: Serialise, + T3: Serialise, + T4: Serialise, + T5: Serialise, + T6: Serialise, { + fn serialise(&self, stream: &mut SStream) { + self.0.serialise(stream); + self.1.serialise(stream); + self.2.serialise(stream); + self.3.serialise(stream); + self.4.serialise(stream); + self.5.serialise(stream); + self.6.serialise(stream); + } +} + +impl<T0, T1, T2, T3, T4, T5, T6, T7> Serialise for (T0, T1, T2, T3, T4, T5, T6, T7) +where + T0: Serialise, + T1: Serialise, + T2: Serialise, + T3: Serialise, + T4: Serialise, + T5: Serialise, + T6: Serialise, + T7: Serialise, { + fn serialise(&self, stream: &mut SStream) { + self.0.serialise(stream); + self.1.serialise(stream); + self.2.serialise(stream); + self.3.serialise(stream); + self.4.serialise(stream); + self.5.serialise(stream); + self.6.serialise(stream); + self.7.serialise(stream); + } +} + +impl<T0, T1, T2, T3, T4, T5, T6, T7, T8> Serialise for (T0, T1, T2, T3, T4, T5, T6, T7, T8) +where + T0: Serialise, + T1: Serialise, + T2: Serialise, + T3: Serialise, + T4: Serialise, + T5: Serialise, + T6: Serialise, + T7: Serialise, + T8: Serialise, { + fn serialise(&self, stream: &mut SStream) { + self.0.serialise(stream); + self.1.serialise(stream); + self.2.serialise(stream); + self.3.serialise(stream); + self.4.serialise(stream); + self.5.serialise(stream); + self.6.serialise(stream); + self.7.serialise(stream); + self.8.serialise(stream); + } +} + +impl<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9> Serialise for (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9) +where + T0: Serialise, + T1: Serialise, + T2: Serialise, + T3: Serialise, + T4: Serialise, + T5: Serialise, + T6: Serialise, + T7: Serialise, + T8: Serialise, + T9: Serialise, { + fn serialise(&self, stream: &mut SStream) { + self.0.serialise(stream); + self.1.serialise(stream); + self.2.serialise(stream); + self.3.serialise(stream); + self.4.serialise(stream); + self.5.serialise(stream); + self.6.serialise(stream); + self.7.serialise(stream); + self.8.serialise(stream); + self.9.serialise(stream); + } +} + +impl<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> Serialise for (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10) +where + T0: Serialise, + T1: Serialise, + T2: Serialise, + T3: Serialise, + T4: Serialise, + T5: Serialise, + T6: Serialise, + T7: Serialise, + T8: Serialise, + T9: Serialise, + T10: Serialise, { + fn serialise(&self, stream: &mut SStream) { + self.0.serialise(stream); + self.1.serialise(stream); + self.2.serialise(stream); + self.3.serialise(stream); + self.4.serialise(stream); + self.5.serialise(stream); + self.6.serialise(stream); + self.7.serialise(stream); + self.8.serialise(stream); + self.9.serialise(stream); + self.10.serialise(stream); + } +} + +impl<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11> Serialise for (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11) +where + T0: Serialise, + T1: Serialise, + T2: Serialise, + T3: Serialise, + T4: Serialise, + T5: Serialise, + T6: Serialise, + T7: Serialise, + T8: Serialise, + T9: Serialise, + T10: Serialise, + T11: Serialise, { + fn serialise(&self, stream: &mut SStream) { + self.0.serialise(stream); + self.1.serialise(stream); + self.2.serialise(stream); + self.3.serialise(stream); + self.4.serialise(stream); + self.5.serialise(stream); + self.6.serialise(stream); + self.7.serialise(stream); + self.8.serialise(stream); + self.9.serialise(stream); + self.10.serialise(stream); + self.11.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); |