// // writeEmbeddedMap serializes the EMBEDDEDMAP type. Currently, OrientDB only uses string // types for the map keys, so that is an assumption of this method as well. // func (serde ORecordSerializerV0) writeEmbeddedMap(buf *obuf.WriteBuf, m oschema.OEmbeddedMap) error { // number of entries in the map err := varint.EncodeAndWriteVarInt32(buf, int32(m.Len())) if err != nil { return oerror.NewTrace(err) } ptrPos := make([]int, 0, m.Len()) // position in buf where data ptr int needs to be written // TODO: do the map entries have to be written in any particular order? I will assume no for now keys, vals, types := m.All() /* ---[ write embedded map header ]--- */ for i, k := range keys { // key type err = rw.WriteByte(buf, byte(oschema.STRING)) if err != nil { return oerror.NewTrace(err) } // write the key value err = varint.WriteString(buf, k) if err != nil { return oerror.NewTrace(err) } ptrPos = append(ptrPos, buf.Len()) buf.Skip(4) // placeholder integer for data ptr dataType := types[i] if dataType == oschema.UNKNOWN { dataType = getDataType(vals[i]) // TODO: not sure this is necessary } // write data type of the data err = rw.WriteByte(buf, byte(dataType)) if err != nil { return oerror.NewTrace(err) } } /* ---[ write embedded map data values ]--- */ for i := 0; i < len(vals); i++ { currPos := buf.Len() buf.Seek(uint(ptrPos[i])) err = rw.WriteInt(buf, int32(currPos)) if err != nil { return oerror.NewTrace(err) } buf.Seek(uint(currPos)) err = serde.writeDataValue(buf, vals[i], types[i]) if err != nil { return oerror.NewTrace(err) } } return nil }
// // serializeDocument writes the classname and the serialized record // (header and data sections) of the ODocument to the obuf.WriteBuf. // // Because this method writes the classname but NOT the serialization // version, this method is safe for recursive calls for EMBEDDED types. // func (serde ORecordSerializerV0) serializeDocument(wbuf *obuf.WriteBuf, doc *oschema.ODocument) error { err := varint.WriteString(wbuf, doc.Classname) if err != nil { return oerror.NewTrace(err) } ogl.Debugf("serdebuf A: %v\n", wbuf.Bytes()) // DEBUG ogl.Debugf("doc A: %v\n", doc) // DEBUG return serde.writeSerializedRecord(wbuf, doc) }
// // Serialization format for EMBEDDEDLIST and EMBEDDEDSET // +-------------+------------+-------------------+ // |size:varInt | type:Otype | items:item_data[] | // +-------------+------------+-------------------+ // // The item_data data structure is: // +------------------+--------------+ // | data_type:OType | data:byte[] | // +------------------+--------------+ // func (serde ORecordSerializerV0) serializeEmbeddedCollection(buf *obuf.WriteBuf, ls oschema.OEmbeddedList) error { err := varint.EncodeAndWriteVarInt32(buf, int32(ls.Len())) if err != nil { return oerror.NewTrace(err) } // following the lead of the Java driver, you don't specify the type of the list overall // (I tried to and it doesn't work, at least with OrientDB-2.0.1) err = rw.WriteByte(buf, byte(oschema.ANY)) if err != nil { return oerror.NewTrace(err) } for _, val := range ls.Values() { buf.WriteByte(byte(ls.Type())) err = serde.writeDataValue(buf, val, ls.Type()) if err != nil { return oerror.NewTrace(err) } } return nil }
// // In Progress attempt to rewrite writeSerializedRecord and related fns // using a seekable/skipping WriteBuf // func (serde ORecordSerializerV0) writeSerializedRecord(wbuf *obuf.WriteBuf, doc *oschema.ODocument) (err error) { nfields := len(doc.FieldNames()) ptrPos := make([]int, 0, nfields) // position in buf where data ptr int needs to be written currDB := serde.dbc.GetCurrDB() oclass, ok := currDB.Classes[doc.Classname] docFields := doc.GetFields() for _, fld := range docFields { var oprop *oschema.OProperty if ok { oprop = oclass.Properties[fld.Name] } // FROM THE JAVA CLIENT: // if (properties[i] != null) { // OVarIntSerializer.write(bytes, (properties[i].getId() + 1) * -1); // if (properties[i].getType() != OType.ANY) // pos[i] = bytes.alloc(OIntegerSerializer.INT_SIZE); // else // pos[i] = bytes.alloc(OIntegerSerializer.INT_SIZE + 1); // TODO: why does ANY required an additional byte? // } else { // writeString(bytes, entry.getKey()); // pos[i] = bytes.alloc(OIntegerSerializer.INT_SIZE + 1); if oprop != nil { // if property is known in the global properties, then // just write its encoded id varint.EncodeAndWriteVarInt32(wbuf, encodeFieldIDForHeader(oprop.ID)) ptrPos = append(ptrPos, wbuf.Len()) wbuf.Skip(4) // Note: no need to write property type when writing property ID } else { // property Name err = varint.WriteString(wbuf, fld.Name) if err != nil { return oerror.NewTrace(err) } ptrPos = append(ptrPos, wbuf.Len()) wbuf.Skip(4) // property Type err = rw.WriteByte(wbuf, byte(fld.Type)) if err != nil { return oerror.NewTrace(err) } } } wbuf.WriteByte(0) // End of Header sentinel // now write out the data values for i, fld := range docFields { currPos := wbuf.Len() wbuf.Seek(uint(ptrPos[i])) err = rw.WriteInt(wbuf, int32(currPos)) if err != nil { return oerror.NewTrace(err) } wbuf.Seek(uint(currPos)) err = serde.writeDataValue(wbuf, fld.Value, fld.Type) if err != nil { return oerror.NewTrace(err) } } return nil }