From dda4ceddd03bce804e8f03f2639f223a3412dbe3 Mon Sep 17 00:00:00 2001 From: Ali Ghahremani Date: Sun, 3 Dec 2023 23:49:32 +0330 Subject: [PATCH 1/3] perf: zero-copy impl on commas module (it's 30-50% faster now) --- src/commas/add_commas.rs | 30 ++++++++++++++++++------------ src/commas/remove_commas.rs | 3 +-- 2 files changed, 19 insertions(+), 14 deletions(-) diff --git a/src/commas/add_commas.rs b/src/commas/add_commas.rs index 7c51c04..7868458 100644 --- a/src/commas/add_commas.rs +++ b/src/commas/add_commas.rs @@ -5,12 +5,10 @@ /// // function: /// use rust_persian_tools::commas::add_commas::add_commas; /// assert_eq!(add_commas("30000000"), "30,000,000"); -/// assert_eq!(add_commas(30000000), "30,000,000"); /// /// // method: /// use crate::rust_persian_tools::commas::add_commas::AddCommas; /// assert_eq!("30000000".add_commas(), "30,000,000"); -/// assert_eq!(30000000.add_commas(), "30,000,000"); /// /// // method on your custom type: /// struct YourCustomType; @@ -20,20 +18,20 @@ /// } /// } /// ``` -pub fn add_commas(str: impl ToString) -> String { - let mut str: String = str.to_string(); +pub fn add_commas(inp: &str) -> String { + let comma_less = |c: &char| c != &','; - str = str.replace(',', ""); - let mut result = String::new(); - - let end = str + let mut end = inp .chars() + .filter(comma_less) .position(|c| c == '.') - .unwrap_or_else(|| str.chars().count()); + .unwrap_or_else(|| inp.chars().filter(comma_less).count()); - for (i, ch) in str.chars().enumerate() { + let mut result = String::new(); + for (i, ch) in inp.chars().filter(comma_less).enumerate() { if end == i { - result.push_str(&str[end..str.chars().count()]); + end += inp.chars().filter(|c| c == &',').count(); + result.push_str(&inp[end..inp.chars().count()]); break; } if (end - i) % 3 == 0 && i != 0 { @@ -49,7 +47,13 @@ pub trait AddCommas { fn add_commas(&self) -> String; } -impl AddCommas for T { +impl AddCommas for str { + fn add_commas(&self) -> String { + add_commas(self) + } +} + +impl AddCommas for String { fn add_commas(&self) -> String { add_commas(self) } @@ -57,6 +61,8 @@ impl AddCommas for T { #[cfg(test)] mod tests { + use std::time::Instant; + use super::*; #[test] diff --git a/src/commas/remove_commas.rs b/src/commas/remove_commas.rs index 3275678..b7a1c47 100644 --- a/src/commas/remove_commas.rs +++ b/src/commas/remove_commas.rs @@ -10,8 +10,7 @@ /// use crate::rust_persian_tools::commas::remove_commas::RemoveCommas; /// assert_eq!("30,000,000".remove_commas(), "30000000".to_string()); /// ``` -pub fn remove_commas(str: impl Into) -> String { - let str: String = str.into(); +pub fn remove_commas(str: &str) -> String { str.replace(',', "") } From f50ba3a60b93161b1cf3a403eefa6f08f24a6aef Mon Sep 17 00:00:00 2001 From: Ali Ghahremani Date: Mon, 4 Dec 2023 00:41:24 +0330 Subject: [PATCH 2/3] feat: remove_commas_mut (25% faster then remove_commas) --- src/commas/add_commas.rs | 2 -- src/commas/remove_commas.rs | 22 ++++++++++++++++++++++ 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/src/commas/add_commas.rs b/src/commas/add_commas.rs index 7868458..2ce1324 100644 --- a/src/commas/add_commas.rs +++ b/src/commas/add_commas.rs @@ -61,8 +61,6 @@ impl AddCommas for String { #[cfg(test)] mod tests { - use std::time::Instant; - use super::*; #[test] diff --git a/src/commas/remove_commas.rs b/src/commas/remove_commas.rs index b7a1c47..f16f4c9 100644 --- a/src/commas/remove_commas.rs +++ b/src/commas/remove_commas.rs @@ -14,6 +14,21 @@ pub fn remove_commas(str: &str) -> String { str.replace(',', "") } +/// Remove all commas in string in place\ +/// 3,000,000 -> 3000000\ +/// Example: +/// ```rust +/// // function: +/// use rust_persian_tools::commas::remove_commas::remove_commas_mut; +/// let mut input = String::from("30,000,000"); +/// remove_commas_mut(&mut input); +/// assert_eq!(input, "30000000".to_string()); +/// +/// ``` +pub fn remove_commas_mut(str: &mut String) { + str.retain(|c| c != ',') +} + pub trait RemoveCommas { fn remove_commas(&self) -> String; } @@ -38,4 +53,11 @@ mod tests { fn remove_commas_test() { assert_eq!(remove_commas("30,000,000"), "30000000".to_string()); } + + #[test] + fn remove_commas_mut_test() { + let mut input = String::from("30,000,000"); + remove_commas_mut(&mut input); + assert_eq!(input, "30000000".to_string()); + } } From ca2abefaaa83ddca54a8cccdd9c377052663f747 Mon Sep 17 00:00:00 2001 From: Ali Ghahremani Date: Mon, 4 Dec 2023 01:01:49 +0330 Subject: [PATCH 3/3] improve: switch to AsRef (no performace overhead) --- src/commas/add_commas.rs | 3 ++- src/commas/remove_commas.rs | 8 +++++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/commas/add_commas.rs b/src/commas/add_commas.rs index 2ce1324..f977323 100644 --- a/src/commas/add_commas.rs +++ b/src/commas/add_commas.rs @@ -18,7 +18,8 @@ /// } /// } /// ``` -pub fn add_commas(inp: &str) -> String { +pub fn add_commas(inp: impl AsRef) -> String { + let inp = inp.as_ref(); let comma_less = |c: &char| c != &','; let mut end = inp diff --git a/src/commas/remove_commas.rs b/src/commas/remove_commas.rs index f16f4c9..0953fa0 100644 --- a/src/commas/remove_commas.rs +++ b/src/commas/remove_commas.rs @@ -10,11 +10,11 @@ /// use crate::rust_persian_tools::commas::remove_commas::RemoveCommas; /// assert_eq!("30,000,000".remove_commas(), "30000000".to_string()); /// ``` -pub fn remove_commas(str: &str) -> String { - str.replace(',', "") +pub fn remove_commas(str: impl AsRef) -> String { + str.as_ref().replace(',', "") } -/// Remove all commas in string in place\ +/// Remove all commas in string\ /// 3,000,000 -> 3000000\ /// Example: /// ```rust @@ -47,6 +47,8 @@ impl RemoveCommas for str { #[cfg(test)] mod tests { + use std::time::Instant; + use super::*; #[test]