From 72da69ebcec2bf8906371ed8633a2cdfc8c5c5cf Mon Sep 17 00:00:00 2001 From: Erik Arvidsson Date: Wed, 20 Sep 2017 16:46:19 -0700 Subject: [PATCH] Add readTypeOfValue (#3728) This improves csv-import a bit since it allows us to skip allocation of values in the struct when we only want the type. --- go/types/leaf_sequence.go | 3 +-- go/types/struct.go | 6 +++++- go/types/value_decoder.go | 36 ++++++++++++++++++++++++++++++++++++ 3 files changed, 42 insertions(+), 3 deletions(-) diff --git a/go/types/leaf_sequence.go b/go/types/leaf_sequence.go index 730071581a..a1cdc29714 100644 --- a/go/types/leaf_sequence.go +++ b/go/types/leaf_sequence.go @@ -121,8 +121,7 @@ func (seq leafSequence) typeOf() *Type { count := dec.readCount() ts := make([]*Type, count) for i := uint64(0); i < count; i++ { - v := dec.readValue() - ts[i] = v.typeOf() + ts[i] = dec.readTypeOfValue() } return makeCompoundType(kind, makeCompoundType(UnionKind, ts...)) } diff --git a/go/types/struct.go b/go/types/struct.go index 7a02a937f3..a80670e76d 100644 --- a/go/types/struct.go +++ b/go/types/struct.go @@ -159,6 +159,10 @@ func (s Struct) WalkRefs(cb RefCallback) { func (s Struct) typeOf() *Type { dec := s.decoder() + return readStructTypeOfValue(&dec) +} + +func readStructTypeOfValue(dec *valueDecoder) *Type { dec.skipKind() name := dec.readString() count := dec.readCount() @@ -167,7 +171,7 @@ func (s Struct) typeOf() *Type { typeFields[i] = StructField{ Name: dec.readString(), Optional: false, - Type: dec.readValue().typeOf(), + Type: dec.readTypeOfValue(), } } return makeStructTypeQuickly(name, typeFields) diff --git a/go/types/value_decoder.go b/go/types/value_decoder.go index f08b9b3be9..41a3e8fc37 100644 --- a/go/types/value_decoder.go +++ b/go/types/value_decoder.go @@ -348,6 +348,42 @@ func (r *valueDecoder) skipValue() { } } +// readTypeOfValue is basically readValue().typeOf() but it ensures that we do +// not allocate values where we do not need to. +func (r *valueDecoder) readTypeOfValue() *Type { + k := r.peekKind() + switch k { + case BlobKind: + r.skipBlob() + return BlobType + case BoolKind: + r.skipKind() + r.skipBool() + return BoolType + case NumberKind: + r.skipKind() + r.skipNumber() + return NumberType + case StringKind: + r.skipKind() + r.skipString() + return StringType + case ListKind, MapKind, RefKind, SetKind: + // These do not decode the actual values anyway. + return r.readValue().typeOf() + case StructKind: + return readStructTypeOfValue(r) + case TypeKind: + r.skipKind() + r.skipType() + return TypeType + case CycleKind, UnionKind, ValueKind: + d.Panic("A value instance can never have type %s", k) + } + + panic("not reachable") +} + func (r *valueDecoder) copyValue(w nomsWriter) { start := r.pos() r.skipValue()