Skip to content

Commit 3fb1230

Browse files
authored
toml: fix toml encoding of complex types (#19408)
* Improve default toml encoder for complex types The default toml encoder failed for more complex structs, as certain edge cases were not covered. This commit attempts to fix this by adding additional handling for these edge cases. * Improve map encoding Since maps currently only support keys that have a string representation, we can utilize this during map encoding. * Add test cases for toml encoding Added test cases for toml encoding of complex nested structs and structs that contain maps. * Add additional test cases
1 parent edc9ff4 commit 3fb1230

File tree

2 files changed

+86
-23
lines changed

2 files changed

+86
-23
lines changed

vlib/toml/tests/encode_and_decode_test.v

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,47 @@ fn test_custom_encode_of_complex_struct() {
149149
]'
150150
}
151151

152+
struct Example3 {
153+
arr_arr [][]Problem
154+
}
155+
156+
struct Example4 {
157+
mp map[string]Problem
158+
}
159+
160+
pub fn (example Example3) to_toml() string {
161+
return '[This is Valid]'
162+
}
163+
164+
pub fn (example Example4) to_toml() string {
165+
return '[This is Valid]'
166+
}
167+
168+
fn test_custom_encode_of_nested_complex_struct() {
169+
assert toml.encode(Example3{}) == '[This is Valid]'
170+
assert toml.encode(Example4{}) == '[This is Valid]'
171+
}
172+
173+
struct Example5 {
174+
mp map[string]Problem
175+
}
176+
177+
fn test_map_encode_of_complex_struct() {
178+
mut mp := map[string]Problem{}
179+
mp['key_one'] = Problem{}
180+
mp['key_two'] = Problem{}
181+
assert toml.encode(Example5{ mp: mp }) == 'mp = { key_one = "a problem", key_two = "a problem" }'
182+
}
183+
184+
struct Example6 {
185+
ptr voidptr
186+
r rune
187+
}
188+
189+
fn test_encode_for_exotic_types() {
190+
assert toml.encode(Example6{ ptr: &voidptr(0), r: `🚀` }) == 'ptr = "0x0"\nr = "🚀"'
191+
}
192+
152193
fn test_array_encode_decode() {
153194
a := Arrs{
154195
strs: ['foo', 'bar']

vlib/toml/toml.v

Lines changed: 45 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -93,32 +93,54 @@ pub fn encode[T](typ T) string {
9393
fn encode_struct[T](typ T) map[string]Any {
9494
mut mp := map[string]Any{}
9595
$for field in T.fields {
96-
value := typ.$(field.name)
97-
$if field.is_enum {
98-
mp[field.name] = Any(int(value))
99-
} $else $if field.is_struct {
100-
mp[field.name] = encode_struct(value)
101-
} $else $if field.is_array {
102-
mut arr := []Any{}
103-
for v in value {
104-
$if v is Date {
105-
arr << Any(v)
106-
} $else $if v is Time {
107-
arr << Any(v)
108-
} $else $if v is DateTime {
109-
arr << Any(v)
110-
} $else $if v is $struct {
111-
arr << Any(encode(v))
112-
} $else {
113-
arr << Any(v)
114-
}
96+
mp[field.name] = to_any(typ.$(field.name))
97+
}
98+
return mp
99+
}
100+
101+
fn to_any[T](value T) Any {
102+
$if T is $enum {
103+
return Any(int(value))
104+
} $else $if T is Date {
105+
return Any(value)
106+
} $else $if T is Time {
107+
return Any(value)
108+
} $else $if T is Null {
109+
return Any(value)
110+
} $else $if T is bool {
111+
return Any(value)
112+
} $else $if T is $float {
113+
return Any(value)
114+
} $else $if T is i64 {
115+
return Any(value)
116+
} $else $if T is int {
117+
return Any(value)
118+
} $else $if T is u64 {
119+
return Any(value)
120+
} $else $if T is DateTime {
121+
return Any(value)
122+
} $else $if T is $struct {
123+
$for method in T.methods {
124+
$if method.name == 'to_toml' {
125+
return Any(value.$method())
115126
}
116-
mp[field.name] = arr
117-
} $else {
118-
mp[field.name] = Any(value)
119127
}
128+
return encode_struct(value)
129+
} $else $if T is $array {
130+
mut arr := []Any{cap: value.len}
131+
for v in value {
132+
arr << to_any(v)
133+
}
134+
return arr
135+
} $else $if T is $map {
136+
mut mmap := map[string]Any{}
137+
for key, val in value {
138+
mmap['${key}'] = to_any(val)
139+
}
140+
return mmap
141+
} $else {
142+
return Any('${value}')
120143
}
121-
return mp
122144
}
123145

124146
// DateTime is the representation of an RFC 3339 datetime string.

0 commit comments

Comments
 (0)