From cfafb1abb9a15b3b8f4e8d4707b9f95c997217f4 Mon Sep 17 00:00:00 2001 From: j-mendez Date: Sun, 24 Dec 2023 14:49:56 -0500 Subject: [PATCH] feat(lib): add string helpers --- Cargo.lock | 2 +- Cargo.toml | 2 +- src/lib.rs | 115 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 117 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e4f265d..8143a2a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,7 +4,7 @@ version = 3 [[package]] name = "case_insensitive_string" -version = "0.2.0" +version = "0.2.2" dependencies = [ "compact_str", "serde", diff --git a/Cargo.toml b/Cargo.toml index 7e01b28..e566507 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "case_insensitive_string" -version = "0.2.0" +version = "0.2.2" authors = ["Jeff Mendez "] edition = "2021" description = "A case insensitive string struct." diff --git a/src/lib.rs b/src/lib.rs index 35ac81e..39dbc71 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -109,4 +109,119 @@ impl CaseInsensitiveString { pub fn inner(&self) -> &compact_str::CompactString { &self.0 } + + /// Appends the given [`char`] to the end of this [`CaseInsensitiveString`]. + /// + /// # Examples + /// ``` + /// # use case_insensitive_string::CaseInsensitiveString; + /// let mut s = CaseInsensitiveString::new("foo"); + /// + /// s.push('b'); + /// s.push('a'); + /// s.push('r'); + /// + /// assert_eq!("foobar", s); + /// ``` + pub fn push(&mut self, ch: char) { + self.push_str(ch.encode_utf8(&mut [0; 4])); + } + + /// Appends a given string slice onto the end of this [`CaseInsensitiveString`] + /// + /// # Examples + /// ``` + /// # use case_insensitive_string::CaseInsensitiveString; + /// let mut s = CaseInsensitiveString::new("abc"); + /// + /// s.push_str("123"); + /// + /// assert_eq!("abc123", s); + /// ``` + #[inline] + pub fn push_str(&mut self, s: &str) { + self.0.push_str(s) + } + + /// Removes a [`char`] from this [`CaseInsensitiveString`] at a byte position and returns it. + /// + /// This is an *O*(*n*) operation, as it requires copying every element in the + /// buffer. + /// + /// # Panics + /// + /// Panics if `idx` is larger than or equal to the [`CaseInsensitiveString`]'s length, + /// or if it does not lie on a [`char`] boundary. + /// + /// # Examples + /// + /// ### Basic usage: + /// + /// ``` + /// # use case_insensitive_string::CaseInsensitiveString; + /// let mut c = CaseInsensitiveString::from("hello world"); + /// + /// assert_eq!(c.remove(0), 'h'); + /// assert_eq!(c, "ello world"); + /// + /// assert_eq!(c.remove(5), 'w'); + /// assert_eq!(c, "ello orld"); + /// ``` + /// + /// ### Past total length: + /// + /// ```should_panic + /// # use case_insensitive_string::CaseInsensitiveString; + /// let mut c = CaseInsensitiveString::from("hello there!"); + /// c.remove(100); + /// ``` + /// + /// ### Not on char boundary: + /// + /// ```should_panic + /// # use case_insensitive_string::CaseInsensitiveString; + /// let mut c = CaseInsensitiveString::from("🦄"); + /// c.remove(1); + /// ``` + #[inline] + pub fn remove(&mut self, idx: usize) -> char { + self.0.remove(idx) + } + + /// Returns the length of the [`CaseInsensitiveString`] in `bytes`, not [`char`]s or graphemes. + /// + /// When using `UTF-8` encoding (which all strings in Rust do) a single character will be 1 to 4 + /// bytes long, therefore the return value of this method might not be what a human considers + /// the length of the string. + /// + /// # Examples + /// ``` + /// # use case_insensitive_string::CaseInsensitiveString; + /// let ascii = CaseInsensitiveString::new("hello world"); + /// assert_eq!(ascii.len(), 11); + /// + /// let emoji = CaseInsensitiveString::new("👱"); + /// assert_eq!(emoji.len(), 4); + /// ``` + #[inline] + pub fn len(&self) -> usize { + self.0.len() + } + + /// Returns `true` if the [`CaseInsensitiveString`] has a length of 0, `false` otherwise + /// + /// # Examples + /// ``` + /// # use case_insensitive_string::CaseInsensitiveString; + /// let mut msg = CaseInsensitiveString::new(""); + /// assert!(msg.is_empty()); + /// + /// // add some characters + /// msg.push_str("hello reader!"); + /// assert!(!msg.is_empty()); + /// ``` + #[inline] + pub fn is_empty(&self) -> bool { + self.len() == 0 + } }