1use std::fmt;
4
5#[derive(Debug, Clone, PartialEq, Default)]
12pub enum Value {
13 #[default]
14 Null,
15 Bool(bool),
16 Int(i64),
17 Float(f64),
18 Str(String),
19 List(Vec<Value>),
20 Map(Map),
21 Ref(Ref),
23 Tag(Ref),
25 Res(Res),
27 Lang(String),
29 Text(String),
31 Image(String),
33 Color(u32),
35}
36
37#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
41pub struct Ref {
42 pub kind: String,
43 pub id: String,
44}
45
46impl Ref {
47 pub fn new(kind: impl Into<String>, id: impl Into<String>) -> Self {
48 Self {
49 kind: kind.into(),
50 id: id.into(),
51 }
52 }
53
54 pub fn namespace(&self) -> &str {
56 self.id.split_once(':').map_or("minecraft", |(ns, _)| ns)
57 }
58}
59
60#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
63pub struct Res {
64 pub set: String,
65 pub key: String,
66}
67
68#[derive(Debug, Clone, PartialEq, Default)]
70pub struct Map(Vec<(String, Value)>);
71
72impl Map {
73 pub fn new() -> Self {
74 Self(Vec::new())
75 }
76
77 pub fn with_capacity(n: usize) -> Self {
78 Self(Vec::with_capacity(n))
79 }
80
81 pub fn get(&self, key: &str) -> Option<&Value> {
82 self.0.iter().find(|(k, _)| k == key).map(|(_, v)| v)
83 }
84
85 pub fn get_mut(&mut self, key: &str) -> Option<&mut Value> {
86 self.0.iter_mut().find(|(k, _)| k == key).map(|(_, v)| v)
87 }
88
89 pub fn value_at(&self, i: usize) -> Option<&Value> {
91 self.0.get(i).map(|(_, v)| v)
92 }
93
94 pub fn index_of(&self, key: &str) -> Option<usize> {
96 self.0.iter().position(|(k, _)| k == key)
97 }
98
99 pub fn insert(&mut self, key: impl Into<String>, value: Value) -> Option<Value> {
101 let key = key.into();
102 match self.get_mut(&key) {
103 Some(slot) => Some(std::mem::replace(slot, value)),
104 None => {
105 self.0.push((key, value));
106 None
107 }
108 }
109 }
110
111 pub(crate) fn push_unchecked(&mut self, key: String, value: Value) {
113 self.0.push((key, value));
114 }
115
116 pub fn remove(&mut self, key: &str) -> Option<Value> {
117 let i = self.index_of(key)?;
118 Some(self.0.remove(i).1)
119 }
120
121 pub fn len(&self) -> usize {
122 self.0.len()
123 }
124
125 pub fn is_empty(&self) -> bool {
126 self.0.is_empty()
127 }
128
129 pub fn iter(&self) -> impl ExactSizeIterator<Item = (&str, &Value)> {
130 self.0.iter().map(|(k, v)| (k.as_str(), v))
131 }
132
133 pub fn keys(&self) -> impl ExactSizeIterator<Item = &str> {
134 self.0.iter().map(|(k, _)| k.as_str())
135 }
136
137 pub fn retain(&mut self, mut keep: impl FnMut(&str, &Value) -> bool) {
138 self.0.retain(|(k, v)| keep(k, v));
139 }
140}
141
142impl IntoIterator for Map {
143 type Item = (String, Value);
144 type IntoIter = std::vec::IntoIter<(String, Value)>;
145 fn into_iter(self) -> Self::IntoIter {
146 self.0.into_iter()
147 }
148}
149
150impl<K: Into<String>> FromIterator<(K, Value)> for Map {
151 fn from_iter<I: IntoIterator<Item = (K, Value)>>(iter: I) -> Self {
152 let mut map = Map::new();
153 for (k, v) in iter {
154 map.insert(k, v);
155 }
156 map
157 }
158}
159
160impl Value {
161 pub fn kind_name(&self) -> &'static str {
163 match self {
164 Value::Null => "null",
165 Value::Bool(_) => "true/false",
166 Value::Int(_) => "an integer",
167 Value::Float(_) => "a number",
168 Value::Str(_) => "a string",
169 Value::List(_) => "a list",
170 Value::Map(_) => "an object",
171 Value::Ref(_) => "a reference",
172 Value::Tag(_) => "a tag",
173 Value::Res(_) => "a resource",
174 Value::Lang(_) => "a translation key",
175 Value::Text(_) => "a text",
176 Value::Image(_) => "an image",
177 Value::Color(_) => "a color",
178 }
179 }
180
181 pub fn is_null(&self) -> bool {
182 matches!(self, Value::Null)
183 }
184
185 pub fn as_bool(&self) -> Option<bool> {
186 match self {
187 Value::Bool(b) => Some(*b),
188 _ => None,
189 }
190 }
191
192 pub fn as_i64(&self) -> Option<i64> {
193 match self {
194 Value::Int(n) => Some(*n),
195 Value::Float(f) if f.fract() == 0.0 && f.abs() < 9.0e15 => Some(*f as i64),
196 _ => None,
197 }
198 }
199
200 pub fn as_f64(&self) -> Option<f64> {
201 match self {
202 Value::Int(n) => Some(*n as f64),
203 Value::Float(f) => Some(*f),
204 _ => None,
205 }
206 }
207
208 pub fn as_str(&self) -> Option<&str> {
210 match self {
211 Value::Str(s) | Value::Text(s) | Value::Image(s) => Some(s),
212 _ => None,
213 }
214 }
215
216 pub fn as_list(&self) -> Option<&[Value]> {
217 match self {
218 Value::List(l) => Some(l),
219 _ => None,
220 }
221 }
222
223 pub fn as_map(&self) -> Option<&Map> {
224 match self {
225 Value::Map(m) => Some(m),
226 _ => None,
227 }
228 }
229
230 pub fn get(&self, key: &str) -> Option<&Value> {
232 self.as_map()?.get(key)
233 }
234
235 pub fn at(&self, path: &Path) -> Option<&Value> {
237 let mut v = self;
238 for seg in path.segments() {
239 v = match (seg, v) {
240 (Seg::Key(k), Value::Map(m)) => m.get(k)?,
241 (Seg::Index(i), Value::List(l)) => l.get(*i)?,
242 _ => return None,
243 };
244 }
245 Some(v)
246 }
247}
248
249impl From<bool> for Value {
250 fn from(b: bool) -> Self {
251 Value::Bool(b)
252 }
253}
254impl From<i64> for Value {
255 fn from(n: i64) -> Self {
256 Value::Int(n)
257 }
258}
259impl From<f64> for Value {
260 fn from(f: f64) -> Self {
261 Value::Float(f)
262 }
263}
264impl From<&str> for Value {
265 fn from(s: &str) -> Self {
266 Value::Str(s.to_string())
267 }
268}
269impl From<String> for Value {
270 fn from(s: String) -> Self {
271 Value::Str(s)
272 }
273}
274impl From<Vec<Value>> for Value {
275 fn from(l: Vec<Value>) -> Self {
276 Value::List(l)
277 }
278}
279impl From<Map> for Value {
280 fn from(m: Map) -> Self {
281 Value::Map(m)
282 }
283}
284
285#[derive(Debug, Clone, PartialEq, Eq, Hash)]
287pub enum Seg {
288 Key(String),
289 Index(usize),
290}
291
292#[derive(Debug, Clone, PartialEq, Eq, Hash, Default)]
294pub struct Path(Vec<Seg>);
295
296impl Path {
297 pub fn root() -> Self {
298 Self(Vec::new())
299 }
300
301 pub fn segments(&self) -> &[Seg] {
302 &self.0
303 }
304
305 pub fn is_root(&self) -> bool {
306 self.0.is_empty()
307 }
308
309 pub fn push(&mut self, seg: Seg) {
310 self.0.push(seg);
311 }
312
313 pub fn pop(&mut self) {
314 self.0.pop();
315 }
316
317 pub fn key(&self, key: &str) -> Path {
318 let mut p = self.clone();
319 p.0.push(Seg::Key(key.to_string()));
320 p
321 }
322
323 pub fn index(&self, i: usize) -> Path {
324 let mut p = self.clone();
325 p.0.push(Seg::Index(i));
326 p
327 }
328}
329
330impl fmt::Display for Path {
331 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
332 if self.0.is_empty() {
333 return f.write_str("(root)");
334 }
335 for (i, seg) in self.0.iter().enumerate() {
336 match seg {
337 Seg::Key(k) if is_plain_key(k) => {
338 if i > 0 {
339 f.write_str(".")?;
340 }
341 f.write_str(k)?;
342 }
343 Seg::Key(k) => write!(f, "[{k:?}]")?,
344 Seg::Index(n) => write!(f, "[{n}]")?,
345 }
346 }
347 Ok(())
348 }
349}
350
351fn is_plain_key(k: &str) -> bool {
352 let mut chars = k.chars();
353 chars
354 .next()
355 .is_some_and(|c| c.is_ascii_alphabetic() || c == '_' || c == '$')
356 && chars.all(|c| c.is_ascii_alphanumeric() || c == '_' || c == '$')
357}