示例#1
0
func (t target) FinishMap(x vdl.MapTarget) error {
	mt := x.(*mapTarget)
	listTarget, err := mt.valuePlaceholder.StartList(vdl.ListType(mt.valueType), len(mt.cachedValues))
	if err != nil {
		return err
	}
	for i, val := range mt.cachedValues {
		te, err := listTarget.StartElem(i)
		if err != nil {
			return err
		}
		if err := vdl.FromValue(te, val); err != nil {
			return err
		}
		if err := listTarget.FinishElem(te); err != nil {
			return err
		}
	}
	return nil
}
示例#2
0
func (mtv *mojomToTargetTranscoder) transcodeValue(vt *vdl.Type, target vdl.Target, isTopType, isNullable bool) error {
	switch vt.Kind() {
	case vdl.Bool:
		value, err := mtv.modec.ReadBool()
		if err != nil {
			return err
		}
		return target.FromBool(value, vt)
	case vdl.Int8:
		value, err := mtv.modec.ReadInt8()
		if err != nil {
			return err
		}
		return target.FromInt(int64(value), vt)
	case vdl.Int16:
		value, err := mtv.modec.ReadInt16()
		if err != nil {
			return err
		}
		return target.FromInt(int64(value), vt)
	case vdl.Int32:
		value, err := mtv.modec.ReadInt32()
		if err != nil {
			return err
		}
		return target.FromInt(int64(value), vt)
	case vdl.Int64:
		value, err := mtv.modec.ReadInt64()
		if err != nil {
			return err
		}
		return target.FromInt(value, vt)
	case vdl.Byte:
		value, err := mtv.modec.ReadUint8()
		if err != nil {
			return err
		}
		return target.FromUint(uint64(value), vt)
	case vdl.Uint16:
		value, err := mtv.modec.ReadUint16()
		if err != nil {
			return err
		}
		return target.FromUint(uint64(value), vt)
	case vdl.Uint32:
		value, err := mtv.modec.ReadUint32()
		if err != nil {
			return err
		}
		return target.FromUint(uint64(value), vt)
	case vdl.Uint64:
		value, err := mtv.modec.ReadUint64()
		if err != nil {
			return err
		}
		return target.FromUint(value, vt)
	case vdl.Float32:
		value, err := mtv.modec.ReadFloat32()
		if err != nil {
			return err
		}
		return target.FromFloat(float64(value), vt)
	case vdl.Float64:
		value, err := mtv.modec.ReadFloat64()
		if err != nil {
			return err
		}
		return target.FromFloat(value, vt)
	case vdl.String:
		switch ptr, err := mtv.modec.ReadPointer(); {
		case err != nil:
			return err
		case ptr == 0:
			return fmt.Errorf("invalid null string pointer")
		default:
			value, err := mtv.modec.ReadString()
			if err != nil {
				return err
			}
			return target.FromString(value, vt)
		}
		return nil
	case vdl.Enum:
		index, err := mtv.modec.ReadInt32()
		if err != nil {
			return err
		}
		if int(index) >= vt.NumEnumLabel() || index < 0 {
			return fmt.Errorf("enum label out of range")
		}
		target.FromEnumLabel(vt.EnumLabel(int(index)), vt)
		return nil
	case vdl.Array, vdl.List:
		switch ptr, err := mtv.modec.ReadPointer(); {
		case err != nil:
			return err
		case ptr == 0 && isNullable:
			return target.FromNil(vdl.OptionalType(vt))
		case ptr == 0 && !isNullable:
			return fmt.Errorf("invalid null struct pointer")
		}

		if vt.IsBytes() {
			str, err := mtv.modec.ReadString()
			if err != nil {
				return err
			}
			return target.FromBytes([]byte(str), vt)
		} else {
			elemBitSize := baseTypeSizeBits(vt.Elem())
			numElems, err := mtv.modec.StartArray(elemBitSize)
			if err != nil {
				return err
			}
			listTarget, err := target.StartList(vt, int(numElems))
			if err != nil {
				return err
			}
			for i := 0; i < int(numElems); i++ {
				elemTarget, err := listTarget.StartElem(i)
				if err != nil {
					return err
				}
				if err := mtv.transcodeValue(vt.Elem(), elemTarget, false, false); err != nil {
					return err
				}
				if err := listTarget.FinishElem(elemTarget); err != nil {
					return err
				}
			}
			if err := target.FinishList(listTarget); err != nil {
				return err
			}
		}
		return mtv.modec.Finish()
	case vdl.Set:
		panic("unimplemented")
		/*switch ptr, err := d.dec.ReadPointer(); {
		case err != nil:
			return err
		case ptr == 0 && isNullable:
			return target.FromNil(vdl.OptionalType(vt))
		case ptr == 0 && !isNullable:
			return fmt.Errorf("invalid null struct pointer")
		}
		keyBitSize := baseTypeSizeBits(vt.Key())
		numKeys, err := d.dec.StartArray(keyBitSize)
		if err != nil {
			return err
		}
		setTarget, err := target.StartSet(vt, int(numKeys))
		if err != nil {
			return err
		}
		for i := 0; i < int(numKeys); i++ {
			keyTarget, err := setTarget.StartKey()
			if err != nil {
				return err
			}
			if err := d.decodeValue(mt.Key, keyTarget, false, false); err != nil {
				return err
			}
			if err := setTarget.FinishKey(keyTarget); err != nil {
				return err
			}
		}
		if err := target.FinishSet(setTarget); err != nil {
			return err
		}
		return d.dec.Finish()*/
	case vdl.Map:
		switch ptr, err := mtv.modec.ReadPointer(); {
		case err != nil:
			return err
		case ptr == 0 && isNullable:
			return target.FromNil(vdl.OptionalType(vt))
		case ptr == 0 && !isNullable:
			return fmt.Errorf("invalid null struct pointer")
		}
		if err := mtv.modec.StartMap(); err != nil {
			return err
		}
		var keys, values []*vdl.Value
		keysTarget, err := vdl.ReflectTarget(reflect.ValueOf(&keys))
		if err != nil {
			return err
		}
		keysListType := vdl.ListType(vt.Key())
		if err := mtv.transcodeValue(keysListType, keysTarget, false, false); err != nil {
			return err
		}
		valuesTarget, err := vdl.ReflectTarget(reflect.ValueOf(&values))
		if err != nil {
			return err
		}
		valuesListType := vdl.ListType(vt.Elem())
		if err := mtv.transcodeValue(valuesListType, valuesTarget, false, false); err != nil {
			return err
		}

		if len(keys) != len(values) {
			return fmt.Errorf("values don't match keys")
		}
		mapTarget, err := target.StartMap(vt, len(keys))
		if err != nil {
			return err
		}
		for i, key := range keys {
			value := values[i]

			keyTarget, err := mapTarget.StartKey()
			if err != nil {
				return err
			}
			if err := vdl.FromValue(keyTarget, key); err != nil {
				return err
			}
			fieldTarget, err := mapTarget.FinishKeyStartField(keyTarget)
			if err != nil {
				return err
			}
			if err := vdl.FromValue(fieldTarget, value); err != nil {
				return err
			}
			if err := mapTarget.FinishField(keyTarget, fieldTarget); err != nil {
				return err
			}
		}
		if err := target.FinishMap(mapTarget); err != nil {
			return err
		}

		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 := mtv.modec.ReadPointer(); {
			case err != nil:
				return err
			case ptr == 0 && isNullable:
				return target.FromNil(vdl.OptionalType(vt))
			case ptr == 0 && !isNullable:
				return fmt.Errorf("invalid null struct pointer")
			}
		}
		_, err := mtv.modec.StartStruct()
		if err != nil {
			return err
		}
		targetFields, err := target.StartFields(vt)
		if err != nil {
			return err
		}
		for _, alloc := range computeStructLayout(vt) {
			mfield := vt.Field(alloc.vdlStructIndex)
			switch vkey, vfield, err := targetFields.StartField(mfield.Name); {
			// TODO(toddw): Handle err == vdl.ErrFieldNoExist case?
			case err != nil:
				return err
			default:
				if err := mtv.transcodeValue(mfield.Type, vfield, false, false); err != nil {
					return err
				}
				if err := targetFields.FinishField(vkey, vfield); err != nil {
					return err
				}
			}
		}
		// TODO(toddw): Fill in fields that weren't decoded with their zero value.
		if err := target.FinishFields(targetFields); err != nil {
			return err
		}
		return mtv.modec.Finish()
	case vdl.Union:
		size, tag, err := mtv.modec.ReadUnionHeader()
		if err != nil {
			return err
		}
		if size == 0 {
			mtv.modec.SkipUnionValue()
			return target.FromNil(vdl.OptionalType(vt))
		}
		if int(tag) >= vt.NumField() {
			return fmt.Errorf("union tag out of bounds")
		}
		fld := vt.Field(int(tag))
		targetFields, err := target.StartFields(vt)
		if err != nil {
			return err
		}
		vKey, vField, err := targetFields.StartField(fld.Name)
		if err != nil {
			return err
		}
		if fld.Type.Kind() == vdl.Union {
			switch ptr, err := mtv.modec.ReadPointer(); {
			case err != nil:
				return err
			case ptr == 0 && isNullable:
				return target.FromNil(vdl.OptionalType(fld.Type))
			case ptr == 0 && !isNullable:
				return fmt.Errorf("invalid null union pointer")
			}
			if err := mtv.modec.StartNestedUnion(); err != nil {
				return err
			}
		}
		if err := mtv.transcodeValue(fld.Type, vField, false, false); err != nil {
			return err
		}
		if fld.Type.Kind() == vdl.Union {
			if err := mtv.modec.Finish(); err != nil {
				return err
			}
		}
		if err := targetFields.FinishField(vKey, vField); err != nil {
			return err
		}
		if err := target.FinishFields(targetFields); err != nil {
			return err
		}
		mtv.modec.FinishReadingUnionValue()
		return nil
	case vdl.Optional:
		return mtv.transcodeValue(vt.Elem(), target, false, true)
	case vdl.Any:
		panic("unimplemented")
	//case vdl.TypeObject:
	//	panic("unimplemented")
	default:
		panic(fmt.Errorf("decodeValue unhandled vdl type: %v", vt))
	}
}
示例#3
0
func TestVdlAndMojoTypeConversion(t *testing.T) {
	// Create types.
	enumType := vdl.NamedType("v23proxy/tests/transcoder_testcases.TestEnum", vdl.EnumType("A", "B", "C"))
	basicStructType := vdl.NamedType("v23proxy/tests/transcoder_testcases.TestBasicStruct", vdl.StructType(vdl.Field{"Enum", enumType}, vdl.Field{"A", vdl.Int32Type}))

	builder := vdl.TypeBuilder{}
	strct := builder.Struct()
	strct.AppendField("Enum", enumType)
	namedStruct := builder.Named("v23proxy/tests/transcoder_testcases.TestCyclicStruct").AssignBase(strct)
	strct.AppendField("CyclicStruct", builder.Optional().AssignElem(namedStruct))
	strct.AppendField("A", vdl.Int32Type)
	builder.Build()
	cyclicStructType, err := namedStruct.Built()
	if err != nil {
		t.Fatalf("error building struct: %v", err)
	}

	tests := []struct {
		vdl   *vdl.Type
		mojom mojom_types.Type
		mp    map[string]mojom_types.UserDefinedType
	}{
		{
			vdl.BoolType,
			&mojom_types.TypeSimpleType{mojom_types.SimpleType_Bool},
			map[string]mojom_types.UserDefinedType{},
		},
		{
			vdl.ByteType,
			&mojom_types.TypeSimpleType{mojom_types.SimpleType_Uint8},
			map[string]mojom_types.UserDefinedType{},
		},
		{
			vdl.Uint16Type,
			&mojom_types.TypeSimpleType{mojom_types.SimpleType_Uint16},
			map[string]mojom_types.UserDefinedType{},
		},
		{
			vdl.Uint32Type,
			&mojom_types.TypeSimpleType{mojom_types.SimpleType_Uint32},
			map[string]mojom_types.UserDefinedType{},
		},
		{
			vdl.Uint64Type,
			&mojom_types.TypeSimpleType{mojom_types.SimpleType_Uint64},
			map[string]mojom_types.UserDefinedType{},
		},
		{
			vdl.Int8Type,
			&mojom_types.TypeSimpleType{mojom_types.SimpleType_Int8},
			map[string]mojom_types.UserDefinedType{},
		},
		{
			vdl.Int16Type,
			&mojom_types.TypeSimpleType{mojom_types.SimpleType_Int16},
			map[string]mojom_types.UserDefinedType{},
		},
		{
			vdl.Int32Type,
			&mojom_types.TypeSimpleType{mojom_types.SimpleType_Int32},
			map[string]mojom_types.UserDefinedType{},
		},
		{
			vdl.Int64Type,
			&mojom_types.TypeSimpleType{mojom_types.SimpleType_Int64},
			map[string]mojom_types.UserDefinedType{},
		},
		{
			vdl.Float32Type,
			&mojom_types.TypeSimpleType{mojom_types.SimpleType_Float},
			map[string]mojom_types.UserDefinedType{},
		},
		{
			vdl.Float64Type,
			&mojom_types.TypeSimpleType{mojom_types.SimpleType_Double},
			map[string]mojom_types.UserDefinedType{},
		},
		{
			vdl.StringType,
			&mojom_types.TypeStringType{mojom_types.StringType{false}},
			map[string]mojom_types.UserDefinedType{},
		},
		// ?string is currently disallowed in vdl, so skipping
		{
			vdl.ArrayType(3, vdl.Int64Type),
			&mojom_types.TypeArrayType{mojom_types.ArrayType{false, 3, &mojom_types.TypeSimpleType{mojom_types.SimpleType_Int64}}},
			map[string]mojom_types.UserDefinedType{},
		},
		// ?[3]int64 is currently disallowed in vdl, so skipping
		{
			vdl.ListType(vdl.Int64Type),
			&mojom_types.TypeArrayType{mojom_types.ArrayType{false, -1, &mojom_types.TypeSimpleType{mojom_types.SimpleType_Int64}}},
			map[string]mojom_types.UserDefinedType{},
		},
		// ?[]int64 is currently disallowed in vdl, so skipping
		{
			vdl.MapType(vdl.Int64Type, vdl.BoolType),
			&mojom_types.TypeMapType{mojom_types.MapType{false, &mojom_types.TypeSimpleType{mojom_types.SimpleType_Int64}, &mojom_types.TypeSimpleType{mojom_types.SimpleType_Bool}}},
			map[string]mojom_types.UserDefinedType{},
		},
		// ?map[int64]bool is currently disallowed in vdl, so skipping
		{
			enumType,
			&mojom_types.TypeTypeReference{mojom_types.TypeReference{Nullable: false, TypeKey: stringPtr("TYPE_KEY:v23proxy.tests.transcoder_testcases.TestEnum")}},
			map[string]mojom_types.UserDefinedType{
				"TYPE_KEY:v23proxy.tests.transcoder_testcases.TestEnum": transcoder_testcases.GetAllMojomTypeDefinitions()["TYPE_KEY:v23proxy.tests.transcoder_testcases.TestEnum"],
			},
		},
		{
			basicStructType,
			&mojom_types.TypeTypeReference{mojom_types.TypeReference{Nullable: false, TypeKey: stringPtr("TYPE_KEY:v23proxy.tests.transcoder_testcases.TestBasicStruct")}},
			map[string]mojom_types.UserDefinedType{
				"TYPE_KEY:v23proxy.tests.transcoder_testcases.TestBasicStruct": transcoder_testcases.GetAllMojomTypeDefinitions()["TYPE_KEY:v23proxy.tests.transcoder_testcases.TestBasicStruct"],
				"TYPE_KEY:v23proxy.tests.transcoder_testcases.TestEnum":        transcoder_testcases.GetAllMojomTypeDefinitions()["TYPE_KEY:v23proxy.tests.transcoder_testcases.TestEnum"],
			},
		},
		{
			cyclicStructType,
			&mojom_types.TypeTypeReference{mojom_types.TypeReference{Nullable: false, TypeKey: stringPtr("TYPE_KEY:v23proxy.tests.transcoder_testcases.TestCyclicStruct")}},
			map[string]mojom_types.UserDefinedType{
				"TYPE_KEY:v23proxy.tests.transcoder_testcases.TestCyclicStruct": transcoder_testcases.GetAllMojomTypeDefinitions()["TYPE_KEY:v23proxy.tests.transcoder_testcases.TestCyclicStruct"],
				"TYPE_KEY:v23proxy.tests.transcoder_testcases.TestEnum":         transcoder_testcases.GetAllMojomTypeDefinitions()["TYPE_KEY:v23proxy.tests.transcoder_testcases.TestEnum"],
			},
		},
	}

	for _, test := range tests {
		mojomtype, mp := transcoder.VDLToMojomType(test.vdl)

		// Note: Equality is only guaranteed if the casing matches up. Mojom no longer sends out UpperCamelCase values.
		if !reflect.DeepEqual(mojomtype, test.mojom) {
			t.Errorf("vdl type %v, when converted to mojo type was %#v. expected %#v", test.vdl, mojomtype, test.mojom)
		}
		// Note: Equality of structs is virtually impossible. The DeclarationData of the values in the map contains lots of information we cannot recover from vdl.
		//if !reflect.DeepEqual(mp, test.mp) {
		//	t.Errorf("vdl type %v, when converted to mojo type did not match expected user defined types. got %#v, expected %#v", test.vdl, mp, test.mp)
		//}
		for k, _ := range test.mp {
			if _, ok := mp[k]; !ok {
				t.Errorf("vdl type %v, when converted to mojo type did not create an entry for %s", test.vdl, k)
			}
		}
		if len(mp) != len(test.mp) {
			t.Errorf("vdl type %v, when converted to mojo type created %d map entries, expected %d", test.vdl, len(mp), len(test.mp))
		}

		vt, err := transcoder.MojomToVDLType(test.mojom, test.mp)
		if err != nil {
			t.Errorf("error converting mojo type %#v (with user defined types %v): %v", test.mojom, test.mp, err)
		}
		if !reflect.DeepEqual(vt, test.vdl) {
			t.Errorf("mojom type %#v (with user defined types %v), when converted to vdl type was %v. expected %v", test.mojom, test.mp, vt, test.vdl)
		}
	}
}