示例#1
0
文件: decoder.go 项目: askk/ripple
func readObject(r Reader, v *reflect.Value) error {
	var err error
	for enc, err := readEncoding(r); err == nil; enc, err = readEncoding(r) {
		name := encodings[*enc]
		// fmt.Println(name, v, v.IsValid(), enc.typ, enc.field)
		switch enc.typ {
		case ST_ARRAY:
			if name == "EndOfArray" {
				return errorEndOfArray
			}
			array := getField(v, enc)
		loop:
			for {
				child := reflect.New(array.Type().Elem()).Elem()
				err := readObject(r, &child)
				switch err {
				case errorEndOfArray:
					break loop
				case errorEndOfObject:
					array.Set(reflect.Append(*array, child))
				default:
					return err
				}
			}
		case ST_OBJECT:
			switch name {
			case "EndOfObject":
				return errorEndOfObject
			case "PreviousFields", "NewFields", "FinalFields":
				leType := LedgerEntryType(v.Elem().FieldByName("LedgerEntryType").Uint())
				le := LedgerEntryFactory[leType]()
				fields := reflect.ValueOf(le)
				v.Elem().FieldByName(name).Set(fields)
				if err := readObject(r, &fields); err != nil && err != errorEndOfObject {
					return err
				}
				// var fields Fields
				// f := reflect.ValueOf(&fields)
				// v.Elem().FieldByName(name).Set(f)
				// if readObject(r, &f); err != nil && err != errorEndOfObject {
				// 	return err
				// }
			case "ModifiedNode", "DeletedNode", "CreatedNode":
				var node AffectedNode
				n := reflect.ValueOf(&node)
				var effect NodeEffect
				e := reflect.ValueOf(&effect)
				e.Elem().FieldByName(name).Set(n)
				v.Set(e.Elem())
				return readObject(r, &n)
			case "Memo":
				var memo Memo
				m := reflect.ValueOf(&memo)
				inner := reflect.ValueOf(&memo.Memo)
				err := readObject(r, &inner)
				v.Set(m.Elem())
				return err
			default:
				return fmt.Errorf("Unexpected object: %s for field: %s", v.Type(), name)
			}
		default:
			if v.Kind() == reflect.Struct {
				return fmt.Errorf("Unexpected object: %s for field: %s", v.Type(), name)
			}
			field := getField(v, enc)
			if !field.CanAddr() {
				return fmt.Errorf("Missing field: %s %+v", name, enc)
			}
			switch v := field.Addr().Interface().(type) {
			case Wire:
				if err := v.Unmarshal(r); err != nil {
					return err
				}
			default:
				if err := read(r, v); err != nil {
					return err
				}
			}
		}
	}
	return err
}