plugx_config/parser/yaml.rs
1//! YAML configuration parser.
2//!
3//! This is only usable if you enabled `yaml` Cargo feature.
4//!
5//! ### Example
6//! ```rust
7//! use plugx_config::parser::{Parser, yaml::Yaml};
8//! use plugx_input::Input;
9//!
10//! let bytes = br#"
11//! hello:
12//! - "w"
13//! - "o"
14//! - "l"
15//! - "d"
16//! foo:
17//! bar:
18//! baz: Qux
19//! abc: 3.14
20//! xyz: false
21//! "#;
22//!
23//! let parser = Yaml::new();
24//! // You can set nested key separator like this:
25//! // parser.set_key_separator("__");
26//! let parsed: Input = parser.try_parse(bytes.as_slice()).unwrap();
27//! assert!(
28//! parsed.as_map().len() == 2 &&
29//! parsed.as_map().contains_key("foo") &&
30//! parsed.as_map().contains_key("hello")
31//! );
32//! let foo = parsed.as_map().get("foo").unwrap();
33//! assert!(
34//! foo.as_map().len() == 2 &&
35//! foo.as_map().contains_key("bar") &&
36//! foo.as_map().contains_key("xyz")
37//! );
38//! let bar = foo.as_map().get("bar").unwrap();
39//! assert_eq!(bar.as_map().get("baz").unwrap(), &"Qux".into());
40//! assert_eq!(bar.as_map().get("abc").unwrap(), &3.14.into());
41//! let xyz = foo.as_map().get("xyz").unwrap();
42//! assert_eq!(xyz, &false.into());
43//! let list = ["w", "o", "l", "d"].into();
44//! assert_eq!(parsed.as_map().get("hello").unwrap(), &list);
45//! ```
46//!
47
48use crate::parser::Parser;
49use anyhow::anyhow;
50use cfg_if::cfg_if;
51use plugx_input::Input;
52use std::fmt::{Debug, Display, Formatter};
53
54#[derive(Default, Debug, Copy, Clone)]
55pub struct Yaml;
56
57impl Display for Yaml {
58 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
59 f.write_str("YAML")
60 }
61}
62
63impl Yaml {
64 pub fn new() -> Self {
65 Default::default()
66 }
67}
68
69impl Parser for Yaml {
70 fn supported_format_list(&self) -> Vec<String> {
71 ["yml".into(), "yaml".into()].into()
72 }
73
74 fn try_parse(&self, bytes: &[u8]) -> anyhow::Result<Input> {
75 serde_yaml::from_slice(bytes)
76 .map(|parsed: Input| {
77 cfg_if! {
78 if #[cfg(feature = "tracing")] {
79 tracing::trace!(
80 input=String::from_utf8_lossy(bytes).to_string(),
81 output=%parsed,
82 "Parsed YAML contents"
83 );
84 } else if #[cfg(feature = "logging")] {
85 log::trace!(
86 "msg=\"Parsed YAML contents\" input={:?} output={:?}",
87 String::from_utf8_lossy(bytes).to_string(),
88 parsed.to_string()
89 );
90 }
91 }
92 parsed
93 })
94 .map_err(|error| anyhow!(error))
95 }
96
97 fn is_format_supported(&self, bytes: &[u8]) -> Option<bool> {
98 Some(serde_yaml::from_slice::<serde_yaml::Value>(bytes).is_ok())
99 }
100}