예제 #1
0
func (t target) FromEnumLabel(src string, tt *vdl.Type) error {
	// enums in mojo are treated as an int32 on the wire (but have gaps in their values).
	// This implementation assumes that we will use generated VDL values and not have gaps.
	index := tt.EnumIndex(src)
	binary.LittleEndian.PutUint32(t.current.Bytes(), uint32(index))
	return nil
}
예제 #2
0
func neededStructAllocationSize(vt *vdl.Type) uint32 {
	var totalBits uint32
	for fi := 0; fi < vt.NumField(); fi++ {
		field := vt.Field(fi)
		totalBits += baseTypeSizeBits(field.Type)
	}
	return roundBitsTo64Alignment(totalBits)
}
예제 #3
0
func (t target) FromFloat(src float64, tt *vdl.Type) error {
	switch tt.Kind() {
	case vdl.Float32:
		binary.LittleEndian.PutUint32(t.current.Bytes(), math.Float32bits(float32(src)))
	case vdl.Float64:
		binary.LittleEndian.PutUint64(t.current.Bytes(), math.Float64bits(src))
	default:
		return fmt.Errorf("invalid FromFloat(%v, %v)", src, tt)
	}
	return nil
}
예제 #4
0
func (t target) FromInt(src int64, tt *vdl.Type) error {
	switch tt.Kind() {
	case vdl.Int8:
		t.current.Bytes()[0] = byte(src)
	case vdl.Int16:
		binary.LittleEndian.PutUint16(t.current.Bytes(), uint16(src))
	case vdl.Int32:
		binary.LittleEndian.PutUint32(t.current.Bytes(), uint32(src))
	case vdl.Int64:
		binary.LittleEndian.PutUint64(t.current.Bytes(), uint64(src))
	default:
		return fmt.Errorf("invalid FromInt(%v, %v)", src, tt)
	}
	return nil
}
예제 #5
0
func baseTypeSizeBits(vt *vdl.Type) uint32 {
	switch vt.Kind() {
	case vdl.Bool:
		return 1
	case vdl.Byte, vdl.Int8:
		return 8
	case vdl.Uint16, vdl.Int16:
		return 16
	case vdl.Uint32, vdl.Int32, vdl.Float32, vdl.Enum:
		return 32
	case vdl.Union:
		return 128 // Header + value / pointer to inner union
	default: // Either Uint64, Int64, Float64 or pointer.
		return 64
	}
}
예제 #6
0
// TODO(bprosnitz) This uses list, should we use map instead?
func (t target) StartSet(tt *vdl.Type, len int) (vdl.SetTarget, error) {
	if tt.Kind() == vdl.Optional {
		tt = tt.Elem()
	}
	bitsNeeded := baseTypeSizeBits(tt.Key()) * uint32(len)
	block := t.allocator().Allocate((bitsNeeded+7)/8, uint32(len))
	t.writePointer(block)
	if tt.Key().Kind() == vdl.Bool {
		return &bitListTarget{
			block: block,
		}, nil
	} else {
		return &listTarget{
			incrementSize: baseTypeSizeBits(tt.Key()) / 8,
			block:         block,
		}, nil
	}
}
예제 #7
0
func structType(t *vdl.Type, mp map[string]mojom_types.UserDefinedType) mojom_types.UserDefinedType {
	structFields := make([]mojom_types.StructField, t.NumField())
	for i := 0; i < t.NumField(); i++ {
		structFields[i] = mojom_types.StructField{
			DeclData: &mojom_types.DeclarationData{ShortName: strPtr(t.Field(i).Name)},
			Type:     vdlToMojomTypeInternal(t.Field(i).Type, false, false, mp),
			Offset:   0, // Despite the fact that we can calculated the offset, set it to zero to match the generator
		}
	}
	_, name := vdl.SplitIdent(t.Name())
	return &mojom_types.UserDefinedTypeStructType{
		mojom_types.MojomStruct{
			DeclData: &mojom_types.DeclarationData{
				ShortName:      strPtr(name),
				FullIdentifier: strPtr(mojomIdentifier(t)),
			},
			Fields: structFields,
		},
	}
}
예제 #8
0
func unionType(t *vdl.Type, mp map[string]mojom_types.UserDefinedType) mojom_types.UserDefinedType {
	unionFields := make([]mojom_types.UnionField, t.NumField())
	for i := 0; i < t.NumField(); i++ {
		unionFields[i] = mojom_types.UnionField{
			DeclData: &mojom_types.DeclarationData{ShortName: strPtr(t.Field(i).Name)},
			Type:     vdlToMojomTypeInternal(t.Field(i).Type, false, false, mp),
			Tag:      uint32(i),
		}
	}
	_, name := vdl.SplitIdent(t.Name())
	return &mojom_types.UserDefinedTypeUnionType{
		mojom_types.MojomUnion{
			DeclData: &mojom_types.DeclarationData{
				ShortName:      strPtr(name),
				FullIdentifier: strPtr(mojomIdentifier(t)),
			},
			Fields: unionFields,
		},
	}
}
예제 #9
0
// computeStructLayout computes a representation of the fields in a struct, as
// a list ordered by mojom byte field order.
func computeStructLayout(t *vdl.Type) (layout structLayout) {
	a := structBitAllocation{}

	for i := 0; i < t.NumField(); i++ {
		bits := baseTypeSizeBits(t.Field(i).Type)
		a = allocateStructBits(a, i+1, int(bits))
	}

	lastVal := 0
	for i, v := range a {
		if v != lastVal && v != 0 {
			layout = append(layout, structLayoutField{
				vdlStructIndex: v - 1,
				byteOffset:     uint32(i / 8),
				bitOffset:      uint8(i % 8),
			})
			lastVal = v
		}
	}

	return
}
예제 #10
0
func addUserDefinedType(t *vdl.Type, mp map[string]mojom_types.UserDefinedType) string {
	key := mojomTypeKey(t)
	if _, ok := mp[key]; ok {
		return key
	}
	mp[key] = nil // placeholder to stop recursion

	var udt mojom_types.UserDefinedType
	switch t.Kind() {
	case vdl.Struct:
		udt = structType(t, mp)
	case vdl.Union:
		udt = unionType(t, mp)
	case vdl.Enum:
		udt = enumType(t)
	default:
		panic(fmt.Sprintf("conversion from VDL kind %v to mojom user defined type not implemented", t.Kind()))
	}

	mp[key] = udt
	return key
}
예제 #11
0
func enumType(t *vdl.Type) mojom_types.UserDefinedType {
	enumValues := make([]mojom_types.EnumValue, t.NumEnumLabel())
	for i := 0; i < t.NumEnumLabel(); i++ {
		enumValues[i] = mojom_types.EnumValue{
			DeclData: &mojom_types.DeclarationData{ShortName: strPtr(t.EnumLabel(i))},
			IntValue: int32(i),
		}
	}
	_, name := vdl.SplitIdent(t.Name())
	return &mojom_types.UserDefinedTypeEnumType{
		mojom_types.MojomEnum{
			DeclData: &mojom_types.DeclarationData{
				ShortName:      strPtr(name),
				FullIdentifier: strPtr(mojomIdentifier(t)),
			},
			Values: enumValues,
		},
	}
}
예제 #12
0
func (t target) StartFields(tt *vdl.Type) (vdl.FieldsTarget, error) {
	if tt.Kind() == vdl.Optional {
		tt = tt.Elem()
	}
	if tt.Kind() == vdl.Union {
		return unionFieldsTarget{
			vdlType: tt,
			block:   t.current,
		}, nil
	}
	fieldsTarget, block, err := structFieldShared(tt, t.allocator(), true)
	t.writePointer(block)
	return fieldsTarget, err

}
예제 #13
0
func (t target) StartMap(tt *vdl.Type, len int) (vdl.MapTarget, error) {
	if tt.Kind() == vdl.Optional {
		tt = tt.Elem()
	}
	pointerBlock := t.allocator().Allocate(16, 0)
	t.writePointer(pointerBlock)

	st := target{
		current: pointerBlock.Slice(0, 8),
	}
	keys, err := st.StartSet(vdl.SetType(tt.Key()), len)
	if err != nil {
		return nil, err
	}
	valuePlaceholder := target{
		current: pointerBlock.Slice(8, 16),
	}
	return &mapTarget{
		keys:             keys,
		valuePlaceholder: valuePlaceholder,
		valueType:        tt.Elem(),
	}, nil
}
예제 #14
0
func JoinRawBytesAsStruct(targ vdl.Target, structType *vdl.Type, fields []*vom.RawBytes) error {
	st, err := targ.StartFields(structType)
	if err != nil {
		return err
	}
	if structType.NumField() != len(fields) {
		return fmt.Errorf("received %d fields, but %v has %d fields", len(fields), structType, structType.NumField())
	}
	for i := 0; i < structType.NumField(); i++ {
		f := structType.Field(i)
		k, t, err := st.StartField(f.Name)
		if err != nil {
			return err
		}
		if err := fields[i].FillVDLTarget(t, f.Type); err != nil {
			return err
		}
		if err := st.FinishField(k, t); err != nil {
			return err
		}
	}
	return targ.FinishFields(st)
}
예제 #15
0
func mojomIdentifier(t *vdl.Type) string {
	return strings.Replace(t.Name(), "/", ".", -1)
}
예제 #16
0
func (t target) fromZero(tt *vdl.Type) error {
	if tt.IsBytes() {
		return t.FromBytes(nil, tt)
	}
	switch tt.Kind() {
	case vdl.Optional:
		elemType := tt.Elem()
		switch elemType.Kind() {
		case vdl.Union, vdl.Struct: // Array? String? Bytes? List? Set?
			// Note: for union, this zeros 16 bytes, but for others it does just 8.
			zeroBytes(t.current.Bytes())
		default:
			panic(fmt.Sprintf("Vdl type %v cannot be optional", tt))
		}
	case vdl.Any:
		panic("Any rep not yet determined")
	case vdl.Bool:
		return t.FromBool(false, tt)
	case vdl.Byte, vdl.Uint16, vdl.Uint32, vdl.Uint64:
		return t.FromUint(0, tt)
	case vdl.Int8, vdl.Int16, vdl.Int32, vdl.Int64:
		return t.FromInt(0, tt)
	case vdl.Float32, vdl.Float64:
		return t.FromFloat(0, tt)
	case vdl.String:
		return t.FromString("", tt)
	case vdl.Enum:
		return t.FromEnumLabel(tt.EnumLabel(0), tt)
	case vdl.TypeObject:
		return t.FromTypeObject(vdl.AnyType)
	case vdl.List:
		lt, err := t.StartList(tt, 0)
		if err != nil {
			return err
		}
		return t.FinishList(lt)
	case vdl.Array:
		lt, err := t.StartList(tt, tt.Len())
		if err != nil {
			return err
		}
		for i := 0; i < tt.Len(); i++ {
			targ, err := lt.StartElem(i)
			if err != nil {
				return err
			}
			if err := targ.(target).fromZero(tt.Elem()); err != nil {
				return err
			}
			if err := lt.FinishElem(targ); err != nil {
				return err
			}
		}
		return t.FinishList(lt)
	case vdl.Map:
		mt, err := t.StartMap(tt, 0)
		if err != nil {
			return err
		}
		return t.FinishMap(mt)
	case vdl.Set:
		st, err := t.StartSet(tt, 0)
		if err != nil {
			return err
		}
		return t.FinishSet(st)
	case vdl.Struct:
		st, err := t.StartFields(tt)
		if err != nil {
			return err
		}
		for i := 0; i < tt.NumField(); i++ {
			fld := tt.Field(i)
			kt, ft, err := st.StartField(fld.Name)
			if err != nil {
				return err
			}
			if err := ft.(target).fromZero(fld.Type); err != nil {
				return err
			}
			if err := st.FinishField(kt, ft); err != nil {
				return err
			}
		}
		return t.FinishFields(st)
	case vdl.Union:
		st, err := t.StartFields(tt)
		if err != nil {
			return err
		}
		fld := tt.Field(0)
		kt, ft, err := st.StartField(fld.Name)
		if err != nil {
			return err
		}
		if err := ft.(target).fromZero(fld.Type); err != nil {
			return err
		}
		if err := st.FinishField(kt, ft); err != nil {
			return err
		}
		return t.FinishFields(st)
	default:
		panic(fmt.Sprintf("unknown type %v", tt))
	}
	return nil
}
예제 #17
0
func vdlToMojomTypeInternal(t *vdl.Type, outermostType bool, nullable bool, mp map[string]mojom_types.UserDefinedType) (mojomtype mojom_types.Type) {
	switch t.Kind() {
	case vdl.Bool, vdl.Float64, vdl.Float32, vdl.Int8, vdl.Int16, vdl.Int32, vdl.Int64, vdl.Byte, vdl.Uint16, vdl.Uint32, vdl.Uint64:
		return &mojom_types.TypeSimpleType{
			simpleTypeCode(t.Kind()),
		}
	case vdl.String:
		return &mojom_types.TypeStringType{
			stringType(nullable),
		}
	case vdl.Array:
		elem := vdlToMojomTypeInternal(t.Elem(), false, false, mp)
		return &mojom_types.TypeArrayType{
			arrayType(elem, nullable, t.Len()),
		}
	case vdl.List:
		elem := vdlToMojomTypeInternal(t.Elem(), false, false, mp)
		return &mojom_types.TypeArrayType{
			listType(elem, nullable),
		}
	case vdl.Map:
		key := vdlToMojomTypeInternal(t.Key(), false, false, mp)
		elem := vdlToMojomTypeInternal(t.Elem(), false, false, mp)
		return &mojom_types.TypeMapType{
			mapType(key, elem, nullable),
		}
	case vdl.Struct, vdl.Union, vdl.Enum:
		udtKey := addUserDefinedType(t, mp)
		ret := &mojom_types.TypeTypeReference{
			mojom_types.TypeReference{
				Nullable: nullable,
				TypeKey:  &udtKey,
			},
		}
		if !outermostType {
			// This is needed to match the output of the generator exactly, the outermost type
			// is not given an identifier.
			ret.Value.Identifier = ret.Value.TypeKey
		}
		return ret
	case vdl.Optional:
		return vdlToMojomTypeInternal(t.Elem(), false, true, mp)
	default:
		panic(fmt.Sprintf("conversion from VDL kind %v to mojom type not implemented", t.Kind()))
	}
}
예제 #18
0
func (targ *structSplitTarget) StartFields(tt *vdl.Type) (vdl.FieldsTarget, error) {
	targ.tt = tt
	targ.fields = make([]*vom.RawBytes, tt.NumField())
	return &structSplitFieldsTarget{targ}, nil
}
예제 #19
0
func (t target) FromNil(tt *vdl.Type) error {
	if tt.Kind() == vdl.Optional || tt.Kind() == vdl.Any {
		return t.fromZero(tt)
	}
	return fmt.Errorf("FromNil called on non-nillable type")
}
예제 #20
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))
	}
}