git_policy_cli/js_text.rs
1//! What:
2//! Text operations with the exact semantics of the JavaScript built-ins the incumbent
3//! applies to strings it shares with the native wrapper.
4//! Why:
5//! Durable strings such as process birth identities are produced by `.trim()` in the
6//! incumbent;
7//! the native wrapper must produce byte-identical strings,
8//! and Rust's
9//! `str::trim` uses a different whitespace set (it trims U+0085 and keeps U+FEFF).
10//!
11//! In TS you'd write (pseudocode):
12//! ```ts
13//! text.trim()
14//! ```
15
16/// What:
17/// Whether a character is whitespace or a line terminator to ECMAScript `trim`.
18/// `char` is one Unicode scalar value.
19/// Why:
20/// ECMA-262 `TrimString` removes `WhiteSpace` (tab,
21/// vertical tab,
22/// form feed,
23/// space,
24/// no-break space,
25/// U+FEFF and every `Zs` character) and `LineTerminator` (LF,
26/// CR,
27/// U+2028,
28/// U+2029);
29/// nothing else.
30///
31/// In TS you'd write (pseudocode):
32/// ```ts
33/// /^\s$/u.test(character) // JavaScript's \s is exactly this set
34/// ```
35pub fn is_javascript_whitespace(character: char) -> bool {
36 // The `Zs` block U+2000 to U+200A is a range; every other member is listed.
37 if ('\u{2000}'..='\u{200a}').contains(&character) {
38 return true;
39 }
40 // `matches!` tests a value against a pattern of alternatives.
41 return matches!(
42 character,
43 '\u{0009}'
44 | '\u{000a}'
45 | '\u{000b}'
46 | '\u{000c}'
47 | '\u{000d}'
48 | '\u{0020}'
49 | '\u{00a0}'
50 | '\u{1680}'
51 | '\u{2028}'
52 | '\u{2029}'
53 | '\u{202f}'
54 | '\u{205f}'
55 | '\u{3000}'
56 | '\u{feff}'
57 );
58}
59
60/// What:
61/// Remove leading and trailing JavaScript whitespace,
62/// as `String.prototype.trim`.
63/// `&str` borrows text;
64/// the result borrows a slice of it.
65/// Why:
66/// Shared strings must be trimmed exactly as the incumbent trims them.
67///
68/// In TS you'd write (pseudocode):
69/// ```ts
70/// function trimJavascript(text: string): string { return text.trim(); }
71/// ```
72pub fn trim_javascript(text: &str) -> &str {
73 return text.trim_matches(is_javascript_whitespace);
74}
75
76/// What:
77/// Remove trailing JavaScript whitespace,
78/// as `String.prototype.trimEnd`.
79/// `&str` borrows text;
80/// the result borrows a slice of it.
81/// Why:
82/// Git's PID file text is trimmed at the end only before its `pid ` prefix is read.
83///
84/// In TS you'd write (pseudocode):
85/// ```ts
86/// function trimJavascriptEnd(text: string): string { return text.trimEnd(); }
87/// ```
88pub fn trim_javascript_end(text: &str) -> &str {
89 return text.trim_end_matches(is_javascript_whitespace);
90}
91
92/// The whitespace table stays out of the release executable.
93#[cfg(test)]
94#[path = "js_text_tests.rs"]
95mod tests;