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
#[derive(Debug)]
#[repr(transparent)]
pub struct Path(std::path::PathBuf);
use serde::{Serialize, Serializer};
impl Serialize for Path {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
match self.0.to_str() {
Some(path) => serializer.serialize_str(path),
None => {
log::warn!("path contains invalid UTF-8 characters : {:?}", self.0);
serializer.serialize_str(&grep_cli::escape_os(self.0.as_ref()))
}
}
}
}
impl<T> From<T> for Path
where
T: Into<std::path::PathBuf>,
{
fn from(path: T) -> Self {
Self(path.into())
}
}
impl AsRef<std::path::Path> for Path {
fn as_ref(&self) -> &std::path::Path {
&self.0
}
}
#[cfg(test)]
mod tests {
#[cfg(unix)]
#[test]
fn shouldnt_panic_on_invalid_utf8_path() {
use super::*;
use std::ffi::OsString;
use std::os::unix::ffi::OsStringExt;
use std::path::PathBuf;
let invalid_utf8: &[u8] = b"\xe7\xe7";
assert!(String::from_utf8(invalid_utf8.to_vec()).is_err());
let path = PathBuf::from(OsString::from_vec(invalid_utf8.to_vec()));
assert!(serde_json::to_string(&path).is_err());
let path = Path(PathBuf::from(OsString::from_vec(invalid_utf8.to_vec())));
assert!(serde_json::to_string(&path).is_ok());
}
}