Skip to main content

pistonite_cu/parse/
yaml_impl.rs

1/// `serde` YAML integration via the `serde_yaml_ng` crate
2///
3/// Since `serde` derives requires linking with `serde` crate,
4/// you have to add it to your `Cargo.toml`:
5/// ```toml
6/// [dependencies]
7/// serde = "1"
8/// ```
9///
10/// ```rust
11/// # use pistonite_cu as cu;
12/// use cu::pre::*; // with `serde` feature, Serialize and Deserialize are
13///                 // part of the prelude
14///
15/// #[derive(Debug, PartialEq, Serialize, Deserialize)]
16/// struct FooBar {
17///     foo: String,
18/// }
19///
20/// # fn main() -> cu::Result<()> {
21/// // the yaml module will also be part of the prelude
22///
23/// let value: FooBar = yaml::parse(r#"foo: bar"#)?;
24/// assert_eq!(value.foo, "bar");
25///
26/// # Ok(()) }
27/// ```
28///
29pub mod yaml {
30    use crate::{Context, Parse};
31    use serde::{Deserialize, Serialize};
32    pub use serde_yaml_ng::{Mapping as Map, Number, Sequence as Vec, Value};
33
34    /// YAML parse delegate. See [`yaml`](module@crate::yaml)
35    pub struct Yaml<T>(std::marker::PhantomData<T>);
36    impl<T: for<'a> Deserialize<'a>> Parse for Yaml<T> {
37        type Output = T;
38
39        fn parse_borrowed(x: &str) -> crate::Result<Self::Output> {
40            parse(x)
41        }
42
43        fn parse_read(x: impl std::io::Read) -> crate::Result<Self::Output> {
44            serde_yaml_ng::from_reader(x).with_context(|| {
45                format!(
46                    "failed to parse input as yaml into {}",
47                    std::any::type_name::<T>()
48                )
49            })
50        }
51    }
52
53    /// Parse value from a YAML `&str`
54    #[inline(always)]
55    pub fn parse<'a, T: Deserialize<'a>>(x: &'a str) -> crate::Result<T> {
56        serde_yaml_ng::from_str(x).with_context(|| {
57            format!(
58                "failed to parse input as yaml into {}",
59                std::any::type_name::<T>()
60            )
61        })
62    }
63
64    /// Parse value from a reader that yields YAML
65    #[inline(always)]
66    pub fn read<T: for<'a> Deserialize<'a>>(x: impl std::io::Read) -> crate::Result<T> {
67        Yaml::<T>::parse_read(x)
68    }
69
70    /// Parse value from an async reader that yields YAML
71    #[cfg(feature = "coroutine")]
72    pub async fn co_read<T: for<'a> Deserialize<'a>>(
73        x: impl tokio::io::AsyncRead + Unpin,
74    ) -> crate::Result<T> {
75        crate::co_read::<Yaml<T>>(x).await
76    }
77
78    /// Convert a YAML value into T
79    pub fn from_value<T: for<'a> Deserialize<'a>>(x: Value) -> crate::Result<T> {
80        use crate::Context;
81        crate::check!(
82            serde_yaml_ng::from_value(x),
83            "failed to convert yaml value to {}",
84            std::any::type_name::<T>()
85        )
86    }
87
88    /// Convert a T into a YAML value
89    pub fn to_value<T: ?Sized + Serialize>(x: &T) -> crate::Result<Value> {
90        use crate::Context;
91        crate::check!(
92            serde_yaml_ng::to_value(x),
93            "failed to convert {} to yaml value",
94            std::any::type_name::<T>()
95        )
96    }
97
98    /// Convert the value to a YAML string
99    pub fn stringify<T: serde::Serialize>(x: &T) -> crate::Result<String> {
100        use crate::Context;
101        crate::check!(
102            serde_yaml_ng::to_string(x),
103            "failed to serialize {} to yaml",
104            std::any::type_name::<T>()
105        )
106    }
107
108    /// Serialize the value into YAML and write into the writer
109    pub fn write<T: ?Sized + Serialize>(w: impl std::io::Write, x: &T) -> crate::Result<()> {
110        use crate::Context;
111        crate::check!(
112            serde_yaml_ng::to_writer(w, x),
113            "failed to write serialized {} as yaml",
114            std::any::type_name::<T>()
115        )
116    }
117}