mirror of
https://github.com/PretendoNetwork/nex-go.git
synced 2025-04-02 11:02:14 -04:00
141 lines
3.4 KiB
Go
141 lines
3.4 KiB
Go
package types
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
)
|
|
|
|
// VariantTypes holds a mapping of RVTypes that are accessible in a Variant
|
|
var VariantTypes = make(map[UInt8]RVType)
|
|
|
|
// RegisterVariantType registers a RVType to be accessible in a Variant
|
|
func RegisterVariantType(id UInt8, rvType RVType) {
|
|
VariantTypes[id] = rvType
|
|
}
|
|
|
|
// Variant is an implementation of rdv::Variant.
|
|
// This type can hold many other types, denoted by a type ID.
|
|
type Variant struct {
|
|
TypeID UInt8 `json:"type_id" db:"type_id" bson:"type_id" xml:"TypeID"`
|
|
Type RVType `json:"type" db:"type" bson:"type" xml:"Type"`
|
|
}
|
|
|
|
// WriteTo writes the Variant to the given writable
|
|
func (v Variant) WriteTo(writable Writable) {
|
|
v.TypeID.WriteTo(writable)
|
|
|
|
if v.Type != nil {
|
|
v.Type.WriteTo(writable)
|
|
}
|
|
}
|
|
|
|
// ExtractFrom extracts the Variant from the given readable
|
|
func (v *Variant) ExtractFrom(readable Readable) error {
|
|
err := v.TypeID.ExtractFrom(readable)
|
|
if err != nil {
|
|
return fmt.Errorf("Failed to read Variant type ID. %s", err.Error())
|
|
}
|
|
|
|
typeID := v.TypeID
|
|
|
|
// * Type ID of 0 is a "None" type. There is no data
|
|
if typeID == 0 {
|
|
return nil
|
|
}
|
|
|
|
if _, ok := VariantTypes[typeID]; !ok {
|
|
return fmt.Errorf("Invalid Variant type ID %d", typeID)
|
|
}
|
|
|
|
// * Create a new copy and get a pointer to it.
|
|
// * Required so that we have access to ExtractFrom
|
|
ptr := VariantTypes[typeID].CopyRef()
|
|
if err := ptr.ExtractFrom(readable); err != nil {
|
|
return fmt.Errorf("Failed to read Variant type data. %s", err.Error())
|
|
}
|
|
|
|
v.Type = ptr.Deref() // * Dereference the RVTypePtr pointer back into a non-pointer type
|
|
|
|
return nil
|
|
}
|
|
|
|
// Copy returns a pointer to a copy of the Variant. Requires type assertion when used
|
|
func (v Variant) Copy() RVType {
|
|
copied := NewVariant()
|
|
|
|
copied.TypeID = v.TypeID.Copy().(UInt8)
|
|
|
|
if v.Type != nil {
|
|
copied.Type = v.Type.Copy()
|
|
}
|
|
|
|
return copied
|
|
}
|
|
|
|
// Equals checks if the input is equal in value to the current instance
|
|
func (v Variant) Equals(o RVType) bool {
|
|
if _, ok := o.(Variant); !ok {
|
|
return false
|
|
}
|
|
|
|
other := o.(Variant)
|
|
|
|
if !v.TypeID.Equals(other.TypeID) {
|
|
return false
|
|
}
|
|
|
|
if v.Type != nil {
|
|
return v.Type.Equals(other.Type)
|
|
}
|
|
|
|
return true
|
|
}
|
|
|
|
// CopyRef copies the current value of the Variant
|
|
// and returns a pointer to the new copy
|
|
func (v Variant) CopyRef() RVTypePtr {
|
|
copied := v.Copy().(Variant)
|
|
return &copied
|
|
}
|
|
|
|
// Deref takes a pointer to the Variant
|
|
// and dereferences it to the raw value.
|
|
// Only useful when working with an instance of RVTypePtr
|
|
func (v *Variant) Deref() RVType {
|
|
return *v
|
|
}
|
|
|
|
// String returns a string representation of the struct
|
|
func (v Variant) String() string {
|
|
return v.FormatToString(0)
|
|
}
|
|
|
|
// FormatToString pretty-prints the struct data using the provided indentation level
|
|
func (v Variant) FormatToString(indentationLevel int) string {
|
|
indentationValues := strings.Repeat("\t", indentationLevel+1)
|
|
indentationEnd := strings.Repeat("\t", indentationLevel)
|
|
|
|
var b strings.Builder
|
|
|
|
b.WriteString("Variant{\n")
|
|
b.WriteString(fmt.Sprintf("%sTypeID: %s,\n", indentationValues, v.TypeID))
|
|
|
|
if v.Type != nil {
|
|
b.WriteString(fmt.Sprintf("%sType: %s\n", indentationValues, v.Type))
|
|
} else {
|
|
b.WriteString(fmt.Sprintf("%sType: None\n", indentationValues))
|
|
}
|
|
|
|
b.WriteString(fmt.Sprintf("%s}", indentationEnd))
|
|
|
|
return b.String()
|
|
}
|
|
|
|
// NewVariant returns a new Variant
|
|
func NewVariant() Variant {
|
|
// * Type ID of 0 is a "None" type. There is no data
|
|
return Variant{
|
|
TypeID: NewUInt8(0),
|
|
Type: nil,
|
|
}
|
|
}
|