1use std::path::Path;
9use std::sync::Arc;
10
11use crate::JsonCodec;
12#[cfg(feature = "toml")]
13use crate::TomlCodec;
14use crate::YamlCodec;
15use crate::codec::Codec;
16
17#[must_use]
20pub fn codec_for_name(name: &str) -> Option<Arc<dyn Codec>> {
21 match name.to_ascii_lowercase().as_str() {
22 #[cfg(feature = "toml")]
23 "toml" => Some(Arc::new(TomlCodec)),
24 "json" => Some(Arc::new(JsonCodec::default())),
25 "yaml" | "yml" => Some(Arc::new(YamlCodec)),
26 _ => None,
27 }
28}
29
30#[must_use]
32pub fn codec_for_path(path: &Path) -> Option<Arc<dyn Codec>> {
33 let ext = path.extension().and_then(|ext| ext.to_str())?;
34 codec_for_name(ext)
35}
36
37#[cfg(test)]
38mod tests {
39 use super::*;
40
41 #[test]
42 fn selects_json_by_name_and_path() {
43 assert_eq!(codec_for_name("json").unwrap().name(), "json");
44 assert_eq!(codec_for_name("JSON").unwrap().name(), "json");
45 assert_eq!(
46 codec_for_path(Path::new("/etc/app/config.json"))
47 .unwrap()
48 .name(),
49 "json"
50 );
51 }
52
53 #[cfg(feature = "toml")]
54 #[test]
55 fn selects_toml_by_name_and_path() {
56 assert_eq!(codec_for_name("toml").unwrap().name(), "toml");
57 assert_eq!(
58 codec_for_path(Path::new("config.toml")).unwrap().name(),
59 "toml"
60 );
61 }
62
63 #[test]
64 fn selects_yaml_by_name_and_path() {
65 assert_eq!(codec_for_name("yaml").unwrap().name(), "yaml");
66 assert_eq!(codec_for_name("yml").unwrap().name(), "yaml");
67 assert_eq!(
68 codec_for_path(Path::new("config.yaml")).unwrap().name(),
69 "yaml"
70 );
71 assert_eq!(
72 codec_for_path(Path::new("config.yml")).unwrap().name(),
73 "yaml"
74 );
75 }
76
77 #[test]
78 fn returns_none_for_unknown_or_missing_extension() {
79 assert!(codec_for_name("ini").is_none());
80 assert!(codec_for_path(Path::new("config")).is_none());
81 }
82}