yaml_spanned/
lib.rs

1#[cfg(feature = "serde")]
2pub mod de;
3pub mod error;
4pub mod fmt;
5pub mod from;
6pub mod index;
7pub mod mapping;
8pub mod number;
9pub mod partial_eq;
10#[cfg(feature = "serde")]
11pub mod ser;
12pub mod spanned;
13pub mod tag;
14pub mod value;
15
16pub use error::{Error, ParseError};
17pub use mapping::Mapping;
18pub use number::Number;
19#[cfg(feature = "serde")]
20pub use ser::value::Serializer;
21pub use spanned::Spanned;
22pub use tag::{Tag, TaggedValue};
23pub use value::{Builder, Sequence, Value};
24
25pub type SpannedValue = Spanned<Value>;
26
27pub struct LossyDocumentDeserializer<R> {
28    builder: Builder,
29    parser: libyaml_safer::Parser<R>,
30}
31
32impl<'b, 'r> LossyDocumentDeserializer<&'b mut &'r [u8]>
33where
34    'b: 'r,
35{
36    pub fn new(value: &'b mut &'r [u8]) -> Self {
37        let mut parser = libyaml_safer::Parser::new();
38        parser.set_input_string(value);
39
40        let builder = Builder::default();
41        Self { builder, parser }
42    }
43}
44
45impl<R> std::iter::Iterator for LossyDocumentDeserializer<R>
46where
47    R: std::io::BufRead,
48{
49    type Item = Result<(Spanned<Value>, Vec<ParseError>), Error>;
50
51    fn next(&mut self) -> Option<Self::Item> {
52        let mut errors = vec![];
53
54        match libyaml_safer::Document::load(&mut self.parser) {
55            Ok(document) if document.nodes.is_empty() => None,
56            Ok(mut document) => Some(
57                self.builder
58                    .from_document(&mut document, &mut errors)
59                    .map(|value| (value, errors))
60                    .map_err(Error::from),
61            ),
62            Err(err) => Some(Err(err.into())),
63        }
64    }
65}
66
67pub fn from_str_lossy_iter<'b, 'r>(
68    value: &'b mut &'r [u8],
69) -> LossyDocumentDeserializer<&'b mut &'r [u8]>
70where
71    'b: 'r,
72{
73    LossyDocumentDeserializer::new(value)
74}
75
76pub fn from_str_lossy_all(value: &str) -> Result<Vec<(Spanned<Value>, Vec<ParseError>)>, Error> {
77    let mut parser = libyaml_safer::Parser::new();
78    let mut bytes = value.as_bytes();
79
80    parser.set_input_string(&mut bytes);
81
82    let builder = Builder::default();
83    let mut documents = vec![];
84    loop {
85        let mut errors = vec![];
86
87        let mut document = match libyaml_safer::Document::load(&mut parser) {
88            Ok(document) if document.nodes.is_empty() => break,
89            Ok(document) => document,
90            Err(err) => return Err(err.into()),
91        };
92        let value: Spanned<Value> = builder.from_document(&mut document, &mut errors)?;
93        documents.push((value, errors));
94    }
95
96    Ok(documents)
97}
98
99pub fn from_str_lossy(value: &str) -> Result<(Spanned<Value>, Vec<ParseError>), Error> {
100    let mut parser = libyaml_safer::Parser::new();
101    let mut bytes = value.as_bytes();
102    parser.set_input_string(&mut bytes);
103
104    let mut document = libyaml_safer::Document::load(&mut parser)?;
105    let mut errors = vec![];
106    let builder = Builder::default();
107    let value: Spanned<Value> = builder.from_document(&mut document, &mut errors)?;
108
109    Ok((value, errors))
110}
111
112pub fn from_str(value: &str) -> Result<Spanned<Value>, Error> {
113    let (value, errors) = from_str_lossy(value)?;
114    if errors.is_empty() {
115        Ok(value)
116    } else {
117        Err(Error::Parse(errors))
118    }
119}
120
121pub fn from_str_all(value: &str) -> Result<Vec<Spanned<Value>>, Error> {
122    let documents = from_str_lossy_all(value)?;
123    let (values, errors): (Vec<_>, Vec<_>) = documents.into_iter().unzip();
124    let errors: Vec<_> = errors.into_iter().flatten().collect();
125    if errors.is_empty() {
126        Ok(values)
127    } else {
128        Err(Error::Parse(errors))
129    }
130}
131
132/// Interpret a `yaml_spanned::Value` as an instance of type `T`.
133///
134/// This conversion can fail if the structure of the Value does not match the
135/// structure expected by `T`, for example if `T` is a struct type but the Value
136/// contains something other than a YAML map. It can also fail if the structure
137/// is correct but `T`'s implementation of `Deserialize` decides that something
138/// is wrong with the data, for example required struct fields are missing from
139/// the YAML map or some number is too big to fit in the expected primitive
140/// type.
141///
142/// ```
143/// # use yaml_spanned::Value;
144/// let val = Value::String("foo".to_owned());
145/// let s: String = yaml_spanned::from_value(&val).unwrap();
146/// assert_eq!("foo", s);
147/// ```
148#[cfg(feature = "serde")]
149pub fn from_value<T>(value: &Value) -> Result<T, error::SerdeError>
150where
151    T: serde::de::DeserializeOwned,
152{
153    serde::Deserialize::deserialize(value)
154}
155
156/// Convert a `T` into `yaml_spanned::Value` which is an enum that can represent
157/// any valid YAML data.
158///
159/// This conversion can fail if `T`'s implementation of `Serialize` decides to
160/// return an error.
161///
162/// ```
163/// # use serde_yaml::Value;
164/// let val = serde_yaml::to_value("s").unwrap();
165/// assert_eq!(val, Value::String("s".to_owned()));
166/// ```
167#[cfg(feature = "serde")]
168pub fn to_value<T>(value: T) -> Result<Value, error::SerdeError>
169where
170    T: serde::Serialize,
171{
172    value.serialize(Serializer)
173}
174
175// use serde::ser::SerializeMap;
176//check_for_tag
177// use serde::ser::SerializeMap;
178
179// Prevent downstream code from implementing the Index trait.
180mod private {
181    pub trait Sealed {}
182    impl Sealed for usize {}
183    impl Sealed for str {}
184    impl Sealed for String {}
185    impl Sealed for crate::value::Value {}
186    impl Sealed for crate::spanned::Spanned<crate::value::Value> {}
187    impl<T> Sealed for &T where T: ?Sized + Sealed {}
188}
189
190#[cfg(test)]
191mod tests {
192    static INIT: std::sync::Once = std::sync::Once::new();
193
194    /// Initialize test
195    ///
196    /// This ensures `color_eyre` is setup once.
197    pub fn init() {
198        INIT.call_once(|| {
199            color_eyre::install().ok();
200        });
201    }
202}