Esempio n. 1
0
func (e *extracter) extractField(val reflect.Value, s capnp.Struct, f schema.Field) error {
	typ, err := f.Slot().Type()
	if err != nil {
		return err
	}
	dv, err := f.Slot().DefaultValue()
	if err != nil {
		return err
	}
	if dv.IsValid() && int(typ.Which()) != int(dv.Which()) {
		name, _ := f.NameBytes()
		return fmt.Errorf("extract field %s: default value is a %v, want %v", name, dv.Which(), typ.Which())
	}
	if !isTypeMatch(val.Type(), typ) {
		name, _ := f.NameBytes()
		return fmt.Errorf("can't extract field %s of type %v into a Go %v", name, typ.Which(), val.Type())
	}
	switch typ.Which() {
	case schema.Type_Which_bool:
		v := s.Bit(capnp.BitOffset(f.Slot().Offset()))
		d := dv.Bool()
		val.SetBool(v != d) // != acts as XOR
	case schema.Type_Which_int8:
		v := int8(s.Uint8(capnp.DataOffset(f.Slot().Offset())))
		d := dv.Int8()
		val.SetInt(int64(v ^ d))
	case schema.Type_Which_int16:
		v := int16(s.Uint16(capnp.DataOffset(f.Slot().Offset() * 2)))
		d := dv.Int16()
		val.SetInt(int64(v ^ d))
	case schema.Type_Which_int32:
		v := int32(s.Uint32(capnp.DataOffset(f.Slot().Offset() * 4)))
		d := dv.Int32()
		val.SetInt(int64(v ^ d))
	case schema.Type_Which_int64:
		v := int64(s.Uint64(capnp.DataOffset(f.Slot().Offset() * 8)))
		d := dv.Int64()
		val.SetInt(v ^ d)
	case schema.Type_Which_uint8:
		v := s.Uint8(capnp.DataOffset(f.Slot().Offset()))
		d := dv.Uint8()
		val.SetUint(uint64(v ^ d))
	case schema.Type_Which_uint16:
		v := s.Uint16(capnp.DataOffset(f.Slot().Offset() * 2))
		d := dv.Uint16()
		val.SetUint(uint64(v ^ d))
	case schema.Type_Which_enum:
		v := s.Uint16(capnp.DataOffset(f.Slot().Offset() * 2))
		d := dv.Enum()
		val.SetUint(uint64(v ^ d))
	case schema.Type_Which_uint32:
		v := s.Uint32(capnp.DataOffset(f.Slot().Offset() * 4))
		d := dv.Uint32()
		val.SetUint(uint64(v ^ d))
	case schema.Type_Which_uint64:
		v := s.Uint64(capnp.DataOffset(f.Slot().Offset() * 8))
		d := dv.Uint64()
		val.SetUint(v ^ d)
	case schema.Type_Which_float32:
		v := s.Uint32(capnp.DataOffset(f.Slot().Offset() * 4))
		d := math.Float32bits(dv.Float32())
		val.SetFloat(float64(math.Float32frombits(v ^ d)))
	case schema.Type_Which_float64:
		v := s.Uint64(capnp.DataOffset(f.Slot().Offset() * 8))
		d := math.Float64bits(dv.Float64())
		val.SetFloat(math.Float64frombits(v ^ d))
	case schema.Type_Which_text:
		p, err := s.Ptr(uint16(f.Slot().Offset()))
		if err != nil {
			return err
		}
		var b []byte
		if p.IsValid() {
			b = p.TextBytes()
		} else {
			b, _ = dv.TextBytes()
		}
		if val.Kind() == reflect.String {
			val.SetString(string(b))
		} else {
			// byte slice, as guaranteed by isTypeMatch
			val.SetBytes(b)
		}
	case schema.Type_Which_data:
		p, err := s.Ptr(uint16(f.Slot().Offset()))
		if err != nil {
			return err
		}
		var b []byte
		if p.IsValid() {
			b = p.Data()
		} else {
			b, _ = dv.Data()
		}
		val.SetBytes(b)
	case schema.Type_Which_structType:
		p, err := s.Ptr(uint16(f.Slot().Offset()))
		if err != nil {
			return err
		}
		ss := p.Struct()
		if !ss.IsValid() {
			p, _ = dv.StructValuePtr()
			ss = p.Struct()
		}
		return e.extractStruct(val, typ.StructType().TypeId(), ss)
	case schema.Type_Which_list:
		p, err := s.Ptr(uint16(f.Slot().Offset()))
		if err != nil {
			return err
		}
		l := p.List()
		if !l.IsValid() {
			p, _ = dv.ListPtr()
			l = p.List()
		}
		return e.extractList(val, typ, l)
	default:
		return fmt.Errorf("unknown field type %v", typ.Which())
	}
	return nil
}
Esempio n. 2
0
func (ins *inserter) insertField(s capnp.Struct, f schema.Field, val reflect.Value) error {
	typ, err := f.Slot().Type()
	if err != nil {
		return err
	}
	dv, err := f.Slot().DefaultValue()
	if err != nil {
		return err
	}
	if dv.IsValid() && int(typ.Which()) != int(dv.Which()) {
		name, _ := f.NameBytes()
		return fmt.Errorf("insert field %s: default value is a %v, want %v", name, dv.Which(), typ.Which())
	}
	if !isTypeMatch(val.Type(), typ) {
		name, _ := f.NameBytes()
		return fmt.Errorf("can't insert field %s of type Go %v into a %v", name, val.Type(), typ.Which())
	}
	if !isFieldInBounds(s.Size(), f.Slot().Offset(), typ) {
		name, _ := f.NameBytes()
		return fmt.Errorf("can't insert field %s: allocated struct is too small", name)
	}
	switch typ.Which() {
	case schema.Type_Which_bool:
		v := val.Bool()
		d := dv.Bool()
		s.SetBit(capnp.BitOffset(f.Slot().Offset()), v != d) // != acts as XOR
	case schema.Type_Which_int8:
		v := int8(val.Int())
		d := dv.Int8()
		s.SetUint8(capnp.DataOffset(f.Slot().Offset()), uint8(v^d))
	case schema.Type_Which_int16:
		v := int16(val.Int())
		d := dv.Int16()
		s.SetUint16(capnp.DataOffset(f.Slot().Offset()*2), uint16(v^d))
	case schema.Type_Which_int32:
		v := int32(val.Int())
		d := dv.Int32()
		s.SetUint32(capnp.DataOffset(f.Slot().Offset()*4), uint32(v^d))
	case schema.Type_Which_int64:
		v := val.Int()
		d := dv.Int64()
		s.SetUint64(capnp.DataOffset(f.Slot().Offset()*8), uint64(v^d))
	case schema.Type_Which_uint8:
		v := uint8(val.Uint())
		d := dv.Uint8()
		s.SetUint8(capnp.DataOffset(f.Slot().Offset()), v^d)
	case schema.Type_Which_uint16:
		v := uint16(val.Uint())
		d := dv.Uint16()
		s.SetUint16(capnp.DataOffset(f.Slot().Offset()*2), v^d)
	case schema.Type_Which_enum:
		v := uint16(val.Uint())
		d := dv.Enum()
		s.SetUint16(capnp.DataOffset(f.Slot().Offset()*2), v^d)
	case schema.Type_Which_uint32:
		v := uint32(val.Uint())
		d := dv.Uint32()
		s.SetUint32(capnp.DataOffset(f.Slot().Offset()*4), v^d)
	case schema.Type_Which_uint64:
		v := val.Uint()
		d := dv.Uint64()
		s.SetUint64(capnp.DataOffset(f.Slot().Offset()*8), v^d)
	case schema.Type_Which_float32:
		v := math.Float32bits(float32(val.Float()))
		d := math.Float32bits(dv.Float32())
		s.SetUint32(capnp.DataOffset(f.Slot().Offset()*4), v^d)
	case schema.Type_Which_float64:
		v := math.Float64bits(val.Float())
		d := uint64(math.Float64bits(dv.Float64()))
		s.SetUint64(capnp.DataOffset(f.Slot().Offset()*8), v^d)
	case schema.Type_Which_text:
		off := uint16(f.Slot().Offset())
		if val.Len() == 0 {
			if !isEmptyValue(dv) {
				return s.SetNewText(off, "")
			}
			return s.SetText(off, "")
		}
		if val.Kind() == reflect.String {
			return s.SetText(off, val.String())
		} else {
			return s.SetTextFromBytes(off, val.Bytes())
		}
	case schema.Type_Which_data:
		b := val.Bytes()
		if b == nil && !isEmptyValue(dv) {
			b = []byte{}
		}
		off := uint16(f.Slot().Offset())
		return s.SetData(off, b)
	case schema.Type_Which_structType:
		off := uint16(f.Slot().Offset())
		sval := val
		if val.Kind() == reflect.Ptr {
			if val.IsNil() {
				return s.SetPtr(off, capnp.Ptr{})
			}
			sval = val.Elem()
		}
		id := typ.StructType().TypeId()
		sz, err := ins.structSize(id)
		if err != nil {
			return err
		}
		ss, err := capnp.NewStruct(s.Segment(), sz)
		if err != nil {
			return err
		}
		if err := s.SetPtr(off, ss.ToPtr()); err != nil {
			return err
		}
		return ins.insertStruct(id, ss, sval)
	case schema.Type_Which_list:
		off := uint16(f.Slot().Offset())
		if val.IsNil() && isEmptyValue(dv) {
			return s.SetPtr(off, capnp.Ptr{})
		}
		elem, err := typ.List().ElementType()
		if err != nil {
			return err
		}
		l, err := ins.newList(s.Segment(), elem, int32(val.Len()))
		if err != nil {
			return err
		}
		if err := s.SetPtr(off, l.ToPtr()); err != nil {
			return err
		}
		return ins.insertList(l, typ, val)
	default:
		return fmt.Errorf("unknown field type %v", typ.Which())
	}
	return nil
}