erp_server/config/internal/value.go
2022-10-09 11:39:33 +08:00

120 lines
2.2 KiB
Go

package internal
import (
"encoding/json"
"fmt"
"google.golang.org/protobuf/encoding/protojson"
"google.golang.org/protobuf/proto"
"strconv"
"sync/atomic"
)
var (
_ Value = (*atomicValue)(nil)
_ Value = (*errValue)(nil)
)
// Value is config value interface.
type Value interface {
Bool() bool
Int() int64
Float() float64
String() string
Scan(interface{}) error
Load() interface{}
Store(interface{})
}
type atomicValue struct {
atomic.Value
}
func (v *atomicValue) Bool() bool {
switch val := v.Load().(type) {
case bool:
return val
case int, int32, int64, float64, string:
v, err := strconv.ParseBool(fmt.Sprint(val))
if err == nil {
return v
}
}
return false
}
func (v *atomicValue) Int() int64 {
switch val := v.Load().(type) {
case int:
return int64(val)
case int32:
return int64(val)
case int64:
return val
case float64:
return int64(val)
case string:
v, err := strconv.ParseInt(val, 10, 64)
if err == nil {
return v
}
}
return 0
}
func (v *atomicValue) Float() float64 {
switch val := v.Load().(type) {
case float64:
return val
case int:
return float64(val)
case int32:
return float64(val)
case int64:
return float64(val)
case string:
v, err := strconv.ParseFloat(val, 64)
if err == nil {
return v
}
}
return 0.0
}
func (v *atomicValue) String() string {
switch val := v.Load().(type) {
case string:
return val
case bool, int, int32, int64, float64:
return fmt.Sprint(val)
case []byte:
return string(val)
default:
if s, ok := val.(fmt.Stringer); ok {
return s.String()
}
}
return ""
}
func (v *atomicValue) Scan(obj interface{}) error {
data, err := json.Marshal(v.Load())
if err != nil {
return err
}
if pb, ok := obj.(proto.Message); ok {
return protojson.Unmarshal(data, pb)
}
return json.Unmarshal(data, obj)
}
type errValue struct {
err error
}
func (v errValue) Bool() bool { return false }
func (v errValue) Int() int64 { return 0 }
func (v errValue) Float() float64 { return 0.0 }
func (v errValue) String() string { return "" }
func (v errValue) Scan(interface{}) error { return v.err }
func (v errValue) Load() interface{} { return nil }
func (v errValue) Store(interface{}) {}