func (bag *embeddedRidBag) serializeDelegate(bw *rw.Writer) error { bw.WriteInt(int32(len(bag.links))) for _, l := range bag.links { if err := l.GetIdentity().ToStream(bw); err != nil { return err } } return bw.Err() }
func (c *Client) sendClientInfo(w *rw.Writer) { if c.curProtoVers >= ProtoVersion7 { w.WriteStrings(driverName, driverVersion) // driver info w.WriteShort(int16(c.curProtoVers)) // protocol version w.WriteNull() // client id (needed only for cluster config) } if c.curProtoVers > ProtoVersion21 { w.WriteString(c.recordFormat.String()) } else { panic("CSV serializer is not supported") } if c.curProtoVers > ProtoVersion26 { w.WriteBool(false) // use token (true) or session (false) } }
func (f binaryRecordFormatV0) writeDecimal(w *rw.Writer, o interface{}) { var d orient.Decimal switch v := o.(type) { case int64: d = orient.Decimal{Value: big.NewInt(v)} case *big.Int: d = orient.Decimal{Value: v} case orient.Decimal: d = v default: panic(orient.ErrTypeSerialization{Val: o, Serializer: f}) } w.WriteInt(int32(d.Scale)) // scale value, 0 for ints w.WriteBytes(d.Value.Bytes()) // unscaled value }
func (f binaryRecordFormatV0) writeLinkMap(w *rw.Writer, o interface{}) error { m := o.(map[string]orient.OIdentifiable) // TODO: can use reflect to support map[Stringer]orient.OIdentifiable w.WriteVarint(int64(len(m))) for k, v := range m { // TODO @orient: check skip of complex types // FIXME @orient: changed to support only string key on map f.writeOType(w, orient.STRING) f.writeString(w, k) if v == nil { f.writeNullLink(w) } else { if _, err := f.writeOptimizedLink(w, v); err != nil { return err } } } return w.Err() }
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) writeOptimizedLink(w *rw.Writer, ide orient.OIdentifiable) (int, error) { // TODO: link = recursiveLinkSave(link) rid := ide.GetIdentity() if !rid.IsValid() { return 0, fmt.Errorf("cannot serialize invalid link") } n1, _ := w.WriteVarint(int64(rid.ClusterID)) n2, _ := w.WriteVarint(int64(rid.ClusterPos)) return n1 + n2, w.Err() }
func (f binaryRecordFormatV0) writeLinkCollection(w *rw.Writer, o interface{}) error { switch col := o.(type) { case []orient.RID: w.WriteVarint(int64(len(col))) for _, rid := range col { if rid == nilRID { f.writeNullLink(w) } else { if _, err := f.writeOptimizedLink(w, rid); err != nil { return err } } } case []orient.OIdentifiable: w.WriteVarint(int64(len(col))) for _, item := range col { if item.GetIdentity() == nilRID { f.writeNullLink(w) } else { if _, err := f.writeOptimizedLink(w, item); err != nil { return err } } } case orient.OIdentifiableCollection: // TODO: assert (!(value instanceof OMVRBTreeRIDSet)) w.WriteVarint(int64(col.Len())) for item := range col.OIdentifiableIterator() { if item == nil { f.writeNullLink(w) } else { if _, err := f.writeOptimizedLink(w, item); err != nil { return err } } } default: panic(fmt.Errorf("not a link collection: %T", o)) } return w.Err() }
func (f binaryRecordFormatV0) writeSingleValue(w *rw.Writer, off int, o interface{}, tp, linkedType orient.OType) (err error) { defer func() { if r := recover(); r != nil { if ic, ok := r.(*runtime.TypeAssertionError); ok { err = fmt.Errorf("writeSingleValue(%T -> %v): %v", o, tp, ic) } else { panic(r) } } }() switch tp { case orient.BYTE: w.WriteByte(toByte(o)) case orient.BOOLEAN: w.WriteBool(toBool(o)) case orient.SHORT: w.WriteVarint(int64(toInt16(o))) case orient.INTEGER: w.WriteVarint(int64(toInt32(o))) case orient.LONG: w.WriteVarint(int64(toInt64(o))) case orient.STRING: f.writeString(w, toString(o)) case orient.FLOAT: w.WriteFloat(o.(float32)) case orient.DOUBLE: w.WriteDouble(o.(float64)) case orient.DATETIME: // unix time in milliseconds if t, ok := o.(int64); ok { w.WriteVarint(t) } else { t := o.(time.Time) it := t.Unix()*1000 + int64(t.Nanosecond())/1e6 w.WriteVarint(it) } case orient.DATE: if t, ok := o.(int64); ok { w.WriteVarint(t) } else { t := o.(time.Time) it := t.Unix()*1000 + int64(t.Nanosecond())/1e6 var offset int64 // TODO: int offset = ODateHelper.getDatabaseTimeZone().getOffset(dateValue) w.WriteVarint((it + offset) / millisecPerDay) } case orient.EMBEDDED: var edoc *orient.Document switch d := o.(type) { case orient.Document: edoc = &d case *orient.Document: edoc = d case orient.DocumentSerializable: edoc, err = o.(orient.DocumentSerializable).ToDocument() if err != nil { return } edoc.SetField(documentSerializableClassName, edoc.ClassName()) // TODO: pass empty value as nil? default: edoc = orient.NewEmptyDocument() if err = edoc.From(o); err != nil { return err } // TODO: set classname of struct? } err = f.Serialize(edoc, w, off, false) case orient.EMBEDDEDSET, orient.EMBEDDEDLIST: err = f.writeEmbeddedCollection(w, off, o, linkedType) case orient.DECIMAL: f.writeDecimal(w, o) case orient.BINARY: _, err = f.writeBinary(w, o.([]byte)) case orient.LINKSET, orient.LINKLIST: err = f.writeLinkCollection(w, o) case orient.LINK: _, err = f.writeOptimizedLink(w, o.(orient.OIdentifiable)) case orient.LINKMAP: err = f.writeLinkMap(w, o) case orient.EMBEDDEDMAP: err = f.writeEmbeddedMap(w, off, o) case orient.LINKBAG: err = o.(*orient.RidBag).ToStream(w) case orient.CUSTOM: val := o.(orient.CustomSerializable) f.writeString(w, val.GetClassName()) err = val.ToStream(w) case orient.TRANSIENT, orient.ANY: default: panic(fmt.Errorf("unknown type: %v", tp)) } if err == nil { err = w.Err() } return }
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) }
func (f binaryRecordFormatV0) writeNullLink(w *rw.Writer) int { n1, _ := w.WriteVarint(int64(nilRID.ClusterID)) n2, _ := w.WriteVarint(int64(nilRID.ClusterPos)) return n1 + n2 }
func (binaryRecordFormatV0) writeOType(w *rw.Writer, tp orient.OType) int { w.WriteByte(byte(tp)) return rw.SizeByte }
func (binaryRecordFormatV0) writeBinary(w *rw.Writer, v []byte) (int, error) { return w.WriteBytesVarint(v) }
func (binaryRecordFormatV0) writeString(w *rw.Writer, v string) (int, error) { return w.WriteStringVarint(v) }
func (bag *sbTreeRidBag) serializeDelegate(bw *rw.Writer) error { if bag.collectionPtr == nil { bw.WriteLong(-1) bw.WriteLong(-1) bw.WriteInt(-1) } else { bw.WriteLong(bag.collectionPtr.fileId) bw.WriteLong(bag.collectionPtr.pageIndex) bw.WriteInt(int32(bag.collectionPtr.pageOffset)) } bw.WriteInt(-1) // TODO: cached size; need a real value for compatibility with <= 1.7.5 bw.WriteInt(0) // TODO: support changes in sbTreeRidBag return bw.Err() }