jsrmx/
output.rs

1mod directory;
2mod file;
3mod stream;
4use directory::DirectoryOutput;
5use file::FileOutput;
6use stream::StreamOutput;
7
8use serde::Serialize;
9use serde_json::Value;
10use std::path::{Path, PathBuf};
11
12trait Writeable {
13    fn append<T: Serialize>(&self, content: T) -> std::io::Result<()>;
14    fn set_pretty(&mut self, pretty: bool);
15    fn write<T: Serialize>(&self, content: T) -> std::io::Result<()>;
16    fn write_entries(&self, entries: Vec<(String, Value)>) -> std::io::Result<()>;
17}
18
19#[derive(Clone, Debug)]
20pub enum Output {
21    Directory(DirectoryOutput),
22    File(FileOutput),
23    Stdout(StreamOutput),
24}
25
26impl Output {
27    pub fn append<T: Serialize>(&self, content: T) -> std::io::Result<()> {
28        match self {
29            Self::Directory(output) => output.append(content),
30            Self::File(output) => output.append(content),
31            Self::Stdout(output) => output.append(content),
32        }
33    }
34
35    pub fn write<T: Serialize>(&self, content: T) -> std::io::Result<()> {
36        match self {
37            Self::Directory(output) => output.write(content),
38            Self::File(output) => output.write(content),
39            Self::Stdout(output) => output.write(content),
40        }
41    }
42
43    pub fn set_pretty(&mut self) {
44        match self {
45            Self::Directory(output) => output.set_pretty(true),
46            Self::File(output) => output.set_pretty(true),
47            Self::Stdout(output) => output.set_pretty(true),
48        }
49    }
50
51    pub fn write_entries(&self, entries: Vec<(String, Value)>) -> std::io::Result<()> {
52        match self {
53            Self::Directory(output) => output.write_entries(entries),
54            Self::File(output) => output.write_entries(entries),
55            Self::Stdout(output) => output.write_entries(entries),
56        }
57    }
58}
59
60impl AsRef<Path> for Output {
61    fn as_ref(&self) -> &Path {
62        match self {
63            Output::Directory(output) => output.path.as_path(),
64            Output::File(output) => output.path.as_path(),
65            Output::Stdout(_) => Path::new("-"),
66        }
67    }
68}
69
70impl std::fmt::Display for Output {
71    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
72        match self {
73            Output::Directory(output) => write!(f, "{}", output.path.display()),
74            Output::File(output) => write!(f, "{}", output.path.display()),
75            Output::Stdout(_) => write!(f, "-"),
76        }
77    }
78}
79
80impl std::str::FromStr for Output {
81    type Err = String;
82
83    fn from_str(s: &str) -> Result<Self, Self::Err> {
84        if s == "-" {
85            return Ok(Output::Stdout(StreamOutput::new(false)));
86        }
87
88        let path = PathBuf::from(s);
89        if path.is_dir() {
90            Ok(Output::Directory(DirectoryOutput::new(path, false)))
91        } else if path.extension().is_none() {
92            Ok(Output::Directory(DirectoryOutput::new(path, false)))
93        } else if path.is_file() {
94            Ok(Output::File(FileOutput::new(path, false)))
95        } else {
96            log::info!("Creating file: {}", &path.display());
97            Ok(Output::File(FileOutput::new(path, false)))
98        }
99    }
100}