Example #1
0
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())
}
Example #2
0
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)
}