##// END OF EJS Templates
rust-utils: add util to find a slice in another slice...
Raphaël Gomès -
r44538:191a461d default
parent child Browse files
Show More
@@ -1,93 +1,113
1 // utils module
1 // utils module
2 //
2 //
3 // Copyright 2019 Raphaël Gomès <rgomes@octobus.net>
3 // Copyright 2019 Raphaël Gomès <rgomes@octobus.net>
4 //
4 //
5 // This software may be used and distributed according to the terms of the
5 // This software may be used and distributed according to the terms of the
6 // GNU General Public License version 2 or any later version.
6 // GNU General Public License version 2 or any later version.
7
7
8 //! Contains useful functions, traits, structs, etc. for use in core.
8 //! Contains useful functions, traits, structs, etc. for use in core.
9
9
10 pub mod files;
10 pub mod files;
11 pub mod hg_path;
11 pub mod hg_path;
12
12
13 /// Useful until rust/issues/56345 is stable
14 ///
15 /// # Examples
16 ///
17 /// ```
18 /// use crate::hg::utils::find_slice_in_slice;
19 ///
20 /// let haystack = b"This is the haystack".to_vec();
21 /// assert_eq!(find_slice_in_slice(&haystack, b"the"), Some(8));
22 /// assert_eq!(find_slice_in_slice(&haystack, b"not here"), None);
23 /// ```
24 pub fn find_slice_in_slice<T>(slice: &[T], needle: &[T]) -> Option<usize>
25 where
26 for<'a> &'a [T]: PartialEq,
27 {
28 slice
29 .windows(needle.len())
30 .position(|window| window == needle)
31 }
32
13 /// Replaces the `from` slice with the `to` slice inside the `buf` slice.
33 /// Replaces the `from` slice with the `to` slice inside the `buf` slice.
14 ///
34 ///
15 /// # Examples
35 /// # Examples
16 ///
36 ///
17 /// ```
37 /// ```
18 /// use crate::hg::utils::replace_slice;
38 /// use crate::hg::utils::replace_slice;
19 /// let mut line = b"I hate writing tests!".to_vec();
39 /// let mut line = b"I hate writing tests!".to_vec();
20 /// replace_slice(&mut line, b"hate", b"love");
40 /// replace_slice(&mut line, b"hate", b"love");
21 /// assert_eq!(
41 /// assert_eq!(
22 /// line,
42 /// line,
23 /// b"I love writing tests!".to_vec()
43 /// b"I love writing tests!".to_vec()
24 /// );
44 /// );
25 /// ```
45 /// ```
26 pub fn replace_slice<T>(buf: &mut [T], from: &[T], to: &[T])
46 pub fn replace_slice<T>(buf: &mut [T], from: &[T], to: &[T])
27 where
47 where
28 T: Clone + PartialEq,
48 T: Clone + PartialEq,
29 {
49 {
30 if buf.len() < from.len() || from.len() != to.len() {
50 if buf.len() < from.len() || from.len() != to.len() {
31 return;
51 return;
32 }
52 }
33 for i in 0..=buf.len() - from.len() {
53 for i in 0..=buf.len() - from.len() {
34 if buf[i..].starts_with(from) {
54 if buf[i..].starts_with(from) {
35 buf[i..(i + from.len())].clone_from_slice(to);
55 buf[i..(i + from.len())].clone_from_slice(to);
36 }
56 }
37 }
57 }
38 }
58 }
39
59
40 pub trait SliceExt {
60 pub trait SliceExt {
41 fn trim_end(&self) -> &Self;
61 fn trim_end(&self) -> &Self;
42 fn trim_start(&self) -> &Self;
62 fn trim_start(&self) -> &Self;
43 fn trim(&self) -> &Self;
63 fn trim(&self) -> &Self;
44 fn drop_prefix(&self, needle: &Self) -> Option<&Self>;
64 fn drop_prefix(&self, needle: &Self) -> Option<&Self>;
45 }
65 }
46
66
47 fn is_not_whitespace(c: &u8) -> bool {
67 fn is_not_whitespace(c: &u8) -> bool {
48 !(*c as char).is_whitespace()
68 !(*c as char).is_whitespace()
49 }
69 }
50
70
51 impl SliceExt for [u8] {
71 impl SliceExt for [u8] {
52 fn trim_end(&self) -> &[u8] {
72 fn trim_end(&self) -> &[u8] {
53 if let Some(last) = self.iter().rposition(is_not_whitespace) {
73 if let Some(last) = self.iter().rposition(is_not_whitespace) {
54 &self[..last + 1]
74 &self[..last + 1]
55 } else {
75 } else {
56 &[]
76 &[]
57 }
77 }
58 }
78 }
59 fn trim_start(&self) -> &[u8] {
79 fn trim_start(&self) -> &[u8] {
60 if let Some(first) = self.iter().position(is_not_whitespace) {
80 if let Some(first) = self.iter().position(is_not_whitespace) {
61 &self[first..]
81 &self[first..]
62 } else {
82 } else {
63 &[]
83 &[]
64 }
84 }
65 }
85 }
66
86
67 /// ```
87 /// ```
68 /// use hg::utils::SliceExt;
88 /// use hg::utils::SliceExt;
69 /// assert_eq!(
89 /// assert_eq!(
70 /// b" to trim ".trim(),
90 /// b" to trim ".trim(),
71 /// b"to trim"
91 /// b"to trim"
72 /// );
92 /// );
73 /// assert_eq!(
93 /// assert_eq!(
74 /// b"to trim ".trim(),
94 /// b"to trim ".trim(),
75 /// b"to trim"
95 /// b"to trim"
76 /// );
96 /// );
77 /// assert_eq!(
97 /// assert_eq!(
78 /// b" to trim".trim(),
98 /// b" to trim".trim(),
79 /// b"to trim"
99 /// b"to trim"
80 /// );
100 /// );
81 /// ```
101 /// ```
82 fn trim(&self) -> &[u8] {
102 fn trim(&self) -> &[u8] {
83 self.trim_start().trim_end()
103 self.trim_start().trim_end()
84 }
104 }
85
105
86 fn drop_prefix(&self, needle: &Self) -> Option<&Self> {
106 fn drop_prefix(&self, needle: &Self) -> Option<&Self> {
87 if self.starts_with(needle) {
107 if self.starts_with(needle) {
88 Some(&self[needle.len()..])
108 Some(&self[needle.len()..])
89 } else {
109 } else {
90 None
110 None
91 }
111 }
92 }
112 }
93 }
113 }
General Comments 0
You need to be logged in to leave comments. Login now