func (p *Primitive) IsNumericType() bool {
	t := p.valueType
	return t == Integer || t == Long || t == Double
}
IsNumericType checks for numeric types.
package json
import (
	"encoding/binary"
	"fmt"
	"math"
	gotime "time"
	"github.com/yorkie-team/yorkie/pkg/document/time"
)
type ValueType int
const (
	Null ValueType = iota
	Boolean
	Integer
	Long
	Double
	String
	Bytes
	Date
)
func ValueFromBytes(valueType ValueType, value []byte) interface{} {
	switch valueType {
	case Null:
		return nil
	case Boolean:
		if value[0] == 1 {
			return true
		}
		return false
	case Integer:
		val := int32(binary.LittleEndian.Uint32(value))
		return int(val)
	case Long:
		return int64(binary.LittleEndian.Uint64(value))
	case Double:
		return math.Float64frombits(binary.LittleEndian.Uint64(value))
	case String:
		return string(value)
	case Bytes:
		return value
	case Date:
		v := int64(binary.LittleEndian.Uint64(value))
		return gotime.Unix(v, 0)
	}
	panic("unsupported type")
}
type Primitive struct {
	valueType ValueType
	value     interface{}
	createdAt *time.Ticket
	movedAt   *time.Ticket
	removedAt *time.Ticket
}
func NewPrimitive(value interface{}, createdAt *time.Ticket) *Primitive {
	if value == nil {
		return &Primitive{
			valueType: Null,
			value:     nil,
			createdAt: createdAt,
		}
	}
	switch val := value.(type) {
	case bool:
		return &Primitive{
			valueType: Boolean,
			value:     val,
			createdAt: createdAt,
		}
	case int:
		if val > math.MaxInt32 || val < math.MinInt32 {
			return &Primitive{
				valueType: Long,
				value:     int64(val),
				createdAt: createdAt,
			}
		}
		return &Primitive{
			valueType: Integer,
			value:     val,
			createdAt: createdAt,
		}
	case int64:
		return &Primitive{
			valueType: Long,
			value:     val,
			createdAt: createdAt,
		}
	case float64:
		return &Primitive{
			valueType: Double,
			value:     val,
			createdAt: createdAt,
		}
	case string:
		return &Primitive{
			valueType: String,
			value:     val,
			createdAt: createdAt,
		}
	case []byte:
		return &Primitive{
			valueType: Bytes,
			value:     val,
			createdAt: createdAt,
		}
	case gotime.Time:
		return &Primitive{
			valueType: Date,
			value:     val,
			createdAt: createdAt,
		}
	}
	panic("unsupported type")
}
func (p *Primitive) Bytes() []byte {
	if p.valueType == Null {
		return nil
	}
	switch val := p.value.(type) {
	case bool:
		if val {
			return []byte{1}
		}
		return []byte{0}
	case int:
		bytes := [4]byte{}
		binary.LittleEndian.PutUint32(bytes[:], uint32(val))
		return bytes[:]
	case int64:
		bytes := [8]byte{}
		binary.LittleEndian.PutUint64(bytes[:], uint64(val))
		return bytes[:]
	case float64:
		bytes := [8]byte{}
		binary.LittleEndian.PutUint64(bytes[:], math.Float64bits(val))
		return bytes[:]
	case string:
		return []byte(val)
	case []byte:
		return val
	case gotime.Time:
		bytes := [8]byte{}
		binary.LittleEndian.PutUint64(bytes[:], uint64(val.UTC().Unix()))
		return bytes[:]
	}
	panic("unsupported type")
}
func (p *Primitive) Marshal() string {
	switch p.valueType {
	case Null:
		return "null"
	case Boolean:
		return fmt.Sprintf("%t", p.value)
	case Integer:
		return fmt.Sprintf("%d", p.value)
	case Long:
		return fmt.Sprintf("%d", p.value)
	case Double:
		return fmt.Sprintf("%f", p.value)
	case String:
		return fmt.Sprintf("\"%s\"", p.value)
	case Bytes:
		return fmt.Sprintf("\"%s\"", p.value)
	case Date:
		return p.value.(gotime.Time).Format(gotime.RFC3339)
	}
	panic("unsupported type")
}
func (p *Primitive) DeepCopy() Element {
	primitive := *p
	return &primitive
}
func (p *Primitive) CreatedAt() *time.Ticket {
	return p.createdAt
}
func (p *Primitive) MovedAt() *time.Ticket {
	return p.movedAt
}
func (p *Primitive) SetMovedAt(movedAt *time.Ticket) {
	p.movedAt = movedAt
}
func (p *Primitive) RemovedAt() *time.Ticket {
	return p.removedAt
}
func (p *Primitive) SetRemovedAt(removedAt *time.Ticket) {
	p.removedAt = removedAt
}
func (p *Primitive) Remove(removedAt *time.Ticket) bool {
	if (removedAt != nil && removedAt.After(p.createdAt)) &&
		(p.removedAt == nil || removedAt.After(p.removedAt)) {
		p.removedAt = removedAt
		return true
	}
	return false
}
func (p *Primitive) Value() interface{} {
	return p.value
}
func (p *Primitive) ValueType() ValueType {
	return p.valueType
}