1 package testsuite
2
3 import (
4 "fmt"
5 "strconv"
6 "time"
7
8 "github.com/pelletier/go-toml/v2"
9 )
10
11
12 func rmTag(typedJson interface{}) (interface{}, error) {
13
14 in := func(key string, m map[string]interface{}) bool {
15 _, ok := m[key]
16 return ok
17 }
18
19
20 switch v := typedJson.(type) {
21
22
23 case map[string]interface{}:
24
25
26 if len(v) == 2 && in("type", v) && in("value", v) {
27 ut, err := untag(v)
28 if err != nil {
29 return ut, fmt.Errorf("tag.Remove: %w", err)
30 }
31 return ut, nil
32 }
33
34
35 m := make(map[string]interface{}, len(v))
36 for k, v2 := range v {
37 var err error
38 m[k], err = rmTag(v2)
39 if err != nil {
40 return nil, err
41 }
42 }
43 return m, nil
44
45
46 case []interface{}:
47 a := make([]interface{}, len(v))
48 for i := range v {
49 var err error
50 a[i], err = rmTag(v[i])
51 if err != nil {
52 return nil, err
53 }
54 }
55 return a, nil
56 }
57
58
59 return nil, fmt.Errorf("unrecognized JSON format '%T'", typedJson)
60 }
61
62
63 func untag(typed map[string]interface{}) (interface{}, error) {
64 t := typed["type"].(string)
65 v := typed["value"].(string)
66 switch t {
67 case "string":
68 return v, nil
69 case "integer":
70 n, err := strconv.ParseInt(v, 10, 64)
71 if err != nil {
72 return nil, fmt.Errorf("untag: %w", err)
73 }
74 return n, nil
75 case "float":
76 f, err := strconv.ParseFloat(v, 64)
77 if err != nil {
78 return nil, fmt.Errorf("untag: %w", err)
79 }
80 return f, nil
81
82
83 case "datetime":
84 return time.Parse("2006-01-02T15:04:05.999999999Z07:00", v)
85 case "datetime-local":
86 var t toml.LocalDateTime
87 err := t.UnmarshalText([]byte(v))
88 if err != nil {
89 return nil, fmt.Errorf("untag: %w", err)
90 }
91 return t, nil
92 case "date-local":
93 var t toml.LocalDate
94 err := t.UnmarshalText([]byte(v))
95 if err != nil {
96 return nil, fmt.Errorf("untag: %w", err)
97 }
98 return t, nil
99 case "time-local":
100 var t toml.LocalTime
101 err := t.UnmarshalText([]byte(v))
102 if err != nil {
103 return nil, fmt.Errorf("untag: %w", err)
104 }
105 return t, nil
106 case "bool":
107 switch v {
108 case "true":
109 return true, nil
110 case "false":
111 return false, nil
112 }
113 return nil, fmt.Errorf("untag: could not parse %q as a boolean", v)
114 }
115
116 return nil, fmt.Errorf("untag: unrecognized tag type %q", t)
117 }
118
119 func parseTime(v, format string, local bool) (t time.Time, err error) {
120 if local {
121 t, err = time.ParseInLocation(format, v, time.Local)
122 } else {
123 t, err = time.Parse(format, v)
124 }
125 if err != nil {
126 return time.Time{}, fmt.Errorf("Could not parse %q as a datetime: %w", v, err)
127 }
128 return t, nil
129 }
130
View as plain text