github.com/hasnat/dolt/go@v0.0.0-20210628190320-9eb5d843fbb7/store/types/type.go (about) 1 // Copyright 2019 Dolthub, Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 // 15 // This file incorporates work covered by the following copyright and 16 // permission notice: 17 // 18 // Copyright 2016 Attic Labs, Inc. All rights reserved. 19 // Licensed under the Apache License, version 2.0: 20 // http://www.apache.org/licenses/LICENSE-2.0 21 22 // Package types contains most of the data structures available to/from Noms. 23 package types 24 25 import ( 26 "context" 27 28 "github.com/dolthub/dolt/go/store/d" 29 30 "github.com/dolthub/dolt/go/store/hash" 31 ) 32 33 // Type defines and describes Noms types, both built-in and user-defined. 34 // Desc provides the composition of the type. It may contain only a types.NomsKind, in the case of 35 // primitives, or it may contain additional information -- e.g. element Types for compound type 36 // specializations, field descriptions for structs, etc. Either way, checking Kind() allows code 37 // to understand how to interpret the rest of the data. 38 // If Kind() refers to a primitive, then Desc has no more info. 39 // If Kind() refers to List, Map, Ref, Set, or Union, then Desc is a list of Types describing the element type(s). 40 // If Kind() refers to Struct, then Desc contains a []field. 41 42 type Type struct { 43 Desc TypeDesc 44 } 45 46 func newType(desc TypeDesc) *Type { 47 return &Type{desc} 48 } 49 50 // Describe generate text that should parse into the struct being described. 51 func (t *Type) Describe(ctx context.Context) (string, error) { 52 return EncodedValue(ctx, t) 53 } 54 55 func (t *Type) TargetKind() NomsKind { 56 return t.Desc.Kind() 57 } 58 59 // Value interface 60 func (t *Type) Value(ctx context.Context) (Value, error) { 61 if t.Kind() == UnknownKind { 62 return nil, ErrUnknownType 63 } 64 65 return t, nil 66 } 67 68 func (t *Type) Equals(other Value) (res bool) { 69 // This is highly optimized to not having to encode a *Type unless we have too. 70 if t == other { 71 return true 72 } 73 74 if otherType, ok := other.(*Type); ok { 75 h, err := t.Hash(Format_Default) 76 77 // TODO - fix panics 78 d.PanicIfError(err) 79 80 oh, err := other.Hash(Format_Default) 81 82 // TODO - fix panics 83 d.PanicIfError(err) 84 85 return t.TargetKind() == otherType.TargetKind() && h == oh 86 } 87 88 return false 89 } 90 91 func (t *Type) Less(nbf *NomsBinFormat, other LesserValuable) (bool, error) { 92 return valueLess(nbf, t, other.(Value)) 93 } 94 95 func (t *Type) Hash(nbf *NomsBinFormat) (hash.Hash, error) { 96 return getHash(t, nbf) 97 } 98 99 func (t *Type) isPrimitive() bool { 100 return true 101 } 102 103 func (t *Type) writeTo(w nomsWriter, nbf *NomsBinFormat) error { 104 err := TypeKind.writeTo(w, nbf) 105 106 if err != nil { 107 return err 108 } 109 110 return t.writeToAsType(w, map[string]*Type{}, nbf) 111 } 112 113 func (t *Type) writeToAsType(w nomsWriter, seensStructs map[string]*Type, nbf *NomsBinFormat) error { 114 return t.Desc.writeTo(w, nbf, t, seensStructs) 115 } 116 117 func (t *Type) WalkValues(ctx context.Context, cb ValueCallback) error { 118 return t.Desc.walkValues(cb) 119 } 120 121 func (t *Type) WalkRefs(nbf *NomsBinFormat, cb RefCallback) error { 122 return nil 123 } 124 125 func (t *Type) typeOf() (*Type, error) { 126 return PrimitiveTypeMap[TypeKind], nil 127 } 128 129 func (t *Type) Kind() NomsKind { 130 return TypeKind 131 } 132 133 func (t *Type) valueReadWriter() ValueReadWriter { 134 return nil 135 } 136 137 // TypeOf returns the type describing the value. This is not an exact type but 138 // often a simplification of the concrete type. 139 func TypeOf(v Value) (*Type, error) { 140 t, err := v.typeOf() 141 142 if err != nil { 143 return nil, err 144 } 145 146 return simplifyType(t, false) 147 } 148 149 // HasStructCycles determines if the type contains any struct cycles. 150 func HasStructCycles(t *Type) bool { 151 return hasStructCycles(t, nil) 152 } 153 154 func hasStructCycles(t *Type, visited []*Type) bool { 155 if _, found := indexOfType(t, visited); found { 156 return true 157 } 158 159 switch desc := t.Desc.(type) { 160 case CompoundDesc: 161 for _, et := range desc.ElemTypes { 162 b := hasStructCycles(et, visited) 163 if b { 164 return true 165 } 166 } 167 168 case StructDesc: 169 for _, f := range desc.fields { 170 b := hasStructCycles(f.Type, append(visited, t)) 171 if b { 172 return true 173 } 174 } 175 176 case CycleDesc: 177 panic("unexpected unresolved cycle") 178 } 179 180 return false 181 } 182 183 func indexOfType(t *Type, tl []*Type) (uint32, bool) { 184 for i, tt := range tl { 185 if tt == t { 186 return uint32(i), true 187 } 188 } 189 return 0, false 190 } 191 192 func (t *Type) readFrom(nbf *NomsBinFormat, b *binaryNomsReader) (Value, error) { 193 panic("unreachable") 194 } 195 196 func (t *Type) skip(nbf *NomsBinFormat, b *binaryNomsReader) { 197 panic("unreachable") 198 } 199 200 func (t *Type) String() string { 201 panic("unreachable") 202 } 203 204 func (t *Type) HumanReadableString() string { 205 panic("unreachable") 206 }