insta/content/yaml/
mod.rs

1pub mod vendored;
2
3use std::path::Path;
4
5use crate::content::{Content, Error};
6
7use crate::content::yaml::vendored::{yaml::Hash as YamlObj, Yaml as YamlValue};
8
9pub fn parse_str(s: &str, filename: &Path) -> Result<Content, Error> {
10    let mut blobs = crate::content::yaml::vendored::yaml::YamlLoader::load_from_str(s)
11        .map_err(|_| Error::FailedParsingYaml(filename.to_path_buf()))?;
12
13    match (blobs.pop(), blobs.pop()) {
14        (Some(blob), None) => from_yaml_blob(blob, filename),
15        _ => Err(Error::FailedParsingYaml(filename.to_path_buf())),
16    }
17}
18
19fn from_yaml_blob(blob: YamlValue, filename: &Path) -> Result<Content, Error> {
20    match blob {
21        YamlValue::Null => Ok(Content::None),
22        YamlValue::Boolean(b) => Ok(Content::from(b)),
23        YamlValue::Integer(num) => Ok(Content::from(num)),
24        YamlValue::Real(real_str) => {
25            let real: f64 = real_str.parse().unwrap();
26            Ok(Content::from(real))
27        }
28        YamlValue::String(s) => Ok(Content::from(s)),
29        YamlValue::Array(seq) => {
30            let seq = seq
31                .into_iter()
32                .map(|x| from_yaml_blob(x, filename))
33                .collect::<Result<_, Error>>()?;
34            Ok(Content::Seq(seq))
35        }
36        YamlValue::Hash(obj) => {
37            let obj = obj
38                .into_iter()
39                .map(|(k, v)| Ok((from_yaml_blob(k, filename)?, from_yaml_blob(v, filename)?)))
40                .collect::<Result<_, Error>>()?;
41            Ok(Content::Map(obj))
42        }
43        YamlValue::BadValue => Err(Error::FailedParsingYaml(filename.to_path_buf())),
44    }
45}
46
47pub fn to_string(content: &Content) -> String {
48    let yaml_blob = to_yaml_value(content);
49
50    let mut buf = String::new();
51    let mut emitter = crate::content::yaml::vendored::emitter::YamlEmitter::new(&mut buf);
52    emitter.dump(&yaml_blob).unwrap();
53
54    if !buf.ends_with('\n') {
55        buf.push('\n');
56    }
57    buf
58}
59
60fn to_yaml_value(content: &Content) -> YamlValue {
61    fn translate_seq(seq: &[Content]) -> YamlValue {
62        let seq = seq.iter().map(to_yaml_value).collect();
63        YamlValue::Array(seq)
64    }
65
66    fn translate_fields(fields: &[(&str, Content)]) -> YamlValue {
67        let fields = fields
68            .iter()
69            .map(|(k, v)| (YamlValue::String(k.to_string()), to_yaml_value(v)))
70            .collect();
71        YamlValue::Hash(fields)
72    }
73
74    match content {
75        Content::Bool(b) => YamlValue::Boolean(*b),
76        Content::U8(n) => YamlValue::Integer(i64::from(*n)),
77        Content::U16(n) => YamlValue::Integer(i64::from(*n)),
78        Content::U32(n) => YamlValue::Integer(i64::from(*n)),
79        Content::U64(n) => YamlValue::Real(n.to_string()),
80        Content::U128(n) => YamlValue::Real(n.to_string()),
81        Content::I8(n) => YamlValue::Integer(i64::from(*n)),
82        Content::I16(n) => YamlValue::Integer(i64::from(*n)),
83        Content::I32(n) => YamlValue::Integer(i64::from(*n)),
84        Content::I64(n) => YamlValue::Integer(*n),
85        Content::I128(n) => YamlValue::Real(n.to_string()),
86        Content::F32(f) => YamlValue::Real(f.to_string()),
87        Content::F64(f) => YamlValue::Real(f.to_string()),
88        Content::Char(c) => YamlValue::String(c.to_string()),
89        Content::String(s) => YamlValue::String(s.to_owned()),
90        Content::Bytes(bytes) => {
91            let bytes = bytes
92                .iter()
93                .map(|b| YamlValue::Integer(i64::from(*b)))
94                .collect();
95            YamlValue::Array(bytes)
96        }
97        Content::None | Content::Unit | Content::UnitStruct(_) => YamlValue::Null,
98        Content::Some(content) => to_yaml_value(content),
99        Content::UnitVariant(_, _, variant) => YamlValue::String(variant.to_string()),
100        Content::NewtypeStruct(_, content) => to_yaml_value(content),
101        Content::NewtypeVariant(_, _, variant, content) => {
102            let mut obj = YamlObj::new();
103            obj.insert(
104                YamlValue::String(variant.to_string()),
105                to_yaml_value(content),
106            );
107            YamlValue::Hash(obj)
108        }
109        Content::Seq(seq) => translate_seq(seq),
110        Content::Tuple(seq) => translate_seq(seq),
111        Content::TupleStruct(_, seq) => translate_seq(seq),
112        Content::TupleVariant(_, _, variant, seq) => {
113            let mut obj = YamlObj::new();
114            obj.insert(YamlValue::String(variant.to_string()), translate_seq(seq));
115            YamlValue::Hash(obj)
116        }
117        Content::Map(map) => {
118            let map = map
119                .iter()
120                .map(|(k, v)| (to_yaml_value(k), to_yaml_value(v)))
121                .collect();
122
123            YamlValue::Hash(map)
124        }
125        Content::Struct(_name, fields) => translate_fields(fields),
126        Content::StructVariant(_, _, variant, fields) => {
127            let mut obj = YamlObj::new();
128            obj.insert(
129                YamlValue::String(variant.to_string()),
130                translate_fields(fields),
131            );
132            YamlValue::Hash(obj)
133        }
134    }
135}