rust: Generalize the `trim_end_newlines` utility of byte strings
authorSimon Sapin <simon.sapin@octobus.net>
Fri, 03 Sep 2021 16:37:20 +0200
changeset 47949 696abab107b4
parent 47948 83f0e93ec34b
child 47950 6961eca0b3ee
rust: Generalize the `trim_end_newlines` utility of byte strings … into `trim_end_matches` that takes a callack. Also add `trim_start_matches`. Differential Revision: https://phab.mercurial-scm.org/D11388
rust/hg-core/src/repo.rs
rust/hg-core/src/utils.rs
--- a/rust/hg-core/src/repo.rs	Mon Aug 30 21:18:29 2021 +0200
+++ b/rust/hg-core/src/repo.rs	Fri Sep 03 16:37:20 2021 +0200
@@ -127,7 +127,8 @@
         } else {
             let bytes = hg_vfs.read("sharedpath")?;
             let mut shared_path =
-                get_path_from_bytes(bytes.trim_end_newlines()).to_owned();
+                get_path_from_bytes(bytes.trim_end_matches(|b| b == b'\n'))
+                    .to_owned();
             if relative {
                 shared_path = dot_hg.join(shared_path)
             }
--- a/rust/hg-core/src/utils.rs	Mon Aug 30 21:18:29 2021 +0200
+++ b/rust/hg-core/src/utils.rs	Fri Sep 03 16:37:20 2021 +0200
@@ -67,36 +67,34 @@
 }
 
 pub trait SliceExt {
-    fn trim_end_newlines(&self) -> &Self;
     fn trim_end(&self) -> &Self;
     fn trim_start(&self) -> &Self;
+    fn trim_end_matches(&self, f: impl FnMut(u8) -> bool) -> &Self;
+    fn trim_start_matches(&self, f: impl FnMut(u8) -> bool) -> &Self;
     fn trim(&self) -> &Self;
     fn drop_prefix(&self, needle: &Self) -> Option<&Self>;
     fn split_2(&self, separator: u8) -> Option<(&[u8], &[u8])>;
 }
 
-#[allow(clippy::trivially_copy_pass_by_ref)]
-fn is_not_whitespace(c: &u8) -> bool {
-    !(*c as char).is_whitespace()
-}
+impl SliceExt for [u8] {
+    fn trim_end(&self) -> &[u8] {
+        self.trim_end_matches(|byte| byte.is_ascii_whitespace())
+    }
 
-impl SliceExt for [u8] {
-    fn trim_end_newlines(&self) -> &[u8] {
-        if let Some(last) = self.iter().rposition(|&byte| byte != b'\n') {
+    fn trim_start(&self) -> &[u8] {
+        self.trim_start_matches(|byte| byte.is_ascii_whitespace())
+    }
+
+    fn trim_end_matches(&self, mut f: impl FnMut(u8) -> bool) -> &Self {
+        if let Some(last) = self.iter().rposition(|&byte| !f(byte)) {
             &self[..=last]
         } else {
             &[]
         }
     }
-    fn trim_end(&self) -> &[u8] {
-        if let Some(last) = self.iter().rposition(is_not_whitespace) {
-            &self[..=last]
-        } else {
-            &[]
-        }
-    }
-    fn trim_start(&self) -> &[u8] {
-        if let Some(first) = self.iter().position(is_not_whitespace) {
+
+    fn trim_start_matches(&self, mut f: impl FnMut(u8) -> bool) -> &Self {
+        if let Some(first) = self.iter().position(|&byte| !f(byte)) {
             &self[first..]
         } else {
             &[]