diff --git a/vlib/toml/tests/encode_and_decode_test.v b/vlib/toml/tests/encode_and_decode_test.v index f69fbdb2700fcd..d9253021980346 100644 --- a/vlib/toml/tests/encode_and_decode_test.v +++ b/vlib/toml/tests/encode_and_decode_test.v @@ -149,6 +149,47 @@ fn test_custom_encode_of_complex_struct() { ]' } +struct Example3 { + arr_arr [][]Problem +} + +struct Example4 { + mp map[string]Problem +} + +pub fn (example Example3) to_toml() string { + return '[This is Valid]' +} + +pub fn (example Example4) to_toml() string { + return '[This is Valid]' +} + +fn test_custom_encode_of_nested_complex_struct() { + assert toml.encode(Example3{}) == '[This is Valid]' + assert toml.encode(Example4{}) == '[This is Valid]' +} + +struct Example5 { + mp map[string]Problem +} + +fn test_map_encode_of_complex_struct() { + mut mp := map[string]Problem{} + mp['key_one'] = Problem{} + mp['key_two'] = Problem{} + assert toml.encode(Example5{ mp: mp }) == 'mp = { key_one = "a problem", key_two = "a problem" }' +} + +struct Example6 { + ptr voidptr + r rune +} + +fn test_encode_for_exotic_types() { + assert toml.encode(Example6{ ptr: &voidptr(0), r: `🚀` }) == 'ptr = "0x0"\nr = "🚀"' +} + fn test_array_encode_decode() { a := Arrs{ strs: ['foo', 'bar'] diff --git a/vlib/toml/toml.v b/vlib/toml/toml.v index faeacc8f50be69..80dc901032b10f 100644 --- a/vlib/toml/toml.v +++ b/vlib/toml/toml.v @@ -93,32 +93,54 @@ pub fn encode[T](typ T) string { fn encode_struct[T](typ T) map[string]Any { mut mp := map[string]Any{} $for field in T.fields { - value := typ.$(field.name) - $if field.is_enum { - 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 { - $if v is Date { - arr << Any(v) - } $else $if v is Time { - arr << Any(v) - } $else $if v is DateTime { - arr << Any(v) - } $else $if v is $struct { - arr << Any(encode(v)) - } $else { - arr << Any(v) - } + mp[field.name] = to_any(typ.$(field.name)) + } + return mp +} + +fn to_any[T](value T) Any { + $if T is $enum { + return Any(int(value)) + } $else $if T is Date { + return Any(value) + } $else $if T is Time { + return Any(value) + } $else $if T is Null { + return Any(value) + } $else $if T is bool { + return Any(value) + } $else $if T is $float { + return Any(value) + } $else $if T is i64 { + return Any(value) + } $else $if T is int { + return Any(value) + } $else $if T is u64 { + return Any(value) + } $else $if T is DateTime { + return Any(value) + } $else $if T is $struct { + $for method in T.methods { + $if method.name == 'to_toml' { + return Any(value.$method()) } - mp[field.name] = arr - } $else { - mp[field.name] = Any(value) } + return encode_struct(value) + } $else $if T is $array { + mut arr := []Any{cap: value.len} + for v in value { + arr << to_any(v) + } + return arr + } $else $if T is $map { + mut mmap := map[string]Any{} + for key, val in value { + mmap['${key}'] = to_any(val) + } + return mmap + } $else { + return Any('${value}') } - return mp } // DateTime is the representation of an RFC 3339 datetime string.