func writeStruct(w io.Writer, val *reflect.StructValue) (err os.Error) { if _, err = fmt.Fprint(w, "{"); err != nil { return } typ := val.Type().(*reflect.StructType) for i := 0; i < val.NumField(); i++ { fieldValue := val.Field(i) if _, err = fmt.Fprintf(w, "%s:", Quote(typ.Field(i).Name)); err != nil { return } if err = writeValue(w, fieldValue); err != nil { return } if i < val.NumField()-1 { if _, err = fmt.Fprint(w, ","); err != nil { return } } } _, err = fmt.Fprint(w, "}") return }
// Generic struct printer. // Doesn't care about the string tag "domain-name", // but does look for an "ipv4" tag on uint32 variables // and the "ipv6" tag on array variables, // printing them as IP addresses. func printStructValue(val *reflect.StructValue) string { s := "{" for i := 0; i < val.NumField(); i++ { if i > 0 { s += ", " } f := val.Type().(*reflect.StructType).Field(i) if !f.Anonymous { s += f.Name + "=" } fval := val.Field(i) if fv, ok := fval.(*reflect.StructValue); ok { s += printStructValue(fv) } else if fv, ok := fval.(*reflect.UintValue); ok && f.Tag == "ipv4" { i := fv.Get() s += IPv4(byte(i>>24), byte(i>>16), byte(i>>8), byte(i)).String() } else if fv, ok := fval.(*reflect.ArrayValue); ok && f.Tag == "ipv6" { i := fv.Interface().([]byte) s += IP(i).String() } else { s += fmt.Sprint(fval.Interface()) } } s += "}" return s }
func writeStruct(w io.Writer, val *reflect.StructValue) (err os.Error) { _, err = fmt.Fprint(w, "d") if err != nil { return } typ := val.Type().(*reflect.StructType) numFields := val.NumField() svList := make(StringValueArray, numFields) for i := 0; i < numFields; i++ { field := typ.Field(i) key := field.Name if len(field.Tag) > 0 { key = field.Tag } svList[i].key = key svList[i].value = val.Field(i) } err = writeSVList(w, svList) if err != nil { return } _, err = fmt.Fprint(w, "e") if err != nil { return } return }
// TODO(rsc): Move into generic library? // Unpack a reflect.StructValue from msg. // Same restrictions as packStructValue. func unpackStructValue(val *reflect.StructValue, msg []byte, off int) (off1 int, ok bool) { for i := 0; i < val.NumField(); i++ { f := val.Type().(*reflect.StructType).Field(i) switch fv := val.Field(i).(type) { default: BadType: fmt.Fprintf(os.Stderr, "net: dns: unknown packing type %v", f.Type) return len(msg), false case *reflect.StructValue: off, ok = unpackStructValue(fv, msg, off) case *reflect.UintValue: switch fv.Type().Kind() { default: goto BadType case reflect.Uint16: if off+2 > len(msg) { return len(msg), false } i := uint16(msg[off])<<8 | uint16(msg[off+1]) fv.Set(uint64(i)) off += 2 case reflect.Uint32: if off+4 > len(msg) { return len(msg), false } i := uint32(msg[off])<<24 | uint32(msg[off+1])<<16 | uint32(msg[off+2])<<8 | uint32(msg[off+3]) fv.Set(uint64(i)) off += 4 } case *reflect.StringValue: var s string switch f.Tag { default: fmt.Fprintf(os.Stderr, "net: dns: unknown string tag %v", f.Tag) return len(msg), false case "domain-name": s, off, ok = unpackDomainName(msg, off) if !ok { return len(msg), false } case "": if off >= len(msg) || off+1+int(msg[off]) > len(msg) { return len(msg), false } n := int(msg[off]) off++ b := make([]byte, n) for i := 0; i < n; i++ { b[i] = msg[off+i] } off += n s = string(b) } fv.Set(s) } } return off, true }
// TODO(rsc): Move into generic library? // Pack a reflect.StructValue into msg. Struct members can only be uint16, uint32, string, // and other (often anonymous) structs. func packStructValue(val *reflect.StructValue, msg []byte, off int) (off1 int, ok bool) { for i := 0; i < val.NumField(); i++ { f := val.Type().(*reflect.StructType).Field(i) switch fv := val.Field(i).(type) { default: BadType: fmt.Fprintf(os.Stderr, "net: dns: unknown packing type %v", f.Type) return len(msg), false case *reflect.StructValue: off, ok = packStructValue(fv, msg, off) case *reflect.UintValue: i := fv.Get() switch fv.Type().Kind() { default: goto BadType case reflect.Uint16: if off+2 > len(msg) { return len(msg), false } msg[off] = byte(i >> 8) msg[off+1] = byte(i) off += 2 case reflect.Uint32: if off+4 > len(msg) { return len(msg), false } msg[off] = byte(i >> 24) msg[off+1] = byte(i >> 16) msg[off+2] = byte(i >> 8) msg[off+3] = byte(i) off += 4 } case *reflect.StringValue: // There are multiple string encodings. // The tag distinguishes ordinary strings from domain names. s := fv.Get() switch f.Tag { default: fmt.Fprintf(os.Stderr, "net: dns: unknown string tag %v", f.Tag) return len(msg), false case "domain-name": off, ok = packDomainName(s, msg, off) if !ok { return len(msg), false } case "": // Counted string: 1 byte length. if len(s) > 255 || off+1+len(s) > len(msg) { return len(msg), false } msg[off] = byte(len(s)) off++ off += copy(msg[off:], s) } } } return off, true }
func encodeStruct(w io.Writer, v *reflect.StructValue) (err os.Error) { n := v.NumField() if err = printfLine(w, "*%d", n); err != nil { return } for i := 0; i < n; i++ { if err = encode(w, v.Field(i).Interface()); err != nil { return } } return nil }
func ToByteSliceArray(v *reflect.StructValue) (bsa [][]byte, ok bool) { n := v.NumField() bsa = make([][]byte, n) for i := 0; i < n; i++ { bsa[i], ok = GetByteArrayAtIndex(v, i) if !ok { if debug() { } break } } return }
func fuzzyEqualStruct(a *reflect.StructValue, b *reflect.StructValue) bool { numA, numB := a.NumField(), b.NumField() if numA != numB { return false } for i := 0; i < numA; i++ { if !fuzzyEqualValue(a.Field(i), b.Field(i)) { return false } } return true }
func writeStruct(w io.Writer, val *reflect.StructValue) os.Error { fmt.Fprint(w, "{") typ := val.Type().(*reflect.StructType) for i := 0; i < val.NumField(); i++ { fieldValue := val.Field(i) fmt.Fprintf(w, "%q:", typ.Field(i).Name) if err := writeValue(w, fieldValue); err != nil { return err } if i < val.NumField()-1 { fmt.Fprint(w, ",") } } fmt.Fprint(w, "}") return nil }
// object consumes an object from d.data[d.off-1:], decoding into the value v. // the first byte of the object ('{') has been read already. func (d *decodeState) object(v reflect.Value) { // Check for unmarshaler. unmarshaler, pv := d.indirect(v, false) if unmarshaler != nil { d.off-- err := unmarshaler.UnmarshalJSON(d.next()) if err != nil { d.error(err) } return } v = pv // Decoding into nil interface? Switch to non-reflect code. iv, ok := v.(*reflect.InterfaceValue) if ok { iv.Set(reflect.NewValue(d.objectInterface())) return } // Check type of target: struct or map[string]T var ( mv *reflect.MapValue sv *reflect.StructValue ) switch v := v.(type) { case *reflect.MapValue: // map must have string type t := v.Type().(*reflect.MapType) if t.Key() != reflect.Typeof("") { d.saveError(&UnmarshalTypeError{"object", v.Type()}) break } mv = v if mv.IsNil() { mv.SetValue(reflect.MakeMap(t)) } case *reflect.StructValue: sv = v default: d.saveError(&UnmarshalTypeError{"object", v.Type()}) } if mv == nil && sv == nil { d.off-- d.next() // skip over { } in input return } for { // Read opening " of string key or closing }. op := d.scanWhile(scanSkipSpace) if op == scanEndObject { // closing } - can only happen on first iteration. break } if op != scanBeginLiteral { d.error(errPhase) } // Read string key. start := d.off - 1 op = d.scanWhile(scanContinue) item := d.data[start : d.off-1] key, ok := unquote(item) if !ok { d.error(errPhase) } // Figure out field corresponding to key. var subv reflect.Value if mv != nil { subv = reflect.MakeZero(mv.Type().(*reflect.MapType).Elem()) } else { // First try for field with that tag. for i := 0; i < sv.NumField(); i++ { f := sv.Type().(*reflect.StructType).Field(i) if f.Tag == key { subv = sv.Field(i) break } } if subv == nil { // Second, exact match. subv = sv.FieldByName(key) if subv == nil { // Third, case-insensitive match. subv = sv.FieldByNameFunc(func(s string) bool { return matchName(key, s) }) } } } // Read : before value. if op == scanSkipSpace { op = d.scanWhile(scanSkipSpace) } if op != scanObjectKey { d.error(errPhase) } // Read value. d.value(subv) // Write value back to map; // if using struct, subv points into struct already. if mv != nil { mv.SetElem(reflect.NewValue(key), subv) } // Next token must be , or }. op = d.scanWhile(scanSkipSpace) if op == scanEndObject { break } if op != scanObjectValue { d.error(errPhase) } } }