package hrana import ( "encoding/base64" "fmt" "strconv" "strings" "time" ) type Value struct { Type string `json:"type"` Value any `json:"value,omitempty"` Base64 string `json:"base64,omitempty"` } func (v Value) ToValue(columnType *string) any { if v.Type == "blob" { bytes, err := base64.StdEncoding.WithPadding(base64.NoPadding).DecodeString(v.Base64) if err != nil { return nil } return bytes } else if v.Type == "integer" { integer, err := strconv.ParseInt(v.Value.(string), 10, 64) if err != nil { return nil } return integer } else if columnType != nil { if (strings.ToLower(*columnType) == "timestamp" || strings.ToLower(*columnType) == "datetime") && v.Type == "text" { for _, format := range []string{ "2006-01-02 15:04:05.999999999-07:00", "2006-01-02T15:04:05.999999999-07:00", "2006-01-02 15:04:05.999999999", "2006-01-02T15:04:05.999999999", "2006-01-02 15:04:05", "2006-01-02T15:04:05", "2006-01-02 15:04", "2006-01-02T15:04", "2006-01-02", } { if t, err := time.ParseInLocation(format, v.Value.(string), time.UTC); err == nil { return t } } } } return v.Value } func ToValue(v any) (Value, error) { var res Value if v == nil { res.Type = "null" } else if integer, ok := v.(int64); ok { res.Type = "integer" res.Value = strconv.FormatInt(integer, 10) } else if integer, ok := v.(int); ok { res.Type = "integer" res.Value = strconv.FormatInt(int64(integer), 10) } else if text, ok := v.(string); ok { res.Type = "text" res.Value = text } else if blob, ok := v.([]byte); ok { res.Type = "blob" res.Base64 = base64.StdEncoding.WithPadding(base64.NoPadding).EncodeToString(blob) } else if float, ok := v.(float64); ok { res.Type = "float" res.Value = float } else if t, ok := v.(time.Time); ok { res.Type = "text" res.Value = t.Format("2006-01-02 15:04:05.999999999-07:00") } else if t, ok := v.(bool); ok { res.Type = "integer" res.Value = "0" if t { res.Value = "1" } } else { return res, fmt.Errorf("unsupported value type: %s", v) } return res, nil }