func testSerializeEmbCol(t *testing.T, off int, col interface{}, origBase64 string) { buf := bytes.NewBuffer(nil) for i := 0; i < off; i++ { buf.WriteByte(0) } if err := (binaryRecordFormatV0{}).writeEmbeddedCollection(rw.NewWriter(buf), off, col, orient.UNKNOWN); err != nil { t.Fatal(err) } testBase64Compare(t, buf.Bytes(), origBase64) }
// SerializeAnyStreamable serializes a given object func SerializeAnyStreamable(o CustomSerializable) ([]byte, error) { buf := bytes.NewBuffer(nil) bw := rw.NewWriter(buf) bw.WriteString(o.GetClassName()) if err := o.ToStream(bw); err != nil { return nil, err } if err := bw.Err(); err != nil { return nil, err } return buf.Bytes(), nil }
func (bag *RidBag) ToStream(w io.Writer) error { var first byte hasUUID := false // TODO: do we need to send it? if !bag.IsRemote() { first |= 0x1 } if hasUUID { first |= 0x2 } bw := rw.NewWriter(w) bw.WriteByte(first) if hasUUID { bw.WriteRawBytes(bag.id[:]) } return bag.delegate.serializeDelegate(bw) }
func testSerializeEmbMap(t *testing.T, off int, mp interface{}, origBase64 string) { buf := bytes.NewBuffer(nil) for i := 0; i < off; i++ { buf.WriteByte(0) } if err := (binaryRecordFormatV0{}).writeEmbeddedMap(rw.NewWriter(buf), off, mp); err != nil { t.Fatal(err) } testBase64Compare(t, buf.Bytes(), origBase64) r := rw.NewReadSeeker(bytes.NewReader(buf.Bytes())) out, err := (binaryRecordFormatV0{}).readEmbeddedMap(r, nil) if err != nil { t.Fatal(err) } if reflect.TypeOf(out) != reflect.TypeOf(mp) { t.Logf("types are not the same: %T -> %T", mp, out) } }
func TestSerializeDatetimeV0(t *testing.T) { buf := bytes.NewBuffer(nil) val := time.Now() val = time.Unix(val.Unix(), int64(val.Nanosecond()/1e6)*1e6) // precise to milliseconds if err := (binaryRecordFormatV0{}).writeSingleValue(rw.NewWriter(buf), 0, val, orient.DATETIME, orient.UNKNOWN); err != nil { t.Fatal(err) } r := rw.NewReadSeeker(bytes.NewReader(buf.Bytes())) out, err := (binaryRecordFormatV0{}).readSingleValue(r, orient.DATETIME, nil) if err != nil { t.Fatal(err) } if val2, ok := out.(time.Time); !ok { t.Fatalf("expected Time, got: %T", out) } else if !val.Equal(val2) { t.Fatalf("values differs: %v != %v", val, val2) } }
func TestSerializeDecimalV0(t *testing.T) { buf := bytes.NewBuffer(nil) val := big.NewInt(123456789) if err := (binaryRecordFormatV0{}).writeSingleValue(rw.NewWriter(buf), 0, val, orient.DECIMAL, orient.UNKNOWN); err != nil { t.Fatal(err) } testBase64Compare(t, buf.Bytes(), "AAAAAAAAAAQHW80V") r := rw.NewReadSeeker(bytes.NewReader(buf.Bytes())) out, err := (binaryRecordFormatV0{}).readSingleValue(r, orient.DECIMAL, nil) if err != nil { t.Fatal(err) } if val2, ok := out.(orient.Decimal); !ok { t.Fatalf("expected Decimal, got: %T", out) } else if val.Cmp(val2.Value) != 0 { t.Fatalf("values differs: %v != %v", val, val2) } }
func TestReadErrorResponseWithSingleException(t *testing.T) { buf := new(bytes.Buffer) bw := rw.NewWriter(buf) bw.WriteByte(byte(1)) // indicates continue of exception class/msg array bw.WriteStrings("org.foo.BlargException", "wibble wibble!!") bw.WriteByte(byte(0)) // indicates end of exception class/msg array bw.WriteBytes([]byte("this is a stacktrace simulator\nEOL")) var serverExc error serverExc = obinary.ReadErrorResponse(rw.NewReader(buf)) e, ok := serverExc.(orient.OServerException) if !ok { t.Fatal("wrong exception type") } equals(t, 1, len(e.Exceptions)) equals(t, "org.foo.BlargException", e.Exceptions[0].ExcClass()) equals(t, "wibble wibble!!", e.Exceptions[0].ExcMessage()) }
func (f BinaryRecordFormat) ToStream(w io.Writer, rec orient.ORecord) error { doc, ok := rec.(*orient.Document) if !ok { return orient.ErrTypeSerialization{Val: rec, Serializer: f} } // TODO: can send empty document to stream if serialization fails? bw := rw.NewWriter(w) bw.WriteByte(byte(binaryFormatCurrentVersion)) off := rw.SizeByte // TODO: apply partial serialization to prevent infinite recursion of records ser := binaryFormatVerions[binaryFormatCurrentVersion]() ser.SetGlobalPropertyFunc(f.fnc) if err := bw.Err(); err != nil { return err } if err := ser.Serialize(doc, w, off, false); err != nil { return err } return bw.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 TestReadErrorResponseWithMultipleExceptions(t *testing.T) { buf := new(bytes.Buffer) bw := rw.NewWriter(buf) bw.WriteByte(byte(1)) // indicates more exceptions to come bw.WriteStrings("org.foo.BlargException", "Too many blorgles!!") bw.WriteByte(byte(1)) // indicates more exceptions to come bw.WriteStrings("org.foo.FeebleException", "Not enough juice") bw.WriteByte(byte(1)) // indicates more exceptions to come bw.WriteStrings("org.foo.WobbleException", "Orbital decay") bw.WriteByte(byte(0)) // indicates end of exceptions bw.WriteBytes([]byte("this is a stacktrace simulator\nEOL")) serverExc := obinary.ReadErrorResponse(rw.NewReader(buf)) e, ok := serverExc.(orient.OServerException) if !ok { t.Fatal("wrong exception type") } equals(t, "org.foo.BlargException", e.Exceptions[0].ExcClass()) equals(t, "Not enough juice", e.Exceptions[1].ExcMessage()) equals(t, "org.foo.WobbleException", e.Exceptions[2].ExcClass()) equals(t, "Orbital decay", e.Exceptions[2].ExcMessage()) }
// Dial creates a new binary connection to OrientDB server. // The Client returned is ready to make calls to the OrientDB but has not // yet established a database session or a session with the OrientDB server. // After this, the user needs to call either OpenDatabase or CreateServerSession. func Dial(addr string) (*Client, error) { addr, err := validateAddr(addr) if err != nil { return nil, err } conn, err := net.DialTimeout("tcp", addr, time.Minute) if err != nil { return nil, err } c := &Client{ addr: addr, conn: conn, done: make(chan struct{}), br: bufio.NewReader(conn), bw: bufio.NewWriter(conn), } c.pr = rw.NewReader(c.br) c.pw = rw.NewWriter(c.bw) if err := c.handshakeVersion(); err != nil { conn.Close() return nil, err } c.sess = make(map[int32]*session) c.root = c.newSess(noSessionId) go c.run() return c, nil }
func (rid RID) ToStream(w io.Writer) error { bw := rw.NewWriter(w) bw.WriteShort(rid.ClusterID) bw.WriteLong(rid.ClusterPos) return bw.Err() }
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) Serialize(doc *orient.Document, w io.Writer, off int, classOnly bool) error { buf := bytes.NewBuffer(nil) bw := rw.NewWriter(buf) if _, err := f.serializeClass(bw, doc); err != nil { return err } if classOnly { f.writeEmptyString(bw) if err := bw.Err(); err != nil { return err } return rw.NewWriter(w).WriteRawBytes(buf.Bytes()) } fields := doc.FieldsArray() type item struct { Pos int Ptr int Field *orient.DocEntry Type orient.OType } var ( items = make([]item, 0, len(fields)) ) for _, entry := range fields { it := item{Field: entry} // TODO: use global properties for serialization, if class is known f.writeString(bw, entry.Name) it.Pos = buf.Len() // save buffer offset of pointer bw.WriteInt(0) // placeholder for data pointer tp := f.getFieldType(entry) if tp == orient.UNKNOWN { return fmt.Errorf("Can't serialize type %T with Document binary serializer", entry.Type) } bw.WriteByte(byte(tp)) it.Type = tp items = append(items, it) } f.writeEmptyString(bw) for i, it := range items { if it.Field.Value == nil { continue } ptr := buf.Len() if err := f.writeSingleValue(bw, off+ptr, it.Field.Value, it.Type, f.getLinkedType(doc, it.Type, it.Field.Name)); err != nil { return err } if buf.Len() != ptr { items[i].Ptr = ptr } else { items[i].Ptr = 0 } } if err := bw.Err(); err != nil { return err } data := buf.Bytes() for _, it := range items { if it.Ptr != 0 { rw.Order.PutUint32(data[it.Pos:], uint32(int32(it.Ptr+off))) } } return rw.NewWriter(w).WriteRawBytes(data) }