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