evobench_tools/serde_types/
tilde_path.rs

1use std::{
2    path::{Path, PathBuf},
3    str::FromStr,
4};
5
6use anyhow::Result;
7use serde::de::Visitor;
8
9use crate::utillib::path_resolve_home::path_resolve_home;
10
11/// Accept paths starting with `~/` to mean going from the user's home
12/// directory. Does not currently support `~user/`.
13#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Hash)]
14pub struct TildePath<P: AsRef<Path>>(P);
15
16impl<P: AsRef<Path>> TildePath<P> {
17    /// Change paths starting with `~/` to replace the `~` with the user's
18    /// home directory. XX Careful: if path is not representable as unicode
19    /// string, no expansion is attempted!
20    pub fn resolve(&self) -> Result<PathBuf> {
21        path_resolve_home(self.0.as_ref())
22    }
23}
24
25impl FromStr for TildePath<PathBuf> {
26    type Err = core::convert::Infallible;
27
28    fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
29        Ok(Self(PathBuf::from_str(s)?))
30    }
31}
32
33struct OurVisitor;
34impl<'de> Visitor<'de> for OurVisitor {
35    type Value = TildePath<PathBuf>;
36
37    fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
38        formatter.write_str("anything, this is infallible")
39    }
40
41    fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
42    where
43        E: serde::de::Error,
44    {
45        v.parse().map_err(E::custom)
46    }
47}
48
49impl<'de> serde::Deserialize<'de> for TildePath<PathBuf> {
50    fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
51        deserializer.deserialize_str(OurVisitor)
52    }
53}
54
55impl serde::Serialize for TildePath<PathBuf> {
56    fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
57    where
58        S: serde::Serializer,
59    {
60        if let Some(s) = self.0.to_str() {
61            serializer.serialize_str(s)
62        } else {
63            Err(serde::ser::Error::custom("path contains invalid UTF-8"))
64        }
65    }
66}