func (f binaryRecordFormatV0) writeEmbeddedCollection(w *rw.Writer, off int, o interface{}, linkedType orient.OType) error { mv := reflect.ValueOf(o) // TODO: handle OEmbeddedList if mv.Kind() != reflect.Slice && mv.Kind() != reflect.Array { panic(fmt.Sprintf("only maps are supported as %v, got %T", orient.EMBEDDEDMAP, o)) } buf := bytes.NewBuffer(nil) bw := rw.NewWriter(buf) bw.WriteVarint(int64(mv.Len())) // TODO @orient: manage embedded type from schema and auto-determined. f.writeOType(bw, orient.ANY) for i := 0; i < mv.Len(); i++ { item := mv.Index(i).Interface() // TODO @orient: manage in a better way null entry if item == nil { f.writeOType(bw, orient.ANY) continue } var tp orient.OType = linkedType if tp == orient.UNKNOWN { tp = f.getTypeFromValueEmbedded(item) } if tp != orient.UNKNOWN { f.writeOType(bw, tp) ptr := buf.Len() if err := f.writeSingleValue(bw, off+ptr, item, tp, orient.UNKNOWN); err != nil { return err } } else { panic(orient.ErrTypeSerialization{Val: item, Serializer: f}) } } if err := bw.Err(); err != nil { return err } return w.WriteRawBytes(buf.Bytes()) }
func (f binaryRecordFormatV0) writeEmbeddedMap(w *rw.Writer, off int, o interface{}) error { mv := reflect.ValueOf(o) if mv.Kind() != reflect.Map { panic(fmt.Sprintf("only maps are supported as %v, got %T", orient.EMBEDDEDMAP, o)) } buf := bytes.NewBuffer(nil) bw := rw.NewWriter(buf) type item struct { Pos int Val interface{} Type orient.OType Ptr int } items := make([]item, 0, mv.Len()) bw.WriteVarint(int64(mv.Len())) keys := mv.MapKeys() for _, kv := range keys { k := kv.Interface() v := mv.MapIndex(kv).Interface() // TODO @orient: check skip of complex types // FIXME @orient: changed to support only string key on map f.writeOType(bw, orient.STRING) f.writeString(bw, fmt.Sprint(k)) // convert key to string it := item{Pos: buf.Len(), Val: v} bw.WriteInt(0) // ptr placeholder tp := f.getTypeFromValueEmbedded(v) if tp == orient.UNKNOWN { panic(orient.ErrTypeSerialization{Val: v, Serializer: f}) } it.Type = tp f.writeOType(bw, tp) items = append(items, it) } for i := range items { ptr := buf.Len() if err := f.writeSingleValue(bw, off+ptr, items[i].Val, items[i].Type, orient.UNKNOWN); err != nil { return err } if ptr != buf.Len() { items[i].Ptr = ptr } else { items[i].Ptr = 0 } } if err := bw.Err(); err != nil { return err } data := buf.Bytes() for i := range items { if items[i].Ptr > 0 { rw.Order.PutUint32(data[items[i].Pos:], uint32(int32(items[i].Ptr+off))) } } return w.WriteRawBytes(data) }