config/file/format/
mod.rs

1use std::error::Error;
2
3use crate::map::Map;
4use crate::{file::FileStoredFormat, value::Value, Format};
5
6#[cfg(feature = "toml")]
7mod toml;
8
9#[cfg(feature = "json")]
10mod json;
11
12#[cfg(feature = "yaml")]
13mod yaml;
14
15#[cfg(feature = "ini")]
16mod ini;
17
18#[cfg(feature = "ron")]
19mod ron;
20
21#[cfg(feature = "json5")]
22mod json5;
23
24/// File formats provided by the library.
25///
26/// Although it is possible to define custom formats using [`Format`] trait it is recommended to use `FileFormat` if possible.
27#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
28#[non_exhaustive]
29pub enum FileFormat {
30    /// TOML (parsed with toml)
31    #[cfg(feature = "toml")]
32    Toml,
33
34    /// JSON (parsed with `serde_json`)
35    #[cfg(feature = "json")]
36    Json,
37
38    /// YAML (parsed with `yaml_rust2`)
39    #[cfg(feature = "yaml")]
40    Yaml,
41
42    /// INI (parsed with `rust_ini`)
43    #[cfg(feature = "ini")]
44    Ini,
45
46    /// RON (parsed with ron)
47    #[cfg(feature = "ron")]
48    Ron,
49
50    /// JSON5 (parsed with json5)
51    #[cfg(feature = "json5")]
52    Json5,
53}
54
55impl FileFormat {
56    pub(crate) fn all() -> &'static [FileFormat] {
57        &[
58            #[cfg(feature = "toml")]
59            FileFormat::Toml,
60            #[cfg(feature = "json")]
61            FileFormat::Json,
62            #[cfg(feature = "yaml")]
63            FileFormat::Yaml,
64            #[cfg(feature = "ini")]
65            FileFormat::Ini,
66            #[cfg(feature = "ron")]
67            FileFormat::Ron,
68            #[cfg(feature = "json5")]
69            FileFormat::Json5,
70        ]
71    }
72
73    pub(crate) fn extensions(&self) -> &'static [&'static str] {
74        match self {
75            #[cfg(feature = "toml")]
76            FileFormat::Toml => &["toml"],
77
78            #[cfg(feature = "json")]
79            FileFormat::Json => &["json"],
80
81            #[cfg(feature = "yaml")]
82            FileFormat::Yaml => &["yaml", "yml"],
83
84            #[cfg(feature = "ini")]
85            FileFormat::Ini => &["ini"],
86
87            #[cfg(feature = "ron")]
88            FileFormat::Ron => &["ron"],
89
90            #[cfg(feature = "json5")]
91            FileFormat::Json5 => &["json5"],
92
93            #[cfg(all(
94                not(feature = "toml"),
95                not(feature = "json"),
96                not(feature = "yaml"),
97                not(feature = "ini"),
98                not(feature = "ron"),
99                not(feature = "json5"),
100            ))]
101            _ => unreachable!("No features are enabled, this library won't work without features"),
102        }
103    }
104
105    pub(crate) fn parse(
106        &self,
107        uri: Option<&String>,
108        text: &str,
109    ) -> Result<Map<String, Value>, Box<dyn Error + Send + Sync>> {
110        match self {
111            #[cfg(feature = "toml")]
112            FileFormat::Toml => toml::parse(uri, text),
113
114            #[cfg(feature = "json")]
115            FileFormat::Json => json::parse(uri, text),
116
117            #[cfg(feature = "yaml")]
118            FileFormat::Yaml => yaml::parse(uri, text),
119
120            #[cfg(feature = "ini")]
121            FileFormat::Ini => ini::parse(uri, text),
122
123            #[cfg(feature = "ron")]
124            FileFormat::Ron => ron::parse(uri, text),
125
126            #[cfg(feature = "json5")]
127            FileFormat::Json5 => json5::parse(uri, text),
128
129            #[cfg(all(
130                not(feature = "toml"),
131                not(feature = "json"),
132                not(feature = "yaml"),
133                not(feature = "ini"),
134                not(feature = "ron"),
135                not(feature = "json5"),
136            ))]
137            _ => unreachable!("No features are enabled, this library won't work without features"),
138        }
139    }
140}
141
142impl Format for FileFormat {
143    fn parse(
144        &self,
145        uri: Option<&String>,
146        text: &str,
147    ) -> Result<Map<String, Value>, Box<dyn Error + Send + Sync>> {
148        self.parse(uri, text)
149    }
150}
151
152impl FileStoredFormat for FileFormat {
153    fn file_extensions(&self) -> &'static [&'static str] {
154        self.extensions()
155    }
156}