diff --git a/serde/build.rs b/serde/build.rs index e36ed62f5..a78b6d79a 100644 --- a/serde/build.rs +++ b/serde/build.rs @@ -29,8 +29,9 @@ fn main() { println!("cargo:rustc-cfg=core_reverse"); } - // CString::into_boxed_c_str stabilized in Rust 1.20: + // CString::into_boxed_c_str and PathBuf::into_boxed_path stabilized in Rust 1.20: // https://doc.rust-lang.org/std/ffi/struct.CString.html#method.into_boxed_c_str + // https://doc.rust-lang.org/std/path/struct.PathBuf.html#method.into_boxed_path if minor >= 20 { println!("cargo:rustc-cfg=de_boxed_c_str"); } diff --git a/serde/src/de/impls.rs b/serde/src/de/impls.rs index e96314809..cffe05900 100644 --- a/serde/src/de/impls.rs +++ b/serde/src/de/impls.rs @@ -1580,6 +1580,24 @@ impl<'de> Visitor<'de> for PathBufVisitor { { Ok(From::from(v)) } + + fn visit_bytes(self, v: &[u8]) -> Result + where + E: Error, + { + str::from_utf8(v) + .map(From::from) + .map_err(|_| Error::invalid_value(Unexpected::Bytes(v), &self)) + } + + fn visit_byte_buf(self, v: Vec) -> Result + where + E: Error, + { + String::from_utf8(v) + .map(From::from) + .map_err(|e| Error::invalid_value(Unexpected::Bytes(&e.into_bytes()), &self)) + } } #[cfg(feature = "std")] @@ -1592,6 +1610,9 @@ impl<'de> Deserialize<'de> for PathBuf { } } +#[cfg(all(feature = "std", de_boxed_c_str))] +forwarded_impl!((), Box, PathBuf::into_boxed_path); + //////////////////////////////////////////////////////////////////////////////// // If this were outside of the serde crate, it would just use: diff --git a/test_suite/tests/test_de.rs b/test_suite/tests/test_de.rs index 16628efd6..025d87b09 100644 --- a/test_suite/tests/test_de.rs +++ b/test_suite/tests/test_de.rs @@ -889,11 +889,37 @@ declare_tests! { Path::new("/usr/local/lib") => &[ Token::BorrowedStr("/usr/local/lib"), ], + Path::new("/usr/local/lib") => &[ + Token::BorrowedBytes(b"/usr/local/lib"), + ], } test_path_buf { PathBuf::from("/usr/local/lib") => &[ + Token::Str("/usr/local/lib"), + ], + PathBuf::from("/usr/local/lib") => &[ + Token::String("/usr/local/lib"), + ], + PathBuf::from("/usr/local/lib") => &[ + Token::Bytes(b"/usr/local/lib"), + ], + PathBuf::from("/usr/local/lib") => &[ + Token::ByteBuf(b"/usr/local/lib"), + ], + } + test_boxed_path { + PathBuf::from("/usr/local/lib").into_boxed_path() => &[ + Token::Str("/usr/local/lib"), + ], + PathBuf::from("/usr/local/lib").into_boxed_path() => &[ Token::String("/usr/local/lib"), ], + PathBuf::from("/usr/local/lib").into_boxed_path() => &[ + Token::Bytes(b"/usr/local/lib"), + ], + PathBuf::from("/usr/local/lib").into_boxed_path() => &[ + Token::ByteBuf(b"/usr/local/lib"), + ], } test_cstring { CString::new("abc").unwrap() => &[