mirror of
https://github.com/dolthub/dolt.git
synced 2026-01-25 10:26:22 -06:00
225 lines
4.4 KiB
Go
225 lines
4.4 KiB
Go
package types
|
|
|
|
import (
|
|
"github.com/attic-labs/noms/d"
|
|
"github.com/attic-labs/noms/ref"
|
|
)
|
|
|
|
type structData map[string]Value
|
|
|
|
type Struct struct {
|
|
data structData
|
|
t Type
|
|
typeDef Type
|
|
unionIndex uint32
|
|
unionValue Value
|
|
ref *ref.Ref
|
|
}
|
|
|
|
func newStructFromData(data structData, unionIndex uint32, unionValue Value, typ, typeDef Type) Struct {
|
|
d.Chk.Equal(typ.Kind(), UnresolvedKind)
|
|
d.Chk.True(typ.HasPackageRef())
|
|
d.Chk.True(typ.HasOrdinal())
|
|
d.Chk.Equal(typeDef.Kind(), StructKind)
|
|
return Struct{data, typ, typeDef, unionIndex, unionValue, &ref.Ref{}}
|
|
}
|
|
|
|
func NewStruct(typ, typeDef Type, data structData) Struct {
|
|
newData := make(structData)
|
|
unionIndex := uint32(0)
|
|
var unionValue Value
|
|
|
|
desc := typeDef.Desc.(StructDesc)
|
|
for _, f := range desc.Fields {
|
|
if v, ok := data[f.Name]; ok {
|
|
newData[f.Name] = v
|
|
} else {
|
|
d.Chk.True(f.Optional, "Missing required field %s", f.Name)
|
|
}
|
|
}
|
|
for i, f := range desc.Union {
|
|
v, ok := data[f.Name]
|
|
if ok {
|
|
unionIndex = uint32(i)
|
|
unionValue = v
|
|
break
|
|
}
|
|
}
|
|
return newStructFromData(newData, unionIndex, unionValue, typ, typeDef)
|
|
}
|
|
|
|
func (s Struct) Equals(other Value) bool {
|
|
return other != nil && s.t.Equals(other.Type()) && s.Ref() == other.Ref()
|
|
}
|
|
|
|
func (s Struct) Ref() ref.Ref {
|
|
return EnsureRef(s.ref, s)
|
|
}
|
|
|
|
func (s Struct) Chunks() (chunks []ref.Ref) {
|
|
chunks = append(chunks, s.t.Chunks()...)
|
|
for _, f := range s.desc().Fields {
|
|
if v, ok := s.data[f.Name]; ok {
|
|
chunks = append(chunks, v.Chunks()...)
|
|
} else {
|
|
d.Chk.True(f.Optional)
|
|
}
|
|
}
|
|
|
|
if s.hasUnion() {
|
|
chunks = append(chunks, s.unionValue.Chunks()...)
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
func (s Struct) ChildValues() (res []Value) {
|
|
res = append(res, s.t)
|
|
for _, f := range s.desc().Fields {
|
|
if v, ok := s.data[f.Name]; ok {
|
|
res = append(res, v)
|
|
} else {
|
|
d.Chk.True(f.Optional)
|
|
}
|
|
}
|
|
if s.hasUnion() {
|
|
res = append(res, s.unionValue)
|
|
}
|
|
return
|
|
}
|
|
|
|
func (s Struct) Type() Type {
|
|
return s.t
|
|
}
|
|
|
|
func (s Struct) desc() StructDesc {
|
|
return s.typeDef.Desc.(StructDesc)
|
|
}
|
|
|
|
func (s Struct) hasUnion() bool {
|
|
return len(s.desc().Union) > 0
|
|
}
|
|
|
|
func (s Struct) MaybeGet(n string) (Value, bool) {
|
|
_, idx, ok := s.findField(n)
|
|
if !ok {
|
|
return nil, false
|
|
}
|
|
if idx == -1 {
|
|
v, ok := s.data[n]
|
|
return v, ok
|
|
}
|
|
if s.unionIndex != uint32(idx) {
|
|
return nil, false
|
|
}
|
|
return s.unionValue, true
|
|
}
|
|
|
|
func (s Struct) Get(n string) Value {
|
|
_, idx, ok := s.findField(n)
|
|
d.Chk.True(ok, `Struct has no field "%s"`, n)
|
|
if idx == -1 {
|
|
v, ok := s.data[n]
|
|
d.Chk.True(ok)
|
|
return v
|
|
}
|
|
d.Chk.Equal(s.unionIndex, uint32(idx), `Union field "%s" is not set`, n)
|
|
return s.unionValue
|
|
}
|
|
|
|
func (s Struct) Set(n string, v Value) Struct {
|
|
f, idx, ok := s.findField(n)
|
|
d.Chk.True(ok, "Struct has no field %s", n)
|
|
assertType(f.T, v)
|
|
data := make(structData, len(s.data))
|
|
unionIndex := s.unionIndex
|
|
unionValue := s.unionValue
|
|
for k, v := range s.data {
|
|
data[k] = v
|
|
}
|
|
|
|
if idx == -1 {
|
|
data[n] = v
|
|
} else {
|
|
unionIndex = uint32(idx)
|
|
unionValue = v
|
|
}
|
|
|
|
return newStructFromData(data, unionIndex, unionValue, s.t, s.typeDef)
|
|
}
|
|
|
|
func (s Struct) UnionIndex() uint32 {
|
|
return s.unionIndex
|
|
}
|
|
|
|
func (s Struct) UnionValue() Value {
|
|
return s.unionValue
|
|
}
|
|
|
|
func (s Struct) findField(n string) (Field, int32, bool) {
|
|
for _, f := range s.desc().Fields {
|
|
if f.Name == n {
|
|
return f, -1, true
|
|
}
|
|
}
|
|
for i, f := range s.desc().Union {
|
|
if f.Name == n {
|
|
return f, int32(i), true
|
|
}
|
|
}
|
|
return Field{}, -1, false
|
|
}
|
|
|
|
func structBuilder(values []Value, typ, typeDef Type) Value {
|
|
i := 0
|
|
desc := typeDef.Desc.(StructDesc)
|
|
data := structData{}
|
|
unionIndex := uint32(0)
|
|
var unionValue Value
|
|
|
|
for _, f := range desc.Fields {
|
|
if f.Optional {
|
|
b := bool(values[i].(Bool))
|
|
i++
|
|
if b {
|
|
data[f.Name] = values[i]
|
|
i++
|
|
}
|
|
} else {
|
|
data[f.Name] = values[i]
|
|
i++
|
|
}
|
|
}
|
|
if len(desc.Union) > 0 {
|
|
unionIndex = uint32(values[i].(Uint32))
|
|
i++
|
|
unionValue = values[i]
|
|
i++
|
|
}
|
|
|
|
return newStructFromData(data, unionIndex, unionValue, typ, typeDef)
|
|
}
|
|
|
|
func structReader(s Struct, typ, typeDef Type) []Value {
|
|
values := []Value{}
|
|
|
|
desc := typeDef.Desc.(StructDesc)
|
|
for _, f := range desc.Fields {
|
|
v, ok := s.data[f.Name]
|
|
if f.Optional {
|
|
values = append(values, Bool(ok))
|
|
if ok {
|
|
values = append(values, v)
|
|
}
|
|
} else {
|
|
d.Chk.True(ok)
|
|
values = append(values, v)
|
|
}
|
|
}
|
|
if len(desc.Union) > 0 {
|
|
values = append(values, Uint32(s.unionIndex), s.unionValue)
|
|
}
|
|
|
|
return values
|
|
}
|