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  }