toml: streamline value() api (#12568)
parent
f825306cff
commit
11d70624af
|
@ -163,24 +163,21 @@ pub fn (a Any) default_to(value Any) Any {
|
|||
}
|
||||
|
||||
// value queries a value from the map.
|
||||
// `key` should be in "dotted" form (`a.b.c`).
|
||||
// `key` supports quoted keys like `a."b.c"`.
|
||||
// `key` supports a small query syntax scheme:
|
||||
// Maps can be queried in "dotted" form e.g. `a.b.c`.
|
||||
// quoted keys are supported as `a."b.c"` or `a.'b.c'`.
|
||||
// Arrays can be queried with `a[0].b[1].[2]`.
|
||||
pub fn (m map[string]Any) value(key string) Any {
|
||||
key_split := parse_dotted_key(key) or { return Any(Null{}) }
|
||||
return m.value_(key_split)
|
||||
return Any(m).value(key)
|
||||
}
|
||||
|
||||
fn (m map[string]Any) value_(key []string) Any {
|
||||
value := m[key[0]] or { return Any(Null{}) }
|
||||
// `match` isn't currently very suitable for these types of sum type constructs...
|
||||
if value is map[string]Any {
|
||||
if key.len <= 1 {
|
||||
return value
|
||||
}
|
||||
nm := (value as map[string]Any)
|
||||
return nm.value_(key[1..])
|
||||
}
|
||||
return value
|
||||
// value queries a value from the array.
|
||||
// `key` supports a small query syntax scheme:
|
||||
// The array can be queried with `[0].b[1].[2]`.
|
||||
// Maps can be queried in "dotted" form e.g. `a.b.c`.
|
||||
// quoted keys are supported as `a."b.c"` or `a.'b.c'`.
|
||||
pub fn (a []Any) value(key string) Any {
|
||||
return Any(a).value(key)
|
||||
}
|
||||
|
||||
pub fn (a []Any) as_strings() []string {
|
||||
|
@ -190,3 +187,42 @@ pub fn (a []Any) as_strings() []string {
|
|||
}
|
||||
return sa
|
||||
}
|
||||
|
||||
// value queries a value from the `Any` type.
|
||||
// `key` supports a small query syntax scheme:
|
||||
// Maps can be queried in "dotted" form e.g. `a.b.c`.
|
||||
// quoted keys are supported as `a."b.c"` or `a.'b.c'`.
|
||||
// Arrays can be queried with `a[0].b[1].[2]`.
|
||||
pub fn (a Any) value(key string) Any {
|
||||
key_split := parse_dotted_key(key) or { return Any(Null{}) }
|
||||
return a.value_(a, key_split)
|
||||
}
|
||||
|
||||
// value_ returns the `Any` value found at `key`.
|
||||
fn (a Any) value_(value Any, key []string) Any {
|
||||
assert key.len > 0
|
||||
mut any_value := Any(Null{})
|
||||
k, index := parse_array_key(key[0])
|
||||
if k == '' {
|
||||
arr := value as []Any
|
||||
any_value = arr[index] or { return Any(Null{}) }
|
||||
}
|
||||
if value is map[string]Any {
|
||||
any_value = value[k] or { return Any(Null{}) }
|
||||
if index > -1 {
|
||||
arr := any_value as []Any
|
||||
any_value = arr[index] or { return Any(Null{}) }
|
||||
}
|
||||
}
|
||||
if key.len <= 1 {
|
||||
return any_value
|
||||
}
|
||||
match any_value {
|
||||
map[string]Any, []Any {
|
||||
return a.value_(any_value, key[1..])
|
||||
}
|
||||
else {
|
||||
return value
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,6 +15,22 @@ colors = [
|
|||
"yellow",
|
||||
[ "transparent" ]
|
||||
]
|
||||
|
||||
[[tests]]
|
||||
id = 1
|
||||
|
||||
[[tests]]
|
||||
id = 2
|
||||
|
||||
[values]
|
||||
test = 2
|
||||
|
||||
[[themes]]
|
||||
name = "Ice"
|
||||
colors = [
|
||||
"blue",
|
||||
"white"
|
||||
]
|
||||
'
|
||||
|
||||
fn test_value_query_in_array() {
|
||||
|
@ -29,4 +45,33 @@ fn test_value_query_in_array() {
|
|||
assert value == 'toml'
|
||||
value = toml_doc.value('errors[11]').default_to('<none>').string()
|
||||
assert value == '<none>'
|
||||
value = toml_doc.value('themes[2].colors[0]').string()
|
||||
assert value == 'blue'
|
||||
}
|
||||
|
||||
fn test_any_value_query() {
|
||||
toml_doc := toml.parse(toml_text) or { panic(err) }
|
||||
themes := toml_doc.value('themes')
|
||||
assert themes.value('[0].colors[0]').string() == 'red'
|
||||
|
||||
themes_arr := toml_doc.value('themes') as []toml.Any
|
||||
assert themes_arr[0].value('colors[0]').string() == 'red'
|
||||
|
||||
mut any := themes
|
||||
assert any.value('[1].name').string() == 'Lemon'
|
||||
any = any.value('[1]')
|
||||
assert any.value('name').string() == 'Lemon'
|
||||
|
||||
any = toml_doc.value('themes').value('[1].colors').value('[1]')
|
||||
assert any.string() == 'yellow'
|
||||
|
||||
any = toml_doc.value('themes[1]').value('colors[1]')
|
||||
assert any.string() == 'yellow'
|
||||
|
||||
any = toml_doc.value('themes[1].colors[0]')
|
||||
assert any.string() == 'green'
|
||||
|
||||
any = toml_doc.value('values')
|
||||
any = any.value('test')
|
||||
assert any.int() == 2
|
||||
}
|
||||
|
|
|
@ -150,6 +150,21 @@ pub fn parse_dotted_key(key string) ?[]string {
|
|||
return out
|
||||
}
|
||||
|
||||
// parse_array_key converts `key` string to a key and index part.
|
||||
fn parse_array_key(key string) (string, int) {
|
||||
mut index := -1
|
||||
mut k := key
|
||||
if k.contains('[') {
|
||||
index = k.all_after('[').all_before(']').int()
|
||||
if k.starts_with('[') {
|
||||
k = '' // k.all_after(']')
|
||||
} else {
|
||||
k = k.all_before('[')
|
||||
}
|
||||
}
|
||||
return k, index
|
||||
}
|
||||
|
||||
// to_any converts the `Doc` to toml.Any type.
|
||||
pub fn (d Doc) to_any() Any {
|
||||
return d.ast_to_any(d.ast.table)
|
||||
|
@ -169,16 +184,8 @@ pub fn (d Doc) value(key string) Any {
|
|||
fn (d Doc) value_(value ast.Value, key []string) Any {
|
||||
assert key.len > 0
|
||||
mut ast_value := ast.Value(ast.Null{})
|
||||
mut index := -1
|
||||
mut k := key[0]
|
||||
if k.contains('[') {
|
||||
index = k.all_after('[').all_before(']').int()
|
||||
if k.starts_with('[') {
|
||||
k = '' // k.all_after(']')
|
||||
} else {
|
||||
k = k.all_before('[')
|
||||
}
|
||||
}
|
||||
k, index := parse_array_key(key[0])
|
||||
|
||||
if k == '' {
|
||||
a := value as []ast.Value
|
||||
ast_value = a[index] or { return Any(Null{}) }
|
||||
|
@ -195,12 +202,15 @@ fn (d Doc) value_(value ast.Value, key []string) Any {
|
|||
if key.len <= 1 {
|
||||
return d.ast_to_any(ast_value)
|
||||
}
|
||||
// `match` isn't currently very suitable for these types of sum type constructs...
|
||||
if ast_value is map[string]ast.Value || ast_value is []ast.Value {
|
||||
match ast_value {
|
||||
map[string]ast.Value, []ast.Value {
|
||||
return d.value_(ast_value, key[1..])
|
||||
}
|
||||
else {
|
||||
return d.ast_to_any(value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ast_to_any converts `from` ast.Value to toml.Any value.
|
||||
pub fn (d Doc) ast_to_any(value ast.Value) Any {
|
||||
|
|
Loading…
Reference in New Issue