lib_humus_configuration/
format.rs

1// SPDX-FileCopyrightText: 2025 Slatian
2//
3// SPDX-License-Identifier: LGPL-3.0-or-later
4
5use serde::{Deserialize, Serialize};
6
7use std::fmt;
8use std::fmt::Display;
9use std::path::Path;
10
11/// Enumerates supported configuration formats.
12///
13/// **⚠️ Warning:** Available variants depend on the enabled feature flags, don't do exhaustive matching on them in libraries.
14#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
15#[serde(rename_all = "snake_case")]
16pub enum ConfigFormat {
17	/// JSON
18	///
19	/// Detected via the `.json` file extension.
20	#[cfg(feature="json")]
21	Json,
22
23	/// [JSON5](https://json5.org/)
24	///
25	/// Detected via the `.json5` file extension.
26	#[cfg(feature="json5")]
27	Json5,
28
29	/// [TOML](https://toml.io/)
30	///
31	/// Detected via the `.toml` file extension.
32	#[cfg(feature="toml")]
33	Toml,
34}
35
36impl ConfigFormat {
37	/// From a given path this guesses the appropriate format based on the file extension
38	pub fn guess_from_path(path: impl AsRef<Path>) -> Option<Self> {
39		match path.as_ref().extension()?.to_str()? {
40			#[cfg(feature="json")]
41			"json" => Some(Self::Json),
42			#[cfg(feature="json5")]
43			"json5" => Some(Self::Json5),
44			#[cfg(feature="toml")]
45			"toml" => Some(Self::Toml),
46			_ => None,
47		}
48	}
49}
50
51impl Display for ConfigFormat {
52	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
53		match self {
54			#[cfg(feature="json")]
55			Self::Json => f.write_str("json"),
56			#[cfg(feature="json5")]
57			Self::Json5 => f.write_str("json5"),
58			#[cfg(feature="toml")]
59			Self::Toml => f.write_str("toml"),
60		}
61	}
62}
63
64#[cfg(all(test, feature="json"))]
65#[test]
66fn test_path_format_guessing_json() {
67	assert_eq!(
68		ConfigFormat::guess_from_path("test-data/test.json"),
69		Some(ConfigFormat::Json)
70	);
71	assert_eq!(
72		ConfigFormat::guess_from_path("test-data/.test.json"),
73		Some(ConfigFormat::Json)
74	);
75	assert_eq!(
76		ConfigFormat::guess_from_path("test-data/.test.foo.json"),
77		Some(ConfigFormat::Json)
78	);
79}
80
81#[cfg(all(test, feature="json5"))]
82#[test]
83fn test_path_format_guessing_json5() {
84	assert_eq!(
85		ConfigFormat::guess_from_path("test-data/test.json5"),
86		Some(ConfigFormat::Json5)
87	);
88}
89
90#[cfg(all(test, feature="toml"))]
91#[test]
92fn test_path_format_guessing_toml() {
93	assert_eq!(
94		ConfigFormat::guess_from_path("test-data/test.toml"),
95		Some(ConfigFormat::Toml)
96	);
97}
98
99#[cfg(test)]
100#[test]
101fn test_path_format_guessing_none() {
102	assert_eq!(ConfigFormat::guess_from_path("test-data/test.txt"), None);
103	assert_eq!(ConfigFormat::guess_from_path("test-data/test"), None);
104	assert_eq!(ConfigFormat::guess_from_path("test-data/"), None);
105}