summaryrefslogtreecommitdiff
path: root/src/fixed_string
diff options
context:
space:
mode:
Diffstat (limited to 'src/fixed_string')
-rw-r--r--src/fixed_string/mod.rs298
-rw-r--r--src/fixed_string/test.rs43
2 files changed, 0 insertions, 341 deletions
diff --git a/src/fixed_string/mod.rs b/src/fixed_string/mod.rs
deleted file mode 100644
index b0342d3..0000000
--- a/src/fixed_string/mod.rs
+++ /dev/null
@@ -1,298 +0,0 @@
-// 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/>.
-
-#[cfg(test)]
-mod test;
-
-use crate::{
- Deserialise,
- Dstream,
- Error,
- FixedStringIter,
- Serialise,
- Sstream,
-};
-
-use alloc::string::String;
-use core::cmp::Ordering;
-use core::fmt::{Debug, Display, Formatter};
-use core::ops::{Index, IndexMut};
-use core::str::FromStr;
-
-/// Owned string with maximum size.
-///
-/// This is in contrast to [String], which has no size limit is practice, and [str], which is unsized.
-#[derive(Clone)]
-pub struct FixedString<const N: usize> {
- buf: [char; N],
- len: usize,
-}
-
-impl<const N: usize> FixedString<N> {
- /// Constructs a new fixed string.
- ///
- /// The contents of the provided string are copied into the internal buffer.
- /// All residual characters are instanced as U+0000 `NULL`.
- ///
- /// # Errors
- ///
- /// If the given string `s` cannot fit into `N` characters, an [`ArrayTooShort`](Error::ArrayTooShort) error is returned.
- pub fn new(s: &str) -> Result<Self, Error> {
- let mut buf = ['\0'; N];
- let len = s.chars().count();
-
- for (i, c) in s.chars().enumerate() {
- if i >= N { return Err(Error::ArrayTooShort { req: len, len: N }) }
-
- buf[i] = c;
- }
-
- Ok(Self { buf, len })
- }
-
- /// Returns the length of the string.
- ///
- /// This does not necessarily equal the value of `N`, as the internal buffer is not required to be used fully.
- #[inline(always)]
- #[must_use]
- pub const fn len(&self) -> usize { self.len }
-
- /// Checks if the string is empty, i.e. `self.len() == 0x0`.
- #[inline(always)]
- #[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) -> core::slice::Iter<'_, char> { self.buf[0x0..self.len].iter() }
-
- /// Returns a mutable iterator to the contained characters.
- #[inline(always)]
- pub fn iter_mut(&mut self) -> core::slice::IterMut<'_, char> { self.buf[0x0..self.len].iter_mut() }
-}
-
-impl<const N: usize> Debug for FixedString<N> {
- fn fmt(&self, f: &mut Formatter) -> core::fmt::Result {
- write!(f, "\"")?;
- for c in self { write!(f, "{}", c.escape_debug())? }
- write!(f, "\"")?;
-
- Ok(())
- }
-}
-
-impl<const N: usize> Deserialise for FixedString<N> {
- type Error = Error;
-
- fn deserialise(stream: &mut Dstream) -> Result<Self, Self::Error> {
- let len = usize::deserialise(stream)?;
- let data = stream.take(len)?;
-
- let s = core::str::from_utf8(data)
- .map_err(|e| Error::BadString { source: e })?;
-
- let len = s.chars().count();
-
- if len > N {
- return Err(Error::ArrayTooShort { req: len, len: N });
- }
-
- let mut buf = ['\0'; N];
- for (i, c) in s.chars().enumerate() {
- buf[i] = c;
- }
-
- Ok(Self { buf, len })
- }
-}
-
-impl<const N: usize> Default for FixedString<N> {
- #[inline(always)]
- fn default() -> Self { Self {
- buf: ['\0'; N],
- len: 0x0,
- } }
-}
-
-impl<const N: usize> Display for FixedString<N> {
- fn fmt(&self, f: &mut Formatter) -> core::fmt::Result {
- for c in self { write!(f, "{c}")? }
-
- Ok(())
- }
-}
-
-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;
-
- type IntoIter = FixedStringIter<N>;
-
- fn into_iter(self) -> Self::IntoIter {
- FixedStringIter {
- buf: self.buf,
- len: self.len,
-
- pos: Some(0x0),
- }
- }
-}
-
-impl<'a, const N: usize> IntoIterator for &'a FixedString<N> {
- type Item = &'a char;
-
- type IntoIter = core::slice::Iter<'a, char>;
-
- fn into_iter(self) -> Self::IntoIter { self.iter() }
-}
-
-impl<'a, const N: usize> IntoIterator for &'a mut FixedString<N> {
- type Item = &'a mut char;
-
- type IntoIter = core::slice::IterMut<'a, char>;
-
- fn into_iter(self) -> Self::IntoIter { self.iter_mut() }
-}
-
-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() {
- if self.buf[i] != other.buf[i] { return false };
- }
-
- true
- }
-}
-
-impl<const N: usize> PartialEq<&str> for FixedString<N> {
- fn eq(&self, other: &&str) -> bool {
- for (i, c) in other.chars().enumerate() {
- if self.buf.get(i) != Some(&c) { return false };
- }
-
- true
- }
-}
-
-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> {
- type Error = Error;
-
- const SERIALISE_LIMIT: usize = N * 0x4;
-
- fn serialise(&self, stream: &mut Sstream) -> Result<usize, Self::Error> {
- let mut count = 0x0;
-
- let s: String = self.iter().collect();
-
- count += s.len().serialise(stream)?;
- count += stream.add(&s.into_bytes())?;
-
- Ok(count)
- }
-}
-
-impl<const N: usize> TryFrom<&str> for FixedString<N> {
- type Error = Error;
-
- #[inline(always)]
- fn try_from(value: &str) -> Result<Self, Self::Error> { Self::new(value) }
-}
diff --git a/src/fixed_string/test.rs b/src/fixed_string/test.rs
deleted file mode 100644
index 1599efc..0000000
--- a/src/fixed_string/test.rs
+++ /dev/null
@@ -1,43 +0,0 @@
-// 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 core::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));
-}