func testFieldsValue(t *testing.T, v reflect.Value, fields []string, fn func(v gotype.Value) bool) { for _, field := range fields { fv := v.FieldByName(field) k := gotype.Value(fv) if ok := fn(k); !ok { t.Errorf("field %s testing fail - %#v ", field, fn) } } }
func (n *Node) set(v reflect.Value) { // if !v.CanSet() || !v.IsValid() { // return // } // fmt.Println("set==", nameOfNodeType(n.Type), v.Type(), v.Kind()) // fmt.Println(n.Dump()) kind := v.Kind() switch { case gotype.IsSimple(kind): if n.Literal != "" { gotype.Value(v).Parse(n.Literal) } case kind == reflect.Invalid || kind == reflect.Uintptr || kind == reflect.UnsafePointer || kind == reflect.Func || kind == reflect.Chan || kind == reflect.Complex64 || kind == reflect.Complex128: //TODO: unsupport case kind == reflect.Array: n.setArray(v) case kind == reflect.Slice: n.setArray(v) case kind == reflect.Map: n.setMap(v) case kind == reflect.Struct: n.setObject(v) case kind == reflect.Interface: if n.Type == NodeLiteral { gotype.Value(v).Parse(n.Literal) } case kind == reflect.Ptr: if v.IsNil() && v.CanSet() { v.Set(reflect.New(v.Type().Elem())) } n.set(v.Elem()) default: //TODO: } }
// Bind func (binder *structBinder) Bind(ctx *HttpContext) ([]reflect.Value, error) { numIn := binder.method.NumIn args := make([]reflect.Value, numIn, numIn) for i := 0; i < numIn; i++ { in := binder.method.In[i] args[i] = reflect.Zero(in) if in.Kind() == reflect.Struct { args[i] = reflect.New(in).Elem() } else if in.Kind() == reflect.Ptr && in.Elem().Kind() == reflect.Struct { args[i] = reflect.New(in.Elem()) } else { continue } uType := gotype.UnderlyingType(in) uValue := gotype.Underlying(args[i]) filedNum := uType.NumField() for f := 0; f < filedNum; f++ { field := uType.Field(f) fieldValue := uValue.Field(f) fieldType := field.Type if !fieldValue.CanSet() { continue } fieldKind := fieldType.Kind() name := strings.ToLower(field.Name) str, ok := ctx.RouteData[name] if !ok { str = ctx.Request.FormValue(name) } if str == "" { continue } if gotype.IsSimple(fieldKind) { gotype.Value(fieldValue).Parse(str) } else { //TODO } } } return args, nil }
func (n *Node) setArray(v reflect.Value) { kind := v.Kind() if n.Type != NodeList || (kind != reflect.Slice && kind != reflect.Array) { return } typ := v.Type() if n.List == nil { if v.CanSet() { v.Set(reflect.Zero(typ)) } return } l := len(n.List) if kind == reflect.Slice { if v.CanSet() { v.Set(reflect.MakeSlice(v.Type(), l, l)) } else { return } } vl := v.Len() elemType := typ.Elem() elemKind := elemType.Kind() simple := gotype.IsSimple(elemKind) for i, x := range n.List { if i < vl { // capacity of array maybe less of i if simple && x.Type == NodeLiteral { gotype.Value(v.Index(i)).Parse(x.Literal) } else { x.set(v.Index(i)) } } } if kind == reflect.Array && l < vl { for i := l; i < vl; i++ { z := reflect.Zero(v.Type().Elem()) //reset v.Index(i).Set(z) } } }
func (n *Node) setObject(v reflect.Value) { kind := v.Kind() if n.Type != NodeHash || kind != reflect.Struct { return } typ := v.Type() if n.Hash == nil { if v.CanSet() { v.Set(reflect.Zero(typ)) return } } numFiled := typ.NumField() for i := 0; i < numFiled; i++ { field := typ.Field(i) if field.PkgPath != "" { continue } name := field.Name filedNode, ok := n.Child(name) if !ok { filedNode, ok = n.ChildFold(name) } if !ok { continue } fv := v.Field(i) if !fv.CanSet() { continue } kind := field.Type.Kind() if filedNode.Type == NodeLiteral && gotype.IsSimple(kind) { gotype.Value(fv).Parse(filedNode.Literal) } else { filedNode.set(fv) } } }
// copy value from src to dest, the dest must be struct func ExtdStruct(dest reflect.Value, src Getter) { if !dest.IsValid() || dest.Kind() != reflect.Struct || src == nil { return } typ := dest.Type() num := typ.NumField() for i := 0; i < num; i++ { field := typ.Field(i) x, ok := src.Get(field.Name) if !ok || !x.IsValid() { continue } v := gotype.Value(dest.Field(i)) v.Set(x) } }
// TODO: adjust indent algorithm func (e *encoder) visitReflectValue(v reflect.Value) { if !v.IsValid() { e.WriteString("") } //v = gotype.Underlying(v) kind := v.Kind() switch kind { case reflect.Bool, reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Float32, reflect.Float64: e.WriteString(gotype.Value(v).Format()) case reflect.String: s := v.String() if b, quote := stringNeedQuote(s); b { e.WriteString(quote) e.WriteString(s) e.WriteString(quote) //e.WriteString("\n") } else { e.WriteString(s) } case reflect.Struct: //fmt.Fprintln(e, "{") e.WriteByte('{') e.WriteByte('\n') e.indentInner() typ := v.Type() count := typ.NumField() for i := 0; i < count; i++ { f := typ.Field(i) if f.PkgPath != "" { continue } e.indent() //fmt.Fprint(e, f.Name) e.WriteString(f.Name) //fmt.Fprint(e, ":") e.WriteByte(':') e.visitReflectValue(v.Field(i)) //fmt.Fprintln(e, "") e.WriteByte('\n') } e.indentOuter() e.indent() //fmt.Fprintln(e, "}") e.WriteByte('}') e.WriteByte('\n') case reflect.Map: if !gotype.IsSimple(v.Type().Key().Kind()) { return } if v.IsNil() { //fmt.Fprint(e, "") //fmt.Fprint(e, "null") e.WriteByte(' ') break } //fmt.Fprintln(e, "{") e.WriteByte('{') e.WriteByte('\n') e.indentInner() keys := v.MapKeys() for _, k := range keys { e.indent() //fmt.Fprint(e, k) e.WriteString(k.String()) //fmt.Fprint(e, ":") e.WriteByte(':') e.visitReflectValue(v.MapIndex(k)) //fmt.Fprintln(e, "") e.WriteByte('\n') } e.indentOuter() e.indent() //fmt.Fprintln(e, "}") e.WriteByte('}') e.WriteByte('\n') case reflect.Slice: if v.IsNil() { //fmt.Fprint(e, "") //fmt.Fprint(e, "null") e.WriteByte(' ') break } e.visitArray(v) case reflect.Array: e.visitArray(v) case reflect.Interface, reflect.Ptr: if v.IsNil() || !v.IsValid() { //fmt.Fprint(e, "") //fmt.Fprint(e, "null") e.WriteByte(' ') return } e.visitReflectValue(v.Elem()) default: fmt.Fprint(e, v.Interface()) //return errors.New("Unsupported type " + v.Type().String()) } return }