func (f binaryRecordFormatV0) readLinkMap(r *rw.ReadSeeker, doc *orient.Document) (interface{}, error) { size := int(r.ReadVarint()) if size == 0 { return nil, r.Err() } type entry struct { Key interface{} Val orient.OIdentifiable } var ( result = make([]entry, 0, size) // TODO: can't return just this slice, need some public implementation keyTypes = make(map[orient.OType]bool, 2) ) for i := 0; i < size; i++ { keyType := f.readOType(r) keyTypes[keyType] = true key, err := f.readSingleValue(r, keyType, doc) if err != nil { return nil, err } value := f.readOptimizedLink(r) if value == nilRID { result = append(result, entry{Key: key, Val: nil}) } else { result = append(result, entry{Key: key, Val: value}) } } if len(keyTypes) == 1 { // TODO: reflect-based converter tp := orient.UNKNOWN for k, _ := range keyTypes { tp = k break } switch tp { case orient.UNKNOWN: return result, nil case orient.STRING: mp := make(map[string]orient.OIdentifiable, len(result)) for _, kv := range result { mp[kv.Key.(string)] = kv.Val } return mp, nil default: panic(fmt.Errorf("don't how to make map of type %v", tp)) } } else { panic(fmt.Errorf("map with different key type: %+v", keyTypes)) } //return result }
func (f binaryRecordFormatV0) readEmbeddedCollection(r *rw.ReadSeeker, doc *orient.Document) ([]interface{}, error) { n := int(r.ReadVarint()) if vtype := f.readOType(r); vtype == orient.ANY { out := make([]interface{}, n) // TODO: convert to determined slice type with reflect? var err error for i := range out { if itemType := f.readOType(r); itemType != orient.ANY { out[i], err = f.readSingleValue(r, itemType, doc) if err != nil { return nil, err } } } return out, nil } // TODO: @orient: manage case where type is known return nil, r.Err() }
func (f binaryRecordFormatV0) readSingleValue(r *rw.ReadSeeker, valueType orient.OType, doc *orient.Document) (value interface{}, err error) { defer func() { if r := recover(); r != nil { if ic, ok := r.(*runtime.TypeAssertionError); ok { err = fmt.Errorf("writeSingleValue(%v): %v", valueType, ic) } else { panic(r) } } }() switch valueType { case orient.INTEGER: value = int32(r.ReadVarint()) case orient.LONG: value = int64(r.ReadVarint()) case orient.SHORT: value = int16(r.ReadVarint()) case orient.STRING: value = f.readString(r) case orient.DOUBLE: value = r.ReadDouble() case orient.FLOAT: value = r.ReadFloat() case orient.BYTE: value = f.readByte(r) case orient.BOOLEAN: value = f.readByte(r) == 1 case orient.DATETIME: longTime := r.ReadVarint() value = time.Unix(longTime/1000, (longTime%1000)*1e6) case orient.DATE: // long savedTime = OVarIntSerializer.readAsLong(bytes) * MILLISEC_PER_DAY; // int offset = ODateHelper.getDatabaseTimeZone().getOffset(savedTime); // value = new Date(savedTime - offset); savedTime := r.ReadVarint() * millisecPerDay t := time.Unix(savedTime/1000, (savedTime%1000)*1e6) //.UTC().Local() // _, offset := t.Zone() // value = t.Add(-time.Duration(offset) * time.Second) value = t case orient.EMBEDDED: doc2 := orient.NewEmptyDocument() if err = f.Deserialize(doc2, r); err != nil { return nil, err } value = doc2 // if (((ODocument) value).containsField(ODocumentSerializable.CLASS_NAME)) { // String className = ((ODocument) value).field(ODocumentSerializable.CLASS_NAME); // try { // Class<?> clazz = Class.forName(className); // ODocumentSerializable newValue = (ODocumentSerializable) clazz.newInstance(); // newValue.fromDocument((ODocument) value); // value = newValue; // } catch (Exception e) { // throw new RuntimeException(e); // } // } else // ODocumentInternal.addOwner((ODocument) value, document); case orient.EMBEDDEDSET, orient.EMBEDDEDLIST: value, err = f.readEmbeddedCollection(r, doc) case orient.LINKSET, orient.LINKLIST: value = f.readLinkCollection(r) case orient.BINARY: value = f.readBinary(r) case orient.LINK: value = f.readOptimizedLink(r) case orient.LINKMAP: value, err = f.readLinkMap(r, doc) case orient.EMBEDDEDMAP: value, err = f.readEmbeddedMap(r, doc) case orient.DECIMAL: value = f.readDecimal(r) case orient.LINKBAG: bag := orient.NewRidBag() if err = bag.FromStream(r); err != nil { return nil, err } bag.SetOwner(doc) value = bag case orient.TRANSIENT: case orient.ANY: case orient.CUSTOM: // TODO: implement via Register global function panic("CUSTOM type is not supported for now") // try { // String className = readString(bytes); // Class<?> clazz = Class.forName(className); // OSerializableStream stream = (OSerializableStream) clazz.newInstance(); // stream.fromStream(readBinary(bytes)); // if (stream instanceof OSerializableWrapper) // value = ((OSerializableWrapper) stream).getSerializable(); // else // value = stream; // } catch (Exception e) { // throw new RuntimeException(e); // } } if err == nil { err = r.Err() } return }
func (f binaryRecordFormatV0) readEmbeddedMap(r *rw.ReadSeeker, doc *orient.Document) (interface{}, error) { size := int(r.ReadVarint()) if size == 0 { return nil, r.Err() } last := int64(0) type entry struct { Key interface{} Val interface{} } var ( result = make([]entry, 0, size) // TODO: can't return just this slice, need some public implementation keyTypes = make(map[orient.OType]bool, 1) valueTypes = make(map[orient.OType]bool, 2) ) for i := 0; i < size; i++ { keyType := f.readOType(r) key, err := f.readSingleValue(r, keyType, doc) if err != nil { return nil, err } valuePos := f.readInteger(r) valueType := f.readOType(r) keyTypes[keyType] = true valueTypes[valueType] = true if valuePos != 0 { headerCursor, _ := r.Seek(0, 1) r.Seek(int64(valuePos), 0) value, err := f.readSingleValue(r, valueType, doc) if err != nil { return nil, err } if off, _ := r.Seek(0, 1); off > last { last = off } r.Seek(headerCursor, 0) result = append(result, entry{Key: key, Val: value}) } else { result = append(result, entry{Key: key, Val: nil}) } } if off, _ := r.Seek(0, 1); last > off { r.Seek(last, 0) } if err := r.Err(); err != nil { return nil, err } //fmt.Printf("embedded map: types: %+v, vals: %+v\n", keyTypes, valueTypes) var ( keyType reflect.Type valType reflect.Type = orient.UNKNOWN.ReflectType() ) if len(keyTypes) == 1 { for k, _ := range keyTypes { if k == orient.UNKNOWN { return result, nil } keyType = k.ReflectType() break } } else { panic(fmt.Errorf("map with different key type: %+v", keyTypes)) } if len(valueTypes) == 1 { for v, _ := range valueTypes { valType = v.ReflectType() break } } rv := reflect.MakeMap(reflect.MapOf(keyType, valType)) for _, kv := range result { rv.SetMapIndex(reflect.ValueOf(kv.Key), reflect.ValueOf(kv.Val)) } return rv.Interface(), nil }
func (f binaryRecordFormatV0) Deserialize(doc *orient.Document, r *rw.ReadSeeker) error { className := f.readString(r) if err := r.Err(); err != nil { return err } if len(className) != 0 { doc.FillClassNameIfNeeded(className) } var ( fieldName string valuePos int valueType orient.OType last int64 ) for { //var prop core.OGlobalProperty leng := int(r.ReadVarint()) if err := r.Err(); err != nil { return err } if leng == 0 { // SCAN COMPLETED break } else if leng > 0 { // PARSE FIELD NAME fieldNameBytes := make([]byte, leng) r.ReadRawBytes(fieldNameBytes) fieldName = string(fieldNameBytes) valuePos = int(f.readInteger(r)) valueType = f.readOType(r) } else { // LOAD GLOBAL PROPERTY BY ID prop := f.getGlobalProperty(doc, leng) fieldName = prop.Name valuePos = int(f.readInteger(r)) if prop.Type != orient.ANY { valueType = prop.Type } else { valueType = f.readOType(r) } } if doc.RawContainsField(fieldName) { continue } if valuePos != 0 { headerCursor, _ := r.Seek(0, 1) r.Seek(int64(valuePos), 0) value, err := f.readSingleValue(r, valueType, doc) if err != nil { return err } if cur, _ := r.Seek(0, 1); cur > last { last = cur } r.Seek(headerCursor, 0) doc.RawSetField(fieldName, value, valueType) } else { doc.RawSetField(fieldName, nil, orient.UNKNOWN) } } //doc.ClearSource() if cur, _ := r.Seek(0, 1); last > cur { r.Seek(last, 0) } return r.Err() }