git.sr.ht/~pingoo/stdx@v0.0.0-20240218134121-094174641f6e/toml/internal/tag/add.go (about) 1 package tag 2 3 import ( 4 "fmt" 5 "math" 6 "time" 7 8 "git.sr.ht/~pingoo/stdx/toml/internal" 9 ) 10 11 // Add JSON tags to a data structure as expected by toml-test. 12 func Add(key string, tomlData interface{}) interface{} { 13 // Switch on the data type. 14 switch orig := tomlData.(type) { 15 default: 16 panic(fmt.Sprintf("Unknown type: %T", tomlData)) 17 18 // A table: we don't need to add any tags, just recurse for every table 19 // entry. 20 case map[string]interface{}: 21 typed := make(map[string]interface{}, len(orig)) 22 for k, v := range orig { 23 typed[k] = Add(k, v) 24 } 25 return typed 26 27 // An array: we don't need to add any tags, just recurse for every table 28 // entry. 29 case []map[string]interface{}: 30 typed := make([]map[string]interface{}, len(orig)) 31 for i, v := range orig { 32 typed[i] = Add("", v).(map[string]interface{}) 33 } 34 return typed 35 case []interface{}: 36 typed := make([]interface{}, len(orig)) 37 for i, v := range orig { 38 typed[i] = Add("", v) 39 } 40 return typed 41 42 // Datetime: tag as datetime. 43 case time.Time: 44 switch orig.Location() { 45 default: 46 return tag("datetime", orig.Format("2006-01-02T15:04:05.999999999Z07:00")) 47 case internal.LocalDatetime: 48 return tag("datetime-local", orig.Format("2006-01-02T15:04:05.999999999")) 49 case internal.LocalDate: 50 return tag("date-local", orig.Format("2006-01-02")) 51 case internal.LocalTime: 52 return tag("time-local", orig.Format("15:04:05.999999999")) 53 } 54 55 // Tag primitive values: bool, string, int, and float64. 56 case bool: 57 return tag("bool", fmt.Sprintf("%v", orig)) 58 case string: 59 return tag("string", orig) 60 case int64: 61 return tag("integer", fmt.Sprintf("%d", orig)) 62 case float64: 63 // Special case for nan since NaN == NaN is false. 64 if math.IsNaN(orig) { 65 return tag("float", "nan") 66 } 67 return tag("float", fmt.Sprintf("%v", orig)) 68 } 69 } 70 71 func tag(typeName string, data interface{}) map[string]interface{} { 72 return map[string]interface{}{ 73 "type": typeName, 74 "value": data, 75 } 76 }