Mercurial > public > mercurial-scm > hg
annotate rust/hg-core/src/utils/strings.rs @ 53042:cdd7bf612c7b stable tip
bundle-spec: properly format boolean parameter (issue6960)
This was breaking automatic clone bundle generation. This changeset fixes it and
add a test to catch it in the future.
author | Pierre-Yves David <pierre-yves.david@octobus.net> |
---|---|
date | Tue, 11 Mar 2025 02:29:42 +0100 |
parents | 874c64e041b5 |
children |
rev | line source |
---|---|
52760
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
1 //! Contains string-related utilities. |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
2 |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
3 use crate::utils::hg_path::HgPath; |
52969
874c64e041b5
rhg-annotate: support whitespace options
Mitchell Kember <mkember@janestreet.com>
parents:
52760
diff
changeset
|
4 use lazy_static::lazy_static; |
874c64e041b5
rhg-annotate: support whitespace options
Mitchell Kember <mkember@janestreet.com>
parents:
52760
diff
changeset
|
5 use regex::bytes::Regex; |
874c64e041b5
rhg-annotate: support whitespace options
Mitchell Kember <mkember@janestreet.com>
parents:
52760
diff
changeset
|
6 use std::{borrow::Cow, cell::Cell, fmt, io::Write as _, ops::Deref as _}; |
52760
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
7 |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
8 /// Useful until rust/issues/56345 is stable |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
9 /// |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
10 /// # Examples |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
11 /// |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
12 /// ``` |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
13 /// use hg::utils::strings::find_slice_in_slice; |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
14 /// |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
15 /// let haystack = b"This is the haystack".to_vec(); |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
16 /// assert_eq!(find_slice_in_slice(&haystack, b"the"), Some(8)); |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
17 /// assert_eq!(find_slice_in_slice(&haystack, b"not here"), None); |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
18 /// ``` |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
19 pub fn find_slice_in_slice<T>(slice: &[T], needle: &[T]) -> Option<usize> |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
20 where |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
21 for<'a> &'a [T]: PartialEq, |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
22 { |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
23 slice |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
24 .windows(needle.len()) |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
25 .position(|window| window == needle) |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
26 } |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
27 |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
28 /// Replaces the `from` slice with the `to` slice inside the `buf` slice. |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
29 /// |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
30 /// # Examples |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
31 /// |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
32 /// ``` |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
33 /// use hg::utils::strings::replace_slice; |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
34 /// let mut line = b"I hate writing tests!".to_vec(); |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
35 /// replace_slice(&mut line, b"hate", b"love"); |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
36 /// assert_eq!( |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
37 /// line, |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
38 /// b"I love writing tests!".to_vec() |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
39 /// ); |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
40 /// ``` |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
41 pub fn replace_slice<T>(buf: &mut [T], from: &[T], to: &[T]) |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
42 where |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
43 T: Clone + PartialEq, |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
44 { |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
45 if buf.len() < from.len() || from.len() != to.len() { |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
46 return; |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
47 } |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
48 for i in 0..=buf.len() - from.len() { |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
49 if buf[i..].starts_with(from) { |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
50 buf[i..(i + from.len())].clone_from_slice(to); |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
51 } |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
52 } |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
53 } |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
54 |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
55 pub trait SliceExt { |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
56 fn trim_end(&self) -> &Self; |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
57 fn trim_start(&self) -> &Self; |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
58 fn trim_end_matches(&self, f: impl FnMut(u8) -> bool) -> &Self; |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
59 fn trim_start_matches(&self, f: impl FnMut(u8) -> bool) -> &Self; |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
60 fn trim(&self) -> &Self; |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
61 fn drop_prefix(&self, needle: &Self) -> Option<&Self>; |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
62 fn split_2(&self, separator: u8) -> Option<(&[u8], &[u8])>; |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
63 fn split_2_by_slice(&self, separator: &[u8]) -> Option<(&[u8], &[u8])>; |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
64 } |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
65 |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
66 impl SliceExt for [u8] { |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
67 fn trim_end(&self) -> &[u8] { |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
68 self.trim_end_matches(|byte| byte.is_ascii_whitespace()) |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
69 } |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
70 |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
71 fn trim_start(&self) -> &[u8] { |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
72 self.trim_start_matches(|byte| byte.is_ascii_whitespace()) |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
73 } |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
74 |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
75 fn trim_end_matches(&self, mut f: impl FnMut(u8) -> bool) -> &Self { |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
76 if let Some(last) = self.iter().rposition(|&byte| !f(byte)) { |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
77 &self[..=last] |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
78 } else { |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
79 &[] |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
80 } |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
81 } |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
82 |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
83 fn trim_start_matches(&self, mut f: impl FnMut(u8) -> bool) -> &Self { |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
84 if let Some(first) = self.iter().position(|&byte| !f(byte)) { |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
85 &self[first..] |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
86 } else { |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
87 &[] |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
88 } |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
89 } |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
90 |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
91 /// ``` |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
92 /// use hg::utils::strings::SliceExt; |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
93 /// assert_eq!( |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
94 /// b" to trim ".trim(), |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
95 /// b"to trim" |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
96 /// ); |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
97 /// assert_eq!( |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
98 /// b"to trim ".trim(), |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
99 /// b"to trim" |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
100 /// ); |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
101 /// assert_eq!( |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
102 /// b" to trim".trim(), |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
103 /// b"to trim" |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
104 /// ); |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
105 /// ``` |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
106 fn trim(&self) -> &[u8] { |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
107 self.trim_start().trim_end() |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
108 } |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
109 |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
110 fn drop_prefix(&self, needle: &Self) -> Option<&Self> { |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
111 if self.starts_with(needle) { |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
112 Some(&self[needle.len()..]) |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
113 } else { |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
114 None |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
115 } |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
116 } |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
117 |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
118 fn split_2(&self, separator: u8) -> Option<(&[u8], &[u8])> { |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
119 let pos = memchr::memchr(separator, self)?; |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
120 Some((&self[..pos], &self[pos + 1..])) |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
121 } |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
122 |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
123 fn split_2_by_slice(&self, separator: &[u8]) -> Option<(&[u8], &[u8])> { |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
124 find_slice_in_slice(self, separator) |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
125 .map(|pos| (&self[..pos], &self[pos + separator.len()..])) |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
126 } |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
127 } |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
128 |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
129 pub trait Escaped { |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
130 /// Return bytes escaped for display to the user |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
131 fn escaped_bytes(&self) -> Vec<u8>; |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
132 } |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
133 |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
134 impl Escaped for u8 { |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
135 fn escaped_bytes(&self) -> Vec<u8> { |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
136 let mut acc = vec![]; |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
137 match self { |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
138 c @ b'\'' | c @ b'\\' => { |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
139 acc.push(b'\\'); |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
140 acc.push(*c); |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
141 } |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
142 b'\t' => { |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
143 acc.extend(br"\\t"); |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
144 } |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
145 b'\n' => { |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
146 acc.extend(br"\\n"); |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
147 } |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
148 b'\r' => { |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
149 acc.extend(br"\\r"); |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
150 } |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
151 c if (*c < b' ' || *c >= 127) => { |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
152 write!(acc, "\\x{:x}", self).unwrap(); |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
153 } |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
154 c => { |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
155 acc.push(*c); |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
156 } |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
157 } |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
158 acc |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
159 } |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
160 } |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
161 |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
162 impl<'a, T: Escaped> Escaped for &'a [T] { |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
163 fn escaped_bytes(&self) -> Vec<u8> { |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
164 self.iter().flat_map(Escaped::escaped_bytes).collect() |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
165 } |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
166 } |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
167 |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
168 impl<T: Escaped> Escaped for Vec<T> { |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
169 fn escaped_bytes(&self) -> Vec<u8> { |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
170 self.deref().escaped_bytes() |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
171 } |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
172 } |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
173 |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
174 impl<'a> Escaped for &'a HgPath { |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
175 fn escaped_bytes(&self) -> Vec<u8> { |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
176 self.as_bytes().escaped_bytes() |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
177 } |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
178 } |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
179 |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
180 #[cfg(unix)] |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
181 pub fn shell_quote(value: &[u8]) -> Vec<u8> { |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
182 if value.iter().all(|&byte| { |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
183 matches!( |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
184 byte, |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
185 b'a'..=b'z' |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
186 | b'A'..=b'Z' |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
187 | b'0'..=b'9' |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
188 | b'.' |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
189 | b'_' |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
190 | b'/' |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
191 | b'+' |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
192 | b'-' |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
193 ) |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
194 }) { |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
195 value.to_owned() |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
196 } else { |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
197 let mut quoted = Vec::with_capacity(value.len() + 2); |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
198 quoted.push(b'\''); |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
199 for &byte in value { |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
200 if byte == b'\'' { |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
201 quoted.push(b'\\'); |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
202 } |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
203 quoted.push(byte); |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
204 } |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
205 quoted.push(b'\''); |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
206 quoted |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
207 } |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
208 } |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
209 |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
210 /// Expand `$FOO` and `${FOO}` environment variables in the given byte string |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
211 pub fn expand_vars(s: &[u8]) -> std::borrow::Cow<[u8]> { |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
212 lazy_static::lazy_static! { |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
213 /// https://github.com/python/cpython/blob/3.9/Lib/posixpath.py#L301 |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
214 /// The `x` makes whitespace ignored. |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
215 /// `-u` disables the Unicode flag, which makes `\w` like Python with the ASCII flag. |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
216 static ref VAR_RE: regex::bytes::Regex = |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
217 regex::bytes::Regex::new(r"(?x-u) |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
218 \$ |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
219 (?: |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
220 (\w+) |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
221 | |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
222 \{ |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
223 ([^}]*) |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
224 \} |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
225 ) |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
226 ").unwrap(); |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
227 } |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
228 VAR_RE.replace_all(s, |captures: ®ex::bytes::Captures| { |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
229 let var_name = crate::utils::files::get_os_str_from_bytes( |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
230 captures |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
231 .get(1) |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
232 .or_else(|| captures.get(2)) |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
233 .expect("either side of `|` must participate in match") |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
234 .as_bytes(), |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
235 ); |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
236 std::env::var_os(var_name) |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
237 .map(crate::utils::files::get_bytes_from_os_str) |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
238 .unwrap_or_else(|| { |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
239 // Referencing an environment variable that does not exist. |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
240 // Leave the $FOO reference as-is. |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
241 captures[0].to_owned() |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
242 }) |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
243 }) |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
244 } |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
245 |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
246 /// Join items of the iterable with the given separator, similar to Python’s |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
247 /// `separator.join(iter)`. |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
248 /// |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
249 /// Formatting the return value consumes the iterator. |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
250 /// Formatting it again will produce an empty string. |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
251 pub fn join_display( |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
252 iter: impl IntoIterator<Item = impl fmt::Display>, |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
253 separator: impl fmt::Display, |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
254 ) -> impl fmt::Display { |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
255 JoinDisplay { |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
256 iter: Cell::new(Some(iter.into_iter())), |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
257 separator, |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
258 } |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
259 } |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
260 |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
261 struct JoinDisplay<I, S> { |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
262 iter: Cell<Option<I>>, |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
263 separator: S, |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
264 } |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
265 |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
266 impl<I, T, S> fmt::Display for JoinDisplay<I, S> |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
267 where |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
268 I: Iterator<Item = T>, |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
269 T: fmt::Display, |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
270 S: fmt::Display, |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
271 { |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
272 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
273 if let Some(mut iter) = self.iter.take() { |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
274 if let Some(first) = iter.next() { |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
275 first.fmt(f)?; |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
276 } |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
277 for value in iter { |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
278 self.separator.fmt(f)?; |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
279 value.fmt(f)?; |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
280 } |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
281 } |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
282 Ok(()) |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
283 } |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
284 } |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
285 |
52759
36d39726c0af
rust: add utils::strings module
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
286 /// Returns a short representation of a user name or email address. |
36d39726c0af
rust: add utils::strings module
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
287 pub fn short_user(user: &[u8]) -> &[u8] { |
36d39726c0af
rust: add utils::strings module
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
288 let mut str = user; |
36d39726c0af
rust: add utils::strings module
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
289 if let Some(i) = memchr::memchr(b'@', str) { |
36d39726c0af
rust: add utils::strings module
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
290 str = &str[..i]; |
36d39726c0af
rust: add utils::strings module
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
291 } |
36d39726c0af
rust: add utils::strings module
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
292 if let Some(i) = memchr::memchr(b'<', str) { |
36d39726c0af
rust: add utils::strings module
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
293 str = &str[i + 1..]; |
36d39726c0af
rust: add utils::strings module
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
294 } |
36d39726c0af
rust: add utils::strings module
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
295 if let Some(i) = memchr::memchr(b' ', str) { |
36d39726c0af
rust: add utils::strings module
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
296 str = &str[..i]; |
36d39726c0af
rust: add utils::strings module
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
297 } |
36d39726c0af
rust: add utils::strings module
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
298 if let Some(i) = memchr::memchr(b'.', str) { |
36d39726c0af
rust: add utils::strings module
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
299 str = &str[..i]; |
36d39726c0af
rust: add utils::strings module
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
300 } |
36d39726c0af
rust: add utils::strings module
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
301 str |
36d39726c0af
rust: add utils::strings module
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
302 } |
36d39726c0af
rust: add utils::strings module
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
303 |
52969
874c64e041b5
rhg-annotate: support whitespace options
Mitchell Kember <mkember@janestreet.com>
parents:
52760
diff
changeset
|
304 /// Options for [`clean_whitespace`]. |
874c64e041b5
rhg-annotate: support whitespace options
Mitchell Kember <mkember@janestreet.com>
parents:
52760
diff
changeset
|
305 #[derive(Copy, Clone)] |
874c64e041b5
rhg-annotate: support whitespace options
Mitchell Kember <mkember@janestreet.com>
parents:
52760
diff
changeset
|
306 pub enum CleanWhitespace { |
874c64e041b5
rhg-annotate: support whitespace options
Mitchell Kember <mkember@janestreet.com>
parents:
52760
diff
changeset
|
307 /// Do nothing. |
874c64e041b5
rhg-annotate: support whitespace options
Mitchell Kember <mkember@janestreet.com>
parents:
52760
diff
changeset
|
308 None, |
874c64e041b5
rhg-annotate: support whitespace options
Mitchell Kember <mkember@janestreet.com>
parents:
52760
diff
changeset
|
309 /// Remove whitespace at ends of lines. |
874c64e041b5
rhg-annotate: support whitespace options
Mitchell Kember <mkember@janestreet.com>
parents:
52760
diff
changeset
|
310 AtEol, |
874c64e041b5
rhg-annotate: support whitespace options
Mitchell Kember <mkember@janestreet.com>
parents:
52760
diff
changeset
|
311 /// Collapse consecutive whitespace characters into a single space. |
874c64e041b5
rhg-annotate: support whitespace options
Mitchell Kember <mkember@janestreet.com>
parents:
52760
diff
changeset
|
312 Collapse, |
874c64e041b5
rhg-annotate: support whitespace options
Mitchell Kember <mkember@janestreet.com>
parents:
52760
diff
changeset
|
313 /// Remove all whitespace characters. |
874c64e041b5
rhg-annotate: support whitespace options
Mitchell Kember <mkember@janestreet.com>
parents:
52760
diff
changeset
|
314 All, |
874c64e041b5
rhg-annotate: support whitespace options
Mitchell Kember <mkember@janestreet.com>
parents:
52760
diff
changeset
|
315 } |
874c64e041b5
rhg-annotate: support whitespace options
Mitchell Kember <mkember@janestreet.com>
parents:
52760
diff
changeset
|
316 |
874c64e041b5
rhg-annotate: support whitespace options
Mitchell Kember <mkember@janestreet.com>
parents:
52760
diff
changeset
|
317 /// Normalizes whitespace in text so that it won't apppear in diffs. |
874c64e041b5
rhg-annotate: support whitespace options
Mitchell Kember <mkember@janestreet.com>
parents:
52760
diff
changeset
|
318 /// Returns `Cow::Borrowed(text)` if the result is unchanged. |
874c64e041b5
rhg-annotate: support whitespace options
Mitchell Kember <mkember@janestreet.com>
parents:
52760
diff
changeset
|
319 pub fn clean_whitespace(text: &[u8], how: CleanWhitespace) -> Cow<[u8]> { |
874c64e041b5
rhg-annotate: support whitespace options
Mitchell Kember <mkember@janestreet.com>
parents:
52760
diff
changeset
|
320 lazy_static! { |
874c64e041b5
rhg-annotate: support whitespace options
Mitchell Kember <mkember@janestreet.com>
parents:
52760
diff
changeset
|
321 // To match wsclean in mdiff.py, this includes "\f". |
874c64e041b5
rhg-annotate: support whitespace options
Mitchell Kember <mkember@janestreet.com>
parents:
52760
diff
changeset
|
322 static ref AT_EOL: Regex = |
874c64e041b5
rhg-annotate: support whitespace options
Mitchell Kember <mkember@janestreet.com>
parents:
52760
diff
changeset
|
323 Regex::new(r"(?m)[ \t\r\f]+$").expect("valid regex"); |
874c64e041b5
rhg-annotate: support whitespace options
Mitchell Kember <mkember@janestreet.com>
parents:
52760
diff
changeset
|
324 // To match fixws in cext/bdiff.c, this does *not* include "\f". |
874c64e041b5
rhg-annotate: support whitespace options
Mitchell Kember <mkember@janestreet.com>
parents:
52760
diff
changeset
|
325 static ref MULTIPLE: Regex = |
874c64e041b5
rhg-annotate: support whitespace options
Mitchell Kember <mkember@janestreet.com>
parents:
52760
diff
changeset
|
326 Regex::new(r"[ \t\r]+").expect("valid regex"); |
874c64e041b5
rhg-annotate: support whitespace options
Mitchell Kember <mkember@janestreet.com>
parents:
52760
diff
changeset
|
327 } |
874c64e041b5
rhg-annotate: support whitespace options
Mitchell Kember <mkember@janestreet.com>
parents:
52760
diff
changeset
|
328 let replacement: &[u8] = match how { |
874c64e041b5
rhg-annotate: support whitespace options
Mitchell Kember <mkember@janestreet.com>
parents:
52760
diff
changeset
|
329 CleanWhitespace::None => return Cow::Borrowed(text), |
874c64e041b5
rhg-annotate: support whitespace options
Mitchell Kember <mkember@janestreet.com>
parents:
52760
diff
changeset
|
330 CleanWhitespace::AtEol => return AT_EOL.replace_all(text, b""), |
874c64e041b5
rhg-annotate: support whitespace options
Mitchell Kember <mkember@janestreet.com>
parents:
52760
diff
changeset
|
331 CleanWhitespace::Collapse => b" ", |
874c64e041b5
rhg-annotate: support whitespace options
Mitchell Kember <mkember@janestreet.com>
parents:
52760
diff
changeset
|
332 CleanWhitespace::All => b"", |
874c64e041b5
rhg-annotate: support whitespace options
Mitchell Kember <mkember@janestreet.com>
parents:
52760
diff
changeset
|
333 }; |
874c64e041b5
rhg-annotate: support whitespace options
Mitchell Kember <mkember@janestreet.com>
parents:
52760
diff
changeset
|
334 let text = MULTIPLE.replace_all(text, replacement); |
874c64e041b5
rhg-annotate: support whitespace options
Mitchell Kember <mkember@janestreet.com>
parents:
52760
diff
changeset
|
335 replace_all_cow(&AT_EOL, text, b"") |
874c64e041b5
rhg-annotate: support whitespace options
Mitchell Kember <mkember@janestreet.com>
parents:
52760
diff
changeset
|
336 } |
874c64e041b5
rhg-annotate: support whitespace options
Mitchell Kember <mkember@janestreet.com>
parents:
52760
diff
changeset
|
337 |
874c64e041b5
rhg-annotate: support whitespace options
Mitchell Kember <mkember@janestreet.com>
parents:
52760
diff
changeset
|
338 /// Helper to call [`Regex::replace_all`] with `Cow` as input and output. |
874c64e041b5
rhg-annotate: support whitespace options
Mitchell Kember <mkember@janestreet.com>
parents:
52760
diff
changeset
|
339 fn replace_all_cow<'a>( |
874c64e041b5
rhg-annotate: support whitespace options
Mitchell Kember <mkember@janestreet.com>
parents:
52760
diff
changeset
|
340 regex: &Regex, |
874c64e041b5
rhg-annotate: support whitespace options
Mitchell Kember <mkember@janestreet.com>
parents:
52760
diff
changeset
|
341 haystack: Cow<'a, [u8]>, |
874c64e041b5
rhg-annotate: support whitespace options
Mitchell Kember <mkember@janestreet.com>
parents:
52760
diff
changeset
|
342 replacement: &[u8], |
874c64e041b5
rhg-annotate: support whitespace options
Mitchell Kember <mkember@janestreet.com>
parents:
52760
diff
changeset
|
343 ) -> Cow<'a, [u8]> { |
874c64e041b5
rhg-annotate: support whitespace options
Mitchell Kember <mkember@janestreet.com>
parents:
52760
diff
changeset
|
344 match haystack { |
874c64e041b5
rhg-annotate: support whitespace options
Mitchell Kember <mkember@janestreet.com>
parents:
52760
diff
changeset
|
345 Cow::Borrowed(haystack) => regex.replace_all(haystack, replacement), |
874c64e041b5
rhg-annotate: support whitespace options
Mitchell Kember <mkember@janestreet.com>
parents:
52760
diff
changeset
|
346 Cow::Owned(haystack) => { |
874c64e041b5
rhg-annotate: support whitespace options
Mitchell Kember <mkember@janestreet.com>
parents:
52760
diff
changeset
|
347 Cow::Owned(regex.replace_all(&haystack, replacement).into_owned()) |
874c64e041b5
rhg-annotate: support whitespace options
Mitchell Kember <mkember@janestreet.com>
parents:
52760
diff
changeset
|
348 } |
874c64e041b5
rhg-annotate: support whitespace options
Mitchell Kember <mkember@janestreet.com>
parents:
52760
diff
changeset
|
349 } |
874c64e041b5
rhg-annotate: support whitespace options
Mitchell Kember <mkember@janestreet.com>
parents:
52760
diff
changeset
|
350 } |
874c64e041b5
rhg-annotate: support whitespace options
Mitchell Kember <mkember@janestreet.com>
parents:
52760
diff
changeset
|
351 |
52759
36d39726c0af
rust: add utils::strings module
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
352 #[cfg(test)] |
36d39726c0af
rust: add utils::strings module
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
353 mod tests { |
36d39726c0af
rust: add utils::strings module
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
354 use super::*; |
36d39726c0af
rust: add utils::strings module
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
355 |
36d39726c0af
rust: add utils::strings module
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
356 #[test] |
52760
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
357 fn test_expand_vars() { |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
358 // Modifying process-global state in a test isn’t great, |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
359 // but hopefully this won’t collide with anything. |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
360 std::env::set_var("TEST_EXPAND_VAR", "1"); |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
361 assert_eq!( |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
362 expand_vars(b"before/$TEST_EXPAND_VAR/after"), |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
363 &b"before/1/after"[..] |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
364 ); |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
365 assert_eq!( |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
366 expand_vars(b"before${TEST_EXPAND_VAR}${TEST_EXPAND_VAR}${TEST_EXPAND_VAR}after"), |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
367 &b"before111after"[..] |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
368 ); |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
369 let s = b"before $SOME_LONG_NAME_THAT_WE_ASSUME_IS_NOT_AN_ACTUAL_ENV_VAR after"; |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
370 assert_eq!(expand_vars(s), &s[..]); |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
371 } |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
372 |
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52759
diff
changeset
|
373 #[test] |
52759
36d39726c0af
rust: add utils::strings module
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
374 fn test_short_user() { |
36d39726c0af
rust: add utils::strings module
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
375 assert_eq!(short_user(b""), b""); |
36d39726c0af
rust: add utils::strings module
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
376 assert_eq!(short_user(b"Name"), b"Name"); |
36d39726c0af
rust: add utils::strings module
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
377 assert_eq!(short_user(b"First Last"), b"First"); |
36d39726c0af
rust: add utils::strings module
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
378 assert_eq!(short_user(b"First Last <user@example.com>"), b"user"); |
36d39726c0af
rust: add utils::strings module
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
379 assert_eq!(short_user(b"First Last <user.name@example.com>"), b"user"); |
36d39726c0af
rust: add utils::strings module
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
380 } |
36d39726c0af
rust: add utils::strings module
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
381 } |