From 15b1a4aa9e50db794bc57acb65192f69d7e5bb96 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 | 117 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 118 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e4f265d..eabe256 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.3" dependencies = [ "compact_str", "serde", diff --git a/Cargo.toml b/Cargo.toml index 7e01b28..2794517 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "case_insensitive_string" -version = "0.2.0" +version = "0.2.3" authors = ["Jeff Mendez "] edition = "2021" description = "A case insensitive string struct." diff --git a/src/lib.rs b/src/lib.rs index 35ac81e..2eea10d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -98,8 +98,8 @@ impl CaseInsensitiveString { &self.0.as_bytes() } - #[inline] #[cfg(not(feature = "compact"))] + #[inline] pub fn inner(&self) -> &String { &self.0 } @@ -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!(CaseInsensitiveString::from("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!(CaseInsensitiveString::new("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".into()); + /// + /// assert_eq!(c.remove(5), 'w'); + /// assert_eq!(c, "ello orld".into()); + /// ``` + /// + /// ### 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 + } }