90 lines
2.1 KiB
Go
90 lines
2.1 KiB
Go
|
|
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" {
|
||
|
|
if v.Base64 == nil {
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
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"
|
||
|
|
b64 := base64.StdEncoding.WithPadding(base64.NoPadding).EncodeToString(blob)
|
||
|
|
res.Base64 = &b64
|
||
|
|
} 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
|
||
|
|
}
|