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 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()) }
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 }