toml: add `encode<T>` and `decode<T>` (#13244)

pull/13246/head
Larpon 2022-01-21 20:21:31 +01:00 committed by GitHub
parent 7ae96f0e38
commit 2b4f7e7685
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 147 additions and 0 deletions

View File

@ -33,6 +33,41 @@ pub fn (a Any) string() string {
}
}
// to_toml returns `Any` as a TOML encoded value.
pub fn (a Any) to_toml() string {
match a {
map[string]Any {
// TODO more format control?
return a.to_inline_toml()
}
[]Any {
return a.to_toml()
}
bool, f32, f64, i64, int, u64 {
return a.str().clone()
}
// NOTE if `.clone()` is not used here:
// string { return a as string }
// ... certain call-patterns to this function will cause a memory corruption.
// See `tests/toml_memory_corruption_test.v` for a matching regression test.
string {
return '"' + (a as string).clone() + '"'
}
DateTime {
return a.str().clone()
}
Date {
return a.str().clone()
}
Time {
return a.str().clone()
}
else {
return a.str().clone()
}
}
}
// int returns `Any` as an 32-bit integer.
pub fn (a Any) int() int {
match a {
@ -181,6 +216,35 @@ pub fn (m map[string]Any) as_strings() map[string]string {
return result
}
// to_toml returns the contents of the map
// as a TOML encoded `string`.
pub fn (m map[string]Any) to_toml() string {
mut toml_text := ''
for k, v in m {
mut key := k
if key.contains(' ') {
key = '"$key"'
}
toml_text += '$key = ' + v.to_toml() + '\n'
}
toml_text = toml_text.trim_right('\n')
return toml_text
}
// to_inline_toml returns the contents of the map
// as an inline table encoded TOML `string`.
pub fn (m map[string]Any) to_inline_toml() string {
mut toml_text := '{'
for k, v in m {
mut key := k
if key.contains(' ') {
key = '"$key"'
}
toml_text += ' $key = ' + v.to_toml() + ','
}
return toml_text + ' }'
}
// value queries a value from the array.
// `key` supports a small query syntax scheme:
// The array can be queried with `[0].b[1].[2]`.
@ -200,6 +264,17 @@ pub fn (a []Any) as_strings() []string {
return sa
}
// to_toml returns the contents of the array
// as a TOML encoded `string`.
pub fn (a []Any) to_toml() string {
mut toml_text := '[\n'
for any in a {
toml_text += ' ' + any.to_toml() + ',\n'
}
toml_text = toml_text.trim_right(',\n')
return toml_text + '\n]'
}
// 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`.

View File

@ -0,0 +1,58 @@
import toml
enum JobTitle {
manager
executive
worker
}
struct Employee {
pub mut:
name string
age int
salary f32
is_human bool
title JobTitle
}
fn (e Employee) to_toml() string {
mut mp := map[string]toml.Any{}
mp['name'] = toml.Any(e.name)
mp['age'] = toml.Any(e.age)
mp['salary'] = toml.Any(e.salary)
mp['is_human'] = toml.Any(e.is_human)
mp['title'] = toml.Any(int(e.title))
return mp.to_toml()
}
fn (mut e Employee) from_toml(any toml.Any) {
mp := any.as_map()
e.name = mp['name'] or { toml.Any('') }.string()
e.age = mp['age'] or { toml.Any(0) }.int()
e.salary = mp['salary'] or { toml.Any(0) }.f32()
e.is_human = mp['is_human'] or { toml.Any(false) }.bool()
e.title = JobTitle(mp['title'] or { toml.Any(0) }.int())
}
fn test_encode_and_decode() {
x := Employee{'Peter', 28, 95000.5, true, .worker}
s := toml.encode<Employee>(x)
eprintln('Employee x: $s')
assert s == r'name = "Peter"
age = 28
salary = 95000.5
is_human = true
title = 2'
y := toml.decode<Employee>(s) or {
println(err)
assert false
return
}
eprintln('Employee y: $y')
assert y.name == 'Peter'
assert y.age == 28
assert y.salary == 95000.5
assert y.is_human == true
assert y.title == .worker
}

View File

@ -12,6 +12,20 @@ import toml.parser
pub struct Null {
}
// decode decodes a TOML `string` into the target type `T`.
pub fn decode<T>(toml_txt string) ?T {
doc := parse_text(toml_txt) ?
mut typ := T{}
typ.from_toml(doc.to_any())
return typ
}
// encode encodes the type `T` into a JSON string.
// Currently encode expects the method `.to_toml()` exists on `T`.
pub fn encode<T>(typ T) string {
return typ.to_toml()
}
// DateTime is the representation of an RFC 3339 datetime string.
pub struct DateTime {
datetime string