summaryrefslogtreecommitdiff
path: root/src/fixed_string
diff options
context:
space:
mode:
Diffstat (limited to 'src/fixed_string')
-rw-r--r--src/fixed_string/mod.rs99
-rw-r--r--src/fixed_string/test.rs43
2 files changed, 126 insertions, 16 deletions
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));
+}