diff --git a/serde/src/de/impls.rs b/serde/src/de/impls.rs index 783eb562..13f5c996 100644 --- a/serde/src/de/impls.rs +++ b/serde/src/de/impls.rs @@ -897,6 +897,44 @@ parse_impl!(net::SocketAddrV6); //////////////////////////////////////////////////////////////////////////////// +#[cfg(feature = "std")] +struct PathVisitor; + +#[cfg(feature = "std")] +impl<'a> Visitor<'a> for PathVisitor { + type Value = &'a Path; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("a borrowed path") + } + + fn visit_borrowed_str(self, v: &'a str) -> Result + where + E: Error, + { + Ok(v.as_ref()) + } + + fn visit_borrowed_bytes(self, v: &'a [u8]) -> Result + where + E: Error, + { + str::from_utf8(v) + .map(AsRef::as_ref) + .map_err(|_| Error::invalid_value(Unexpected::Bytes(v), &self)) + } +} + +#[cfg(feature = "std")] +impl<'de: 'a, 'a> Deserialize<'de> for &'a Path { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + deserializer.deserialize_str(PathVisitor) + } +} + #[cfg(feature = "std")] struct PathBufVisitor; diff --git a/test_suite/tests/test_de.rs b/test_suite/tests/test_de.rs index c5ab4baa..d1bddfaf 100644 --- a/test_suite/tests/test_de.rs +++ b/test_suite/tests/test_de.rs @@ -13,7 +13,7 @@ extern crate serde_derive; use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet}; use std::net; -use std::path::PathBuf; +use std::path::{Path, PathBuf}; use std::time::Duration; use std::default::Default; use std::ffi::{CString, OsString}; @@ -710,6 +710,11 @@ declare_tests! { "1.2.3.4:1234".parse::().unwrap() => &[Token::Str("1.2.3.4:1234")], "[::1]:1234".parse::().unwrap() => &[Token::Str("[::1]:1234")], } + test_path { + Path::new("/usr/local/lib") => &[ + Token::BorrowedStr("/usr/local/lib"), + ], + } test_path_buf { PathBuf::from("/usr/local/lib") => &[ Token::String("/usr/local/lib"),