1use std::fmt::{Display, Error, Formatter};
2use yaml_rust::{YamlEmitter, YamlLoader};
3
4
5#[derive(Clone, Debug, PartialEq)]
7pub struct Yaml {
8 name: String,
9 contents: String,
10}
11
12
13impl Yaml {
15 pub fn get_name(&self) -> String {
18 self.name.clone()
19 }
20
21 pub fn get_section<S: Display>(&self, index: S) -> Result<Self, String> {
24 match YamlLoader::load_from_str(&self.contents) {
25 Ok(reader) => {
26 let result = if reader.len() > 0 {
28 reader[0][index.to_string().as_str()].clone()
29 } else {
30 return Err(format!(
31 "Could not get section '{}' because the parent section is empty",
32 index
33 ));
34 };
35
36 let mut s = Self::from(result);
37 s.name = index.to_string();
38 Ok(s)
39 }
40
41 Err(e) => {
42 return Err(format!(
43 "Could not get section '{}' because {}",
44 index,
45 e.to_string()
46 ));
47 }
48 }
49 }
50
51
52 pub fn get_section_names(&self) -> Result<Vec<String>, String> {
55 match YamlLoader::load_from_str(&self.contents) {
57 Ok(y) => match &y[0] {
58 yaml_rust::Yaml::Hash(h) => Ok(h
59 .keys()
60 .map(|k| match k {
61 yaml_rust::Yaml::String(s) => s.clone(),
62 _ => String::from(""),
63 })
64 .collect()),
65 _ => Ok(vec![]),
66 },
67 Err(_) => {
68 return Err(format!("Malformed yaml section '{}'", self.name));
69 }
70 }
71 }
72
73 pub fn has_section<S: Display>(&self, index: S) -> bool {
76 self.get_section_names()
77 .unwrap()
78 .contains(&index.to_string())
79 }
80
81 pub fn nth<N: Into<i32>>(&self, n: N) -> Self {
82 let vec = self.clone().into_iter().collect::<Vec<Yaml>>();
83
84 let index = n.into() as usize;
85 if index >= vec.len() {
86 Yaml::from(self.to_string())
87 } else {
88 vec[index].clone()
89 }
90 }
91}
92
93impl IntoIterator for Yaml {
96 type Item = Self;
97 type IntoIter = std::vec::IntoIter<Self::Item>;
98
99 fn into_iter(self) -> Self::IntoIter {
100 match YamlLoader::load_from_str(&self.contents) {
101 Ok(y) => match &y[0] {
102 yaml_rust::Yaml::Hash(h) => h
104 .clone()
105 .keys()
106 .map(|k| match k {
107 yaml_rust::Yaml::String(s) => Self::from(y[0].clone()).get_section(s),
108 _ => self.get_section(""),
109 }) .filter(|y| y.is_ok()) .map(|y| y.unwrap()) .collect::<Vec<Self>>(), yaml_rust::Yaml::Array(a) => a
116 .iter()
117 .map(|y| Self::from(y.clone()))
118 .collect::<Vec<Self>>(),
119
120 _ => vec![Yaml::from(self.to_string())],
121 },
122 Err(_) => {
123 vec![Yaml::from(self.to_string())]
125 }
126 }
127 .into_iter()
128 }
129}
130
131impl From<String> for Yaml {
133 fn from(s: String) -> Self {
134 Self {
135 contents: s.to_string(),
136 name: String::from(""),
137 }
138 }
139}
140
141impl From<&str> for Yaml {
143 fn from(s: &str) -> Self {
144 Self::from(s.to_string())
145 }
146}
147
148
149impl From<yaml_rust::Yaml> for Yaml {
151 fn from(yaml: yaml_rust::Yaml) -> Self {
152 let mut out_str = String::new();
153 let mut emitter = YamlEmitter::new(&mut out_str);
154 match emitter.dump(&yaml) {
155 _ => {}
156 };
157
158
159 let lines = out_str.lines().collect::<Vec<&str>>();
160 out_str = if lines.len() > 0 {
161 lines[1..].join("\n").to_string()
162 } else {
163 "".to_string()
164 };
165
166
167 Self::from(out_str)
168 }
169}
170
171
172impl From<Yaml> for String {
173 fn from(yaml: Yaml) -> Self {
174 format!("{}", yaml.to_string())
175 }
176}
177
178impl Display for Yaml {
180 fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
181 write!(f, "{}", self.contents)
182 }
183}