From 4113d234a0926b3b3561628f484d9e5fea9f5bba Mon Sep 17 00:00:00 2001 From: Jonathan Barrow Date: Sun, 21 May 2023 23:41:42 -0400 Subject: [PATCH] Added a real Variant type and updated StreamIn.ReadVariant --- stream_in.go | 24 +++----------- types.go | 88 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 93 insertions(+), 19 deletions(-) diff --git a/stream_in.go b/stream_in.go index f3c84a11..be631553 100644 --- a/stream_in.go +++ b/stream_in.go @@ -122,26 +122,12 @@ func (stream *StreamIn) ReadStructure(structure StructureInterface) (StructureIn } // ReadVariant reads a Variant type. This type can hold 7 different types -func (stream *StreamIn) ReadVariant() interface{} { - switch stream.ReadUInt8() { - case 0: // null - return nil - case 1: // sint64 - return int64(stream.ReadUInt64LE()) - case 2: // double - return float64(stream.ReadUInt64LE()) - case 3: // bool - return stream.ReadUInt8() == 1 - case 4: // string - str, _ := stream.ReadString() - return str - case 5: // datetime - return NewDateTime(stream.ReadUInt64LE()) - case 6: // uint64 - return stream.ReadUInt64LE() - } +func (stream *StreamIn) ReadVariant() *Variant { + variant := NewVariant() + + _ = variant.ExtractFromStream(stream) - return nil + return variant } // ReadMap reads a Map type with the given key and value types diff --git a/types.go b/types.go index 6c645210..d8478ae9 100644 --- a/types.go +++ b/types.go @@ -775,3 +775,91 @@ func (resultRange *ResultRange) Equals(structure StructureInterface) bool { func NewResultRange() *ResultRange { return &ResultRange{} } + +// Variant can hold one of 7 types; nil, int64, float64, bool, string, DateTime, or uint64 +type Variant struct { + TypeID uint8 + // * In reality this type does not have this many fields + // * It only stores the type ID and then the value + // * However to get better typing, we opt to store each possible + // * type as it's own field and just check typeID to know which it has + Int64 int64 + Float64 float64 + Bool bool + String string + DateTime *DateTime + UInt64 uint64 +} + +// ExtractFromStream extracts a Variant structure from a stream +func (variant *Variant) ExtractFromStream(stream *StreamIn) error { + variant.TypeID = stream.ReadUInt8() + + // * A type ID of 0 means no value + switch variant.TypeID { + case 1: // * sint64 + variant.Int64 = int64(stream.ReadUInt64LE()) + case 2: // * double + variant.Float64 = float64(stream.ReadUInt64LE()) + case 3: // * bool + variant.Bool = stream.ReadUInt8() == 1 + case 4: // * string + str, _ := stream.ReadString() + variant.String = str + case 5: // * datetime + variant.DateTime = NewDateTime(stream.ReadUInt64LE()) + case 6: // * uint64 + variant.UInt64 = stream.ReadUInt64LE() + } + + return nil +} + +// Copy returns a new copied instance of RVConnectionData +func (variant *Variant) Copy() *Variant { + copied := NewVariant() + + copied.TypeID = variant.TypeID + copied.Int64 = variant.Int64 + copied.Float64 = variant.Float64 + copied.Bool = variant.Bool + copied.String = variant.String + + if variant.DateTime != nil { + copied.DateTime = variant.DateTime.Copy() + } + + copied.UInt64 = variant.UInt64 + + return copied +} + +// Equals checks if the passed Structure contains the same data as the current instance +func (variant *Variant) Equals(other *Variant) bool { + if variant.TypeID != other.TypeID { + return false + } + + // * A type ID of 0 means no value + switch variant.TypeID { + case 1: // * sint64 + return variant.Int64 == other.Int64 + case 2: // * double + return variant.Float64 == other.Float64 + case 3: // * bool + return variant.Bool == other.Bool + case 4: // * string + return variant.String == other.String + case 5: // * datetime + return variant.DateTime.Equals(other.DateTime) + case 6: // * uint64 + return variant.UInt64 == other.UInt64 + default: // * Something went horribly wrong + return false + } +} + +// NewVariant returns a new Variant +func NewVariant() *Variant { + return &Variant{} +}