Closed woodruffw closed 2 years ago
Oh, and for reference, here's how I've implemented these in the past (open to feedback):
#[doc(hidden)]
#[inline]
fn deserialize_with_tilde<'de, D>(deserializer: D) -> std::result::Result<String, D::Error>
where
D: de::Deserializer<'de>,
{
let unexpanded: &str = Deserialize::deserialize(deserializer)?;
Ok(shellexpand::tilde(unexpanded).into_owned())
}
#[doc(hidden)]
#[inline]
fn deserialize_optional_with_tilde<'de, D>(
deserializer: D,
) -> std::result::Result<Option<String>, D::Error>
where
D: de::Deserializer<'de>,
{
let unexpanded: Option<&str> = Deserialize::deserialize(deserializer)?;
match unexpanded {
Some(unexpanded) => Ok(Some(shellexpand::tilde(unexpanded).into_owned())),
None => Ok(None),
}
}
First, forgive me for replying so late. Thanks for the kind words about the crate!
Regarding your suggestion, here are some of my thoughts:
shellexpand
crate isn't useful in my humble opinion. It just does nothing except for expanding in a string, it doesn't even use the PathBuf
or Path
and one will have to convert to it. Paths in strings in rust on their own are useless, one will always have to convert from a string into one of these types.Path
or PathBuf
would have been much more useful in my opinion.PathBuf
and Path
which, besides just parsing a path string, also canonicalizes the path or does more useful things before that.I am sorry to disappoint! Let me know if you still think it is useful to have here.
And about your solution, yes, it is just the way I'd do the same.
Thanks for the detailed response! That's very fair; I don't think this is worth a PR in light of the feedback, so I'll close this tracking issue.
First of all, thanks for this library! It's very neat, and I think it's a great idea to collect Serde "recipes" like this.
Here are two more I propose:
deserialize_with_tilde
: Return aResult<String>
, where theOk(_)
value is a string with the leading~
replaced with the current user's$HOME
directory.deserialize_optional_with_tilde
: The same as above, butResult<Option<String>>
to allow forOption<String>
as the input type.The behavior here would come from the shellexpand crate, which only substitutes
~
if it's the first character in the string and the string is in "path" form, not "symbolic user" form (i.e.~/foo/
, not~user/foo
).The main application of these is places where Serde is used to load from a config file: users generally prefer to specify paths with
~
rather than their home directory spelled out, and this would save a separate transform after deserialization.Let me know what you think!