github.com/hasnat/dolt/go@v0.0.0-20210628190320-9eb5d843fbb7/store/types/value.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 23 24 import ( 25 "bytes" 26 "context" 27 28 "github.com/dolthub/dolt/go/store/hash" 29 ) 30 31 type ValueCallback func(v Value) error 32 type RefCallback func(ref Ref) error 33 type MarshalCallback func(val Value) (Value, error) 34 35 var MaxPrimitiveKind int 36 var PrimitiveKindMask []bool 37 38 func init() { 39 for _, value := range KindToType { 40 if value != nil && value.isPrimitive() { 41 nomsKind := value.Kind() 42 PrimitiveTypeMap[nomsKind] = makePrimitiveType(nomsKind) 43 } 44 } 45 for k := range PrimitiveTypeMap { 46 if int(k) > MaxPrimitiveKind { 47 MaxPrimitiveKind = int(k) 48 } 49 } 50 PrimitiveKindMask = make([]bool, MaxPrimitiveKind+1) 51 for k := range PrimitiveTypeMap { 52 PrimitiveKindMask[int(k)] = true 53 } 54 55 maxKindInKindToType := 0 56 for k := range KindToType { 57 if int(k) > maxKindInKindToType { 58 maxKindInKindToType = int(k) 59 } 60 } 61 KindToTypeSlice = make([]Value, maxKindInKindToType+1) 62 for k, v := range KindToType { 63 KindToTypeSlice[int(k)] = v 64 } 65 66 } 67 68 // Valuable is an interface from which a Value can be retrieved. 69 type Valuable interface { 70 // Kind is the NomsKind describing the kind of value this is. 71 Kind() NomsKind 72 73 Value(ctx context.Context) (Value, error) 74 } 75 76 type LesserValuable interface { 77 Valuable 78 // Less determines if this Noms value is less than another Noms value. 79 // When comparing two Noms values and both are comparable and the same type (Bool, Float or 80 // String) then the natural ordering is used. For other Noms values the Hash of the value is 81 // used. When comparing Noms values of different type the following ordering is used: 82 // Bool < Float < String < everything else. 83 Less(nbf *NomsBinFormat, other LesserValuable) (bool, error) 84 } 85 86 // Emptyable is an interface for Values which may or may not be empty 87 type Emptyable interface { 88 Empty() bool 89 } 90 91 // Value is the interface all Noms values implement. 92 type Value interface { 93 LesserValuable 94 95 // Equals determines if two different Noms values represents the same underlying value. 96 Equals(other Value) bool 97 98 // Hash is the hash of the value. All Noms values have a unique hash and if two values have the 99 // same hash they must be equal. 100 Hash(*NomsBinFormat) (hash.Hash, error) 101 102 // isPrimitive returns whether the Value is a primitive type 103 isPrimitive() bool 104 105 // WalkValues iterates over the immediate children of this value in the DAG, if any, not including 106 // Type() 107 WalkValues(context.Context, ValueCallback) error 108 109 // WalkRefs iterates over the refs to the underlying chunks. If this value is a collection that has been 110 // chunked then this will return the refs of th sub trees of the prolly-tree. 111 WalkRefs(*NomsBinFormat, RefCallback) error 112 113 // HumanReadableString returns a human-readable string version of this Value (not meant for re-parsing) 114 HumanReadableString() string 115 116 // typeOf is the internal implementation of types.TypeOf. It is not normalized 117 // and unions might have a single element, duplicates and be in the wrong 118 // order. 119 typeOf() (*Type, error) 120 121 // writeTo writes the encoded version of the value to a nomsWriter. 122 writeTo(nomsWriter, *NomsBinFormat) error 123 124 // readFrom reads the encoded version of the value from a binaryNomsReader 125 readFrom(*NomsBinFormat, *binaryNomsReader) (Value, error) 126 127 // skip takes in a binaryNomsReader and skips the encoded version of the value 128 skip(*NomsBinFormat, *binaryNomsReader) 129 } 130 131 type ValueSlice []Value 132 133 func (vs ValueSlice) Equals(other ValueSlice) bool { 134 if len(vs) != len(other) { 135 return false 136 } 137 138 for i, v := range vs { 139 if !v.Equals(other[i]) { 140 return false 141 } 142 } 143 144 return true 145 } 146 147 func (vs ValueSlice) Contains(nbf *NomsBinFormat, v Value) bool { 148 for _, v := range vs { 149 if v.Equals(v) { 150 return true 151 } 152 } 153 return false 154 } 155 156 type ValueSort struct { 157 Values []Value 158 Nbf *NomsBinFormat 159 } 160 161 func (vs ValueSort) Len() int { return len(vs.Values) } 162 func (vs ValueSort) Swap(i, j int) { vs.Values[i], vs.Values[j] = vs.Values[j], vs.Values[i] } 163 func (vs ValueSort) Less(i, j int) (bool, error) { 164 return vs.Values[i].Less(vs.Nbf, vs.Values[j]) 165 } 166 167 func (vs ValueSort) Equals(other ValueSort) bool { 168 return ValueSlice(vs.Values).Equals(ValueSlice(other.Values)) 169 } 170 171 func (vs ValueSort) Contains(v Value) bool { 172 return ValueSlice(vs.Values).Contains(vs.Nbf, v) 173 } 174 175 type valueReadWriter interface { 176 valueReadWriter() ValueReadWriter 177 } 178 179 type TupleSlice []Tuple 180 181 func (vs TupleSlice) Equals(other TupleSlice) bool { 182 if len(vs) != len(other) { 183 return false 184 } 185 186 for i, v := range vs { 187 if !v.Equals(other[i]) { 188 return false 189 } 190 } 191 192 return true 193 } 194 195 func (vs TupleSlice) Contains(nbf *NomsBinFormat, v Tuple) bool { 196 for _, v := range vs { 197 if v.Equals(v) { 198 return true 199 } 200 } 201 return false 202 } 203 204 type TupleSort struct { 205 Tuples []Tuple 206 Nbf *NomsBinFormat 207 } 208 209 func (vs TupleSort) Len() int { 210 return len(vs.Tuples) 211 } 212 213 func (vs TupleSort) Swap(i, j int) { 214 vs.Tuples[i], vs.Tuples[j] = vs.Tuples[j], vs.Tuples[i] 215 } 216 217 func (vs TupleSort) Less(i, j int) (bool, error) { 218 return vs.Tuples[i].TupleLess(vs.Nbf, vs.Tuples[j]) 219 } 220 221 func (vs TupleSort) Equals(other TupleSort) bool { 222 return TupleSlice(vs.Tuples).Equals(other.Tuples) 223 } 224 225 func (vs TupleSort) Contains(v Tuple) bool { 226 return TupleSlice(vs.Tuples).Contains(vs.Nbf, v) 227 } 228 229 type valueImpl struct { 230 vrw ValueReadWriter 231 nbf *NomsBinFormat 232 buff []byte 233 offsets []uint32 234 } 235 236 func (v valueImpl) valueReadWriter() ValueReadWriter { 237 return v.vrw 238 } 239 240 func (v valueImpl) writeTo(enc nomsWriter, nbf *NomsBinFormat) error { 241 enc.writeRaw(v.buff) 242 return nil 243 } 244 245 // IsZeroValue can be used to test if a Value is the same as T{}. 246 func (v valueImpl) IsZeroValue() bool { 247 return v.buff == nil 248 } 249 250 func (v valueImpl) Hash(*NomsBinFormat) (hash.Hash, error) { 251 return hash.Of(v.buff), nil 252 } 253 254 func (v valueImpl) decoder() valueDecoder { 255 return newValueDecoder(v.buff, v.vrw) 256 } 257 258 func (v valueImpl) format() *NomsBinFormat { 259 return v.nbf 260 } 261 262 func (v valueImpl) decoderAtOffset(offset int) valueDecoder { 263 return newValueDecoder(v.buff[offset:], v.vrw) 264 } 265 266 func (v valueImpl) asValueImpl() valueImpl { 267 return v 268 } 269 270 func (v valueImpl) Equals(other Value) bool { 271 if otherValueImpl, ok := other.(asValueImpl); ok { 272 return bytes.Equal(v.buff, otherValueImpl.asValueImpl().buff) 273 } 274 return false 275 } 276 277 func (v valueImpl) Less(nbf *NomsBinFormat, other LesserValuable) (bool, error) { 278 return valueLess(nbf, v, other.(Value)) 279 } 280 281 func (v valueImpl) WalkRefs(nbf *NomsBinFormat, cb RefCallback) error { 282 w := binaryNomsWriter{make([]byte, len(v.buff)+1), 0} 283 err := v.writeTo(&w, nbf) 284 285 if err != nil { 286 return err 287 } 288 289 return walkRefs(w.buff[:w.offset], nbf, cb) 290 } 291 292 type asValueImpl interface { 293 asValueImpl() valueImpl 294 } 295 296 func (v valueImpl) Kind() NomsKind { 297 return NomsKind(v.buff[0]) 298 }