v23: ValueRead and ValueDecoder - vdl.Value impl of Decoder interface
Change-Id: Ie57bbe88f884dd839e06df086abc8dc9ff359de5
diff --git a/vdl/.api b/vdl/.api
index 78bed34..5a28db8 100644
--- a/vdl/.api
+++ b/vdl/.api
@@ -421,6 +421,7 @@
pkg vdl, method (*Value) Bytes() []byte
pkg vdl, method (*Value) ContainsKey(*Value) bool
pkg vdl, method (*Value) CopyBytes([]byte) *Value
+pkg vdl, method (*Value) Decoder() Decoder
pkg vdl, method (*Value) DeleteSetKey(*Value) *Value
pkg vdl, method (*Value) Elem() *Value
pkg vdl, method (*Value) EnumIndex() int
@@ -443,6 +444,7 @@
pkg vdl, method (*Value) TypeObject() *Type
pkg vdl, method (*Value) Uint() uint64
pkg vdl, method (*Value) UnionField() (int, *Value)
+pkg vdl, method (*Value) VDLRead(Decoder) error
pkg vdl, method (*WireError) FillVDLTarget(Target, *Type) error
pkg vdl, method (*WireError) MakeVDLTarget() Target
pkg vdl, method (*WireError) VDLRead(Decoder) error
diff --git a/vdl/value_decoder.go b/vdl/value_decoder.go
new file mode 100644
index 0000000..0506c0d
--- /dev/null
+++ b/vdl/value_decoder.go
@@ -0,0 +1,356 @@
+// Copyright 2016 The Vanadium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package vdl
+
+import (
+ "errors"
+ "fmt"
+)
+
+var (
+ errEmptyDecoderStack = errors.New("vdl: empty decoder stack")
+)
+
+// Decoder returns a decoder that traverses vv.
+func (vv *Value) Decoder() Decoder {
+ return &valueDecoder{initial: vv}
+}
+
+// ValueDecoder is an implementation of Decoder for vdl Value.
+type valueDecoder struct {
+ initial *Value
+ ignoreNext bool
+ stack []vdStackEntry
+}
+
+type vdStackEntry struct {
+ Value *Value // the vdl Value
+ Index int // next index or field (index into vdStackEntry.keys for map/set)
+ NumStarted int // hold state for multiple StartValue() calls
+ IsAny bool // true iff this value is within an any value
+ IsOptional bool // true iff this value is within an optional value
+ Keys []*Value // keys for set/map
+}
+
+func (d *valueDecoder) StartValue() error {
+ if d.ignoreNext {
+ d.ignoreNext = false
+ return nil
+ }
+ var vv *Value
+ if top := d.top(); top == nil {
+ vv = d.initial
+ } else {
+ switch top.Value.Kind() {
+ case Array, List:
+ vv = top.Value.Index(top.Index)
+ case Set:
+ vv = top.Keys[top.Index]
+ case Map:
+ switch top.NumStarted % 2 {
+ case 0:
+ vv = top.Keys[top.Index]
+ case 1:
+ vv = top.Value.MapIndex(top.Keys[top.Index])
+ }
+ case Struct:
+ vv = top.Value.StructField(top.Index)
+ case Union:
+ _, vv = top.Value.UnionField()
+ default:
+ return fmt.Errorf("unknown composite kind: %v", top.Value.Kind())
+ }
+ top.NumStarted++
+ }
+ var isAny, isOptional bool
+ if vv.Kind() == Any {
+ isAny = true
+ if !vv.IsNil() {
+ vv = vv.Elem()
+ }
+ }
+ if vv.Kind() == Optional {
+ isOptional = true
+ if !vv.IsNil() {
+ vv = vv.Elem()
+ }
+ }
+ entry := vdStackEntry{
+ Value: vv,
+ IsAny: isAny,
+ IsOptional: isOptional,
+ Index: -1,
+ }
+ if vv.Kind() == Map || vv.Kind() == Set {
+ entry.Keys = vv.Keys()
+ }
+ d.stack = append(d.stack, entry)
+ return nil
+}
+
+func (d *valueDecoder) IgnoreNextStartValue() {
+ d.ignoreNext = true
+}
+
+func (d *valueDecoder) FinishValue() error {
+ if len(d.stack) == 0 {
+ return errEmptyDecoderStack
+ }
+ d.stack = d.stack[:len(d.stack)-1]
+ d.ignoreNext = false
+ return nil
+}
+
+func (d *valueDecoder) SkipValue() error {
+ return nil
+}
+
+func (d *valueDecoder) NextEntry() (bool, error) {
+ top := d.top()
+ if top == nil {
+ return false, errEmptyDecoderStack
+ }
+ top.Index++
+ switch top.Value.Kind() {
+ case Array, List, Set, Map:
+ switch {
+ case top.Index == top.Value.Len():
+ return true, nil
+ case top.Index > top.Value.Len():
+ return false, fmt.Errorf("vdl: NextEntry called after done, stack: %+v", d.stack)
+ }
+ }
+ return false, nil
+}
+
+func (d *valueDecoder) NextField() (string, error) {
+ top := d.top()
+ if top == nil {
+ return "", errEmptyDecoderStack
+ }
+ top.Index++
+ index, max := top.Index, top.Value.Type().NumField()
+ if top.Value.Kind() == Union {
+ max = 1
+ index, _ = top.Value.UnionField()
+ }
+ if top.Index == max {
+ return "", nil
+ } else if top.Index > max {
+ return "", fmt.Errorf("vdl: NextField called after done, stack: %+v", d.stack)
+ }
+ return top.Value.Type().Field(index).Name, nil
+}
+
+func (d *valueDecoder) Type() *Type {
+ if top := d.top(); top != nil {
+ return top.Value.Type()
+ }
+ return nil
+}
+
+func (d *valueDecoder) IsAny() bool {
+ if top := d.top(); top != nil {
+ return top.IsAny
+ }
+ return false
+}
+
+func (d *valueDecoder) IsOptional() bool {
+ if top := d.top(); top != nil {
+ return top.IsOptional
+ }
+ return false
+}
+
+func (d *valueDecoder) IsNil() bool {
+ if top := d.top(); top != nil {
+ return top.Value.IsNil()
+ }
+ return false
+}
+
+func (d *valueDecoder) Index() int {
+ if top := d.top(); top != nil {
+ return top.Index
+ }
+ return -1
+}
+
+func (d *valueDecoder) LenHint() int {
+ if top := d.top(); top != nil {
+ switch top.Value.Kind() {
+ case List, Map, Set, Array:
+ return top.Value.Len()
+ }
+ }
+ return -1
+}
+
+func (d *valueDecoder) DecodeBool() (bool, error) {
+ top := d.top()
+ if top == nil {
+ return false, errEmptyDecoderStack
+ }
+ if top.Value.Kind() != Bool {
+ return false, fmt.Errorf("vdl: type mismatch, got %v, want bool", top.Value.Type())
+ }
+ return top.Value.Bool(), nil
+}
+
+func (d *valueDecoder) DecodeUint(bitlen uint) (uint64, error) {
+ const errFmt = "vdl: %v conversion to uint%d loses precision: %v"
+ top := d.top()
+ if top == nil {
+ return 0, errEmptyDecoderStack
+ }
+ switch top.Value.Kind() {
+ case Byte, Uint16, Uint32, Uint64:
+ x := top.Value.Uint()
+ if shift := 64 - bitlen; x != (x<<shift)>>shift {
+ return 0, fmt.Errorf(errFmt, top.Value, bitlen, x)
+ }
+ return x, nil
+ case Int8, Int16, Int32, Int64:
+ x := top.Value.Int()
+ ux := uint64(x)
+ if shift := 64 - bitlen; x < 0 || ux != (ux<<shift)>>shift {
+ return 0, fmt.Errorf(errFmt, top.Value, bitlen, x)
+ }
+ return ux, nil
+ case Float32, Float64:
+ x := top.Value.Float()
+ ux := uint64(x)
+ if shift := 64 - bitlen; x != float64(ux) || ux != (ux<<shift)>>shift {
+ return 0, fmt.Errorf(errFmt, top.Value, bitlen, x)
+ }
+ return ux, nil
+ default:
+ return 0, fmt.Errorf("vdl: type mismatch, got %v, want uint%d", top.Value.Type(), bitlen)
+ }
+}
+
+func (d *valueDecoder) DecodeInt(bitlen uint) (int64, error) {
+ const errFmt = "vdl: %v conversion to int%d loses precision: %v"
+ top := d.top()
+ if top == nil {
+ return 0, errEmptyDecoderStack
+ }
+ switch top.Value.Kind() {
+ case Byte, Uint16, Uint32, Uint64:
+ x := top.Value.Uint()
+ ix := int64(x)
+ if shift := 64 - bitlen; ix < 0 || x != (x<<shift)>>shift {
+ return 0, fmt.Errorf(errFmt, top.Value, bitlen, x)
+ }
+ return ix, nil
+ case Int8, Int16, Int32, Int64:
+ x := top.Value.Int()
+ if shift := 64 - bitlen; x != (x<<shift)>>shift {
+ return 0, fmt.Errorf(errFmt, top.Value, bitlen, x)
+ }
+ return x, nil
+ case Float32, Float64:
+ x := top.Value.Float()
+ ix := int64(x)
+ if shift := 64 - bitlen; x != float64(ix) || ix != (ix<<shift)>>shift {
+ return 0, fmt.Errorf(errFmt, top.Value, bitlen, x)
+ }
+ return ix, nil
+ default:
+ return 0, fmt.Errorf("vdl: type mismatch, got %v, want int%d", top.Value.Type(), bitlen)
+ }
+}
+
+func (d *valueDecoder) DecodeFloat(bitlen uint) (float64, error) {
+ const errFmt = "vdl: %v conversion to float%d loses precision: %v"
+ top := d.top()
+ if top == nil {
+ return 0, errEmptyDecoderStack
+ }
+ switch top.Value.Kind() {
+ case Byte, Uint16, Uint32, Uint64:
+ x := top.Value.Uint()
+ var max uint64
+ if bitlen > 32 {
+ max = float64MaxInt
+ } else {
+ max = float32MaxInt
+ }
+ if x > max {
+ return 0, fmt.Errorf(errFmt, top.Value, bitlen, x)
+ }
+ return float64(x), nil
+ case Int8, Int16, Int32, Int64:
+ x := top.Value.Int()
+ var min, max int64
+ if bitlen > 32 {
+ min, max = float64MinInt, float64MaxInt
+ } else {
+ min, max = float32MinInt, float32MaxInt
+ }
+ if x < min || x > max {
+ return 0, fmt.Errorf(errFmt, top.Value, bitlen, x)
+ }
+ return float64(x), nil
+ case Float32, Float64:
+ return top.Value.Float(), nil
+ default:
+ return 0, fmt.Errorf("vdl: type mismatch, got %v, want float%d", top.Value.Type(), bitlen)
+ }
+}
+
+func (d *valueDecoder) DecodeBytes(fixedlen int, v *[]byte) error {
+ top := d.top()
+ if top == nil {
+ return errEmptyDecoderStack
+ }
+ if !top.Value.Type().IsBytes() {
+ return fmt.Errorf("vdl: type mismatch, got %v, want bytes", top.Value.Type())
+ }
+ if fixedlen >= 0 && top.Value.Len() != fixedlen {
+ return fmt.Errorf("vdl: %v got %v bytes, want fixed len %v", top.Value.Type(), top.Value.Len(), fixedlen)
+ }
+ if cap(*v) < top.Value.Len() {
+ *v = make([]byte, top.Value.Len())
+ } else {
+ *v = (*v)[:top.Value.Len()]
+ }
+ copy(*v, top.Value.Bytes())
+ return nil
+}
+
+func (d *valueDecoder) DecodeString() (string, error) {
+ top := d.top()
+ if top == nil {
+ return "", errEmptyDecoderStack
+ }
+ switch top.Value.Kind() {
+ case String:
+ return top.Value.RawString(), nil
+ case Enum:
+ return top.Value.EnumLabel(), nil
+ default:
+ return "", fmt.Errorf("vdl: type mismatch, got %v, want string", top.Value.Type())
+ }
+}
+
+func (d *valueDecoder) DecodeTypeObject() (*Type, error) {
+ top := d.top()
+ if top == nil {
+ return nil, errEmptyDecoderStack
+ }
+ if top.Value.Type() != TypeObjectType {
+ return nil, fmt.Errorf("vdl: type mismatch, got %v, want typeobject", top.Value.Type())
+ }
+ return top.Value.TypeObject(), nil
+}
+
+func (d *valueDecoder) top() *vdStackEntry {
+ if len(d.stack) > 0 {
+ return &d.stack[len(d.stack)-1]
+ }
+ return nil
+}
diff --git a/vdl/value_decoder_test.go b/vdl/value_decoder_test.go
new file mode 100644
index 0000000..922bbb0
--- /dev/null
+++ b/vdl/value_decoder_test.go
@@ -0,0 +1,615 @@
+// Copyright 2016 The Vanadium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package vdl
+
+import (
+ "bytes"
+ "reflect"
+ "sort"
+ "testing"
+)
+
+func TestValueDecoderDecodeBool(t *testing.T) {
+ expected := true
+ vd := ValueOf(expected).Decoder()
+ if err := vd.StartValue(); err != nil {
+ t.Errorf("error in StartValue: %v", err)
+ }
+ if got, want := vd.Type(), BoolType; got != want {
+ t.Errorf("got %v, want %v", got, want)
+ }
+ switch val, err := vd.DecodeBool(); {
+ case err != nil:
+ t.Errorf("error decoding value: %v", err)
+ case val != expected:
+ t.Errorf("got %d, want %d", val, expected)
+ }
+ if err := vd.FinishValue(); err != nil {
+ t.Errorf("error in FinishValue: %v", err)
+ }
+}
+
+func TestValueDecoderDecodeUint(t *testing.T) {
+ expected := uint32(5)
+ vd := ValueOf(expected).Decoder()
+ if err := vd.StartValue(); err != nil {
+ t.Errorf("error in StartValue: %v", err)
+ }
+ if got, want := vd.Type(), Uint32Type; got != want {
+ t.Errorf("got %v, want %v", got, want)
+ }
+ switch val, err := vd.DecodeUint(32); {
+ case err != nil:
+ t.Errorf("error decoding value: %v", err)
+ case val != 5:
+ t.Errorf("got %d, want %d", val, expected)
+ }
+ if err := vd.FinishValue(); err != nil {
+ t.Errorf("error in FinishValue: %v", err)
+ }
+}
+
+func TestValueDecoderDecodeInt(t *testing.T) {
+ expected := int64(5)
+ vd := ValueOf(expected).Decoder()
+ if err := vd.StartValue(); err != nil {
+ t.Errorf("error in StartValue: %v", err)
+ }
+ if got, want := vd.Type(), Int64Type; got != want {
+ t.Errorf("got %v, want %v", got, want)
+ }
+ switch val, err := vd.DecodeInt(64); {
+ case err != nil:
+ t.Errorf("error decoding value: %v", err)
+ case val != 5:
+ t.Errorf("got %d, want %d", val, expected)
+ }
+ if err := vd.FinishValue(); err != nil {
+ t.Errorf("error in FinishValue: %v", err)
+ }
+}
+
+func TestValueDecoderDecodeFloat(t *testing.T) {
+ expected := float32(5)
+ vd := ValueOf(expected).Decoder()
+ if err := vd.StartValue(); err != nil {
+ t.Errorf("error in StartValue: %v", err)
+ }
+ if got, want := vd.Type(), Float32Type; got != want {
+ t.Errorf("got %v, want %v", got, want)
+ }
+ switch val, err := vd.DecodeFloat(32); {
+ case err != nil:
+ t.Errorf("error decoding value: %v", err)
+ case val != 5:
+ t.Errorf("got %d, want %d", val, expected)
+ }
+ if err := vd.FinishValue(); err != nil {
+ t.Errorf("error in FinishValue: %v", err)
+ }
+}
+
+func TestValueDecoderDecodeString(t *testing.T) {
+ expected := "abc"
+ vd := ValueOf(expected).Decoder()
+ if err := vd.StartValue(); err != nil {
+ t.Errorf("error in StartValue: %v", err)
+ }
+ if got, want := vd.Type(), StringType; got != want {
+ t.Errorf("got %v, want %v", got, want)
+ }
+ switch val, err := vd.DecodeString(); {
+ case err != nil:
+ t.Errorf("error decoding value: %v", err)
+ case val != expected:
+ t.Errorf("got %v, want %v", val, expected)
+ }
+ if err := vd.FinishValue(); err != nil {
+ t.Errorf("error in FinishValue: %v", err)
+ }
+}
+
+func TestValueDecoderDecodeEnum(t *testing.T) {
+ expectedType := EnumType("A", "B")
+ expected := ZeroValue(expectedType)
+ vd := expected.Decoder()
+ if err := vd.StartValue(); err != nil {
+ t.Errorf("error in StartValue: %v", err)
+ }
+ if got, want := vd.Type(), expectedType; got != want {
+ t.Errorf("got %v, want %v", got, want)
+ }
+ switch val, err := vd.DecodeString(); {
+ case err != nil:
+ t.Errorf("error decoding value: %v", err)
+ case val != expected.EnumLabel():
+ t.Errorf("got %v, want %v", val, expected)
+ }
+ if err := vd.FinishValue(); err != nil {
+ t.Errorf("error in FinishValue: %v", err)
+ }
+}
+
+func TestValueDecoderDecodeByteList(t *testing.T) {
+ expected := []byte("abc")
+ vd := ValueOf(expected).Decoder()
+ if err := vd.StartValue(); err != nil {
+ t.Errorf("error in StartValue: %v", err)
+ }
+ if got, want := vd.Type(), TypeOf(expected); got != want {
+ t.Errorf("got %v, want %v", got, want)
+ }
+ var out []byte
+ if err := vd.DecodeBytes(-1, &out); err != nil {
+ t.Errorf("error decoding value: %v", err)
+ }
+ if !bytes.Equal(expected, out) {
+ t.Errorf("got %v, want %v", out, expected)
+ }
+ if err := vd.FinishValue(); err != nil {
+ t.Errorf("error in FinishValue: %v", err)
+ }
+}
+
+func TestValueDecoderDecodeByteArray(t *testing.T) {
+ expected := [3]byte{byte('a'), byte('b'), byte('c')}
+ vd := ValueOf(expected).Decoder()
+ if err := vd.StartValue(); err != nil {
+ t.Errorf("error in StartValue: %v", err)
+ }
+ if got, want := vd.Type(), TypeOf(expected); got != want {
+ t.Errorf("got %v, want %v", got, want)
+ }
+ var out []byte
+ if err := vd.DecodeBytes(3, &out); err != nil {
+ t.Errorf("error decoding value: %v", err)
+ }
+ if !bytes.Equal(expected[:], out) {
+ t.Errorf("got %v, want %v", out, expected)
+ }
+ if err := vd.FinishValue(); err != nil {
+ t.Errorf("error in FinishValue: %v", err)
+ }
+
+ vd = ValueOf(expected).Decoder()
+ if err := vd.StartValue(); err != nil {
+ t.Errorf("error in StartValue: %v", err)
+ }
+ if err := vd.DecodeBytes(2, &out); err == nil {
+ t.Errorf("expected error decoding with mismatched length")
+ }
+ if err := vd.FinishValue(); err != nil {
+ t.Errorf("error in FinishValue: %v", err)
+ }
+}
+
+func TestValueDecoderDecodeTypeObject(t *testing.T) {
+ expected := TypeOf("abc")
+ vd := ValueOf(expected).Decoder()
+ if err := vd.StartValue(); err != nil {
+ t.Errorf("error in StartValue: %v", err)
+ }
+ if got, want := vd.Type(), TypeObjectType; got != want {
+ t.Errorf("got %v, want %v", got, want)
+ }
+ switch val, err := vd.DecodeTypeObject(); {
+ case err != nil:
+ t.Errorf("error decoding value: %v", err)
+ case val != expected:
+ t.Errorf("got %v, want %v", val, expected)
+ }
+ if err := vd.FinishValue(); err != nil {
+ t.Errorf("error in FinishValue: %v", err)
+ }
+}
+
+func testValueDecoderDecodeSequence(t *testing.T, expected interface{}) {
+ vd := ValueOf(expected).Decoder()
+ if err := vd.StartValue(); err != nil {
+ t.Fatalf("error in StartValue: %v", err)
+ }
+ if got, want := vd.Type(), TypeOf(expected); got != want {
+ t.Errorf("got %v, want %v", got, want)
+ }
+
+ switch done, err := vd.NextEntry(); {
+ case err != nil:
+ t.Fatalf("error in call to NextEntry(): %v", err)
+ case done:
+ t.Fatalf("ended prematurely")
+ }
+ if err := vd.StartValue(); err != nil {
+ t.Fatalf("error in StartValue: %v", err)
+ }
+ if got, want := vd.Type(), StringType; got != want {
+ t.Errorf("got %v, want %v", got, want)
+ }
+ switch val, err := vd.DecodeString(); {
+ case err != nil:
+ t.Errorf("error decoding value: %v", err)
+ case val != "a":
+ t.Errorf("got %v, want %v", val, "a")
+ }
+ if err := vd.FinishValue(); err != nil {
+ t.Fatalf("error in FinishValue: %v", err)
+ }
+
+ switch done, err := vd.NextEntry(); {
+ case err != nil:
+ t.Fatalf("error in call to NextEntry(): %v", err)
+ case done:
+ t.Fatalf("ended prematurely")
+ }
+ if err := vd.StartValue(); err != nil {
+ t.Fatalf("error in StartValue: %v", err)
+ }
+ if got, want := vd.Type(), StringType; got != want {
+ t.Errorf("got %v, want %v", got, want)
+ }
+ switch val, err := vd.DecodeString(); {
+ case err != nil:
+ t.Errorf("error decoding value: %v", err)
+ case val != "b":
+ t.Errorf("got %v, want %v", val, "b")
+ }
+ if err := vd.FinishValue(); err != nil {
+ t.Fatalf("error in FinishValue: %v", err)
+ }
+
+ switch done, err := vd.NextEntry(); {
+ case err != nil:
+ t.Fatalf("error in call to NextEntry(): %v", err)
+ case !done:
+ t.Fatalf("expected end marker")
+ }
+
+ if _, err := vd.NextEntry(); err == nil {
+ t.Errorf("expected error in final call to NextEntry()")
+ }
+
+ if err := vd.FinishValue(); err != nil {
+ t.Fatalf("error in FinishValue: %v", err)
+ }
+}
+
+func TestValueDecoderDecodeList(t *testing.T) {
+ testValueDecoderDecodeSequence(t, []string{"a", "b"})
+}
+
+func TestValueDecoderDecodeArray(t *testing.T) {
+ testValueDecoderDecodeSequence(t, [2]string{"a", "b"})
+}
+
+func TestValueDecoderDecodeSet(t *testing.T) {
+ expected := map[string]struct{}{"a": struct{}{}, "b": struct{}{}}
+ vd := ValueOf(expected).Decoder()
+ if err := vd.StartValue(); err != nil {
+ t.Fatalf("error in StartValue: %v", err)
+ }
+ if got, want := vd.Type(), TypeOf(expected); got != want {
+ t.Errorf("got %v, want %v", got, want)
+ }
+
+ switch done, err := vd.NextEntry(); {
+ case err != nil:
+ t.Fatalf("error in call to NextEntry(): %v", err)
+ case done:
+ t.Fatalf("ended prematurely")
+ }
+ if err := vd.StartValue(); err != nil {
+ t.Fatalf("error in StartValue: %v", err)
+ }
+ if got, want := vd.Type(), StringType; got != want {
+ t.Errorf("got %v, want %v", got, want)
+ }
+ key, err := vd.DecodeString()
+ switch {
+ case err != nil:
+ t.Errorf("error decoding value: %v", err)
+ case key != "a" && key != "b":
+ t.Errorf(`got %v, expected "a" or "b"`, key)
+ }
+ if err := vd.FinishValue(); err != nil {
+ t.Fatalf("error in FinishValue: %v", err)
+ }
+
+ switch done, err := vd.NextEntry(); {
+ case err != nil:
+ t.Fatalf("error in call to NextEntry(): %v", err)
+ case done:
+ t.Fatalf("ended prematurely")
+ }
+ if err := vd.StartValue(); err != nil {
+ t.Fatalf("error in StartValue: %v", err)
+ }
+ if got, want := vd.Type(), StringType; got != want {
+ t.Errorf("got %v, want %v", got, want)
+ }
+ key, err = vd.DecodeString()
+ switch {
+ case err != nil:
+ t.Errorf("error decoding value: %v", err)
+ case key != "a" && key != "b":
+ t.Errorf(`got %v, expected "a" or "b"`, key)
+ }
+ if err := vd.FinishValue(); err != nil {
+ t.Fatalf("error in FinishValue: %v", err)
+ }
+
+ switch done, err := vd.NextEntry(); {
+ case err != nil:
+ t.Fatalf("error in call to NextEntry(): %v", err)
+ case !done:
+ t.Fatalf("expected end marker")
+ }
+
+ if _, err := vd.NextEntry(); err == nil {
+ t.Errorf("expected error in final call to NextEntry()")
+ }
+
+ if err := vd.FinishValue(); err != nil {
+ t.Fatalf("error in FinishValue: %v", err)
+ }
+}
+
+func TestValueDecoderDecodeMap(t *testing.T) {
+ expected := map[string]uint32{"a": 3, "b": 7}
+ vd := ValueOf(expected).Decoder()
+ if err := vd.StartValue(); err != nil {
+ t.Fatalf("error in StartValue: %v", err)
+ }
+ if got, want := vd.Type(), TypeOf(expected); got != want {
+ t.Errorf("got %v, want %v", got, want)
+ }
+
+ switch done, err := vd.NextEntry(); {
+ case err != nil:
+ t.Fatalf("error in call to NextEntry(): %v", err)
+ case done:
+ t.Fatalf("ended prematurely")
+ }
+ if err := vd.StartValue(); err != nil {
+ t.Fatalf("error in StartValue: %v", err)
+ }
+ if got, want := vd.Type(), StringType; got != want {
+ t.Errorf("got %v, want %v", got, want)
+ }
+ key, err := vd.DecodeString()
+ switch {
+ case err != nil:
+ t.Errorf("error decoding value: %v", err)
+ case key != "a" && key != "b":
+ t.Errorf(`got %v, expected "a" or "b"`, key)
+ }
+ if err := vd.FinishValue(); err != nil {
+ t.Fatalf("error in FinishValue: %v", err)
+ }
+ if err := vd.StartValue(); err != nil {
+ t.Fatalf("error in StartValue: %v", err)
+ }
+ if got, want := vd.Type(), Uint32Type; got != want {
+ t.Errorf("got %v, want %v", got, want)
+ }
+ switch val, err := vd.DecodeUint(32); {
+ case err != nil:
+ t.Errorf("error decoding value: %v", err)
+ case val != uint64(expected[key]):
+ t.Errorf("got %v, want %v", expected[key], 3)
+ }
+ if err := vd.FinishValue(); err != nil {
+ t.Fatalf("error in FinishValue: %v", err)
+ }
+
+ switch done, err := vd.NextEntry(); {
+ case err != nil:
+ t.Fatalf("error in call to NextEntry(): %v", err)
+ case done:
+ t.Fatalf("ended prematurely")
+ }
+ if err := vd.StartValue(); err != nil {
+ t.Fatalf("error in StartValue: %v", err)
+ }
+ if got, want := vd.Type(), StringType; got != want {
+ t.Errorf("got %v, want %v", got, want)
+ }
+ key, err = vd.DecodeString()
+ switch {
+ case err != nil:
+ t.Errorf("error decoding value: %v", err)
+ case key != "a" && key != "b":
+ t.Errorf(`got %v, expected "a" or "b"`, key)
+ }
+ if err := vd.FinishValue(); err != nil {
+ t.Fatalf("error in FinishValue: %v", err)
+ }
+ if err := vd.StartValue(); err != nil {
+ t.Fatalf("error in StartValue: %v", err)
+ }
+ if got, want := vd.Type(), Uint32Type; got != want {
+ t.Errorf("got %v, want %v", got, want)
+ }
+ switch val, err := vd.DecodeUint(32); {
+ case err != nil:
+ t.Errorf("error decoding value: %v", err)
+ case val != uint64(expected[key]):
+ t.Errorf("got %v, want %v", val, expected[key])
+ }
+ if err := vd.FinishValue(); err != nil {
+ t.Fatalf("error in FinishValue: %v", err)
+ }
+
+ switch done, err := vd.NextEntry(); {
+ case err != nil:
+ t.Fatalf("error in call to NextEntry(): %v", err)
+ case !done:
+ t.Fatalf("expected end marker")
+ }
+
+ if _, err := vd.NextEntry(); err == nil {
+ t.Errorf("expected error in final call to NextEntry()")
+ }
+
+ if err := vd.FinishValue(); err != nil {
+ t.Fatalf("error in FinishValue: %v", err)
+ }
+}
+
+type decoderTestStruct struct {
+ A int32
+ B []bool
+ C string
+}
+
+func TestValueDecoderDecodeStruct(t *testing.T) {
+ expected := decoderTestStruct{1, []bool{true, false}, "abc"}
+ vd := ValueOf(expected).Decoder()
+ if err := vd.StartValue(); err != nil {
+ t.Errorf("error in StartValue: %v", err)
+ }
+ if got, want := vd.Type(), TypeOf(expected); got != want {
+ t.Errorf("got %v, want %v", got, want)
+ }
+
+ var seen []string
+loop:
+ for {
+ name, err := vd.NextField()
+ switch {
+ case err != nil:
+ t.Fatalf("error in NextField: %v", err)
+ case name == "A":
+ seen = append(seen, name)
+ if err := vd.StartValue(); err != nil {
+ t.Errorf("error in StartValue: %v", err)
+ }
+ switch val, err := vd.DecodeInt(32); {
+ case err != nil:
+ t.Errorf("error during decode: %v", err)
+ case val != 1:
+ t.Errorf("got %v, want %v", val, 1)
+ }
+ if err := vd.FinishValue(); err != nil {
+ t.Errorf("error in FinishValue: %v", err)
+ }
+ case name == "B":
+ seen = append(seen, name)
+ if err := vd.StartValue(); err != nil {
+ t.Errorf("error in StartValue: %v", err)
+ }
+
+ switch done, err := vd.NextEntry(); {
+ case err != nil:
+ t.Errorf("error in NextEntry: %v", err)
+ case done:
+ t.Errorf("unexpected end marker")
+ }
+ if err := vd.SkipValue(); err != nil {
+ t.Errorf("error in IgnoreValue: %v", err)
+ }
+
+ switch done, err := vd.NextEntry(); {
+ case err != nil:
+ t.Errorf("error in NextEntry: %v", err)
+ case done:
+ t.Errorf("unexpected end marker")
+ }
+ if err := vd.StartValue(); err != nil {
+ t.Errorf("error in StartValue: %v", err)
+ }
+ switch val, err := vd.DecodeBool(); {
+ case err != nil:
+ t.Errorf("error during decode: %v", err)
+ case val != false:
+ t.Errorf("got %v, want %v", val, false)
+ }
+ if err := vd.FinishValue(); err != nil {
+ t.Errorf("error in FinishValue: %v", err)
+ }
+
+ if err := vd.FinishValue(); err != nil {
+ t.Errorf("error in FinishValue: %v", err)
+ }
+ case name == "C":
+ seen = append(seen, name)
+ if err := vd.StartValue(); err != nil {
+ t.Errorf("error in StartValue: %v", err)
+ }
+ switch val, err := vd.DecodeString(); {
+ case err != nil:
+ t.Errorf("error during decode: %v", err)
+ case val != "abc":
+ t.Errorf("got %v, want %v", val, "abc")
+ }
+ if err := vd.FinishValue(); err != nil {
+ t.Errorf("error in FinishValue: %v", err)
+ }
+ case name == "":
+ sort.Strings(seen)
+ if !reflect.DeepEqual(seen, []string{"A", "B", "C"}) {
+ t.Errorf("unexpected field names received: %v", seen)
+ }
+ break loop
+ default:
+ t.Fatalf("received unknown field")
+ }
+ }
+
+ if _, err := vd.NextField(); err == nil {
+ t.Errorf("expected error in call to NextField()")
+ }
+ if err := vd.FinishValue(); err != nil {
+ t.Errorf("error in FinishValue: %v", err)
+ }
+}
+
+func TestValueDecoderDecodeUnion(t *testing.T) {
+ b := TypeBuilder{}
+ union := b.Union()
+ union.AppendField("A", BoolType).AppendField("B", StringType)
+ b.Build()
+ expectedType, err := union.Built()
+ if err != nil {
+ t.Fatalf("error building union type: %v", err)
+ }
+ expected := ZeroValue(expectedType)
+ vd := expected.Decoder()
+ if err := vd.StartValue(); err != nil {
+ t.Errorf("error in StartValue: %v", err)
+ }
+ if got, want := vd.Type(), expectedType; got != want {
+ t.Errorf("got %v, want %v", got, want)
+ }
+
+ switch name, err := vd.NextField(); {
+ case err != nil:
+ t.Errorf("error in NextField(): %v", err)
+ case name != "A":
+ t.Errorf("unexpected field name: %v", name)
+ }
+ if err := vd.StartValue(); err != nil {
+ t.Errorf("error in StartValue: %v", err)
+ }
+ switch val, err := vd.DecodeBool(); {
+ case err != nil:
+ t.Errorf("error during decode: %v", err)
+ case val != false:
+ t.Errorf("got %v, want %v", val, false)
+ }
+ if err := vd.FinishValue(); err != nil {
+ t.Errorf("error in FinishValue: %v", err)
+ }
+ switch name, err := vd.NextField(); {
+ case err != nil:
+ t.Errorf("error in NextField(): %v", err)
+ case name != "":
+ t.Errorf("unexpected field after end of fields: %v", name)
+ }
+ if _, err := vd.NextField(); err == nil {
+ t.Errorf("expected error in call to NextField()")
+ }
+ if err := vd.FinishValue(); err != nil {
+ t.Errorf("error in FinishValue: %v", err)
+ }
+}
diff --git a/vdl/value_reader.go b/vdl/value_reader.go
new file mode 100644
index 0000000..901f7d6
--- /dev/null
+++ b/vdl/value_reader.go
@@ -0,0 +1,307 @@
+// Copyright 2016 The Vanadium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package vdl
+
+import (
+ "fmt"
+)
+
+// VDLRead reads from a decoder into this vdl Value.
+func (vv *Value) VDLRead(dec Decoder) error {
+ if vv == nil || vv.t == nil {
+ return fmt.Errorf("cannot decode into nil vdl value")
+ }
+ if err := dec.StartValue(); err != nil {
+ return err
+ }
+ if dec.IsNil() {
+ return vv.readHandleNil(dec)
+ }
+ fillvvAny := vv
+ if vv.Kind() == Any {
+ innerType := dec.Type()
+ if dec.IsOptional() {
+ innerType = OptionalType(innerType)
+ }
+ fillvvAny = ZeroValue(innerType)
+ }
+ fillvv := fillvvAny
+ if fillvvAny.Kind() == Optional {
+ fillvv = ZeroValue(fillvvAny.Type().Elem())
+ }
+
+ if err := fillvv.readFillValue(dec); err != nil {
+ return err
+ }
+
+ if fillvvAny.Kind() == Optional {
+ fillvvAny.Assign(OptionalValue(fillvv))
+ }
+ if vv.Kind() == Any {
+ vv.Assign(fillvvAny)
+ }
+ return dec.FinishValue()
+}
+
+// readHandleNil handles the case that dec.IsNil() is true
+func (vv *Value) readHandleNil(dec Decoder) error {
+ switch {
+ case dec.IsOptional():
+ // handles optional inside-any and optional on-its-own cases
+ if dec.Type().Kind() != Optional {
+ return fmt.Errorf("invalid optional value returned from decoder of type %v", dec.Type())
+ }
+ vv.Assign(ZeroValue(dec.Type()))
+ case dec.IsAny():
+ vv.Assign(nil)
+ default:
+ return fmt.Errorf("invalid non-any, non-optional nil value of type %v", dec.Type())
+ }
+ return dec.FinishValue()
+}
+
+func (vv *Value) readFillValue(dec Decoder) error {
+ // Fill in the value.
+ if vv.Type().IsBytes() {
+ fixedLength := -1
+ if vv.Kind() == Array {
+ fixedLength = vv.Type().Len()
+ }
+ var val []byte
+ if err := dec.DecodeBytes(fixedLength, &val); err != nil {
+ return err
+ }
+ vv.AssignBytes(val)
+ return nil
+ }
+ switch vv.Kind() {
+ case Bool:
+ val, err := dec.DecodeBool()
+ if err != nil {
+ return err
+ }
+ vv.AssignBool(val)
+ case Byte, Uint16, Uint32, Uint64:
+ val, err := dec.DecodeUint(uint(bitlenV(vv.Kind())))
+ if err != nil {
+ return err
+ }
+ vv.AssignUint(val)
+ case Int8, Int16, Int32, Int64:
+ val, err := dec.DecodeInt(uint(bitlenV(vv.Kind())))
+ if err != nil {
+ return err
+ }
+ vv.AssignInt(val)
+ case Float32, Float64:
+ val, err := dec.DecodeFloat(uint(bitlenV(vv.Kind())))
+ if err != nil {
+ return err
+ }
+ vv.AssignFloat(val)
+ case String:
+ val, err := dec.DecodeString()
+ if err != nil {
+ return err
+ }
+ vv.AssignString(val)
+ case TypeObject:
+ val, err := dec.DecodeTypeObject()
+ if err != nil {
+ return err
+ }
+ vv.AssignTypeObject(val)
+ case Enum:
+ val, err := dec.DecodeString()
+ if err != nil {
+ return err
+ }
+
+ index := vv.Type().EnumIndex(val)
+ if index == -1 {
+ return fmt.Errorf("vdl: %v invalid enum label %q", vv.Type(), val)
+ }
+ vv.AssignEnumIndex(index)
+ case Array:
+ if err := vv.readArray(dec); err != nil {
+ return err
+ }
+ case List:
+ if err := vv.readList(dec); err != nil {
+ return err
+ }
+ case Set:
+ if err := vv.readSet(dec); err != nil {
+ return err
+ }
+ case Map:
+ if err := vv.readMap(dec); err != nil {
+ return err
+ }
+ case Struct:
+ if err := vv.readStruct(dec); err != nil {
+ return err
+ }
+ case Union:
+ if err := vv.readUnion(dec); err != nil {
+ return err
+ }
+ default:
+ panic(fmt.Sprintf("unhandled type: %v", dec.Type()))
+ }
+ return nil
+}
+
+func (vv *Value) readSet(dec Decoder) error {
+ if dec.Type().Kind() != Set {
+ return fmt.Errorf("cannot decode into set from %v", dec.Type())
+ }
+ for {
+ switch done, err := dec.NextEntry(); {
+ case err != nil:
+ return err
+ case done:
+ return nil
+ }
+ key := ZeroValue(vv.Type().Key())
+ if err := key.VDLRead(dec); err != nil {
+ return err
+ }
+ vv.AssignSetKey(key)
+ }
+}
+
+func (vv *Value) readArray(dec Decoder) error {
+ switch dec.Type().Kind() {
+ case Array, List:
+ default:
+ return fmt.Errorf("cannot decode into array from %v", dec.Type())
+ }
+ index := 0
+ for {
+ switch done, err := dec.NextEntry(); {
+ case err != nil:
+ return err
+ case done != (index >= vv.Type().Len()):
+ return fmt.Errorf("array len mismatch, got %d, want %v", index, vv.Type())
+ case done:
+ return nil
+ }
+ if err := vv.Index(index).VDLRead(dec); err != nil {
+ return err
+ }
+ index++
+ }
+ return nil
+}
+
+func (vv *Value) readList(dec Decoder) error {
+ switch dec.Type().Kind() {
+ case Array, List:
+ default:
+ return fmt.Errorf("cannot decode into list from %v", dec.Type())
+ }
+ if len := dec.LenHint(); len >= 0 {
+ vv.AssignLen(len)
+ }
+ index := 0
+ for {
+ switch done, err := dec.NextEntry(); {
+ case err != nil:
+ return err
+ case done:
+ return nil
+ }
+ if index >= vv.Len() {
+ vv.AssignLen(index + 1)
+ }
+ if err := vv.Index(index).VDLRead(dec); err != nil {
+ return err
+ }
+ index++
+ }
+ return nil
+}
+
+func (vv *Value) readMap(dec Decoder) error {
+ if dec.Type().Kind() != Map {
+ return fmt.Errorf("cannot decode into map from %v", dec.Type())
+ }
+ for {
+ switch done, err := dec.NextEntry(); {
+ case err != nil:
+ return err
+ case done:
+ return nil
+ }
+ key := ZeroValue(vv.Type().Key())
+ elem := ZeroValue(vv.Type().Elem())
+ if err := key.VDLRead(dec); err != nil {
+ return err
+ }
+ if err := elem.VDLRead(dec); err != nil {
+ return err
+ }
+ vv.AssignMapIndex(key, elem)
+ }
+ return nil
+}
+
+func (vv *Value) readStruct(dec Decoder) error {
+ if dec.Type().Kind() != Struct {
+ return fmt.Errorf("cannot decode into struct from %v", dec.Type())
+ }
+ var matches int
+ for {
+ name, err := dec.NextField()
+ if err != nil {
+ return err
+ }
+ if name == "" {
+ if matches == 0 && dec.Type().NumField() > 0 && vv.Type().NumField() > 0 {
+ return fmt.Errorf("no matching fields found when decoding into struct of type %v", vv.Type())
+ }
+ return nil
+ }
+
+ field := vv.StructFieldByName(name)
+ if field == nil {
+ if err := dec.SkipValue(); err != nil {
+ return err
+ }
+ } else {
+ matches++
+ if err := field.VDLRead(dec); err != nil {
+ return err
+ }
+ }
+ }
+}
+
+func (vv *Value) readUnion(dec Decoder) error {
+ if dec.Type().Kind() != Union {
+ return fmt.Errorf("cannot decode into union from %v", dec.Type())
+ }
+ name, err := dec.NextField()
+ if err != nil {
+ return err
+ }
+ fld, index := vv.Type().FieldByName(name)
+ if index < 0 {
+ return fmt.Errorf("invalid field name %s when decoding into union %v", name, vv.Type())
+ }
+ unionElem := ZeroValue(fld.Type)
+ if err := unionElem.VDLRead(dec); err != nil {
+ return err
+ }
+ vv.AssignUnionField(index, unionElem)
+ switch name, err := dec.NextField(); {
+ case err != nil:
+ return err
+ case name != "":
+ return fmt.Errorf("multiple fields illegally specified for union")
+ }
+ return nil
+}
diff --git a/vdl/value_reader_test.go b/vdl/value_reader_test.go
new file mode 100644
index 0000000..03bee7d
--- /dev/null
+++ b/vdl/value_reader_test.go
@@ -0,0 +1,25 @@
+// Copyright 2016 The Vanadium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package vdl_test
+
+import (
+ "testing"
+
+ "v.io/v23/vdl"
+ "v.io/v23/vom/testdata/data81"
+)
+
+func TestValueRead(t *testing.T) {
+ for _, test := range data81.Tests {
+ out := vdl.ZeroValue(test.Value.Type())
+ if err := out.VDLRead(test.Value.Decoder()); err != nil {
+ t.Errorf("%s: error in ValueRead: %v", test.Name, err)
+ continue
+ }
+ if !vdl.EqualValue(test.Value, out) {
+ t.Errorf("%s: got %v, want %v", test.Name, out, test.Value)
+ }
+ }
+}
diff --git a/vom/encoder.go b/vom/encoder.go
index f55cf48..8d0a30b 100644
--- a/vom/encoder.go
+++ b/vom/encoder.go
@@ -314,7 +314,7 @@
// prepareTypeHelper encodes any unsent types, and manages the type stack. If
// fromNil is true, we skip encoding the typeid for any type, since we'll be
// encoding a nil instead.
-func (e *encoder) prepareTypeHelper(tt *vdl.Type, fromNil bool) error {
+func (e *encoder) prepareTypeHelper(tt *vdl.Type, preventAnyWrap bool) error {
var tid typeId
// Check the bootstrap wire types first to avoid recursive calls to the type
// encoder for wire types.
@@ -332,7 +332,7 @@
// Encoding the top-level. We postpone encoding of the tid until writeMsg
// is called, to handle positive and negative ids, and the message length.
e.pushType(tt)
- case !fromNil && e.topType().Kind() == vdl.Any:
+ case !preventAnyWrap && e.topType().Kind() == vdl.Any:
if e.version == Version80 {
binaryEncodeUint(e.buf, uint64(tid))
} else {
@@ -579,7 +579,9 @@
if !tt.CanBeNil() {
return errTypeMismatch(tt, nilAllowed...)
}
- if err := e.prepareTypeHelper(tt, true); err != nil {
+ // Emit any wrapper iff this is a nil optional within an any.
+ preventAnyWrap := len(e.typeStack) == 0 || e.topType() != vdl.AnyType || tt.Kind() != vdl.Optional
+ if err := e.prepareTypeHelper(tt, preventAnyWrap); err != nil {
return err
}
e.buf.WriteOneByte(WireCtrlNil)
diff --git a/vom/testdata/data80/data80.vdl.go b/vom/testdata/data80/data80.vdl.go
index 9cde28a..c408ad3 100644
--- a/vom/testdata/data80/data80.vdl.go
+++ b/vom/testdata/data80/data80.vdl.go
@@ -2278,6 +2278,28 @@
HexValue: "5205002a0000e1",
},
{
+ Name: "types.StructAny{Any: ?types.NStruct(nil)}",
+ Value: vdl.ValueOf(types.StructAny{
+ Any: vdl.ValueOf((*types.NStruct)(nil)),
+ }),
+ TypeString: "v.io/v23/vom/testdata/types.StructAny struct{Any any}",
+ Hex: "805133060025762e696f2f7632332f766f6d2f74657374646174612f74797065732e537472756374416e7901010003416e79010fe1e1553b060023762e696f2f7632332f766f6d2f74657374646174612f74797065732e4e53747275637401030001410101e10001420103e10001430109e1e1530408012be15204002ae0e1",
+ HexVersion: "80",
+ HexType: "5133060025762e696f2f7632332f766f6d2f74657374646174612f74797065732e537472756374416e7901010003416e79010fe1e1553b060023762e696f2f7632332f766f6d2f74657374646174612f74797065732e4e53747275637401030001410101e10001420103e10001430109e1e1530408012be1",
+ HexValue: "5204002ae0e1",
+ },
+ {
+ Name: "types.StructAny{Any: ?types.NStruct{}}",
+ Value: vdl.ValueOf(types.StructAny{
+ Any: vdl.ValueOf(&types.NStruct{}),
+ }),
+ TypeString: "v.io/v23/vom/testdata/types.StructAny struct{Any any}",
+ Hex: "805133060025762e696f2f7632332f766f6d2f74657374646174612f74797065732e537472756374416e7901010003416e79010fe1e1553b060023762e696f2f7632332f766f6d2f74657374646174612f74797065732e4e53747275637401030001410101e10001420103e10001430109e1e1530408012be15204002ae1e1",
+ HexVersion: "80",
+ HexType: "5133060025762e696f2f7632332f766f6d2f74657374646174612f74797065732e537472756374416e7901010003416e79010fe1e1553b060023762e696f2f7632332f766f6d2f74657374646174612f74797065732e4e53747275637401030001410101e10001420103e10001430109e1e1530408012be1",
+ HexValue: "5204002ae1e1",
+ },
+ {
Name: "types.StructAny{Any: types.StructMap{}}",
Value: vdl.ValueOf(types.StructAny{
Any: vdl.ValueOf(types.StructMap{}),
diff --git a/vom/testdata/data80/vomdata.vdl b/vom/testdata/data80/vomdata.vdl
index ba7420b..660296a 100644
--- a/vom/testdata/data80/vomdata.vdl
+++ b/vom/testdata/data80/vomdata.vdl
@@ -6171,6 +6171,148 @@
"80", "5133060025762e696f2f7632332f766f6d2f74657374646174612f74797065732e537472756374416e7901010003416e79010fe1e1533a070022762e696f2f7632332f766f6d2f74657374646174612f74797065732e4e556e696f6e01030001410101e10001420103e10001430109e1e1", "5205002a0000e1",
},
// 80 Version 128 [vom version 80]
+ // DumpStatus{MsgId: 0, MsgN: 1, Buf(126): "5133060025762e696f2f7632332f766f6d2f74657374646174612f74797065732e537472756374416e7901010003416e79010fe1e1553b060023762e696f2f7632332f766f6d2f74657374646174612f74797065732e4e53747275637401030001410101e10001420103e10001430109e1e1530408012be15204002ae0e1"}
+ // 51 MsgId -41
+ // TypeMsg 41
+ // 33 MsgLen 51
+ // 06 WireTypeIndex 6 [v.io/v23/vom.wireStruct]
+ // 00 Index 0 [v.io/v23/vom.wireStruct.Name]
+ // 25 ByteLen 37 [string len]
+ // 762e696f2f7632332f766f6d2f74657374646174612f74797065732e537472756374416e79 PrimValue "v.io/v23/vom/testdata/types.StructAny" [string]
+ // 01 Index 1 [v.io/v23/vom.wireStruct.Fields]
+ // 01 ValueLen 1 [list len]
+ // 00 Index 0 [v.io/v23/vom.wireField.Name]
+ // 03 ByteLen 3 [string len]
+ // 416e79 PrimValue "Any" [string]
+ // 01 Index 1 [v.io/v23/vom.wireField.Type]
+ // 0f PrimValue 15 [uint]
+ // e1 Control End [v.io/v23/vom.wireField END]
+ // e1 Control End [v.io/v23/vom.wireStruct END]
+ // DumpStatus{MsgId: -41, MsgLen: 51, MsgN: 51, Buf(73): "553b060023762e696f2f7632332f766f6d2f74657374646174612f74797065732e4e53747275637401030001410101e10001420103e10001430109e1e1530408012be15204002ae0e1"}
+ // 55 MsgId -43
+ // TypeMsg 43
+ // 3b MsgLen 59
+ // 06 WireTypeIndex 6 [v.io/v23/vom.wireStruct]
+ // 00 Index 0 [v.io/v23/vom.wireStruct.Name]
+ // 23 ByteLen 35 [string len]
+ // 762e696f2f7632332f766f6d2f74657374646174612f74797065732e4e537472756374 PrimValue "v.io/v23/vom/testdata/types.NStruct" [string]
+ // 01 Index 1 [v.io/v23/vom.wireStruct.Fields]
+ // 03 ValueLen 3 [list len]
+ // 00 Index 0 [v.io/v23/vom.wireField.Name]
+ // 01 ByteLen 1 [string len]
+ // 41 PrimValue "A" [string]
+ // 01 Index 1 [v.io/v23/vom.wireField.Type]
+ // 01 PrimValue 1 [uint]
+ // e1 Control End [v.io/v23/vom.wireField END]
+ // 00 Index 0 [v.io/v23/vom.wireField.Name]
+ // 01 ByteLen 1 [string len]
+ // 42 PrimValue "B" [string]
+ // 01 Index 1 [v.io/v23/vom.wireField.Type]
+ // 03 PrimValue 3 [uint]
+ // e1 Control End [v.io/v23/vom.wireField END]
+ // 00 Index 0 [v.io/v23/vom.wireField.Name]
+ // 01 ByteLen 1 [string len]
+ // 43 PrimValue "C" [string]
+ // 01 Index 1 [v.io/v23/vom.wireField.Type]
+ // 09 PrimValue 9 [uint]
+ // e1 Control End [v.io/v23/vom.wireField END]
+ // e1 Control End [v.io/v23/vom.wireStruct END]
+ // DumpStatus{MsgId: -43, MsgLen: 59, MsgN: 59, Buf(12): "530408012be15204002ae0e1"}
+ // 53 MsgId -42
+ // TypeMsg 42
+ // 04 MsgLen 4
+ // 08 WireTypeIndex 8 [v.io/v23/vom.wireOptional]
+ // 01 Index 1 [v.io/v23/vom.wireOptional.Elem]
+ // 2b PrimValue 43 [uint]
+ // e1 Control End [v.io/v23/vom.wireOptional END]
+ // DumpStatus{MsgId: -42, MsgLen: 4, MsgN: 4, Buf(6): "5204002ae0e1"}
+ // 52 MsgId 41
+ // ValueMsg 41 [v.io/v23/vom/testdata/types.StructAny struct{Any any}]
+ // 04 MsgLen 4
+ // 00 Index 0 [v.io/v23/vom/testdata/types.StructAny.Any]
+ // 2a TypeId 42 [?v.io/v23/vom/testdata/types.NStruct struct{A bool;B string;C int64}]
+ // e0 Control Nil [?v.io/v23/vom/testdata/types.NStruct struct{A bool;B string;C int64} is nil]
+ // e1 Control End [v.io/v23/vom/testdata/types.StructAny END]
+ // DumpStatus{MsgId: 41, MsgLen: 4, MsgN: 4, Value: v.io/v23/vom/testdata/types.StructAny struct{Any any}{Any: ?v.io/v23/vom/testdata/types.NStruct struct{A bool;B string;C int64}(nil)}}
+ {
+ `types.StructAny{Any: ?types.NStruct(nil)}`,
+ types.StructAny{Any: ?types.NStruct(nil)},
+ "v.io/v23/vom/testdata/types.StructAny struct{Any any}",
+ "805133060025762e696f2f7632332f766f6d2f74657374646174612f74797065732e537472756374416e7901010003416e79010fe1e1553b060023762e696f2f7632332f766f6d2f74657374646174612f74797065732e4e53747275637401030001410101e10001420103e10001430109e1e1530408012be15204002ae0e1",
+ "80", "5133060025762e696f2f7632332f766f6d2f74657374646174612f74797065732e537472756374416e7901010003416e79010fe1e1553b060023762e696f2f7632332f766f6d2f74657374646174612f74797065732e4e53747275637401030001410101e10001420103e10001430109e1e1530408012be1", "5204002ae0e1",
+ },
+ // 80 Version 128 [vom version 80]
+ // DumpStatus{MsgId: 0, MsgN: 1, Buf(126): "5133060025762e696f2f7632332f766f6d2f74657374646174612f74797065732e537472756374416e7901010003416e79010fe1e1553b060023762e696f2f7632332f766f6d2f74657374646174612f74797065732e4e53747275637401030001410101e10001420103e10001430109e1e1530408012be15204002ae1e1"}
+ // 51 MsgId -41
+ // TypeMsg 41
+ // 33 MsgLen 51
+ // 06 WireTypeIndex 6 [v.io/v23/vom.wireStruct]
+ // 00 Index 0 [v.io/v23/vom.wireStruct.Name]
+ // 25 ByteLen 37 [string len]
+ // 762e696f2f7632332f766f6d2f74657374646174612f74797065732e537472756374416e79 PrimValue "v.io/v23/vom/testdata/types.StructAny" [string]
+ // 01 Index 1 [v.io/v23/vom.wireStruct.Fields]
+ // 01 ValueLen 1 [list len]
+ // 00 Index 0 [v.io/v23/vom.wireField.Name]
+ // 03 ByteLen 3 [string len]
+ // 416e79 PrimValue "Any" [string]
+ // 01 Index 1 [v.io/v23/vom.wireField.Type]
+ // 0f PrimValue 15 [uint]
+ // e1 Control End [v.io/v23/vom.wireField END]
+ // e1 Control End [v.io/v23/vom.wireStruct END]
+ // DumpStatus{MsgId: -41, MsgLen: 51, MsgN: 51, Buf(73): "553b060023762e696f2f7632332f766f6d2f74657374646174612f74797065732e4e53747275637401030001410101e10001420103e10001430109e1e1530408012be15204002ae1e1"}
+ // 55 MsgId -43
+ // TypeMsg 43
+ // 3b MsgLen 59
+ // 06 WireTypeIndex 6 [v.io/v23/vom.wireStruct]
+ // 00 Index 0 [v.io/v23/vom.wireStruct.Name]
+ // 23 ByteLen 35 [string len]
+ // 762e696f2f7632332f766f6d2f74657374646174612f74797065732e4e537472756374 PrimValue "v.io/v23/vom/testdata/types.NStruct" [string]
+ // 01 Index 1 [v.io/v23/vom.wireStruct.Fields]
+ // 03 ValueLen 3 [list len]
+ // 00 Index 0 [v.io/v23/vom.wireField.Name]
+ // 01 ByteLen 1 [string len]
+ // 41 PrimValue "A" [string]
+ // 01 Index 1 [v.io/v23/vom.wireField.Type]
+ // 01 PrimValue 1 [uint]
+ // e1 Control End [v.io/v23/vom.wireField END]
+ // 00 Index 0 [v.io/v23/vom.wireField.Name]
+ // 01 ByteLen 1 [string len]
+ // 42 PrimValue "B" [string]
+ // 01 Index 1 [v.io/v23/vom.wireField.Type]
+ // 03 PrimValue 3 [uint]
+ // e1 Control End [v.io/v23/vom.wireField END]
+ // 00 Index 0 [v.io/v23/vom.wireField.Name]
+ // 01 ByteLen 1 [string len]
+ // 43 PrimValue "C" [string]
+ // 01 Index 1 [v.io/v23/vom.wireField.Type]
+ // 09 PrimValue 9 [uint]
+ // e1 Control End [v.io/v23/vom.wireField END]
+ // e1 Control End [v.io/v23/vom.wireStruct END]
+ // DumpStatus{MsgId: -43, MsgLen: 59, MsgN: 59, Buf(12): "530408012be15204002ae1e1"}
+ // 53 MsgId -42
+ // TypeMsg 42
+ // 04 MsgLen 4
+ // 08 WireTypeIndex 8 [v.io/v23/vom.wireOptional]
+ // 01 Index 1 [v.io/v23/vom.wireOptional.Elem]
+ // 2b PrimValue 43 [uint]
+ // e1 Control End [v.io/v23/vom.wireOptional END]
+ // DumpStatus{MsgId: -42, MsgLen: 4, MsgN: 4, Buf(6): "5204002ae1e1"}
+ // 52 MsgId 41
+ // ValueMsg 41 [v.io/v23/vom/testdata/types.StructAny struct{Any any}]
+ // 04 MsgLen 4
+ // 00 Index 0 [v.io/v23/vom/testdata/types.StructAny.Any]
+ // 2a TypeId 42 [?v.io/v23/vom/testdata/types.NStruct struct{A bool;B string;C int64}]
+ // e1 Control End [v.io/v23/vom/testdata/types.NStruct END]
+ // e1 Control End [v.io/v23/vom/testdata/types.StructAny END]
+ // DumpStatus{MsgId: 41, MsgLen: 4, MsgN: 4, Value: v.io/v23/vom/testdata/types.StructAny struct{Any any}{Any: ?v.io/v23/vom/testdata/types.NStruct struct{A bool;B string;C int64}({A: false, B: "", C: 0})}}
+ {
+ `types.StructAny{Any: ?types.NStruct{}}`,
+ types.StructAny{Any: ?types.NStruct{}},
+ "v.io/v23/vom/testdata/types.StructAny struct{Any any}",
+ "805133060025762e696f2f7632332f766f6d2f74657374646174612f74797065732e537472756374416e7901010003416e79010fe1e1553b060023762e696f2f7632332f766f6d2f74657374646174612f74797065732e4e53747275637401030001410101e10001420103e10001430109e1e1530408012be15204002ae1e1",
+ "80", "5133060025762e696f2f7632332f766f6d2f74657374646174612f74797065732e537472756374416e7901010003416e79010fe1e1553b060023762e696f2f7632332f766f6d2f74657374646174612f74797065732e4e53747275637401030001410101e10001420103e10001430109e1e1530408012be1", "5204002ae1e1",
+ },
+ // 80 Version 128 [vom version 80]
// DumpStatus{MsgId: 0, MsgN: 1, Buf(120): "5133060025762e696f2f7632332f766f6d2f74657374646174612f74797065732e537472756374416e7901010003416e79010fe1e155060501090209e15333060025762e696f2f7632332f766f6d2f74657374646174612f74797065732e5374727563744d6170010100034d6170012be1e15204002ae1e1"}
// 51 MsgId -41
// TypeMsg 41
diff --git a/vom/testdata/data81/data81.vdl.go b/vom/testdata/data81/data81.vdl.go
index 17bf3eb..85a581c 100644
--- a/vom/testdata/data81/data81.vdl.go
+++ b/vom/testdata/data81/data81.vdl.go
@@ -2278,6 +2278,28 @@
HexValue: "52012a0102060000000000e1",
},
{
+ Name: "types.StructAny{Any: ?types.NStruct(nil)}",
+ Value: vdl.ValueOf(types.StructAny{
+ Any: vdl.ValueOf((*types.NStruct)(nil)),
+ }),
+ TypeString: "v.io/v23/vom/testdata/types.StructAny struct{Any any}",
+ Hex: "815133060025762e696f2f7632332f766f6d2f74657374646174612f74797065732e537472756374416e7901010003416e79010fe1e1553b060023762e696f2f7632332f766f6d2f74657374646174612f74797065732e4e53747275637401030001410101e10001420103e10001430109e1e1530408012be152012a010105000000e0e1",
+ HexVersion: "81",
+ HexType: "5133060025762e696f2f7632332f766f6d2f74657374646174612f74797065732e537472756374416e7901010003416e79010fe1e1553b060023762e696f2f7632332f766f6d2f74657374646174612f74797065732e4e53747275637401030001410101e10001420103e10001430109e1e1530408012be1",
+ HexValue: "52012a010105000000e0e1",
+ },
+ {
+ Name: "types.StructAny{Any: ?types.NStruct{}}",
+ Value: vdl.ValueOf(types.StructAny{
+ Any: vdl.ValueOf(&types.NStruct{}),
+ }),
+ TypeString: "v.io/v23/vom/testdata/types.StructAny struct{Any any}",
+ Hex: "815133060025762e696f2f7632332f766f6d2f74657374646174612f74797065732e537472756374416e7901010003416e79010fe1e1553b060023762e696f2f7632332f766f6d2f74657374646174612f74797065732e4e53747275637401030001410101e10001420103e10001430109e1e1530408012be152012a010105000000e1e1",
+ HexVersion: "81",
+ HexType: "5133060025762e696f2f7632332f766f6d2f74657374646174612f74797065732e537472756374416e7901010003416e79010fe1e1553b060023762e696f2f7632332f766f6d2f74657374646174612f74797065732e4e53747275637401030001410101e10001420103e10001430109e1e1530408012be1",
+ HexValue: "52012a010105000000e1e1",
+ },
+ {
Name: "types.StructAny{Any: types.StructMap{}}",
Value: vdl.ValueOf(types.StructAny{
Any: vdl.ValueOf(types.StructMap{}),
diff --git a/vom/testdata/data81/vomdata.vdl b/vom/testdata/data81/vomdata.vdl
index 68769dd..aa4fd5a 100644
--- a/vom/testdata/data81/vomdata.vdl
+++ b/vom/testdata/data81/vomdata.vdl
@@ -6369,6 +6369,158 @@
"81", "5133060025762e696f2f7632332f766f6d2f74657374646174612f74797065732e537472756374416e7901010003416e79010fe1e1533a070022762e696f2f7632332f766f6d2f74657374646174612f74797065732e4e556e696f6e01030001410101e10001420103e10001430109e1e1", "52012a0102060000000000e1",
},
// 81 Version 129 [vom version 81]
+ // DumpStatus{MsgId: 0, MsgN: 1, Buf(131): "5133060025762e696f2f7632332f766f6d2f74657374646174612f74797065732e537472756374416e7901010003416e79010fe1e1553b060023762e696f2f7632332f766f6d2f74657374646174612f74797065732e4e53747275637401030001410101e10001420103e10001430109e1e1530408012be152012a010105000000e0e1"}
+ // 51 MsgId -41
+ // TypeMsg 41
+ // 33 MsgLen 51
+ // 06 WireTypeIndex 6 [v.io/v23/vom.wireStruct]
+ // 00 Index 0 [v.io/v23/vom.wireStruct.Name]
+ // 25 ByteLen 37 [string len]
+ // 762e696f2f7632332f766f6d2f74657374646174612f74797065732e537472756374416e79 PrimValue "v.io/v23/vom/testdata/types.StructAny" [string]
+ // 01 Index 1 [v.io/v23/vom.wireStruct.Fields]
+ // 01 ValueLen 1 [list len]
+ // 00 Index 0 [v.io/v23/vom.wireField.Name]
+ // 03 ByteLen 3 [string len]
+ // 416e79 PrimValue "Any" [string]
+ // 01 Index 1 [v.io/v23/vom.wireField.Type]
+ // 0f PrimValue 15 [uint]
+ // e1 Control End [v.io/v23/vom.wireField END]
+ // e1 Control End [v.io/v23/vom.wireStruct END]
+ // DumpStatus{MsgId: -41, MsgLen: 51, MsgN: 51, Buf(78): "553b060023762e696f2f7632332f766f6d2f74657374646174612f74797065732e4e53747275637401030001410101e10001420103e10001430109e1e1530408012be152012a010105000000e0e1"}
+ // 55 MsgId -43
+ // TypeMsg 43
+ // 3b MsgLen 59
+ // 06 WireTypeIndex 6 [v.io/v23/vom.wireStruct]
+ // 00 Index 0 [v.io/v23/vom.wireStruct.Name]
+ // 23 ByteLen 35 [string len]
+ // 762e696f2f7632332f766f6d2f74657374646174612f74797065732e4e537472756374 PrimValue "v.io/v23/vom/testdata/types.NStruct" [string]
+ // 01 Index 1 [v.io/v23/vom.wireStruct.Fields]
+ // 03 ValueLen 3 [list len]
+ // 00 Index 0 [v.io/v23/vom.wireField.Name]
+ // 01 ByteLen 1 [string len]
+ // 41 PrimValue "A" [string]
+ // 01 Index 1 [v.io/v23/vom.wireField.Type]
+ // 01 PrimValue 1 [uint]
+ // e1 Control End [v.io/v23/vom.wireField END]
+ // 00 Index 0 [v.io/v23/vom.wireField.Name]
+ // 01 ByteLen 1 [string len]
+ // 42 PrimValue "B" [string]
+ // 01 Index 1 [v.io/v23/vom.wireField.Type]
+ // 03 PrimValue 3 [uint]
+ // e1 Control End [v.io/v23/vom.wireField END]
+ // 00 Index 0 [v.io/v23/vom.wireField.Name]
+ // 01 ByteLen 1 [string len]
+ // 43 PrimValue "C" [string]
+ // 01 Index 1 [v.io/v23/vom.wireField.Type]
+ // 09 PrimValue 9 [uint]
+ // e1 Control End [v.io/v23/vom.wireField END]
+ // e1 Control End [v.io/v23/vom.wireStruct END]
+ // DumpStatus{MsgId: -43, MsgLen: 59, MsgN: 59, Buf(17): "530408012be152012a010105000000e0e1"}
+ // 53 MsgId -42
+ // TypeMsg 42
+ // 04 MsgLen 4
+ // 08 WireTypeIndex 8 [v.io/v23/vom.wireOptional]
+ // 01 Index 1 [v.io/v23/vom.wireOptional.Elem]
+ // 2b PrimValue 43 [uint]
+ // e1 Control End [v.io/v23/vom.wireOptional END]
+ // DumpStatus{MsgId: -42, MsgLen: 4, MsgN: 4, Buf(11): "52012a010105000000e0e1"}
+ // 52 MsgId 41
+ // ValueMsg 41 [v.io/v23/vom/testdata/types.StructAny struct{Any any}]
+ // 01 TypeIdsLen 1
+ // 2a TypeId 42
+ // 01 AnyLensLen 1
+ // 01 AnyMsgLen 1
+ // 05 MsgLen 5
+ // 00 Index 0 [v.io/v23/vom/testdata/types.StructAny.Any]
+ // 00 TypeId 0 [?v.io/v23/vom/testdata/types.NStruct struct{A bool;B string;C int64}]
+ // 00 AnyMsgLen 0 [len 1]
+ // e0 Control Nil [?v.io/v23/vom/testdata/types.NStruct struct{A bool;B string;C int64} is nil]
+ // e1 Control End [v.io/v23/vom/testdata/types.StructAny END]
+ // DumpStatus{MsgId: 41, MsgLen: 5, MsgN: 5, Value: v.io/v23/vom/testdata/types.StructAny struct{Any any}{Any: ?v.io/v23/vom/testdata/types.NStruct struct{A bool;B string;C int64}(nil)}}
+ {
+ `types.StructAny{Any: ?types.NStruct(nil)}`,
+ types.StructAny{Any: ?types.NStruct(nil)},
+ "v.io/v23/vom/testdata/types.StructAny struct{Any any}",
+ "815133060025762e696f2f7632332f766f6d2f74657374646174612f74797065732e537472756374416e7901010003416e79010fe1e1553b060023762e696f2f7632332f766f6d2f74657374646174612f74797065732e4e53747275637401030001410101e10001420103e10001430109e1e1530408012be152012a010105000000e0e1",
+ "81", "5133060025762e696f2f7632332f766f6d2f74657374646174612f74797065732e537472756374416e7901010003416e79010fe1e1553b060023762e696f2f7632332f766f6d2f74657374646174612f74797065732e4e53747275637401030001410101e10001420103e10001430109e1e1530408012be1", "52012a010105000000e0e1",
+ },
+ // 81 Version 129 [vom version 81]
+ // DumpStatus{MsgId: 0, MsgN: 1, Buf(131): "5133060025762e696f2f7632332f766f6d2f74657374646174612f74797065732e537472756374416e7901010003416e79010fe1e1553b060023762e696f2f7632332f766f6d2f74657374646174612f74797065732e4e53747275637401030001410101e10001420103e10001430109e1e1530408012be152012a010105000000e1e1"}
+ // 51 MsgId -41
+ // TypeMsg 41
+ // 33 MsgLen 51
+ // 06 WireTypeIndex 6 [v.io/v23/vom.wireStruct]
+ // 00 Index 0 [v.io/v23/vom.wireStruct.Name]
+ // 25 ByteLen 37 [string len]
+ // 762e696f2f7632332f766f6d2f74657374646174612f74797065732e537472756374416e79 PrimValue "v.io/v23/vom/testdata/types.StructAny" [string]
+ // 01 Index 1 [v.io/v23/vom.wireStruct.Fields]
+ // 01 ValueLen 1 [list len]
+ // 00 Index 0 [v.io/v23/vom.wireField.Name]
+ // 03 ByteLen 3 [string len]
+ // 416e79 PrimValue "Any" [string]
+ // 01 Index 1 [v.io/v23/vom.wireField.Type]
+ // 0f PrimValue 15 [uint]
+ // e1 Control End [v.io/v23/vom.wireField END]
+ // e1 Control End [v.io/v23/vom.wireStruct END]
+ // DumpStatus{MsgId: -41, MsgLen: 51, MsgN: 51, Buf(78): "553b060023762e696f2f7632332f766f6d2f74657374646174612f74797065732e4e53747275637401030001410101e10001420103e10001430109e1e1530408012be152012a010105000000e1e1"}
+ // 55 MsgId -43
+ // TypeMsg 43
+ // 3b MsgLen 59
+ // 06 WireTypeIndex 6 [v.io/v23/vom.wireStruct]
+ // 00 Index 0 [v.io/v23/vom.wireStruct.Name]
+ // 23 ByteLen 35 [string len]
+ // 762e696f2f7632332f766f6d2f74657374646174612f74797065732e4e537472756374 PrimValue "v.io/v23/vom/testdata/types.NStruct" [string]
+ // 01 Index 1 [v.io/v23/vom.wireStruct.Fields]
+ // 03 ValueLen 3 [list len]
+ // 00 Index 0 [v.io/v23/vom.wireField.Name]
+ // 01 ByteLen 1 [string len]
+ // 41 PrimValue "A" [string]
+ // 01 Index 1 [v.io/v23/vom.wireField.Type]
+ // 01 PrimValue 1 [uint]
+ // e1 Control End [v.io/v23/vom.wireField END]
+ // 00 Index 0 [v.io/v23/vom.wireField.Name]
+ // 01 ByteLen 1 [string len]
+ // 42 PrimValue "B" [string]
+ // 01 Index 1 [v.io/v23/vom.wireField.Type]
+ // 03 PrimValue 3 [uint]
+ // e1 Control End [v.io/v23/vom.wireField END]
+ // 00 Index 0 [v.io/v23/vom.wireField.Name]
+ // 01 ByteLen 1 [string len]
+ // 43 PrimValue "C" [string]
+ // 01 Index 1 [v.io/v23/vom.wireField.Type]
+ // 09 PrimValue 9 [uint]
+ // e1 Control End [v.io/v23/vom.wireField END]
+ // e1 Control End [v.io/v23/vom.wireStruct END]
+ // DumpStatus{MsgId: -43, MsgLen: 59, MsgN: 59, Buf(17): "530408012be152012a010105000000e1e1"}
+ // 53 MsgId -42
+ // TypeMsg 42
+ // 04 MsgLen 4
+ // 08 WireTypeIndex 8 [v.io/v23/vom.wireOptional]
+ // 01 Index 1 [v.io/v23/vom.wireOptional.Elem]
+ // 2b PrimValue 43 [uint]
+ // e1 Control End [v.io/v23/vom.wireOptional END]
+ // DumpStatus{MsgId: -42, MsgLen: 4, MsgN: 4, Buf(11): "52012a010105000000e1e1"}
+ // 52 MsgId 41
+ // ValueMsg 41 [v.io/v23/vom/testdata/types.StructAny struct{Any any}]
+ // 01 TypeIdsLen 1
+ // 2a TypeId 42
+ // 01 AnyLensLen 1
+ // 01 AnyMsgLen 1
+ // 05 MsgLen 5
+ // 00 Index 0 [v.io/v23/vom/testdata/types.StructAny.Any]
+ // 00 TypeId 0 [?v.io/v23/vom/testdata/types.NStruct struct{A bool;B string;C int64}]
+ // 00 AnyMsgLen 0 [len 1]
+ // e1 Control End [v.io/v23/vom/testdata/types.NStruct END]
+ // e1 Control End [v.io/v23/vom/testdata/types.StructAny END]
+ // DumpStatus{MsgId: 41, MsgLen: 5, MsgN: 5, Value: v.io/v23/vom/testdata/types.StructAny struct{Any any}{Any: ?v.io/v23/vom/testdata/types.NStruct struct{A bool;B string;C int64}({A: false, B: "", C: 0})}}
+ {
+ `types.StructAny{Any: ?types.NStruct{}}`,
+ types.StructAny{Any: ?types.NStruct{}},
+ "v.io/v23/vom/testdata/types.StructAny struct{Any any}",
+ "815133060025762e696f2f7632332f766f6d2f74657374646174612f74797065732e537472756374416e7901010003416e79010fe1e1553b060023762e696f2f7632332f766f6d2f74657374646174612f74797065732e4e53747275637401030001410101e10001420103e10001430109e1e1530408012be152012a010105000000e1e1",
+ "81", "5133060025762e696f2f7632332f766f6d2f74657374646174612f74797065732e537472756374416e7901010003416e79010fe1e1553b060023762e696f2f7632332f766f6d2f74657374646174612f74797065732e4e53747275637401030001410101e10001420103e10001430109e1e1530408012be1", "52012a010105000000e1e1",
+ },
+ // 81 Version 129 [vom version 81]
// DumpStatus{MsgId: 0, MsgN: 1, Buf(125): "5133060025762e696f2f7632332f766f6d2f74657374646174612f74797065732e537472756374416e7901010003416e79010fe1e155060501090209e15333060025762e696f2f7632332f766f6d2f74657374646174612f74797065732e5374727563744d6170010100034d6170012be1e152012a010105000000e1e1"}
// 51 MsgId -41
// TypeMsg 41
diff --git a/vom/testdata/vomdata.vdl.config b/vom/testdata/vomdata.vdl.config
index 873b4b3..209e8f0 100644
--- a/vom/testdata/vomdata.vdl.config
+++ b/vom/testdata/vomdata.vdl.config
@@ -198,6 +198,7 @@
t.StructAny{t.NListUint64{}}, t.StructAny{t.NByteArray{}}, t.StructAny{t.NArray2Uint64{}},
t.StructAny{t.NSetUint64{}}, t.StructAny{t.NMapUint64String{}},
t.StructAny{t.NStruct{}}, t.StructAny{t.NUnion{A: false}},
+ t.StructAny{?t.NStruct(nil)}, t.StructAny{?t.NStruct{}},
t.StructAny{t.StructMap{}}, t.StructAny{t.StructMap{{0: 0}}},
t.StructAny{typeobject(any)},
?t.StructAny(nil), ?t.StructAny{nil}, ?t.StructAny{false},