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() }