prison_architect_savefile/
lib.rs1mod format;
2mod parse;
3
4pub use crate::parse::ParseError;
5
6use std::{collections::HashMap, fmt, io, path::Path, vec};
7
8pub fn read(path: impl AsRef<Path>) -> io::Result<Node> {
10 Node::read(path)
11}
12
13#[derive(Default, Clone, PartialEq, Eq)]
15pub struct Node {
16 properties: HashMap<String, Vec<String>>,
17 children: HashMap<String, Vec<Node>>,
18}
19
20impl Node {
21 pub fn new() -> Self {
23 Default::default()
24 }
25
26 pub fn parse(input: impl AsRef<str>) -> Result<Self, ParseError> {
28 input.as_ref().parse()
29 }
30
31 pub fn read(path: impl AsRef<Path>) -> io::Result<Self> {
33 let input = fs_err::read_to_string(path)?;
34 Node::parse(input).map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err))
35 }
36
37 pub fn write(&self, path: impl AsRef<Path>) -> io::Result<()> {
39 let output = self.to_string();
40 fs_err::write(path, output)
41 }
42
43 pub fn properties(&self) -> impl Iterator<Item = (&str, &str)> {
45 self.properties
46 .iter()
47 .flat_map(|(key, values)| values.iter().map(|value| (key.as_str(), value.as_str())))
48 }
49
50 pub fn property(&self, key: impl AsRef<str>) -> Option<&str> {
52 self.properties
53 .get(key.as_ref())
54 .and_then(|value| value.first())
55 .map(|value| value.as_str())
56 }
57
58 pub fn has_property(&mut self, key: impl AsRef<str>) -> bool {
60 self.properties
61 .get(key.as_ref())
62 .map_or(false, |values| !values.is_empty())
63 }
64
65 pub fn set_property(&mut self, key: impl Into<String>, value: impl Into<String>) {
67 let values = self.properties.entry(key.into()).or_default();
68 values.clear();
69 values.push(value.into());
70 }
71
72 pub fn add_property(&mut self, key: impl Into<String>, value: impl Into<String>) {
74 self.properties
75 .entry(key.into())
76 .or_default()
77 .push(value.into())
78 }
79
80 pub fn clear_property(&mut self, key: impl AsRef<str>) -> impl Iterator<Item = String> {
82 match self.properties.remove(key.as_ref()) {
83 Some(properties) => properties.into_iter(),
84 None => vec::IntoIter::default(),
85 }
86 }
87
88 pub fn clear_properties(&mut self) -> impl Iterator<Item = (String, String)> + '_ {
90 self.properties.drain().flat_map(|(key, properties)| {
91 properties
92 .into_iter()
93 .map(move |property| (key.clone(), property))
94 })
95 }
96
97 pub fn extend_properties<K, V>(&mut self, properties: impl IntoIterator<Item = (K, V)>)
99 where
100 K: Into<String>,
101 V: Into<String>,
102 {
103 for (key, value) in properties {
104 self.properties
105 .entry(key.into())
106 .or_default()
107 .push(value.into())
108 }
109 }
110
111 pub fn children(&self) -> impl Iterator<Item = (&str, &Node)> {
113 self.children
114 .iter()
115 .flat_map(|(key, children)| children.iter().map(|child| (key.as_str(), child)))
116 }
117
118 pub fn children_mut(&mut self) -> impl Iterator<Item = (&str, &mut Node)> {
120 self.children
121 .iter_mut()
122 .flat_map(|(key, children)| children.iter_mut().map(|child| (key.as_str(), child)))
123 }
124
125 pub fn child(&self, key: &str) -> Option<&Node> {
127 self.children.get(key).and_then(|child| child.first())
128 }
129
130 pub fn child_mut(&mut self, key: &str) -> Option<&mut Node> {
132 self.children
133 .get_mut(key)
134 .and_then(|child| child.first_mut())
135 }
136
137 pub fn has_child(&mut self, key: impl AsRef<str>) -> bool {
139 self.children
140 .get(key.as_ref())
141 .map_or(false, |values| !values.is_empty())
142 }
143
144 pub fn set_child(&mut self, key: impl Into<String>, child: Node) {
146 let values = self.children.entry(key.into()).or_default();
147 values.clear();
148 values.push(child);
149 }
150
151 pub fn add_child(&mut self, key: impl Into<String>, child: Node) {
153 self.children.entry(key.into()).or_default().push(child)
154 }
155
156 pub fn clear_child(&mut self, key: impl AsRef<str>) -> impl Iterator<Item = Node> {
158 match self.children.remove(key.as_ref()) {
159 Some(children) => children.into_iter(),
160 None => vec::IntoIter::default(),
161 }
162 }
163
164 pub fn clear_children(&mut self) -> impl Iterator<Item = (String, Node)> + '_ {
166 self.children
167 .drain()
168 .flat_map(|(key, children)| children.into_iter().map(move |child| (key.clone(), child)))
169 }
170
171 pub fn extend_children<K>(&mut self, properties: impl IntoIterator<Item = (K, Node)>)
173 where
174 K: Into<String>,
175 {
176 for (key, child) in properties {
177 self.children.entry(key.into()).or_default().push(child)
178 }
179 }
180}
181
182impl fmt::Debug for Node {
183 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
184 f.debug_map()
185 .entries(self.properties())
186 .entries(self.children())
187 .finish()
188 }
189}