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.
|
// value queries a value from the map.
|
||||||
// `key` should be in "dotted" form (`a.b.c`).
|
// `key` supports a small query syntax scheme:
|
||||||
// `key` supports quoted keys like `a."b.c"`.
|
// 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 {
|
pub fn (m map[string]Any) value(key string) Any {
|
||||||
key_split := parse_dotted_key(key) or { return Any(Null{}) }
|
return Any(m).value(key)
|
||||||
return m.value_(key_split)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (m map[string]Any) value_(key []string) Any {
|
// value queries a value from the array.
|
||||||
value := m[key[0]] or { return Any(Null{}) }
|
// `key` supports a small query syntax scheme:
|
||||||
// `match` isn't currently very suitable for these types of sum type constructs...
|
// The array can be queried with `[0].b[1].[2]`.
|
||||||
if value is map[string]Any {
|
// Maps can be queried in "dotted" form e.g. `a.b.c`.
|
||||||
if key.len <= 1 {
|
// quoted keys are supported as `a."b.c"` or `a.'b.c'`.
|
||||||
return value
|
pub fn (a []Any) value(key string) Any {
|
||||||
}
|
return Any(a).value(key)
|
||||||
nm := (value as map[string]Any)
|
|
||||||
return nm.value_(key[1..])
|
|
||||||
}
|
|
||||||
return value
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (a []Any) as_strings() []string {
|
pub fn (a []Any) as_strings() []string {
|
||||||
|
@ -190,3 +187,42 @@ pub fn (a []Any) as_strings() []string {
|
||||||
}
|
}
|
||||||
return sa
|
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",
|
"yellow",
|
||||||
[ "transparent" ]
|
[ "transparent" ]
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[tests]]
|
||||||
|
id = 1
|
||||||
|
|
||||||
|
[[tests]]
|
||||||
|
id = 2
|
||||||
|
|
||||||
|
[values]
|
||||||
|
test = 2
|
||||||
|
|
||||||
|
[[themes]]
|
||||||
|
name = "Ice"
|
||||||
|
colors = [
|
||||||
|
"blue",
|
||||||
|
"white"
|
||||||
|
]
|
||||||
'
|
'
|
||||||
|
|
||||||
fn test_value_query_in_array() {
|
fn test_value_query_in_array() {
|
||||||
|
@ -29,4 +45,33 @@ fn test_value_query_in_array() {
|
||||||
assert value == 'toml'
|
assert value == 'toml'
|
||||||
value = toml_doc.value('errors[11]').default_to('<none>').string()
|
value = toml_doc.value('errors[11]').default_to('<none>').string()
|
||||||
assert value == '<none>'
|
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
|
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.
|
// to_any converts the `Doc` to toml.Any type.
|
||||||
pub fn (d Doc) to_any() Any {
|
pub fn (d Doc) to_any() Any {
|
||||||
return d.ast_to_any(d.ast.table)
|
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 {
|
fn (d Doc) value_(value ast.Value, key []string) Any {
|
||||||
assert key.len > 0
|
assert key.len > 0
|
||||||
mut ast_value := ast.Value(ast.Null{})
|
mut ast_value := ast.Value(ast.Null{})
|
||||||
mut index := -1
|
k, index := parse_array_key(key[0])
|
||||||
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('[')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if k == '' {
|
if k == '' {
|
||||||
a := value as []ast.Value
|
a := value as []ast.Value
|
||||||
ast_value = a[index] or { return Any(Null{}) }
|
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 {
|
if key.len <= 1 {
|
||||||
return d.ast_to_any(ast_value)
|
return d.ast_to_any(ast_value)
|
||||||
}
|
}
|
||||||
// `match` isn't currently very suitable for these types of sum type constructs...
|
match ast_value {
|
||||||
if ast_value is map[string]ast.Value || ast_value is []ast.Value {
|
map[string]ast.Value, []ast.Value {
|
||||||
return d.value_(ast_value, key[1..])
|
return d.value_(ast_value, key[1..])
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
return d.ast_to_any(value)
|
return d.ast_to_any(value)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ast_to_any converts `from` ast.Value to toml.Any value.
|
// ast_to_any converts `from` ast.Value to toml.Any value.
|
||||||
pub fn (d Doc) ast_to_any(value ast.Value) Any {
|
pub fn (d Doc) ast_to_any(value ast.Value) Any {
|
||||||
|
|
Loading…
Reference in New Issue