1 /// The query resolver that operates on the AST and the TOML object
3 use toml
::{map::Map, Value}
;
4 use crate::tokenizer
::Token
;
5 use crate::error
::{Error, Result}
;
7 pub fn resolve
<'doc
>(toml
: &'doc
mut Value
, tokens
: &Token
) -> Result
<&'doc
mut Value
> {
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
24 Token
::Identifier { ref ident, .. }
=> {
26 &mut Value
::Table(ref mut t
) => {
27 if t
.contains_key(ident
) {
29 Some(next
) => resolve(t
.get_mut(ident
).unwrap(), next
),
30 None
=> t
.get_mut(ident
).ok_or_else(|| unreachable
!()),
35 let subdoc
= t
.entry(ident
.clone()).or_insert(Value
::Table(Map
::new()));
38 None
=> Ok(t
.entry(ident
.clone()).or_insert(Value
::Table(Map
::new()))),
42 &mut Value
::Array(_
) => Err(Error
::NoIdentifierInArray(ident
.clone())),
46 Token
::Index { idx , .. }
=> {
48 &mut Value
::Table(_
) => Err(Error
::NoIndexInTable(idx
)),
49 &mut Value
::Array(ref mut ary
) => {
52 Some(next
) => resolve(ary
.get_mut(idx
).unwrap(), next
),
53 None
=> ary
.get_mut(idx
).ok_or_else(|| unreachable
!()),
56 if let Some(next
) = tokens
.next() {
58 Token
::Identifier { .. }
=> {
59 ary
.push(Value
::Table(Map
::new()));
61 Token
::Index { .. }
=> {
62 ary
.push(Value
::Array(vec
![]));
66 panic
!("Cannot do this")
80 use toml
::from_str
as toml_from_str
;
82 use crate::tokenizer
::*;
85 macro_rules
! do_resolve
{
86 ( $toml
:ident
=> $query
:expr
) => {
87 resolve(&mut $toml
, &tokenize_with_seperator(&String
::from($query
), '
.'
).unwrap())
92 fn test_resolve_empty_toml_simple_query() {
93 let mut toml
= toml_from_str("").unwrap();
94 let result
= do_resolve
!(toml
=> "example");
96 assert
!(result
.is_ok());
97 let result
= result
.unwrap();
98 assert
!(is_match
!(result
, &mut Value
::Table(_
)));
100 &mut Value
::Table(ref tab
) => assert
!(tab
.is_empty()),
101 _
=> assert
!(false, "Expected Table, got something else"),
106 fn test_resolve_present_bool() {
107 let mut toml
= toml_from_str("example = true").unwrap();
108 let result
= do_resolve
!(toml
=> "example");
110 assert
!(result
.is_ok());
111 let result
= result
.unwrap();
113 assert
!(is_match
!(result
, &mut Value
::Boolean(true)));
117 fn test_resolve_present_integer() {
118 let mut toml
= toml_from_str("example = 1").unwrap();
119 let result
= do_resolve
!(toml
=> "example");
121 assert
!(result
.is_ok());
122 let result
= result
.unwrap();
124 assert
!(is_match
!(result
, &mut Value
::Integer(1)));
128 fn test_resolve_present_float() {
129 let mut toml
= toml_from_str("example = 1.0").unwrap();
130 let result
= do_resolve
!(toml
=> "example");
132 assert
!(result
.is_ok());
133 let result
= result
.unwrap();
135 assert
!(is_match
!(result
, &mut Value
::Float(_
)));
136 assert_eq
!(result
.as_float(), Some(1.0));
140 fn test_resolve_present_string() {
141 let mut toml
= toml_from_str("example = 'string'").unwrap();
142 let result
= do_resolve
!(toml
=> "example");
144 assert
!(result
.is_ok());
145 let result
= result
.unwrap();
147 assert
!(is_match
!(result
, &mut Value
::String(_
)));
149 &mut Value
::String(ref s
) => assert_eq
!("string", s
),
150 _
=> panic
!("What just happened?"),
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");
159 assert
!(result
.is_ok());
160 let result
= result
.unwrap();
162 assert
!(is_match
!(result
, &mut Value
::Array(_
)));
164 &mut Value
::Array(ref ary
) => {
165 assert_eq
!(ary
[0], Value
::Boolean(true));
166 assert_eq
!(ary
[1], Value
::Boolean(false));
168 _
=> panic
!("What just happened?"),
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");
177 assert
!(result
.is_ok());
178 let result
= result
.unwrap();
180 assert
!(is_match
!(result
, &mut Value
::Array(_
)));
182 &mut Value
::Array(ref ary
) => {
183 assert_eq
!(ary
[0], Value
::Integer(1));
184 assert_eq
!(ary
[1], Value
::Integer(1337));
186 _
=> panic
!("What just happened?"),
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");
195 assert
!(result
.is_ok());
196 let result
= result
.unwrap();
198 assert
!(is_match
!(result
, &mut Value
::Array(_
)));
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));
206 _
=> panic
!("What just happened?"),
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]");
215 assert
!(result
.is_ok());
216 let result
= result
.unwrap();
218 assert
!(is_match
!(result
, &mut Value
::Integer(1)));
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]");
226 assert
!(result
.is_ok());
227 let result
= result
.unwrap();
229 assert
!(is_match
!(result
, &mut Value
::Integer(5)));
233 fn test_resolve_table_element_query() {
234 let mut toml
= toml_from_str(r
#"
238 let result
= do_resolve
!(toml
=> "table.value");
240 assert
!(result
.is_ok());
241 let result
= result
.unwrap();
243 assert
!(is_match
!(result
, &mut Value
::Integer(42)));
247 fn test_resolve_table_with_many_elements_element_query() {
248 let mut toml
= toml_from_str(r
#"
256 let result
= do_resolve
!(toml
=> "table.value1");
258 assert
!(result
.is_ok());
259 let result
= result
.unwrap();
261 assert
!(is_match
!(result
, &mut Value
::Integer(42)));
265 fn test_resolve_table_array_query() {
266 let mut toml
= toml_from_str(r
#"
268 value1 = [ 42.0, 50.0 ]
270 let result
= do_resolve
!(toml
=> "table.value1");
272 assert
!(result
.is_ok());
273 let result
= result
.unwrap();
275 assert
!(is_match
!(result
, &mut Value
::Array(_
)));
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));
283 _
=> panic
!("What just happened?"),
288 fn test_resolve_table_array_element_query() {
289 let mut toml
= toml_from_str(r
#"
293 let result
= do_resolve
!(toml
=> "table.value1.[0]");
295 assert
!(result
.is_ok());
296 let result
= result
.unwrap();
298 assert
!(is_match
!(result
, &mut Value
::Integer(42)));
302 fn test_resolve_multi_table_query() {
303 let mut toml
= toml_from_str(r
#"
313 let result
= do_resolve
!(toml
=> "table1.value.[0]");
315 assert
!(result
.is_ok());
316 let result
= result
.unwrap();
318 assert
!(is_match
!(result
, &mut Value
::String(_
)));
320 &mut Value
::String(ref s
) => assert_eq
!("Foo", s
),
321 _
=> panic
!("What just happened?"),
325 static FRUIT_TABLE
: &'
static str = r
#"
329 [fruit.blah.physical]
336 [fruit.blah.physical]
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");
346 assert
!(result
.is_ok());
347 let result
= result
.unwrap();
349 assert
!(is_match
!(result
, &mut Value
::String(_
)));
351 &mut Value
::String(ref s
) => assert_eq
!("apple", s
),
352 _
=> panic
!("What just happened?"),
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");
361 assert
!(result
.is_ok());
362 let result
= result
.unwrap();
364 assert
!(is_match
!(result
, &mut Value
::Table(_
)));
366 &mut Value
::Table(ref tab
) => {
367 match tab
.get("color") {
368 Some(&Value
::String(ref s
)) => assert_eq
!("red", s
),
371 match tab
.get("shape") {
372 Some(&Value
::String(ref s
)) => assert_eq
!("round", s
),
376 _
=> panic
!("What just happened?"),
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");
385 assert
!(result
.is_ok());
386 let result
= result
.unwrap();
388 let tokens
= tokenize_with_seperator(&String
::from("color"), '
.'
).unwrap();
389 let result
= resolve(result
, &tokens
);
391 assert
!(result
.is_ok());
392 let result
= result
.unwrap();
394 assert
!(is_match
!(result
, &mut Value
::String(_
)));
396 &mut Value
::String(ref s
) => assert_eq
!("yellow", s
),
397 _
=> panic
!("What just happened?"),
402 fn test_resolve_query_empty_table() {
403 let mut toml
= toml_from_str(r
#"
406 let result
= do_resolve
!(toml
=> "example");
408 assert
!(result
.is_ok());
409 let result
= result
.unwrap();
411 assert
!(is_match
!(result
, &mut Value
::Table(_
)));
413 &mut Value
::Table(ref t
) => assert
!(t
.is_empty()),
414 _
=> panic
!("What just happened?"),
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");
423 assert
!(result
.is_ok());
424 let result
= result
.unwrap();
425 assert
!(is_match
!(result
, &mut Value
::Table(_
)));
427 &mut Value
::Table(ref t
) => assert
!(t
.is_empty()),
428 _
=> panic
!("What just happened?"),
433 fn test_resolve_query_index_in_table() {
434 let mut toml
= toml_from_str("").unwrap();
435 let result
= do_resolve
!(toml
=> "example.[0]");
437 // TODO: Array creating is not yet implemented properly
438 assert
!(result
.is_err());
440 //assert!(result.is_ok());
441 //let result = result.unwrap();
443 //assert!(is_match!(result, &mut Value::Array(_)));
445 // &mut Value::Array(ref a) => assert!(a.is_empty()),
446 // _ => panic!("What just happened?"),
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");
455 assert
!(result
.is_ok());
456 let result
= result
.unwrap();
459 &mut Value
::Table(ref t
) => assert
!(t
.is_empty()),
460 _
=> panic
!("What just happened?"),
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");
469 assert
!(result
.is_ok());
470 let result
= result
.unwrap();
473 &mut Value
::Table(ref t
) => assert
!(t
.is_empty()),
474 _
=> panic
!("What just happened?"),
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]");
483 // TODO: Array creating is not yet implemented properly
484 assert
!(result
.is_err());
486 //assert!(result.is_ok());
487 //let result = result.unwrap();
490 // &mut Value::Array(ref a) => assert!(a.is_empty()),
491 // _ => panic!("What just happened?"),