config/file/format/
mod.rs1use std::collections::HashMap;
2use std::error::Error;
3use std::sync::OnceLock;
4
5use crate::map::Map;
6use crate::{file::FileStoredFormat, value::Value, Format};
7
8#[cfg(feature = "toml")]
9mod toml;
10
11#[cfg(feature = "json")]
12mod json;
13
14#[cfg(feature = "yaml")]
15mod yaml;
16
17#[cfg(feature = "ini")]
18mod ini;
19
20#[cfg(feature = "ron")]
21mod ron;
22
23#[cfg(feature = "json5")]
24mod json5;
25
26#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
30#[non_exhaustive]
31pub enum FileFormat {
32 #[cfg(feature = "toml")]
34 Toml,
35
36 #[cfg(feature = "json")]
38 Json,
39
40 #[cfg(feature = "yaml")]
42 Yaml,
43
44 #[cfg(feature = "ini")]
46 Ini,
47
48 #[cfg(feature = "ron")]
50 Ron,
51
52 #[cfg(feature = "json5")]
54 Json5,
55}
56
57pub(crate) fn all_extensions() -> &'static HashMap<FileFormat, Vec<&'static str>> {
58 #![allow(unused_mut)] static ALL_EXTENSIONS: OnceLock<HashMap<FileFormat, Vec<&'static str>>> = OnceLock::new();
61 ALL_EXTENSIONS.get_or_init(|| {
62 let mut formats: HashMap<FileFormat, Vec<_>> = HashMap::new();
63
64 #[cfg(feature = "toml")]
65 formats.insert(FileFormat::Toml, vec!["toml"]);
66
67 #[cfg(feature = "json")]
68 formats.insert(FileFormat::Json, vec!["json"]);
69
70 #[cfg(feature = "yaml")]
71 formats.insert(FileFormat::Yaml, vec!["yaml", "yml"]);
72
73 #[cfg(feature = "ini")]
74 formats.insert(FileFormat::Ini, vec!["ini"]);
75
76 #[cfg(feature = "ron")]
77 formats.insert(FileFormat::Ron, vec!["ron"]);
78
79 #[cfg(feature = "json5")]
80 formats.insert(FileFormat::Json5, vec!["json5"]);
81
82 formats
83 })
84}
85
86impl FileFormat {
87 pub(crate) fn extensions(&self) -> &'static [&'static str] {
88 all_extensions().get(self).unwrap()
92 }
93
94 pub(crate) fn parse(
95 &self,
96 uri: Option<&String>,
97 text: &str,
98 ) -> Result<Map<String, Value>, Box<dyn Error + Send + Sync>> {
99 match self {
100 #[cfg(feature = "toml")]
101 FileFormat::Toml => toml::parse(uri, text),
102
103 #[cfg(feature = "json")]
104 FileFormat::Json => json::parse(uri, text),
105
106 #[cfg(feature = "yaml")]
107 FileFormat::Yaml => yaml::parse(uri, text),
108
109 #[cfg(feature = "ini")]
110 FileFormat::Ini => ini::parse(uri, text),
111
112 #[cfg(feature = "ron")]
113 FileFormat::Ron => ron::parse(uri, text),
114
115 #[cfg(feature = "json5")]
116 FileFormat::Json5 => json5::parse(uri, text),
117
118 #[cfg(all(
119 not(feature = "toml"),
120 not(feature = "json"),
121 not(feature = "yaml"),
122 not(feature = "ini"),
123 not(feature = "ron"),
124 not(feature = "json5"),
125 ))]
126 _ => unreachable!("No features are enabled, this library won't work without features"),
127 }
128 }
129}
130
131impl Format for FileFormat {
132 fn parse(
133 &self,
134 uri: Option<&String>,
135 text: &str,
136 ) -> Result<Map<String, Value>, Box<dyn Error + Send + Sync>> {
137 self.parse(uri, text)
138 }
139}
140
141impl FileStoredFormat for FileFormat {
142 fn file_extensions(&self) -> &'static [&'static str] {
143 self.extensions()
144 }
145}