| 1 | type StringAlias = string |
| 2 | type BoolAlias = bool |
| 3 | type IntAlias = int |
| 4 | |
| 5 | struct Decoder { |
| 6 | json string |
| 7 | } |
| 8 | |
| 9 | pub fn decode[T](val string) !T { |
| 10 | mut decoder := Decoder{ |
| 11 | json: val |
| 12 | } |
| 13 | |
| 14 | mut result := T{} |
| 15 | decoder.decode_value(mut result)! |
| 16 | return result |
| 17 | } |
| 18 | |
| 19 | fn (mut decoder Decoder) decode_value[T](mut val T) ! { |
| 20 | $if T.unaliased_typ is string { |
| 21 | } $else $if T.unaliased_typ in [$int, $float, $enum] { |
| 22 | bytes := unsafe { decoder.json.str.vbytes(decoder.json.len) } |
| 23 | unsafe { |
| 24 | string_buffer_to_generic_number(mut val, bytes) |
| 25 | } |
| 26 | } $else { |
| 27 | return error('cannot encode value with ${typeof(val).name} type') |
| 28 | } |
| 29 | } |
| 30 | |
| 31 | @[direct_array_access; unsafe] |
| 32 | pub fn string_buffer_to_generic_number[T](mut result T, data []u8) { |
| 33 | $if T is $option { |
| 34 | } $else $if T.unaliased_typ is string { |
| 35 | panic('should not happens') |
| 36 | } $else $if T.unaliased_typ is $int { |
| 37 | mut is_negative := false |
| 38 | for ch in data { |
| 39 | if ch == `-` { |
| 40 | is_negative = true |
| 41 | continue |
| 42 | } |
| 43 | digit := T(ch - `0`) |
| 44 | result = T(*result * 10 + digit) |
| 45 | } |
| 46 | if is_negative { |
| 47 | result *= -1 |
| 48 | } |
| 49 | } $else { |
| 50 | panic('unsupported type ${typeof[T]().name}') |
| 51 | } |
| 52 | } |
| 53 | |
| 54 | fn test_main() { |
| 55 | value := '1234567890123456789' |
| 56 | _ := decode[int](value)! |
| 57 | _ := decode[IntAlias](value)! |
| 58 | _ := decode[StringAlias]('"abcd"')! |
| 59 | _ := decode[int](value)! |
| 60 | _ := decode[string]('"abcd"')! |
| 61 | |
| 62 | assert true |
| 63 | } |
| 64 | |