func isGoConstType(t schema.Type) bool { w := t.Which() return w == schema.Type_Which_bool || w == schema.Type_Which_int8 || w == schema.Type_Which_uint8 || w == schema.Type_Which_int16 || w == schema.Type_Which_uint16 || w == schema.Type_Which_int32 || w == schema.Type_Which_uint32 || w == schema.Type_Which_int64 || w == schema.Type_Which_uint64 || w == schema.Type_Which_text || w == schema.Type_Which_enum }
func isFieldInBounds(sz capnp.ObjectSize, off uint32, t schema.Type) bool { switch t.Which() { case schema.Type_Which_void: return true case schema.Type_Which_bool: return sz.DataSize >= capnp.Size(off/8+1) case schema.Type_Which_int8, schema.Type_Which_uint8: return sz.DataSize >= capnp.Size(off+1) case schema.Type_Which_int16, schema.Type_Which_uint16, schema.Type_Which_enum: return sz.DataSize >= capnp.Size(off+1)*2 case schema.Type_Which_int32, schema.Type_Which_uint32, schema.Type_Which_float32: return sz.DataSize >= capnp.Size(off+1)*4 case schema.Type_Which_int64, schema.Type_Which_uint64, schema.Type_Which_float64: return sz.DataSize >= capnp.Size(off+1)*8 case schema.Type_Which_text, schema.Type_Which_data, schema.Type_Which_list, schema.Type_Which_structType, schema.Type_Which_interface, schema.Type_Which_anyPointer: return sz.PointerCount >= uint16(off+1) default: return false } }
func (ins *inserter) newList(s *capnp.Segment, t schema.Type, len int32) (capnp.List, error) { switch t.Which() { case schema.Type_Which_void: l := capnp.NewVoidList(s, len) return l.List, nil case schema.Type_Which_bool: l, err := capnp.NewBitList(s, len) return l.List, err case schema.Type_Which_int8, schema.Type_Which_uint8: l, err := capnp.NewUInt8List(s, len) return l.List, err case schema.Type_Which_int16, schema.Type_Which_uint16, schema.Type_Which_enum: l, err := capnp.NewUInt16List(s, len) return l.List, err case schema.Type_Which_int32, schema.Type_Which_uint32, schema.Type_Which_float32: l, err := capnp.NewUInt32List(s, len) return l.List, err case schema.Type_Which_int64, schema.Type_Which_uint64, schema.Type_Which_float64: l, err := capnp.NewUInt64List(s, len) return l.List, err case schema.Type_Which_text, schema.Type_Which_data, schema.Type_Which_list, schema.Type_Which_interface, schema.Type_Which_anyPointer: l, err := capnp.NewPointerList(s, len) return l.List, err case schema.Type_Which_structType: sz, err := ins.structSize(t.StructType().TypeId()) if err != nil { return capnp.List{}, err } return capnp.NewCompositeList(s, sz, len) default: return capnp.List{}, fmt.Errorf("new list: unknown element type: %v", t.Which()) } }
func isTypeMatch(r reflect.Type, s schema.Type) bool { switch s.Which() { case schema.Type_Which_text: return r.Kind() == reflect.String || r.Kind() == reflect.Slice && r.Elem().Kind() == reflect.Uint8 case schema.Type_Which_data: return r.Kind() == reflect.Slice && r.Elem().Kind() == reflect.Uint8 case schema.Type_Which_structType: return isStructOrStructPtr(r) case schema.Type_Which_list: e, _ := s.List().ElementType() return r.Kind() == reflect.Slice && isTypeMatch(r.Elem(), e) } k, ok := typeMap[s.Which()] return ok && k == r.Kind() }
func (e *extracter) extractList(val reflect.Value, typ schema.Type, l capnp.List) error { vt := val.Type() elem, err := typ.List().ElementType() if err != nil { return err } if !isTypeMatch(vt, typ) { // TODO(light): the error won't be that useful for nested lists. return fmt.Errorf("can't extract %v list into a Go %v", elem.Which(), vt) } if !l.IsValid() { val.Set(reflect.Zero(vt)) return nil } n := l.Len() val.Set(reflect.MakeSlice(vt, n, n)) switch elem.Which() { case schema.Type_Which_bool: for i := 0; i < n; i++ { val.Index(i).SetBool(capnp.BitList{List: l}.At(i)) } case schema.Type_Which_int8: for i := 0; i < n; i++ { val.Index(i).SetInt(int64(capnp.Int8List{List: l}.At(i))) } case schema.Type_Which_int16: for i := 0; i < n; i++ { val.Index(i).SetInt(int64(capnp.Int16List{List: l}.At(i))) } case schema.Type_Which_int32: for i := 0; i < n; i++ { val.Index(i).SetInt(int64(capnp.Int32List{List: l}.At(i))) } case schema.Type_Which_int64: for i := 0; i < n; i++ { val.Index(i).SetInt(capnp.Int64List{List: l}.At(i)) } case schema.Type_Which_uint8: for i := 0; i < n; i++ { val.Index(i).SetUint(uint64(capnp.UInt8List{List: l}.At(i))) } case schema.Type_Which_uint16, schema.Type_Which_enum: for i := 0; i < n; i++ { val.Index(i).SetUint(uint64(capnp.UInt16List{List: l}.At(i))) } case schema.Type_Which_uint32: for i := 0; i < n; i++ { val.Index(i).SetUint(uint64(capnp.UInt32List{List: l}.At(i))) } case schema.Type_Which_uint64: for i := 0; i < n; i++ { val.Index(i).SetUint(capnp.UInt64List{List: l}.At(i)) } case schema.Type_Which_float32: for i := 0; i < n; i++ { val.Index(i).SetFloat(float64(capnp.Float32List{List: l}.At(i))) } case schema.Type_Which_float64: for i := 0; i < n; i++ { val.Index(i).SetFloat(capnp.Float64List{List: l}.At(i)) } case schema.Type_Which_text: if val.Type().Elem().Kind() == reflect.String { for i := 0; i < n; i++ { s, err := capnp.TextList{List: l}.At(i) if err != nil { // TODO(light): collect errors and finish return err } val.Index(i).SetString(s) } } else { for i := 0; i < n; i++ { b, err := capnp.TextList{List: l}.BytesAt(i) if err != nil { // TODO(light): collect errors and finish return err } val.Index(i).SetBytes(b) } } case schema.Type_Which_data: for i := 0; i < n; i++ { b, err := capnp.DataList{List: l}.At(i) if err != nil { // TODO(light): collect errors and finish return err } val.Index(i).SetBytes(b) } case schema.Type_Which_list: for i := 0; i < n; i++ { p, err := capnp.PointerList{List: l}.PtrAt(i) // TODO(light): collect errors and finish if err != nil { return err } if err := e.extractList(val.Index(i), elem, p.List()); err != nil { return err } } case schema.Type_Which_structType: if val.Type().Elem().Kind() == reflect.Struct { for i := 0; i < n; i++ { err := e.extractStruct(val.Index(i), elem.StructType().TypeId(), l.Struct(i)) if err != nil { return err } } } else { for i := 0; i < n; i++ { newval := reflect.New(val.Type().Elem().Elem()) val.Index(i).Set(newval) err := e.extractStruct(newval, elem.StructType().TypeId(), l.Struct(i)) if err != nil { return err } } } default: return fmt.Errorf("unknown list type %v", elem.Which()) } return nil }
func (ins *inserter) insertList(l capnp.List, typ schema.Type, val reflect.Value) error { elem, err := typ.List().ElementType() if err != nil { return err } if !isTypeMatch(val.Type(), typ) { // TODO(light): the error won't be that useful for nested lists. return fmt.Errorf("can't insert Go %v into a %v list", val.Type(), elem.Which()) } n := val.Len() switch elem.Which() { case schema.Type_Which_void: case schema.Type_Which_bool: for i := 0; i < n; i++ { capnp.BitList{List: l}.Set(i, val.Index(i).Bool()) } case schema.Type_Which_int8: for i := 0; i < n; i++ { capnp.Int8List{List: l}.Set(i, int8(val.Index(i).Int())) } case schema.Type_Which_int16: for i := 0; i < n; i++ { capnp.Int16List{List: l}.Set(i, int16(val.Index(i).Int())) } case schema.Type_Which_int32: for i := 0; i < n; i++ { capnp.Int32List{List: l}.Set(i, int32(val.Index(i).Int())) } case schema.Type_Which_int64: for i := 0; i < n; i++ { capnp.Int64List{List: l}.Set(i, val.Index(i).Int()) } case schema.Type_Which_uint8: for i := 0; i < n; i++ { capnp.UInt8List{List: l}.Set(i, uint8(val.Index(i).Uint())) } case schema.Type_Which_uint16, schema.Type_Which_enum: for i := 0; i < n; i++ { capnp.UInt16List{List: l}.Set(i, uint16(val.Index(i).Uint())) } case schema.Type_Which_uint32: for i := 0; i < n; i++ { capnp.UInt32List{List: l}.Set(i, uint32(val.Index(i).Uint())) } case schema.Type_Which_uint64: for i := 0; i < n; i++ { capnp.UInt64List{List: l}.Set(i, val.Index(i).Uint()) } case schema.Type_Which_float32: for i := 0; i < n; i++ { capnp.Float32List{List: l}.Set(i, float32(val.Index(i).Float())) } case schema.Type_Which_float64: for i := 0; i < n; i++ { capnp.Float64List{List: l}.Set(i, val.Index(i).Float()) } case schema.Type_Which_text: if val.Type().Elem().Kind() == reflect.String { for i := 0; i < n; i++ { err := capnp.TextList{List: l}.Set(i, val.Index(i).String()) if err != nil { // TODO(light): collect errors and finish return err } } } else { for i := 0; i < n; i++ { b := val.Index(i).Bytes() if len(b) == 0 { err := capnp.PointerList{List: l}.SetPtr(i, capnp.Ptr{}) if err != nil { // TODO(light): collect errors and finish return err } } t, err := capnp.NewTextFromBytes(l.Segment(), b) if err != nil { // TODO(light): collect errors and finish return err } err = capnp.PointerList{List: l}.SetPtr(i, t.ToPtr()) if err != nil { // TODO(light): collect errors and finish return err } } } case schema.Type_Which_data: for i := 0; i < n; i++ { b := val.Index(i).Bytes() if len(b) == 0 { err := capnp.PointerList{List: l}.SetPtr(i, capnp.Ptr{}) if err != nil { // TODO(light): collect errors and finish return err } } err := capnp.DataList{List: l}.Set(i, b) if err != nil { // TODO(light): collect errors and finish return err } } case schema.Type_Which_list: pl := capnp.PointerList{List: l} for i := 0; i < n; i++ { vi := val.Index(i) if vi.IsNil() { if err := pl.SetPtr(i, capnp.Ptr{}); err != nil { return err } continue } ee, err := elem.List().ElementType() if err != nil { return err } li, err := ins.newList(l.Segment(), ee, int32(vi.Len())) if err != nil { return err } if err := pl.SetPtr(i, li.ToPtr()); err != nil { return err } if err := ins.insertList(li, elem, vi); err != nil { return err } } case schema.Type_Which_structType: id := elem.StructType().TypeId() for i := 0; i < n; i++ { err := ins.insertStruct(id, l.Struct(i), val.Index(i)) if err != nil { // TODO(light): collect errors and finish return err } } default: return fmt.Errorf("unknown list type %v", elem.Which()) } return nil }
func (enc *Encoder) marshalList(elem schema.Type, l capnp.List) error { enc.w.WriteByte('[') switch elem.Which() { case schema.Type_Which_void: for i := 0; i < l.Len(); i++ { if i > 0 { enc.w.WriteString(", ") } enc.w.WriteString(voidMarker) } case schema.Type_Which_bool: bl := capnp.BitList{List: l} for i := 0; i < bl.Len(); i++ { if i > 0 { enc.w.WriteString(", ") } enc.marshalBool(bl.At(i)) } case schema.Type_Which_int8: il := capnp.Int8List{List: l} for i := 0; i < il.Len(); i++ { if i > 0 { enc.w.WriteString(", ") } enc.marshalInt(int64(il.At(i))) } case schema.Type_Which_int16: il := capnp.Int16List{List: l} for i := 0; i < il.Len(); i++ { if i > 0 { enc.w.WriteString(", ") } enc.marshalInt(int64(il.At(i))) } case schema.Type_Which_int32: il := capnp.Int32List{List: l} for i := 0; i < il.Len(); i++ { if i > 0 { enc.w.WriteString(", ") } enc.marshalInt(int64(il.At(i))) } case schema.Type_Which_int64: il := capnp.Int64List{List: l} for i := 0; i < il.Len(); i++ { if i > 0 { enc.w.WriteString(", ") } enc.marshalInt(il.At(i)) } case schema.Type_Which_uint8: il := capnp.UInt8List{List: l} for i := 0; i < il.Len(); i++ { if i > 0 { enc.w.WriteString(", ") } enc.marshalUint(uint64(il.At(i))) } case schema.Type_Which_uint16: il := capnp.UInt16List{List: l} for i := 0; i < il.Len(); i++ { if i > 0 { enc.w.WriteString(", ") } enc.marshalUint(uint64(il.At(i))) } case schema.Type_Which_uint32: il := capnp.UInt32List{List: l} for i := 0; i < il.Len(); i++ { if i > 0 { enc.w.WriteString(", ") } enc.marshalUint(uint64(il.At(i))) } case schema.Type_Which_uint64: il := capnp.UInt64List{List: l} for i := 0; i < il.Len(); i++ { if i > 0 { enc.w.WriteString(", ") } enc.marshalUint(il.At(i)) } case schema.Type_Which_float32: fl := capnp.Float32List{List: l} for i := 0; i < fl.Len(); i++ { if i > 0 { enc.w.WriteString(", ") } enc.marshalFloat32(fl.At(i)) } case schema.Type_Which_float64: fl := capnp.Float64List{List: l} for i := 0; i < fl.Len(); i++ { if i > 0 { enc.w.WriteString(", ") } enc.marshalFloat64(fl.At(i)) } case schema.Type_Which_data: dl := capnp.DataList{List: l} for i := 0; i < dl.Len(); i++ { if i > 0 { enc.w.WriteString(", ") } d, err := dl.At(i) if err != nil { return err } enc.marshalText(d) } case schema.Type_Which_text: tl := capnp.TextList{List: l} for i := 0; i < tl.Len(); i++ { if i > 0 { enc.w.WriteString(", ") } t, err := tl.BytesAt(i) if err != nil { return err } enc.marshalText(t) } case schema.Type_Which_structType: for i := 0; i < l.Len(); i++ { if i > 0 { enc.w.WriteString(", ") } err := enc.marshalStruct(elem.StructType().TypeId(), l.Struct(i)) if err != nil { return err } } case schema.Type_Which_list: ee, err := elem.List().ElementType() if err != nil { return err } for i := 0; i < l.Len(); i++ { if i > 0 { enc.w.WriteString(", ") } p, err := capnp.PointerList{List: l}.PtrAt(i) if err != nil { return err } err = enc.marshalList(ee, p.List()) if err != nil { return err } } case schema.Type_Which_enum: il := capnp.UInt16List{List: l} typ := elem.Enum().TypeId() // TODO(light): only search for node once for i := 0; i < il.Len(); i++ { if i > 0 { enc.w.WriteString(", ") } enc.marshalEnum(typ, il.At(i)) } case schema.Type_Which_interface: for i := 0; i < l.Len(); i++ { if i > 0 { enc.w.WriteString(", ") } enc.w.WriteString(interfaceMarker) } case schema.Type_Which_anyPointer: for i := 0; i < l.Len(); i++ { if i > 0 { enc.w.WriteString(", ") } enc.w.WriteString(anyPointerMarker) } default: return fmt.Errorf("unknown list type %v", elem.Which()) } enc.w.WriteByte(']') return nil }
func makeTypeRef(t schema.Type, rel *node, nodes nodeMap) (typeRef, error) { nodeRef := func(id uint64) (typeRef, error) { ni, err := nodes.mustFind(id) if err != nil { return typeRef{}, err } return makeNodeTypeRef(ni, rel) } if ref, ok := staticTypeRefs[t.Which()]; ok { return ref, nil } switch t.Which() { case schema.Type_Which_enum: return nodeRef(t.Enum().TypeId()) case schema.Type_Which_structType: return nodeRef(t.StructType().TypeId()) case schema.Type_Which_interface: return nodeRef(t.Interface().TypeId()) case schema.Type_Which_list: lt, _ := t.List().ElementType() if ref, ok := staticListTypeRefs[lt.Which()]; ok { return ref, nil } switch lt.Which() { case schema.Type_Which_enum: ref, err := nodeRef(lt.Enum().TypeId()) if err != nil { return ref, err } ref.name = ref.name + "_List" ref.newfunc = "New" + ref.name return ref, nil case schema.Type_Which_structType: ref, err := nodeRef(lt.StructType().TypeId()) if err != nil { return ref, err } ref.name = ref.name + "_List" ref.newfunc = "New" + ref.name return ref, nil case schema.Type_Which_anyPointer, schema.Type_Which_list, schema.Type_Which_interface: return typeRef{name: "PointerList", newfunc: "NewPointerList", imp: capnpImportSpec}, nil } } return typeRef{}, fmt.Errorf("unable to reference type %v", t.Which()) }
// Value formats a value from a schema (like a field default) as Go source. func (g *generator) Value(rel *node, t schema.Type, v schema.Value) (string, error) { if !isValueOfType(v, t) { return "", fmt.Errorf("value type is %v, but found %v value", t.Which(), v.Which()) } switch t.Which() { case schema.Type_Which_void: return "struct{}{}", nil case schema.Type_Which_interface: // The only statically representable interface value is null. return g.imports.Capnp() + ".Client(nil)", nil case schema.Type_Which_bool: if v.Bool() { return "true", nil } else { return "false", nil } case schema.Type_Which_uint8, schema.Type_Which_uint16, schema.Type_Which_uint32, schema.Type_Which_uint64: return fmt.Sprintf("uint%d(%d)", intbits(t.Which()), uintValue(v)), nil case schema.Type_Which_int8, schema.Type_Which_int16, schema.Type_Which_int32, schema.Type_Which_int64: return fmt.Sprintf("int%d(%d)", intbits(t.Which()), intValue(v)), nil case schema.Type_Which_float32: return fmt.Sprintf("%s.Float32frombits(0x%x)", g.imports.Math(), math.Float32bits(v.Float32())), nil case schema.Type_Which_float64: return fmt.Sprintf("%s.Float64frombits(0x%x)", g.imports.Math(), math.Float64bits(v.Float64())), nil case schema.Type_Which_text: text, _ := v.Text() return strconv.Quote(text), nil case schema.Type_Which_data: buf := make([]byte, 0, 1024) buf = append(buf, "[]byte{"...) data, _ := v.Data() for i, b := range data { if i > 0 { buf = append(buf, ',', ' ') } buf = strconv.AppendUint(buf, uint64(b), 10) } buf = append(buf, '}') return string(buf), nil case schema.Type_Which_enum: en := g.nodes[t.Enum().TypeId()] if en == nil || !en.IsValid() || en.Which() != schema.Node_Which_enum { return "", errors.New("expected enum type") } enums, _ := en.Enum().Enumerants() val := int(v.Enum()) if val >= enums.Len() { rn, err := g.RemoteNodeName(en, rel) if err != nil { return "", err } return fmt.Sprintf("%s(%d)", rn, val), nil } ev := makeEnumval(en, val, enums.At(val)) imp, err := importForNode(en, rel) if err != nil { return "", err } if imp.path == "" { return ev.FullName(), nil } qname := g.imports.add(imp) return qname + "." + ev.FullName(), nil case schema.Type_Which_structType: data, _ := v.StructValuePtr() var buf bytes.Buffer tn, err := g.nodes.mustFind(t.StructType().TypeId()) if err != nil { return "", err } sd, err := g.data.copyData(data) if err != nil { return "", err } err = templates.ExecuteTemplate(&buf, "structValue", structValueParams{ G: g, Node: rel, Typ: tn, Value: sd, }) return buf.String(), err case schema.Type_Which_anyPointer: data, _ := v.AnyPointerPtr() var buf bytes.Buffer sd, err := g.data.copyData(data) if err != nil { return "", err } err = templates.ExecuteTemplate(&buf, "pointerValue", pointerValueParams{ G: g, Value: sd, }) return buf.String(), err case schema.Type_Which_list: data, _ := v.ListPtr() var buf bytes.Buffer ftyp, err := g.RemoteTypeName(t, rel) if err != nil { return "", err } sd, err := g.data.copyData(data) if err != nil { return "", err } err = templates.ExecuteTemplate(&buf, "listValue", listValueParams{ G: g, Typ: ftyp, Value: sd, }) return buf.String(), err default: return "", fmt.Errorf("unhandled value type %v", t.Which()) } }
func isValueOfType(v schema.Value, t schema.Type) bool { // Ensure that the value is for the given type. The schema ensures the union ordinals match. return !v.IsValid() || int(v.Which()) == int(t.Which()) }