2018-09-18 22:42:38 +02:00
|
|
|
package core
|
|
|
|
|
|
|
|
import (
|
|
|
|
"encoding/json"
|
2018-11-07 20:52:25 +02:00
|
|
|
|
|
|
|
"github.com/pkg/errors"
|
2018-09-18 22:42:38 +02:00
|
|
|
)
|
|
|
|
|
2019-02-08 20:45:21 +02:00
|
|
|
//revive:disable-next-line:redefines-builtin-id
|
2018-09-18 22:42:38 +02:00
|
|
|
type Type int64
|
|
|
|
|
|
|
|
const (
|
|
|
|
NoneType Type = 0
|
|
|
|
BooleanType Type = 1
|
|
|
|
IntType Type = 2
|
|
|
|
FloatType Type = 3
|
|
|
|
StringType Type = 4
|
|
|
|
DateTimeType Type = 5
|
|
|
|
ArrayType Type = 6
|
|
|
|
ObjectType Type = 7
|
2018-10-05 22:35:08 +02:00
|
|
|
HTMLElementType Type = 8
|
|
|
|
HTMLDocumentType Type = 9
|
2018-09-18 22:42:38 +02:00
|
|
|
BinaryType Type = 10
|
2018-11-13 02:58:12 +02:00
|
|
|
CustomType Type = 99
|
2018-09-18 22:42:38 +02:00
|
|
|
)
|
|
|
|
|
|
|
|
var typestr = map[Type]string{
|
|
|
|
NoneType: "none",
|
|
|
|
BooleanType: "boolean",
|
|
|
|
IntType: "int",
|
|
|
|
FloatType: "float",
|
|
|
|
StringType: "string",
|
|
|
|
DateTimeType: "datetime",
|
|
|
|
ArrayType: "array",
|
|
|
|
ObjectType: "object",
|
2018-10-05 22:35:08 +02:00
|
|
|
HTMLElementType: "HTMLElement",
|
|
|
|
HTMLDocumentType: "HTMLDocument",
|
2018-09-18 22:42:38 +02:00
|
|
|
BinaryType: "BinaryType",
|
2018-11-13 02:58:12 +02:00
|
|
|
CustomType: "CustomType",
|
2018-09-18 22:42:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
func (t Type) String() string {
|
|
|
|
return typestr[t]
|
|
|
|
}
|
|
|
|
|
2018-11-07 20:52:25 +02:00
|
|
|
// Value represents an interface of
|
|
|
|
// any type that needs to be used during runtime
|
2018-09-18 22:42:38 +02:00
|
|
|
type Value interface {
|
|
|
|
json.Marshaler
|
|
|
|
Type() Type
|
|
|
|
String() string
|
|
|
|
Compare(other Value) int
|
|
|
|
Unwrap() interface{}
|
2018-10-05 21:17:22 +02:00
|
|
|
Hash() uint64
|
2018-10-12 17:58:08 +02:00
|
|
|
Copy() Value
|
2018-09-18 22:42:38 +02:00
|
|
|
}
|
|
|
|
|
2018-12-22 06:14:41 +02:00
|
|
|
// Getter represents an interface of
|
|
|
|
// complex types that needs to be used to read values by path.
|
|
|
|
// The interface is created to let user-defined types be used in dot notation data access.
|
|
|
|
type Getter interface {
|
|
|
|
GetIn(path []Value) (Value, error)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Setter represents an interface of
|
|
|
|
// complex types that needs to be used to write values by path.
|
|
|
|
// The interface is created to let user-defined types be used in dot notation assignment.
|
|
|
|
type Setter interface {
|
|
|
|
SetIn(path []Value, value Value) error
|
|
|
|
}
|
|
|
|
|
2018-11-07 20:52:25 +02:00
|
|
|
// IsTypeOf return true when value's type
|
|
|
|
// is equal to check type.
|
|
|
|
// Returns false, otherwise.
|
2018-09-18 22:42:38 +02:00
|
|
|
func IsTypeOf(value Value, check Type) bool {
|
|
|
|
return value.Type() == check
|
|
|
|
}
|
|
|
|
|
2018-11-07 20:52:25 +02:00
|
|
|
// ValidateType checks the match of
|
|
|
|
// value's type and required types.
|
2018-09-18 22:42:38 +02:00
|
|
|
func ValidateType(value Value, required ...Type) error {
|
|
|
|
var valid bool
|
|
|
|
ct := value.Type()
|
|
|
|
|
|
|
|
for _, t := range required {
|
|
|
|
if ct == t {
|
|
|
|
valid = true
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if !valid {
|
|
|
|
return TypeError(value.Type(), required...)
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
2018-11-07 20:52:25 +02:00
|
|
|
|
|
|
|
// PairValueType is a supporting
|
|
|
|
// structure that used in validateValueTypePairs.
|
|
|
|
type PairValueType struct {
|
|
|
|
Value Value
|
|
|
|
Types []Type
|
|
|
|
}
|
|
|
|
|
|
|
|
// ValidateValueTypePairs validate pairs of
|
|
|
|
// Values and Types.
|
|
|
|
// Returns error when type didn't match
|
|
|
|
func ValidateValueTypePairs(pairs ...PairValueType) error {
|
|
|
|
var err error
|
|
|
|
|
|
|
|
for idx, pair := range pairs {
|
|
|
|
err = ValidateType(pair.Value, pair.Types...)
|
|
|
|
if err != nil {
|
|
|
|
return errors.Errorf("pair %d: %v", idx, err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|