Repository navigation
Expand file tree
/
Copy pathutils.rs
More file actions
104 lines (92 loc) · 3.55 KB
/
Copy pathutils.rs
File metadata and controls
104 lines (92 loc) · 3.55 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
use std::{
fmt::{self, Write as _},
str,
};
/// Display potentially non-UTF8 string in a lossy way, *without* allocating a new buffer to hold
/// the string.
pub fn display_utf8_lossy(input: &[u8]) -> impl fmt::Display + '_ {
struct StringDisplay<'a>(&'a [u8]);
impl fmt::Display for StringDisplay<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let mut input = self.0;
loop {
match str::from_utf8(input) {
Ok(valid) => {
f.write_str(valid)?;
break;
}
Err(error) => {
let (valid, after_valid) = input.split_at(error.valid_up_to());
f.write_str(str::from_utf8(valid).unwrap())?;
f.write_str("\u{FFFD}")?;
if let Some(invalid_sequence_length) = error.error_len() {
input = &after_valid[invalid_sequence_length..]
} else {
break;
}
}
}
}
Ok(())
}
}
StringDisplay(input)
}
/// Like [`display_utf8_lossy`], returns an `impl fmt::Debug` type that uses debug character escapes
/// and surrounds the string by '"' characters.
pub fn debug_utf8_lossy(input: &[u8]) -> impl fmt::Debug + '_ {
struct StringDebug<'a>(&'a [u8]);
impl fmt::Debug for StringDebug<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fn write_escape_str(f: &mut fmt::Formatter, s: &str) -> fmt::Result {
for c in s.chars() {
for c in c.escape_debug() {
f.write_char(c)?;
}
}
Ok(())
}
fn write_escape_bytes(f: &mut fmt::Formatter, s: &[u8]) -> fmt::Result {
fn to_hex_digit(b: u8) -> Option<char> {
if b < 10 {
char::from_u32('0' as u32 + b as u32)
} else if b < 16 {
char::from_u32('a' as u32 + (b as u32 - 10))
} else {
None
}
}
for b in s {
f.write_str("\\x")?;
f.write_char(to_hex_digit(b >> 4).unwrap())?;
f.write_char(to_hex_digit(b & 0xf).unwrap())?;
}
Ok(())
}
f.write_char('"')?;
let mut input = self.0;
loop {
match str::from_utf8(input) {
Ok(valid) => {
write_escape_str(f, valid)?;
break;
}
Err(error) => {
let (valid, after_valid) = input.split_at(error.valid_up_to());
write_escape_str(f, str::from_utf8(valid).unwrap())?;
if let Some(invalid_sequence_length) = error.error_len() {
write_escape_bytes(f, &after_valid[0..invalid_sequence_length])?;
input = &after_valid[invalid_sequence_length..];
} else {
write_escape_bytes(f, &after_valid[0..])?;
break;
}
}
}
}
f.write_char('"')?;
Ok(())
}
}
StringDebug(input)
}