mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
add decoding of arrays and nested structs
This commit is contained in:
parent
6269eacb6f
commit
288257f9a4
@ -1,18 +1,25 @@
|
||||
import toml
|
||||
|
||||
enum Rank {
|
||||
low
|
||||
medium
|
||||
high
|
||||
enum JobTitle {
|
||||
worker
|
||||
executive
|
||||
manager
|
||||
}
|
||||
|
||||
struct Planet {
|
||||
name string
|
||||
population u64
|
||||
size f64
|
||||
avg_temp int
|
||||
has_water bool
|
||||
rank Rank
|
||||
struct Pet {
|
||||
name string
|
||||
nicknames []string
|
||||
age u64
|
||||
income int
|
||||
height f32
|
||||
has_furr bool
|
||||
title JobTitle
|
||||
address Address
|
||||
}
|
||||
|
||||
struct Address {
|
||||
street string
|
||||
city string
|
||||
}
|
||||
|
||||
struct Employee {
|
||||
@ -21,20 +28,39 @@ mut:
|
||||
age int
|
||||
salary f32
|
||||
is_human bool
|
||||
rank Rank
|
||||
title JobTitle
|
||||
}
|
||||
|
||||
struct Arrs {
|
||||
strs []string
|
||||
bools []bool
|
||||
ints []int
|
||||
i64s []i64
|
||||
u64s []u64
|
||||
f32s []f32
|
||||
f64s []f64
|
||||
dts []toml.DateTime
|
||||
dates []toml.Date
|
||||
times []toml.Time
|
||||
}
|
||||
|
||||
fn test_encode_and_decode() {
|
||||
p := Planet{'Mars', 0, 144.8, -81, true, .high}
|
||||
s := 'name = "Mars"
|
||||
population = 0
|
||||
size = 144.8
|
||||
avg_temp = -81
|
||||
has_water = true
|
||||
rank = 2'
|
||||
p := Pet{'Mr. Scratchy McEvilPaws', ['Freddy', 'Fred', 'Charles'], 8, -1, 0.8, true, .manager, Address{'1428 Elm Street', 'Springwood'}}
|
||||
s := 'name = "Mr. Scratchy McEvilPaws"
|
||||
nicknames = [
|
||||
"Freddy",
|
||||
"Fred",
|
||||
"Charles"
|
||||
]
|
||||
age = 8
|
||||
income = -1
|
||||
height = 0.8
|
||||
has_furr = true
|
||||
title = 2
|
||||
address = { street = "1428 Elm Street", city = "Springwood" }'
|
||||
|
||||
assert toml.encode[Planet](p) == s
|
||||
assert toml.decode[Planet](s)! == p
|
||||
assert toml.encode[Pet](p) == s
|
||||
assert toml.decode[Pet](s)! == p
|
||||
}
|
||||
|
||||
pub fn (e Employee) to_toml() string {
|
||||
@ -43,7 +69,7 @@ pub fn (e Employee) to_toml() string {
|
||||
mp['age'] = toml.Any(e.age)
|
||||
mp['salary'] = toml.Any(f32(e.salary) + 5000.0)
|
||||
mp['is_human'] = toml.Any(e.is_human)
|
||||
mp['rank'] = toml.Any(int(e.rank) + 1)
|
||||
mp['title'] = toml.Any(int(e.title) + 1)
|
||||
return mp.to_toml()
|
||||
}
|
||||
|
||||
@ -53,18 +79,18 @@ pub fn (mut e Employee) from_toml(any toml.Any) {
|
||||
e.age = mp['age'] or { toml.Any(0) }.int()
|
||||
e.salary = mp['salary'] or { toml.Any(0) }.f32() - 15000.0
|
||||
e.is_human = mp['is_human'] or { toml.Any(false) }.bool()
|
||||
e.rank = unsafe { Rank(mp['rank'] or { toml.Any(0) }.int() - 2) }
|
||||
e.title = unsafe { JobTitle(mp['title'] or { toml.Any(0) }.int() - 2) }
|
||||
}
|
||||
|
||||
fn test_custom_encode_and_decode() {
|
||||
x := Employee{'Peter', 28, 95000.5, true, .medium}
|
||||
x := Employee{'Peter', 28, 95000.5, true, .executive}
|
||||
s := toml.encode[Employee](x)
|
||||
eprintln('Employee x: ${s}')
|
||||
assert s == r'name = "Peter"
|
||||
age = 28
|
||||
salary = 100000.5
|
||||
is_human = true
|
||||
rank = 2'
|
||||
title = 2'
|
||||
|
||||
y := toml.decode[Employee](s) or {
|
||||
println(err)
|
||||
@ -76,5 +102,62 @@ rank = 2'
|
||||
assert y.age == 28
|
||||
assert y.salary == 85000.5
|
||||
assert y.is_human == true
|
||||
assert y.rank == .low
|
||||
assert y.title == .worker
|
||||
}
|
||||
|
||||
fn test_array_encode_decode() {
|
||||
a := Arrs{
|
||||
strs: ['foo', 'bar']
|
||||
bools: [true, false]
|
||||
ints: [-1, 2]
|
||||
i64s: [i64(-2)]
|
||||
u64s: [u64(123)]
|
||||
f32s: [f32(1.0), f32(2.5)]
|
||||
f64s: [100000.5, -123.0]
|
||||
dts: [toml.DateTime{'1979-05-27T07:32:00Z'}, toml.DateTime{'1979-05-27T07:32:00Z'}]
|
||||
dates: [toml.Date{'1979-05-27'}, toml.Date{'2022-12-31'}]
|
||||
times: [toml.Time{'07:32:59'}, toml.Time{'17:32:04'}]
|
||||
}
|
||||
|
||||
s := 'strs = [
|
||||
"foo",
|
||||
"bar"
|
||||
]
|
||||
bools = [
|
||||
true,
|
||||
false
|
||||
]
|
||||
ints = [
|
||||
-1,
|
||||
2
|
||||
]
|
||||
i64s = [
|
||||
-2
|
||||
]
|
||||
u64s = [
|
||||
123
|
||||
]
|
||||
f32s = [
|
||||
1.0,
|
||||
2.5
|
||||
]
|
||||
f64s = [
|
||||
100000.5,
|
||||
-123.0
|
||||
]
|
||||
dts = [
|
||||
1979-05-27T07:32:00Z,
|
||||
1979-05-27T07:32:00Z
|
||||
]
|
||||
dates = [
|
||||
1979-05-27,
|
||||
2022-12-31
|
||||
]
|
||||
times = [
|
||||
07:32:59,
|
||||
17:32:04
|
||||
]'
|
||||
|
||||
assert toml.encode[Arrs](a) == s
|
||||
assert toml.decode[Arrs](s)! == a
|
||||
}
|
||||
|
@ -7,7 +7,6 @@ import toml.ast
|
||||
import toml.input
|
||||
import toml.scanner
|
||||
import toml.parser
|
||||
import time
|
||||
|
||||
// Null is used in sumtype checks as a "default" value when nothing else is possible.
|
||||
pub struct Null {
|
||||
@ -24,37 +23,63 @@ pub fn decode[T](toml_txt string) !T {
|
||||
return typ
|
||||
}
|
||||
}
|
||||
typ = decode_struct[T](doc.to_any())
|
||||
decode_struct[T](doc.to_any(), mut typ)
|
||||
return typ
|
||||
}
|
||||
|
||||
fn decode_struct[T](doc Any) T {
|
||||
mut typ := T{}
|
||||
fn decode_struct[T](doc Any, mut typ T) {
|
||||
$for field in T.fields {
|
||||
value := doc.value(field.name)
|
||||
$if field.is_enum {
|
||||
typ.$(field.name) = doc.value(field.name).int()
|
||||
typ.$(field.name) = value.int()
|
||||
} $else $if field.typ is string {
|
||||
typ.$(field.name) = doc.value(field.name).string()
|
||||
typ.$(field.name) = value.string()
|
||||
} $else $if field.typ is bool {
|
||||
typ.$(field.name) = doc.value(field.name).bool()
|
||||
typ.$(field.name) = value.bool()
|
||||
} $else $if field.typ is int {
|
||||
typ.$(field.name) = doc.value(field.name).int()
|
||||
typ.$(field.name) = value.int()
|
||||
} $else $if field.typ is i64 {
|
||||
typ.$(field.name) = doc.value(field.name).i64()
|
||||
typ.$(field.name) = value.i64()
|
||||
} $else $if field.typ is u64 {
|
||||
typ.$(field.name) = doc.value(field.name).u64()
|
||||
typ.$(field.name) = value.u64()
|
||||
} $else $if field.typ is f32 {
|
||||
typ.$(field.name) = doc.value(field.name).f32()
|
||||
typ.$(field.name) = value.f32()
|
||||
} $else $if field.typ is f64 {
|
||||
typ.$(field.name) = doc.value(field.name).f64()
|
||||
typ.$(field.name) = value.f64()
|
||||
} $else $if field.is_array {
|
||||
arr := value.array()
|
||||
match typeof(typ.$(field.name)).name {
|
||||
'[]string' { typ.$(field.name) = arr.as_strings() }
|
||||
'[]int' { typ.$(field.name) = arr.map(it.int()) }
|
||||
'[]i64' { typ.$(field.name) = arr.map(it.i64()) }
|
||||
'[]u64' { typ.$(field.name) = arr.map(it.u64()) }
|
||||
'[]f32' { typ.$(field.name) = arr.map(it.f32()) }
|
||||
'[]f64' { typ.$(field.name) = arr.map(it.f64()) }
|
||||
'[]bool' { typ.$(field.name) = arr.map(it.bool()) }
|
||||
'[]toml.DateTime' { typ.$(field.name) = arr.map(it.datetime()) }
|
||||
'[]toml.Date' { typ.$(field.name) = arr.map(it.date()) }
|
||||
'[]toml.Time' { typ.$(field.name) = arr.map(it.time()) }
|
||||
else {}
|
||||
}
|
||||
} $else $if field.is_struct {
|
||||
// typ.$(field.name) = decode_struct(doc.value(field.name))
|
||||
} $else $if field.typ is time.Time {
|
||||
// TODO: extend
|
||||
typ.$(field.name) = doc.value(field.name).datetime()
|
||||
match typeof(typ.$(field.name)).name {
|
||||
'toml.DateTime' {
|
||||
// typ.$(field.name) = DateTime{value.string()}
|
||||
}
|
||||
'toml.Date' {
|
||||
// typ.$(field.name) = Date{value.string()}
|
||||
}
|
||||
'toml.Time' {
|
||||
// typ.$(field.name) = Time{value.string()}
|
||||
}
|
||||
else {
|
||||
mut s := typ.$(field.name)
|
||||
decode_struct(value, mut s)
|
||||
typ.$(field.name) = s
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return typ
|
||||
}
|
||||
|
||||
// encode encodes the type `T` into a TOML string.
|
||||
@ -77,6 +102,12 @@ fn encode_struct[T](typ T) map[string]Any {
|
||||
mp[field.name] = Any(int(value))
|
||||
} $else $if field.is_struct {
|
||||
mp[field.name] = encode_struct(value)
|
||||
} $else $if field.is_array {
|
||||
mut arr := []Any{}
|
||||
for v in value {
|
||||
arr << Any(v)
|
||||
}
|
||||
mp[field.name] = arr
|
||||
} $else {
|
||||
mp[field.name] = Any(value)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user