]> git.proxmox.com Git - rustc.git/blob - vendor/toml-query/src/resolver/mut_creating_resolver.rs
New upstream version 1.45.0+dfsg1
[rustc.git] / vendor / toml-query / src / resolver / mut_creating_resolver.rs
1 /// The query resolver that operates on the AST and the TOML object
2
3 use toml::{map::Map, Value};
4 use crate::tokenizer::Token;
5 use crate::error::{Error, Result};
6
7 pub fn resolve<'doc>(toml: &'doc mut Value, tokens: &Token) -> Result<&'doc mut Value> {
8
9 // Cases:
10 //
11 // 1. Identifier, toml: table, ident present -> traverse
12 // 2. Identifier, toml: table, no indent present -> create Table
13 // 2.1 If next token -> traverse
14 // 2.2 no next token -> return created Table
15 // 3. Identifier, toml: array -> error
16 // 4. Index, toml: table -> error
17 // 5. Index, toml: array, idx present -> traverse
18 // 6. Index, toml: array, idx not present
19 // 6.1 -> next token is ident -> push Table
20 // 6.2 -> next token is index -> push Array
21 // then traverse
22
23 match *tokens {
24 Token::Identifier { ref ident, .. } => {
25 match toml {
26 &mut Value::Table(ref mut t) => {
27 if t.contains_key(ident) {
28 match tokens.next() {
29 Some(next) => resolve(t.get_mut(ident).unwrap(), next),
30 None => t.get_mut(ident).ok_or_else(|| unreachable!()),
31 }
32 } else {
33 match tokens.next() {
34 Some(next) => {
35 let subdoc = t.entry(ident.clone()).or_insert(Value::Table(Map::new()));
36 resolve(subdoc, next)
37 },
38 None => Ok(t.entry(ident.clone()).or_insert(Value::Table(Map::new()))),
39 }
40 }
41 },
42 &mut Value::Array(_) => Err(Error::NoIdentifierInArray(ident.clone())),
43 _ => unimplemented!()
44 }
45 }
46 Token::Index { idx , .. } => {
47 match toml {
48 &mut Value::Table(_) => Err(Error::NoIndexInTable(idx)),
49 &mut Value::Array(ref mut ary) => {
50 if ary.len() > idx {
51 match tokens.next() {
52 Some(next) => resolve(ary.get_mut(idx).unwrap(), next),
53 None => ary.get_mut(idx).ok_or_else(|| unreachable!()),
54 }
55 } else {
56 if let Some(next) = tokens.next() {
57 match **next {
58 Token::Identifier { .. } => {
59 ary.push(Value::Table(Map::new()));
60 },
61 Token::Index { .. } => {
62 ary.push(Value::Array(vec![]));
63 }
64 }
65 //resolve(toml, next)
66 panic!("Cannot do this")
67 } else {
68 unimplemented!()
69 }
70 }
71 }
72 _ => unimplemented!()
73 }
74 }
75 }
76 }
77
78 #[cfg(test)]
79 mod test {
80 use toml::from_str as toml_from_str;
81 use toml::Value;
82 use crate::tokenizer::*;
83 use super::resolve;
84
85 macro_rules! do_resolve {
86 ( $toml:ident => $query:expr ) => {
87 resolve(&mut $toml, &tokenize_with_seperator(&String::from($query), '.').unwrap())
88 }
89 }
90
91 #[test]
92 fn test_resolve_empty_toml_simple_query() {
93 let mut toml = toml_from_str("").unwrap();
94 let result = do_resolve!(toml => "example");
95
96 assert!(result.is_ok());
97 let result = result.unwrap();
98 assert!(is_match!(result, &mut Value::Table(_)));
99 match result {
100 &mut Value::Table(ref tab) => assert!(tab.is_empty()),
101 _ => assert!(false, "Expected Table, got something else"),
102 }
103 }
104
105 #[test]
106 fn test_resolve_present_bool() {
107 let mut toml = toml_from_str("example = true").unwrap();
108 let result = do_resolve!(toml => "example");
109
110 assert!(result.is_ok());
111 let result = result.unwrap();
112
113 assert!(is_match!(result, &mut Value::Boolean(true)));
114 }
115
116 #[test]
117 fn test_resolve_present_integer() {
118 let mut toml = toml_from_str("example = 1").unwrap();
119 let result = do_resolve!(toml => "example");
120
121 assert!(result.is_ok());
122 let result = result.unwrap();
123
124 assert!(is_match!(result, &mut Value::Integer(1)));
125 }
126
127 #[test]
128 fn test_resolve_present_float() {
129 let mut toml = toml_from_str("example = 1.0").unwrap();
130 let result = do_resolve!(toml => "example");
131
132 assert!(result.is_ok());
133 let result = result.unwrap();
134
135 assert!(is_match!(result, &mut Value::Float(_)));
136 assert_eq!(result.as_float(), Some(1.0));
137 }
138
139 #[test]
140 fn test_resolve_present_string() {
141 let mut toml = toml_from_str("example = 'string'").unwrap();
142 let result = do_resolve!(toml => "example");
143
144 assert!(result.is_ok());
145 let result = result.unwrap();
146
147 assert!(is_match!(result, &mut Value::String(_)));
148 match result {
149 &mut Value::String(ref s) => assert_eq!("string", s),
150 _ => panic!("What just happened?"),
151 }
152 }
153
154 #[test]
155 fn test_resolve_present_array_bools() {
156 let mut toml = toml_from_str("example = [ true, false ]").unwrap();
157 let result = do_resolve!(toml => "example");
158
159 assert!(result.is_ok());
160 let result = result.unwrap();
161
162 assert!(is_match!(result, &mut Value::Array(_)));
163 match result {
164 &mut Value::Array(ref ary) => {
165 assert_eq!(ary[0], Value::Boolean(true));
166 assert_eq!(ary[1], Value::Boolean(false));
167 },
168 _ => panic!("What just happened?"),
169 }
170 }
171
172 #[test]
173 fn test_resolve_present_array_integers() {
174 let mut toml = toml_from_str("example = [ 1, 1337 ]").unwrap();
175 let result = do_resolve!(toml => "example");
176
177 assert!(result.is_ok());
178 let result = result.unwrap();
179
180 assert!(is_match!(result, &mut Value::Array(_)));
181 match result {
182 &mut Value::Array(ref ary) => {
183 assert_eq!(ary[0], Value::Integer(1));
184 assert_eq!(ary[1], Value::Integer(1337));
185 },
186 _ => panic!("What just happened?"),
187 }
188 }
189
190 #[test]
191 fn test_resolve_present_array_floats() {
192 let mut toml = toml_from_str("example = [ 1.0, 133.25 ]").unwrap();
193 let result = do_resolve!(toml => "example");
194
195 assert!(result.is_ok());
196 let result = result.unwrap();
197
198 assert!(is_match!(result, &mut Value::Array(_)));
199 match result {
200 &mut Value::Array(ref ary) => {
201 assert!(is_match!(ary[0], Value::Float(_)));
202 assert_eq!(ary[0].as_float(), Some(1.0));
203 assert!(is_match!(ary[1], Value::Float(_)));
204 assert_eq!(ary[1].as_float(), Some(133.25));
205 },
206 _ => panic!("What just happened?"),
207 }
208 }
209
210 #[test]
211 fn test_resolve_array_index_query_1() {
212 let mut toml = toml_from_str("example = [ 1 ]").unwrap();
213 let result = do_resolve!(toml => "example.[0]");
214
215 assert!(result.is_ok());
216 let result = result.unwrap();
217
218 assert!(is_match!(result, &mut Value::Integer(1)));
219 }
220
221 #[test]
222 fn test_resolve_array_index_query_2() {
223 let mut toml = toml_from_str("example = [ 1, 2, 3, 4, 5 ]").unwrap();
224 let result = do_resolve!(toml => "example.[4]");
225
226 assert!(result.is_ok());
227 let result = result.unwrap();
228
229 assert!(is_match!(result, &mut Value::Integer(5)));
230 }
231
232 #[test]
233 fn test_resolve_table_element_query() {
234 let mut toml = toml_from_str(r#"
235 [table]
236 value = 42
237 "#).unwrap();
238 let result = do_resolve!(toml => "table.value");
239
240 assert!(result.is_ok());
241 let result = result.unwrap();
242
243 assert!(is_match!(result, &mut Value::Integer(42)));
244 }
245
246 #[test]
247 fn test_resolve_table_with_many_elements_element_query() {
248 let mut toml = toml_from_str(r#"
249 [table]
250 value1 = 42
251 value2 = 43
252 value3 = 44
253 value4 = 45
254 value5 = 46
255 "#).unwrap();
256 let result = do_resolve!(toml => "table.value1");
257
258 assert!(result.is_ok());
259 let result = result.unwrap();
260
261 assert!(is_match!(result, &mut Value::Integer(42)));
262 }
263
264 #[test]
265 fn test_resolve_table_array_query() {
266 let mut toml = toml_from_str(r#"
267 [table]
268 value1 = [ 42.0, 50.0 ]
269 "#).unwrap();
270 let result = do_resolve!(toml => "table.value1");
271
272 assert!(result.is_ok());
273 let result = result.unwrap();
274
275 assert!(is_match!(result, &mut Value::Array(_)));
276 match result {
277 &mut Value::Array(ref ary) => {
278 assert!(is_match!(ary[0], Value::Float(_)));
279 assert_eq!(ary[0].as_float(), Some(42.0));
280 assert!(is_match!(ary[1], Value::Float(_)));
281 assert_eq!(ary[1].as_float(), Some(50.0));
282 },
283 _ => panic!("What just happened?"),
284 }
285 }
286
287 #[test]
288 fn test_resolve_table_array_element_query() {
289 let mut toml = toml_from_str(r#"
290 [table]
291 value1 = [ 42 ]
292 "#).unwrap();
293 let result = do_resolve!(toml => "table.value1.[0]");
294
295 assert!(result.is_ok());
296 let result = result.unwrap();
297
298 assert!(is_match!(result, &mut Value::Integer(42)));
299 }
300
301 #[test]
302 fn test_resolve_multi_table_query() {
303 let mut toml = toml_from_str(r#"
304 [table0]
305 value = [ 1 ]
306 [table1]
307 value = [ "Foo" ]
308 [table2]
309 value = [ 42.0 ]
310 [table3]
311 value = [ true ]
312 "#).unwrap();
313 let result = do_resolve!(toml => "table1.value.[0]");
314
315 assert!(result.is_ok());
316 let result = result.unwrap();
317
318 assert!(is_match!(result, &mut Value::String(_)));
319 match result {
320 &mut Value::String(ref s) => assert_eq!("Foo", s),
321 _ => panic!("What just happened?"),
322 }
323 }
324
325 static FRUIT_TABLE : &'static str = r#"
326 [[fruit.blah]]
327 name = "apple"
328
329 [fruit.blah.physical]
330 color = "red"
331 shape = "round"
332
333 [[fruit.blah]]
334 name = "banana"
335
336 [fruit.blah.physical]
337 color = "yellow"
338 shape = "bent"
339 "#;
340
341 #[test]
342 fn test_resolve_array_table_query_1() {
343 let mut toml = toml_from_str(FRUIT_TABLE).unwrap();
344 let result = do_resolve!(toml => "fruit.blah.[0].name");
345
346 assert!(result.is_ok());
347 let result = result.unwrap();
348
349 assert!(is_match!(result, &mut Value::String(_)));
350 match result {
351 &mut Value::String(ref s) => assert_eq!("apple", s),
352 _ => panic!("What just happened?"),
353 }
354 }
355
356 #[test]
357 fn test_resolve_array_table_query_2() {
358 let mut toml = toml_from_str(FRUIT_TABLE).unwrap();
359 let result = do_resolve!(toml => "fruit.blah.[0].physical");
360
361 assert!(result.is_ok());
362 let result = result.unwrap();
363
364 assert!(is_match!(result, &mut Value::Table(_)));
365 match result {
366 &mut Value::Table(ref tab) => {
367 match tab.get("color") {
368 Some(&Value::String(ref s)) => assert_eq!("red", s),
369 _ => assert!(false),
370 }
371 match tab.get("shape") {
372 Some(&Value::String(ref s)) => assert_eq!("round", s),
373 _ => assert!(false),
374 }
375 },
376 _ => panic!("What just happened?"),
377 }
378 }
379
380 #[test]
381 fn test_resolve_query_on_result() {
382 let mut toml = toml_from_str(FRUIT_TABLE).unwrap();
383 let result = do_resolve!(toml => "fruit.blah.[1].physical");
384
385 assert!(result.is_ok());
386 let result = result.unwrap();
387
388 let tokens = tokenize_with_seperator(&String::from("color"), '.').unwrap();
389 let result = resolve(result, &tokens);
390
391 assert!(result.is_ok());
392 let result = result.unwrap();
393
394 assert!(is_match!(result, &mut Value::String(_)));
395 match result {
396 &mut Value::String(ref s) => assert_eq!("yellow", s),
397 _ => panic!("What just happened?"),
398 }
399 }
400
401 #[test]
402 fn test_resolve_query_empty_table() {
403 let mut toml = toml_from_str(r#"
404 [example]
405 "#).unwrap();
406 let result = do_resolve!(toml => "example");
407
408 assert!(result.is_ok());
409 let result = result.unwrap();
410
411 assert!(is_match!(result, &mut Value::Table(_)));
412 match result {
413 &mut Value::Table(ref t) => assert!(t.is_empty()),
414 _ => panic!("What just happened?"),
415 }
416 }
417
418 #[test]
419 fn test_resolve_query_member_of_empty_table() {
420 let mut toml = toml_from_str("").unwrap();
421 let result = do_resolve!(toml => "example.foo");
422
423 assert!(result.is_ok());
424 let result = result.unwrap();
425 assert!(is_match!(result, &mut Value::Table(_)));
426 match result {
427 &mut Value::Table(ref t) => assert!(t.is_empty()),
428 _ => panic!("What just happened?"),
429 }
430 }
431
432 #[test]
433 fn test_resolve_query_index_in_table() {
434 let mut toml = toml_from_str("").unwrap();
435 let result = do_resolve!(toml => "example.[0]");
436
437 // TODO: Array creating is not yet implemented properly
438 assert!(result.is_err());
439
440 //assert!(result.is_ok());
441 //let result = result.unwrap();
442
443 //assert!(is_match!(result, &mut Value::Array(_)));
444 //match result {
445 // &mut Value::Array(ref a) => assert!(a.is_empty()),
446 // _ => panic!("What just happened?"),
447 //}
448 }
449
450 #[test]
451 fn test_resolve_query_identifier_in_array() {
452 let mut toml = toml_from_str("").unwrap();
453 let result = do_resolve!(toml => "example.foo.bar");
454
455 assert!(result.is_ok());
456 let result = result.unwrap();
457
458 match result {
459 &mut Value::Table(ref t) => assert!(t.is_empty()),
460 _ => panic!("What just happened?"),
461 }
462 }
463
464 #[test]
465 fn test_resolve_query_value_as_table() {
466 let mut toml = toml_from_str("").unwrap();
467 let result = do_resolve!(toml => "example.foo.bar");
468
469 assert!(result.is_ok());
470 let result = result.unwrap();
471
472 match result {
473 &mut Value::Table(ref t) => assert!(t.is_empty()),
474 _ => panic!("What just happened?"),
475 }
476 }
477
478 #[test]
479 fn test_resolve_query_value_as_array() {
480 let mut toml = toml_from_str("").unwrap();
481 let result = do_resolve!(toml => "example.foo.[0]");
482
483 // TODO: Array creating is not yet implemented properly
484 assert!(result.is_err());
485
486 //assert!(result.is_ok());
487 //let result = result.unwrap();
488
489 //match result {
490 // &mut Value::Array(ref a) => assert!(a.is_empty()),
491 // _ => panic!("What just happened?"),
492 //}
493 }
494
495 }
496