dts_core/
sink.rs

1use crate::{Encoding, PathExt, Result};
2use std::fmt;
3use std::path::{Path, PathBuf};
4use std::str::FromStr;
5
6/// A target to write serialized output to.
7#[derive(Debug, Clone, PartialEq)]
8pub enum Sink {
9    /// Stdout sink.
10    Stdout,
11    /// Local path sink.
12    Path(PathBuf),
13}
14
15impl Sink {
16    /// Tries to detect the encoding of the sink. Returns `None` if the encoding cannot be
17    /// detected.
18    pub fn encoding(&self) -> Option<Encoding> {
19        match self {
20            Self::Stdout => None,
21            Self::Path(path) => Encoding::from_path(path),
22        }
23    }
24}
25
26impl From<&str> for Sink {
27    fn from(s: &str) -> Self {
28        if s == "-" {
29            Self::Stdout
30        } else {
31            Self::Path(PathBuf::from(s))
32        }
33    }
34}
35
36impl From<&Path> for Sink {
37    fn from(path: &Path) -> Self {
38        Self::Path(path.to_path_buf())
39    }
40}
41
42impl FromStr for Sink {
43    type Err = std::convert::Infallible;
44
45    fn from_str(s: &str) -> Result<Self, Self::Err> {
46        Ok(From::from(s))
47    }
48}
49
50impl fmt::Display for Sink {
51    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
52        match self {
53            Self::Stdout => write!(f, "<stdout>"),
54            Self::Path(path) => path
55                .relative_to_cwd()
56                .unwrap_or_else(|| path.clone())
57                .display()
58                .fmt(f),
59        }
60    }
61}
62
63#[cfg(test)]
64mod test {
65    use super::*;
66    use pretty_assertions::assert_eq;
67
68    #[test]
69    fn test_from_str() {
70        assert_eq!(Sink::from_str("-"), Ok(Sink::Stdout));
71        assert_eq!(
72            Sink::from_str("foo.json"),
73            Ok(Sink::Path(PathBuf::from("foo.json")))
74        );
75    }
76
77    #[test]
78    fn test_encoding() {
79        assert_eq!(Sink::from("-").encoding(), None);
80        assert_eq!(Sink::from("foo").encoding(), None);
81        assert_eq!(Sink::from("foo.json").encoding(), Some(Encoding::Json));
82    }
83
84    #[test]
85    fn test_to_string() {
86        assert_eq!(&Sink::Stdout.to_string(), "<stdout>");
87        assert_eq!(&Sink::from("Cargo.toml").to_string(), "Cargo.toml");
88        assert_eq!(
89            &Sink::from(std::fs::canonicalize("src/lib.rs").unwrap().as_path()).to_string(),
90            "src/lib.rs"
91        );
92        assert_eq!(
93            &Sink::from("/non-existent/path").to_string(),
94            "/non-existent/path"
95        );
96    }
97}