Clean up and tests for mojo <-> vom transcoder
MultiPart: 2/2
Change-Id: Ia146daceda073f495934ba6847e8f92d283f4cc4
diff --git a/Makefile b/Makefile
index 1a94de4..4636b72 100644
--- a/Makefile
+++ b/Makefile
@@ -16,6 +16,14 @@
build-examples: $(BUILD_DIR)/echo_client.mojo $(BUILD_DIR)/echo_server.mojo $(BUILD_DIR)/fortune_client.mojo $(BUILD_DIR)/fortune_server.mojo
+# Go-based unit tests
+test: gen/go/src/mojom/tests/transcoder_testcases/transcoder_testcases.mojom.go
+ $(call MOGO_TEST,v.io/x/mojo/transcoder/...)
+
+gen/go/src/mojom/tests/transcoder_testcases/transcoder_testcases.mojom.go: mojom/mojom/tests/transcoder_testcases.mojom | mojo-env-check
+ $(call MOJOM_GEN,$<,mojom,gen,go)
+ gofmt -w $@
+
$(BUILD_DIR)/echo_client.mojo: $(MOJO_SHARED_LIB) gen/go/src/mojom/examples/echo/echo.mojom.go
$(call MOGO_BUILD,examples/echo/client,$@)
diff --git a/go/src/v.io/x/mojo/proxy/fake_service.go b/go/src/v.io/x/mojo/proxy/fake_service.go
index 294bff3..56e3fa6 100644
--- a/go/src/v.io/x/mojo/proxy/fake_service.go
+++ b/go/src/v.io/x/mojo/proxy/fake_service.go
@@ -273,9 +273,9 @@
// Decode the *vdl.Value from the mojom bytes and mojom type.
outType := transcoder.MojomStructToVDLType(*mm.ResponseParams, desc)
- outVdlValue, err := transcoder.DecodeValue(outMessage.Payload, outType)
- if err != nil {
- return nil, fmt.Errorf("transcoder.DecodeValue failed: %v", err)
+ var outVdlValue *vdl.Value
+ if err := transcoder.MojomToVdl(outMessage.Payload, outType, &outVdlValue); err != nil {
+ return nil, fmt.Errorf("transcoder.MojoToVom failed: %v", err)
}
// Then split the *vdl.Value (struct) into []*vdl.Value
diff --git a/go/src/v.io/x/mojo/proxy/misc.go b/go/src/v.io/x/mojo/proxy/misc.go
index 27d5e78..19b0f70 100644
--- a/go/src/v.io/x/mojo/proxy/misc.go
+++ b/go/src/v.io/x/mojo/proxy/misc.go
@@ -6,8 +6,8 @@
"mojo/public/go/bindings"
- "v.io/x/mojo/transcoder"
"v.io/v23/vdl"
+ "v.io/x/mojo/transcoder"
)
// TODO(alexfandrianto): Since this function could panic, we should consider
@@ -49,7 +49,7 @@
return nil, err
} else {
// Encode here.
- moreBytes, err := transcoder.Encode(vdlValue)
+ moreBytes, err := transcoder.VdlToMojom(vdlValue)
if err != nil {
return nil, fmt.Errorf("mojovdl.Encode failed: %v", err)
}
diff --git a/go/src/v.io/x/mojo/proxy/proxy.go b/go/src/v.io/x/mojo/proxy/proxy.go
index 72ae21d..1e64bfd 100644
--- a/go/src/v.io/x/mojo/proxy/proxy.go
+++ b/go/src/v.io/x/mojo/proxy/proxy.go
@@ -161,9 +161,9 @@
}
// Decode the vdl.Value from the mojom bytes and mojom type.
- inVdlValue, err := transcoder.DecodeValue(value, inVType)
- if err != nil {
- return nil, fmt.Errorf("transcoder.DecodeValue failed: %v", err)
+ var inVdlValue *vdl.Value
+ if err := transcoder.MojomToVdl(value, inVType, &inVdlValue); err != nil {
+ return nil, fmt.Errorf("transcoder.MojoToVom failed: %v", err)
}
// inVdlValue is a struct, but we need to send []interface.
@@ -191,7 +191,7 @@
outVdlValue := combineVdlValueByMojomType(outargs, outVType)
// Finally, encode this *vdl.Value (struct) into mojom bytes and send the response.
- result, err := transcoder.Encode(outVdlValue)
+ result, err := transcoder.VdlToMojom(outVdlValue)
if err != nil {
return nil, fmt.Errorf("transcoder.Encode failed: %v", err)
}
diff --git a/go/src/v.io/x/mojo/transcoder/encode.go b/go/src/v.io/x/mojo/transcoder/encode.go
deleted file mode 100644
index 2625ffb..0000000
--- a/go/src/v.io/x/mojo/transcoder/encode.go
+++ /dev/null
@@ -1,94 +0,0 @@
-package transcoder
-
-import (
- "reflect"
-
- "v.io/v23/vdl"
-)
-
-func Encode(value interface{}) ([]byte, error) {
- enc := &encoder{
- allocator: &allocator{},
- }
- err := vdl.FromReflect(enc, reflect.ValueOf(value))
- return enc.Bytes(), err
-}
-
-type encoder struct {
- allocator *allocator
-}
-
-func (e *encoder) Bytes() []byte {
- return e.allocator.AllocatedBytes()
-}
-
-func (e *encoder) FromBool(src bool, tt *vdl.Type) error {
- panic("cannot encode top level bool")
-}
-func (e *encoder) FromUint(src uint64, tt *vdl.Type) error {
- panic("cannot encode top level uint")
-}
-func (e *encoder) FromInt(src int64, tt *vdl.Type) error {
- panic("cannot encode top level int")
-}
-func (e *encoder) FromFloat(src float64, tt *vdl.Type) error {
- panic("cannot encode top level float")
-}
-func (e *encoder) FromComplex(src complex128, tt *vdl.Type) error {
- panic("cannot encode top level complex")
-}
-func (e *encoder) FromBytes(src []byte, tt *vdl.Type) error {
- panic("cannot encode top level bytes")
-}
-func (e *encoder) FromString(src string, tt *vdl.Type) error {
- panic("cannot encode top level string")
-}
-func (e *encoder) FromEnumLabel(src string, tt *vdl.Type) error {
- panic("cannot encode top level enum")
-}
-func (e *encoder) FromTypeObject(src *vdl.Type) error {
- panic("cannot encode top level type object")
-}
-func (e *encoder) FromNil(tt *vdl.Type) error {
- panic("cannot encode top level nil")
-}
-
-func (e *encoder) StartList(tt *vdl.Type, len int) (vdl.ListTarget, error) {
- panic("UNIMPLEMENTED")
- return nil, nil
-}
-func (e *encoder) FinishList(x vdl.ListTarget) error {
- return nil
-}
-func (e *encoder) StartSet(tt *vdl.Type, len int) (vdl.SetTarget, error) {
- panic("UNIMPLEMENTED")
-}
-func (e *encoder) FinishSet(x vdl.SetTarget) error {
- panic("UNIMPLEMENTED")
-
-}
-func (e *encoder) StartMap(tt *vdl.Type, len int) (vdl.MapTarget, error) {
- panic("UNIMPLEMENTED")
-
-}
-func (e *encoder) FinishMap(x vdl.MapTarget) error {
- panic("UNIMPLEMENTED")
-
-}
-func (e *encoder) StartFields(tt *vdl.Type) (vdl.FieldsTarget, error) {
- if tt.Kind() == vdl.Union {
- panic("not yet supported")
- }
- if tt.Kind() == vdl.Optional {
- tt = tt.Elem()
- }
- block := e.allocator.Allocate(neededStructAllocationSize(tt), 0)
- return fieldsTarget{
- vdlType: tt,
- block: block,
- },
- nil
-}
-func (e *encoder) FinishFields(x vdl.FieldsTarget) error {
- return nil
-}
diff --git a/go/src/v.io/x/mojo/transcoder/decode.go b/go/src/v.io/x/mojo/transcoder/mojom_to_vdl.go
similarity index 77%
rename from go/src/v.io/x/mojo/transcoder/decode.go
rename to go/src/v.io/x/mojo/transcoder/mojom_to_vdl.go
index 432aa14..fe87aab 100644
--- a/go/src/v.io/x/mojo/transcoder/decode.go
+++ b/go/src/v.io/x/mojo/transcoder/mojom_to_vdl.go
@@ -13,99 +13,90 @@
// the desired value. The datatype describes the type of the encoded data.
// Returns an error if the data cannot be decoded into valptr, based on the VDL
// value conversion rules.
-func Decode(data []byte, datatype *vdl.Type, valptr interface{}) error {
+func MojomToVdl(data []byte, datatype *vdl.Type, valptr interface{}) error {
target, err := vdl.ReflectTarget(reflect.ValueOf(valptr))
if err != nil {
return err
}
- d := &decoder{dec: bindings.NewDecoder(data, nil)}
- return d.decodeValue(datatype, target, true, false)
+ mtv := &mojomToVdlTranscoder{modec: bindings.NewDecoder(data, nil)}
+ return mtv.transcodeValue(datatype, target, true, false)
}
-// DecodeValue is like Decode, but decodes mojom-encoded data into a vdl.Value.
-func DecodeValue(data []byte, datatype *vdl.Type) (*vdl.Value, error) {
- v := new(vdl.Value)
- if err := Decode(data, datatype, &v); err != nil {
- return nil, err
- }
- return v, nil
-}
-
-type decoder struct {
- dec *bindings.Decoder
+type mojomToVdlTranscoder struct {
+ modec *bindings.Decoder
typeStack []*vdl.Type
}
-func (d *decoder) decodeValue(vt *vdl.Type, target vdl.Target, isTopType, isNullable bool) error {
+func (mtv *mojomToVdlTranscoder) transcodeValue(vt *vdl.Type, target vdl.Target, isTopType, isNullable bool) error {
switch vt.Kind() {
case vdl.Bool:
- value, err := d.dec.ReadBool()
+ value, err := mtv.modec.ReadBool()
if err != nil {
return err
}
return target.FromBool(value, vt)
case vdl.Int16:
- value, err := d.dec.ReadInt16()
+ value, err := mtv.modec.ReadInt16()
if err != nil {
return err
}
return target.FromInt(int64(value), vt)
case vdl.Int32:
- value, err := d.dec.ReadInt32()
+ value, err := mtv.modec.ReadInt32()
if err != nil {
return err
}
return target.FromInt(int64(value), vt)
case vdl.Int64:
- value, err := d.dec.ReadInt64()
+ value, err := mtv.modec.ReadInt64()
if err != nil {
return err
}
return target.FromInt(value, vt)
case vdl.Byte:
- value, err := d.dec.ReadUint8()
+ value, err := mtv.modec.ReadUint8()
if err != nil {
return err
}
return target.FromUint(uint64(value), vt)
case vdl.Uint16:
- value, err := d.dec.ReadUint16()
+ value, err := mtv.modec.ReadUint16()
if err != nil {
return err
}
return target.FromUint(uint64(value), vt)
case vdl.Uint32:
- value, err := d.dec.ReadUint32()
+ value, err := mtv.modec.ReadUint32()
if err != nil {
return err
}
return target.FromUint(uint64(value), vt)
case vdl.Uint64:
- value, err := d.dec.ReadUint64()
+ value, err := mtv.modec.ReadUint64()
if err != nil {
return err
}
return target.FromUint(value, vt)
case vdl.Float32:
- value, err := d.dec.ReadFloat32()
+ value, err := mtv.modec.ReadFloat32()
if err != nil {
return err
}
return target.FromFloat(float64(value), vt)
case vdl.Float64:
- value, err := d.dec.ReadFloat64()
+ value, err := mtv.modec.ReadFloat64()
if err != nil {
return err
}
return target.FromFloat(value, vt)
case vdl.String:
- switch ptr, err := d.dec.ReadPointer(); {
+ switch ptr, err := mtv.modec.ReadPointer(); {
case err != nil:
return err
case ptr == 0:
return fmt.Errorf("invalid null string pointer")
default:
- value, err := d.dec.ReadString()
+ value, err := mtv.modec.ReadString()
if err != nil {
return err
}
@@ -113,7 +104,7 @@
}
return nil
case vdl.Enum:
- index, err := d.dec.ReadInt32()
+ index, err := mtv.modec.ReadInt32()
if err != nil {
return err
}
@@ -127,7 +118,7 @@
case vdl.Complex128:
panic("unimplemented")
case vdl.Array, vdl.List:
- switch ptr, err := d.dec.ReadPointer(); {
+ switch ptr, err := mtv.modec.ReadPointer(); {
case err != nil:
return err
case ptr == 0 && isNullable:
@@ -137,14 +128,14 @@
}
if vt.IsBytes() {
- str, err := d.dec.ReadString()
+ str, err := mtv.modec.ReadString()
if err != nil {
return err
}
return target.FromBytes([]byte(str), vt)
} else {
elemBitSize := baseTypeSizeBits(vt.Elem())
- numElems, err := d.dec.StartArray(elemBitSize)
+ numElems, err := mtv.modec.StartArray(elemBitSize)
if err != nil {
return err
}
@@ -157,7 +148,7 @@
if err != nil {
return err
}
- if err := d.decodeValue(vt.Elem(), elemTarget, false, false); err != nil {
+ if err := mtv.transcodeValue(vt.Elem(), elemTarget, false, false); err != nil {
return err
}
if err := listTarget.FinishElem(elemTarget); err != nil {
@@ -168,7 +159,7 @@
return err
}
}
- return d.dec.Finish()
+ return mtv.modec.Finish()
case vdl.Set:
panic("unimplemented")
/*switch ptr, err := d.dec.ReadPointer(); {
@@ -205,7 +196,7 @@
}
return d.dec.Finish()*/
case vdl.Map:
- switch ptr, err := d.dec.ReadPointer(); {
+ switch ptr, err := mtv.modec.ReadPointer(); {
case err != nil:
return err
case ptr == 0 && isNullable:
@@ -213,7 +204,7 @@
case ptr == 0 && !isNullable:
return fmt.Errorf("invalid null struct pointer")
}
- if err := d.dec.StartMap(); err != nil {
+ if err := mtv.modec.StartMap(); err != nil {
return err
}
var keys, values []*vdl.Value
@@ -222,7 +213,7 @@
return err
}
keysListType := vdl.ListType(vt.Key())
- if err := d.decodeValue(keysListType, keysTarget, false, false); err != nil {
+ if err := mtv.transcodeValue(keysListType, keysTarget, false, false); err != nil {
return err
}
valuesTarget, err := vdl.ReflectTarget(reflect.ValueOf(&values))
@@ -230,7 +221,7 @@
return err
}
valuesListType := vdl.ListType(vt.Elem())
- if err := d.decodeValue(valuesListType, valuesTarget, false, false); err != nil {
+ if err := mtv.transcodeValue(valuesListType, valuesTarget, false, false); err != nil {
return err
}
@@ -266,12 +257,12 @@
return err
}
- return d.dec.Finish()
+ return mtv.modec.Finish()
case vdl.Struct:
// TODO(toddw): See the comment in encoder.mojomStructSize; we rely on the
// fields to be presented in the canonical mojom field ordering.
if !isTopType {
- switch ptr, err := d.dec.ReadPointer(); {
+ switch ptr, err := mtv.modec.ReadPointer(); {
case err != nil:
return err
case ptr == 0 && isNullable:
@@ -280,7 +271,7 @@
return fmt.Errorf("invalid null struct pointer")
}
}
- _, err := d.dec.StartStruct()
+ _, err := mtv.modec.StartStruct()
if err != nil {
return err
}
@@ -295,7 +286,7 @@
case err != nil:
return err
default:
- if err := d.decodeValue(mfield.Type, vfield, false, false); err != nil {
+ if err := mtv.transcodeValue(mfield.Type, vfield, false, false); err != nil {
return err
}
if err := targetFields.FinishField(vkey, vfield); err != nil {
@@ -307,14 +298,14 @@
if err := target.FinishFields(targetFields); err != nil {
return err
}
- return d.dec.Finish()
+ return mtv.modec.Finish()
case vdl.Union:
- size, tag, err := d.dec.ReadUnionHeader()
+ size, tag, err := mtv.modec.ReadUnionHeader()
if err != nil {
return err
}
if size == 0 {
- d.dec.SkipUnionValue()
+ mtv.modec.SkipUnionValue()
return target.FromNil(vdl.OptionalType(vt))
}
if int(tag) >= vt.NumField() {
@@ -330,7 +321,7 @@
return err
}
if fld.Type.Kind() == vdl.Union {
- switch ptr, err := d.dec.ReadPointer(); {
+ switch ptr, err := mtv.modec.ReadPointer(); {
case err != nil:
return err
case ptr == 0 && isNullable:
@@ -338,15 +329,15 @@
case ptr == 0 && !isNullable:
return fmt.Errorf("invalid null union pointer")
}
- if err := d.dec.StartNestedUnion(); err != nil {
+ if err := mtv.modec.StartNestedUnion(); err != nil {
return err
}
}
- if err := d.decodeValue(fld.Type, vField, false, false); err != nil {
+ if err := mtv.transcodeValue(fld.Type, vField, false, false); err != nil {
return err
}
if fld.Type.Kind() == vdl.Union {
- if err := d.dec.Finish(); err != nil {
+ if err := mtv.modec.Finish(); err != nil {
return err
}
}
@@ -356,10 +347,10 @@
if err := target.FinishFields(targetFields); err != nil {
return err
}
- d.dec.FinishReadingUnionValue()
+ mtv.modec.FinishReadingUnionValue()
return nil
case vdl.Optional:
- return d.decodeValue(vt.Elem(), target, false, true)
+ return mtv.transcodeValue(vt.Elem(), target, false, true)
case vdl.Any:
panic("unimplemented")
//case vdl.TypeObject:
diff --git a/go/src/v.io/x/mojo/transcoder/testdata_test.go b/go/src/v.io/x/mojo/transcoder/testdata_test.go
new file mode 100644
index 0000000..fbc4173
--- /dev/null
+++ b/go/src/v.io/x/mojo/transcoder/testdata_test.go
@@ -0,0 +1,190 @@
+package transcoder_test
+
+import (
+ "mojo/public/interfaces/bindings/tests/rect"
+ "mojo/public/interfaces/bindings/tests/test_structs"
+)
+
+type transcodeTestCase struct {
+ Name string
+ MojoValue interface{}
+ VdlValue interface{}
+}
+
+// Test cases for the mojom <-> vdl transcoder tests. See transcoder_test.go
+var testCases = []transcodeTestCase{
+ // from Mojo's rect
+ {
+ Name: "Rect",
+ MojoValue: &rect.Rect{
+ X: 11,
+ Y: 12,
+ Height: 13,
+ Width: 14,
+ },
+ VdlValue: rect.Rect{
+ X: 11,
+ Y: 12,
+ Height: 13,
+ Width: 14,
+ },
+ },
+ // from Mojo's test_structs
+ {
+ Name: "NamedRegion",
+ MojoValue: &test_structs.NamedRegion{
+ Name: stringPtr("A"),
+ Rects: &[]rect.Rect{
+ rect.Rect{},
+ },
+ },
+ VdlValue: test_structs.NamedRegion{
+ Name: stringPtr("A"),
+ Rects: &[]rect.Rect{
+ rect.Rect{},
+ },
+ },
+ },
+ {
+ Name: "RectPair",
+ MojoValue: &test_structs.RectPair{
+ First: &rect.Rect{X: 0, Y: 1, Height: 2, Width: 3},
+ Second: &rect.Rect{X: 11, Y: 12, Height: 13, Width: 14},
+ },
+ VdlValue: test_structs.RectPair{
+ First: &rect.Rect{X: 0, Y: 1, Height: 2, Width: 3},
+ Second: &rect.Rect{X: 11, Y: 12, Height: 13, Width: 14},
+ },
+ },
+ {
+ Name: "EmptyStruct",
+ MojoValue: &test_structs.EmptyStruct{},
+ VdlValue: test_structs.EmptyStruct{},
+ },
+ // TODO(bprosnitz) HandleStruct?
+ // TODO(bprosnitz) NullableHandleStruct?
+ // TODO(bprosnitz) NoDefaultFieldValues?
+ // TODO(bprosnitz) DefaultFieldValues?
+ {
+ Name: "ScopedConstants",
+ MojoValue: &test_structs.ScopedConstants{
+ test_structs.ScopedConstants_EType_E0,
+ test_structs.ScopedConstants_EType_E1,
+ test_structs.ScopedConstants_EType_E2,
+ test_structs.ScopedConstants_EType_E3,
+ test_structs.ScopedConstants_EType_E4,
+ 10,
+ 10,
+ },
+ VdlValue: test_structs.ScopedConstants{
+ test_structs.ScopedConstants_EType_E0,
+ test_structs.ScopedConstants_EType_E1,
+ test_structs.ScopedConstants_EType_E2,
+ test_structs.ScopedConstants_EType_E3,
+ test_structs.ScopedConstants_EType_E4,
+ 10,
+ 10,
+ },
+ },
+ // TODO(bprosnitz) MapKeyTypes?
+ // TODO(bprosnitz) MapValueTypes?
+ // TODO(bprosnitz) ArrayValueTypes?
+ {
+ Name: "UnsignedArrayValueTypes",
+ MojoValue: &test_structs.UnsignedArrayValueTypes{
+ []uint8{1}, []uint16{2}, []uint32{3}, []uint64{4}, []float32{5}, []float64{6},
+ },
+ VdlValue: test_structs.UnsignedArrayValueTypes{
+ []uint8{1}, []uint16{2}, []uint32{3}, []uint64{4}, []float32{5}, []float64{6},
+ },
+ },
+ {
+ Name: "UnsignedFixedArrayValueTypes",
+ MojoValue: &test_structs.UnsignedFixedArrayValueTypes{
+ [3]uint8{1}, [2]uint16{2}, [2]uint32{3}, [2]uint64{4}, [2]float32{5}, [2]float64{6},
+ },
+ VdlValue: test_structs.UnsignedFixedArrayValueTypes{
+ [3]uint8{1}, [2]uint16{2}, [2]uint32{3}, [2]uint64{4}, [2]float32{5}, [2]float64{6},
+ },
+ },
+ {
+ Name: "BoolArrayValueTypes",
+ MojoValue: &test_structs.BoolArrayValueTypes{
+ []bool{false, true, true, false},
+ },
+ VdlValue: test_structs.BoolArrayValueTypes{
+ []bool{false, true, true, false},
+ },
+ },
+ {
+ Name: "FloatNumberValues",
+ MojoValue: &test_structs.FloatNumberValues{
+ 0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9,
+ },
+ VdlValue: test_structs.FloatNumberValues{
+ 0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9,
+ },
+ },
+ // TODO(bprosnitz) IntegerNumberValues?
+ {
+ Name: "UnsignedNumberValues",
+ MojoValue: &test_structs.UnsignedNumberValues{
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
+ },
+ VdlValue: test_structs.UnsignedNumberValues{
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
+ },
+ },
+ {
+ Name: "BitArrayValues",
+ MojoValue: &test_structs.BitArrayValues{
+ [1]bool{true}, [7]bool{true, false, true}, [9]bool{true, false, true}, []bool{true, false, true},
+ [][]bool{[]bool{true, false, true}}, []*[]bool{&[]bool{true, false, true}}, []*[2]bool{&[2]bool{true, false}},
+ },
+ VdlValue: test_structs.BitArrayValues{
+ [1]bool{true}, [7]bool{true, false, true}, [9]bool{true, false, true}, []bool{true, false, true},
+ [][]bool{[]bool{true, false, true}}, []*[]bool{&[]bool{true, false, true}}, []*[2]bool{&[2]bool{true, false}},
+ },
+ },
+ // TODO(bprosnitz) MultiVersionStruct? + other versions
+ // from Mojo's test_unions
+ // TODO(bprosnitz) PodUnion?
+ // TODO(bprosnitz) ObjectUnion?
+ // TODO(bprosnitz) HandleUnion?
+ // TODO(bprosnitz) WrapperStruct?
+ // TODO(bprosnitz) DummyStruct?
+ // TODO(bprosnitz) SmallStruct?
+ // TODO(bprosnitz) SmallStructNonNullableUnion?
+ // TODO(bprosnitz) SmallObjStruct?
+ // TODO(bprosnitz) TryNonNullStruct?
+ // TODO(bprosnitz) OldUnion?
+ // TODO(bprosnitz) NewUnion?
+ // TODO(bprosnitz) IncludingStruct?
+ // test cases not from Mojo:
+ /*
+ // TODO(bprosnitz) These fail:
+ {
+ Name: "UnnamedPrimitiveTestStruct",
+ MojoValue: &transcoder_testcases.UnnamedPrimitiveTestStruct{1, "A", true, 2},
+ VdlValue: transcoder_testcases.UnnamedPrimitiveTestStruct{1, "A", true, 2},
+ },
+ {
+ Name: "Transcode to Named Primitives",
+ MojoValue: &transcoder_testcases.UnnamedPrimitiveTestStruct{1, "A", true, 2},
+ VdlValue: NamedPrimitiveTestStruct{1, "A", true, 2},
+ },*/
+ // TODO(bprosnitz) More tests of errors, named type conversions, unsupported types, etc
+}
+
+func stringPtr(in string) *string { return &in }
+
+type NUint32 uint32
+type NString string
+type NBool bool
+type NFloat32 float32
+type NamedPrimitiveTestStruct struct {
+ A NUint32
+ B NString
+ C NBool
+ D NFloat32
+}
diff --git a/go/src/v.io/x/mojo/transcoder/transcoder_test.go b/go/src/v.io/x/mojo/transcoder/transcoder_test.go
new file mode 100644
index 0000000..1e5d7bb
--- /dev/null
+++ b/go/src/v.io/x/mojo/transcoder/transcoder_test.go
@@ -0,0 +1,77 @@
+package transcoder_test
+
+import (
+ "reflect"
+ "testing"
+
+ "mojo/public/go/bindings"
+
+ "fmt"
+
+ "bytes"
+
+ "v.io/v23/vdl"
+ "v.io/x/mojo/transcoder"
+)
+
+func TestMojoToVom(t *testing.T) {
+ for _, test := range testCases {
+ testName := test.Name + " mojo->vom"
+
+ data, err := computeExpectedMojomBytes(test.MojoValue)
+ if err != nil {
+ t.Errorf("%s: %v", testName, err)
+ continue
+ }
+
+ var out interface{}
+ if err := transcoder.MojomToVdl(data, vdl.TypeOf(test.VdlValue), &out); err != nil {
+ t.Errorf("%s: error in MojoToVom: %v (was transcoding from %x)", testName, err, data)
+ continue
+ }
+
+ if got, want := out, test.VdlValue; !reflect.DeepEqual(got, want) {
+ t.Errorf("%s: result doesn't match expectation. got %#v, but want %#v", testName, got, want)
+ }
+ }
+}
+
+func TestVomToMojo(t *testing.T) {
+ for _, test := range testCases {
+ testName := test.Name + " vom->mojo"
+
+ data, err := transcoder.VdlToMojom(test.VdlValue)
+ if err != nil {
+ t.Errorf("%s: error in VomToMojo: %v", testName, err)
+ continue
+ }
+
+ expectedData, err := computeExpectedMojomBytes(test.MojoValue)
+ if err != nil {
+ t.Errorf("%s: %v", testName, err)
+ continue
+ }
+
+ if got, want := data, expectedData; !bytes.Equal(got, want) {
+ t.Errorf("%s: got %x, but want %x", testName, got, want)
+ }
+ }
+}
+
+func computeExpectedMojomBytes(mojoValue interface{}) ([]byte, error) {
+ payload, ok := mojoValue.(bindings.Payload)
+ if !ok {
+ return nil, fmt.Errorf("type %T lacks an Encode() method", mojoValue)
+ }
+
+ enc := bindings.NewEncoder()
+ err := payload.Encode(enc)
+ if err != nil {
+ return nil, fmt.Errorf("error in Encode: %v", err)
+ }
+ data, _, err := enc.Data()
+ if err != nil {
+ return nil, fmt.Errorf("error in Data()", err)
+ }
+ return data, nil
+}
diff --git a/go/src/v.io/x/mojo/transcoder/vdl_to_mojom.go b/go/src/v.io/x/mojo/transcoder/vdl_to_mojom.go
new file mode 100644
index 0000000..00945d8
--- /dev/null
+++ b/go/src/v.io/x/mojo/transcoder/vdl_to_mojom.go
@@ -0,0 +1,94 @@
+package transcoder
+
+import (
+ "reflect"
+
+ "v.io/v23/vdl"
+)
+
+func VdlToMojom(value interface{}) ([]byte, error) {
+ vtm := &vdlToMojomTranscoder{
+ allocator: &allocator{},
+ }
+ err := vdl.FromReflect(vtm, reflect.ValueOf(value))
+ return vtm.Bytes(), err
+}
+
+type vdlToMojomTranscoder struct {
+ allocator *allocator
+}
+
+func (vtm *vdlToMojomTranscoder) Bytes() []byte {
+ return vtm.allocator.AllocatedBytes()
+}
+
+func (vtm *vdlToMojomTranscoder) FromBool(src bool, tt *vdl.Type) error {
+ panic("cannot encode top level bool")
+}
+func (vtm *vdlToMojomTranscoder) FromUint(src uint64, tt *vdl.Type) error {
+ panic("cannot encode top level uint")
+}
+func (vtm *vdlToMojomTranscoder) FromInt(src int64, tt *vdl.Type) error {
+ panic("cannot encode top level int")
+}
+func (vtm *vdlToMojomTranscoder) FromFloat(src float64, tt *vdl.Type) error {
+ panic("cannot encode top level float")
+}
+func (vtm *vdlToMojomTranscoder) FromComplex(src complex128, tt *vdl.Type) error {
+ panic("cannot encode top level complex")
+}
+func (vtm *vdlToMojomTranscoder) FromBytes(src []byte, tt *vdl.Type) error {
+ panic("cannot encode top level bytes")
+}
+func (vtm *vdlToMojomTranscoder) FromString(src string, tt *vdl.Type) error {
+ panic("cannot encode top level string")
+}
+func (vtm *vdlToMojomTranscoder) FromEnumLabel(src string, tt *vdl.Type) error {
+ panic("cannot encode top level enum")
+}
+func (vtm *vdlToMojomTranscoder) FromTypeObject(src *vdl.Type) error {
+ panic("cannot encode top level type object")
+}
+func (vtm *vdlToMojomTranscoder) FromNil(tt *vdl.Type) error {
+ panic("cannot encode top level nil")
+}
+
+func (vtm *vdlToMojomTranscoder) StartList(tt *vdl.Type, len int) (vdl.ListTarget, error) {
+ panic("UNIMPLEMENTED")
+ return nil, nil
+}
+func (vtm *vdlToMojomTranscoder) FinishList(x vdl.ListTarget) error {
+ return nil
+}
+func (vtm *vdlToMojomTranscoder) StartSet(tt *vdl.Type, len int) (vdl.SetTarget, error) {
+ panic("UNIMPLEMENTED")
+}
+func (vtm *vdlToMojomTranscoder) FinishSet(x vdl.SetTarget) error {
+ panic("UNIMPLEMENTED")
+
+}
+func (vtm *vdlToMojomTranscoder) StartMap(tt *vdl.Type, len int) (vdl.MapTarget, error) {
+ panic("UNIMPLEMENTED")
+
+}
+func (vtm *vdlToMojomTranscoder) FinishMap(x vdl.MapTarget) error {
+ panic("UNIMPLEMENTED")
+
+}
+func (vtm *vdlToMojomTranscoder) StartFields(tt *vdl.Type) (vdl.FieldsTarget, error) {
+ if tt.Kind() == vdl.Union {
+ panic("not yet supported")
+ }
+ if tt.Kind() == vdl.Optional {
+ tt = tt.Elem()
+ }
+ block := vtm.allocator.Allocate(neededStructAllocationSize(tt), 0)
+ return fieldsTarget{
+ vdlType: tt,
+ block: block,
+ },
+ nil
+}
+func (vtm *vdlToMojomTranscoder) FinishFields(x vdl.FieldsTarget) error {
+ return nil
+}
diff --git a/mojom/mojom/tests/transcoder_testcases.mojom b/mojom/mojom/tests/transcoder_testcases.mojom
new file mode 100644
index 0000000..61ae4f8
--- /dev/null
+++ b/mojom/mojom/tests/transcoder_testcases.mojom
@@ -0,0 +1,12 @@
+// Copyright 2015 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.
+
+module tests;
+
+struct UnnamedPrimitiveTestStruct {
+ uint32 A;
+ string B;
+ bool C;
+ float D;
+};
\ No newline at end of file