func unmarshalInteger(i int64, v reflect.Value) { switch v.Kind() { case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: if v.OverflowInt(i) { panic(&UnmarshalOverflowError{"integer " + strconv.FormatInt(i, 10), v.Type()}) } v.SetInt(i) case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: if i < 0 { panic(&UnmarshalOverflowError{"integer " + strconv.FormatInt(i, 10), v.Type()}) } u := uint64(i) if v.OverflowUint(u) { panic(&UnmarshalOverflowError{"integer " + strconv.FormatUint(u, 10), v.Type()}) } v.SetUint(u) case reflect.Interface: if v.NumMethod() == 0 { v.Set(reflect.ValueOf(i)) return } fallthrough default: panic(&UnmarshalTypeError{"integer " + strconv.FormatInt(i, 10), v.Type()}) } }
func (d *decoder) unmarshalUint(size uint, offset uint, result reflect.Value, uintType uint) (uint, error) { if size > uintType/8 { return 0, newInvalidDatabaseError("the MaxMind DB file's data section contains bad data (uint%v size of %v)", uintType, size) } value, newOffset, err := d.decodeUint(size, offset) if err != nil { return 0, err } switch result.Kind() { default: return newOffset, newUnmarshalTypeError(value, result.Type()) case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: n := int64(value) if result.OverflowInt(n) { return 0, newUnmarshalTypeError(value, result.Type()) } result.SetInt(n) return newOffset, nil case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: if result.OverflowUint(value) { return 0, newUnmarshalTypeError(value, result.Type()) } result.SetUint(value) return newOffset, nil case reflect.Interface: result.Set(reflect.ValueOf(value)) return newOffset, nil } }
func setUint(rv reflect.Value, u uint64) error { switch rv.Kind() { case reflect.Ptr: if rv.IsNil() { if rv.CanSet() { rv.Set(reflect.New(rv.Type().Elem())) // fall through to set indirect below } else { return fmt.Errorf("trying to put uint into unsettable nil ptr") } } return setUint(reflect.Indirect(rv), u) case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: if rv.OverflowUint(u) { return fmt.Errorf("value %d does not fit into target of type %s", u, rv.Kind().String()) } rv.SetUint(u) return nil case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: if (u == 0xffffffffffffffff) || rv.OverflowInt(int64(u)) { return fmt.Errorf("value %d does not fit into target of type %s", u, rv.Kind().String()) } rv.SetInt(int64(u)) return nil case reflect.Interface: rv.Set(reflect.ValueOf(u)) return nil default: return fmt.Errorf("cannot assign uint into Kind=%s Type=%#v %#v", rv.Kind().String(), rv.Type(), rv) } }
func (d *decoder) unmarshalInt32(size uint, offset uint, result reflect.Value) (uint, error) { if size > 4 { return 0, newInvalidDatabaseError("the MaxMind DB file's data section contains bad data (int32 size of %v)", size) } value, newOffset, err := d.decodeInt(size, offset) if err != nil { return 0, err } switch result.Kind() { case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: n := int64(value) if !result.OverflowInt(n) { result.SetInt(n) return newOffset, nil } case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: n := uint64(value) if !result.OverflowUint(n) { result.SetUint(n) return newOffset, nil } case reflect.Interface: if result.NumMethod() == 0 { result.Set(reflect.ValueOf(value)) return newOffset, nil } } return newOffset, newUnmarshalTypeError(value, result.Type()) }
func numberDecoder(node RMNode, data interface{}, v reflect.Value) { val, err := redis.String(data, nil) if err != nil { panic(err) } switch v.Kind() { case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: n, err := strconv.ParseInt(val, 10, 64) if err != nil || v.OverflowInt(n) { panic(fmt.Sprintf("Unable to convert int: %s \n", val)) } v.SetInt(n) case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: n, err := strconv.ParseUint(val, 10, 64) if err != nil || v.OverflowUint(n) { panic(fmt.Sprintf("Unable to convert uint: %s \n", val)) } v.SetUint(n) case reflect.Float32, reflect.Float64: n, err := strconv.ParseFloat(val, v.Type().Bits()) if err != nil || v.OverflowFloat(n) { panic(fmt.Sprintf("Unable to convert float: %s \n", val)) } v.SetFloat(n) default: panic(fmt.Sprintf("Unsupported number convertion for type[%v] with value[%v]", v.Type(), data)) } }
func setStringValue(v reflect.Value, value string) (err error) { s := value // if type is []byte if v.Kind() == reflect.Slice && v.Type().Elem().Kind() == reflect.Uint8 { v.SetBytes([]byte(s)) return } switch v.Kind() { case reflect.String: v.SetString(s) case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: var n int64 n, err = strconv.ParseInt(s, 10, 64) if err != nil { return } if v.OverflowInt(n) { err = fmt.Errorf("overflow int64 for %d.", n) return } v.SetInt(n) case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: var n uint64 n, err = strconv.ParseUint(s, 10, 64) if err != nil { return } if v.OverflowUint(n) { err = fmt.Errorf("overflow uint64 for %d.", n) return } v.SetUint(n) case reflect.Float32, reflect.Float64: var n float64 n, err = strconv.ParseFloat(s, v.Type().Bits()) if err != nil { return } if v.OverflowFloat(n) { err = fmt.Errorf("overflow float64 for %d.", n) return } v.SetFloat(n) case reflect.Bool: var n bool n, err = strconv.ParseBool(s) if err != nil { return } v.SetBool(n) default: err = errors.New(fmt.Sprintf("value %+v can only been set to primary type but was %+v", value, v)) } return }
func (d *Decoder) decodeNumber(n *string, v reflect.Value) error { switch v.Kind() { case reflect.Interface: i, err := d.decodeNumberToInterface(n) if err != nil { return err } v.Set(reflect.ValueOf(i)) return nil case reflect.String: if v.Type() == numberType { // Support Number value type v.Set(reflect.ValueOf(Number(*n))) return nil } v.Set(reflect.ValueOf(*n)) case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: i, err := strconv.ParseInt(*n, 10, 64) if err != nil { return err } if v.OverflowInt(i) { return &UnmarshalTypeError{ Value: fmt.Sprintf("number overflow, %s", *n), Type: v.Type(), } } v.SetInt(i) case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: i, err := strconv.ParseUint(*n, 10, 64) if err != nil { return err } if v.OverflowUint(i) { return &UnmarshalTypeError{ Value: fmt.Sprintf("number overflow, %s", *n), Type: v.Type(), } } v.SetUint(i) case reflect.Float32, reflect.Float64: i, err := strconv.ParseFloat(*n, 64) if err != nil { return err } if v.OverflowFloat(i) { return &UnmarshalTypeError{ Value: fmt.Sprintf("number overflow, %s", *n), Type: v.Type(), } } v.SetFloat(i) default: return &UnmarshalTypeError{Value: "number", Type: v.Type()} } return nil }
func decodeUint(rval reflect.Value, arg string) error { v, err := strconv.ParseUint(arg, 10, 64) if err != nil { return err } if rval.OverflowUint(v) { return fmt.Errorf("value %d would overflow %s", v, rval.Kind()) } rval.Set(reflect.ValueOf(v).Convert(rval.Type())) return nil }
func unmarshalStringToNumberOrBoolean(d *decodeState, s []byte, v reflect.Value, fromQuoted bool) { if fromQuoted { d.saveError(&UnmarshalTypeError{"string", v.Type(), int64(d.off)}) return } switch { default: d.saveError(&UnmarshalTypeError{"string", v.Type(), int64(d.off)}) case isValidNumberBytes(s): switch v.Kind() { default: d.saveError(&UnmarshalTypeError{"string", v.Type(), int64(d.off)}) case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: s := string(s) n, err := strconv.ParseInt(s, 10, 64) if err != nil || v.OverflowInt(n) { d.saveError(&UnmarshalTypeError{"string " + s, v.Type(), int64(d.off)}) break } v.SetInt(n) case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: s := string(s) n, err := strconv.ParseUint(s, 10, 64) if err != nil || v.OverflowUint(n) { d.saveError(&UnmarshalTypeError{"string " + s, v.Type(), int64(d.off)}) break } v.SetUint(n) case reflect.Float32, reflect.Float64: s := string(s) n, err := strconv.ParseFloat(s, v.Type().Bits()) if err != nil || v.OverflowFloat(n) { d.saveError(&UnmarshalTypeError{"string " + s, v.Type(), int64(d.off)}) break } v.SetFloat(n) } case bytes.Equal(s, trueLiteral): switch v.Kind() { default: d.saveError(&UnmarshalTypeError{"string", v.Type(), int64(d.off)}) case reflect.Bool: v.SetBool(true) } case bytes.Equal(s, falseLiteral): switch v.Kind() { default: d.saveError(&UnmarshalTypeError{"string", v.Type(), int64(d.off)}) case reflect.Bool: v.SetBool(false) } } }
func resolve_uint(val string, v reflect.Value) error { val = strings.Replace(val, "_", "", -1) var value uint64 if val[0] == '-' { return errors.New("Unsigned int with negative value: " + val) } if val[0] == '+' { val = val[1:] } base := 10 if val == "0" { v.Set(reflect.Zero(v.Type())) return nil } if strings.HasPrefix(val, "0b") { base = 2 val = val[2:] } else if strings.HasPrefix(val, "0x") { base = 16 val = val[2:] } else if val[0] == '0' { base = 8 val = val[1:] } else if strings.Contains(val, ":") { digits := strings.Split(val, ":") bes := uint64(1) for j := len(digits) - 1; j >= 0; j-- { n, err := strconv.ParseUint(digits[j], 10, 64) n *= bes if err != nil || v.OverflowUint(n) { return errors.New("Unsigned Integer: " + val) } value += n bes *= 60 } v.SetUint(value) return nil } value, err := strconv.ParseUint(val, base, 64) if err != nil || v.OverflowUint(value) { return errors.New("Unsigned Integer: " + val) } v.SetUint(value) return nil }
func resolve_uint(val string, v reflect.Value, useNumber bool, event yaml_event_t) (string, error) { original := val val = strings.Replace(val, "_", "", -1) var value uint64 isNumberValue := v.Type() == numberType if val[0] == '-' { return "", fmt.Errorf("Unsigned int with negative value: '%s' at %s", original, event.start_mark) } if val[0] == '+' { val = val[1:] } base := 0 if val == "0" { if isNumberValue { v.SetString("0") } else { v.Set(reflect.Zero(v.Type())) } return yaml_INT_TAG, nil } if strings.HasPrefix(val, "0o") { base = 8 val = val[2:] } value, err := strconv.ParseUint(val, base, 64) if err != nil { return "", fmt.Errorf("Invalid unsigned integer: '%s' at %s", val, event.start_mark) } if isNumberValue { v.SetString(strconv.FormatUint(value, 10)) } else { if v.OverflowUint(value) { return "", fmt.Errorf("Invalid unsigned integer: '%s' at %s", val, event.start_mark) } v.SetUint(value) } return yaml_INT_TAG, nil }
// called when 'i' was consumed func (d *decoder) parse_int(v reflect.Value) { start := d.offset - 1 d.read_until('e') if d.buf.Len() == 0 { panic(&SyntaxError{ Offset: start, what: "empty integer value", }) } switch v.Kind() { case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: n, err := strconv.ParseInt(d.buf.String(), 10, 64) check_for_int_parse_error(err, start) if v.OverflowInt(n) { panic(&UnmarshalTypeError{ Value: "integer " + d.buf.String(), Type: v.Type(), }) } v.SetInt(n) case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: n, err := strconv.ParseUint(d.buf.String(), 10, 64) check_for_int_parse_error(err, start) if v.OverflowUint(n) { panic(&UnmarshalTypeError{ Value: "integer " + d.buf.String(), Type: v.Type(), }) } v.SetUint(n) case reflect.Bool: if d.buf.Len() == 1 && d.buf.Bytes()[0] == '0' { v.SetBool(false) } v.SetBool(true) default: panic(&UnmarshalTypeError{ Value: "integer " + d.buf.String(), Type: v.Type(), }) } d.buf.Reset() }
// called when 'i' was consumed func (d *decoder) parse_int(v reflect.Value) { start := d.offset - 1 d.read_until('e') if d.buf.Len() == 0 { panic(&SyntaxError{ Offset: start, What: errors.New("empty integer value"), }) } s := d.buf.String() switch v.Kind() { case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: n, err := strconv.ParseInt(s, 10, 64) check_for_int_parse_error(err, start) if v.OverflowInt(n) { panic(&UnmarshalTypeError{ Value: "integer " + s, Type: v.Type(), }) } v.SetInt(n) case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: n, err := strconv.ParseUint(s, 10, 64) check_for_int_parse_error(err, start) if v.OverflowUint(n) { panic(&UnmarshalTypeError{ Value: "integer " + s, Type: v.Type(), }) } v.SetUint(n) case reflect.Bool: v.SetBool(s != "0") default: panic(&UnmarshalTypeError{ Value: "integer " + s, Type: v.Type(), }) } d.buf.Reset() }
func (d *decodeState) numberStore(item []byte, v reflect.Value, fromQuoted bool) { s := string(item) switch v.Kind() { default: if v.Kind() == reflect.String && v.Type() == numberType { v.SetString(s) break } if fromQuoted { d.error(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type())) } d.error(&UnmarshalTypeError{"number", v.Type()}) case reflect.Interface: n, err := d.convertNumber(string(item)) if err != nil { d.saveError(err) break } v.Set(reflect.ValueOf(n)) case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: n, err := strconv.ParseInt(s, 10, 64) if err != nil || v.OverflowInt(n) { d.saveError(&UnmarshalTypeError{"number " + s, v.Type()}) break } v.SetInt(n) case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: n, err := strconv.ParseUint(s, 10, 64) if err != nil || v.OverflowUint(n) { d.saveError(&UnmarshalTypeError{"number " + s, v.Type()}) break } v.SetUint(n) case reflect.Float32, reflect.Float64: n, err := strconv.ParseFloat(s, v.Type().Bits()) if err != nil || v.OverflowFloat(n) { d.saveError(&UnmarshalTypeError{"number " + s, v.Type()}) break } v.SetFloat(n) } }
// Set Value with given string func (d *decodeState) setValue(v reflect.Value, s string) { //fmt.Printf("SET(kind:%s, %s)\n", v.Kind(), s) switch v.Kind() { case reflect.String: v.SetString(s) case reflect.Bool: v.SetBool(boolValue(s)) case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: n, err := strconv.ParseInt(s, 10, 64) if err != nil || v.OverflowInt(n) { d.saveError(&IniError{d.lineNum, d.line, "Invalid int"}) return } v.SetInt(n) case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: n, err := strconv.ParseUint(s, 10, 64) if err != nil || v.OverflowUint(n) { d.saveError(&IniError{d.lineNum, d.line, "Invalid uint"}) return } v.SetUint(n) case reflect.Float32, reflect.Float64: n, err := strconv.ParseFloat(s, v.Type().Bits()) if err != nil || v.OverflowFloat(n) { d.saveError(&IniError{d.lineNum, d.line, "Invalid float"}) return } v.SetFloat(n) case reflect.Slice: d.sliceValue(v, s) default: d.saveError(&IniError{d.lineNum, d.line, fmt.Sprintf("Can't set value of type %s", v.Kind())}) } }
func decodeUint(d *decodeState, kind int, v reflect.Value) { var n uint64 switch kind { default: d.saveErrorAndSkip(kind, v.Type()) return case kindInt64, kindTimestamp, kindDateTime: n = uint64(d.scanInt64()) case kindInt32: n = uint64(d.scanInt32()) case kindFloat: n = uint64(d.scanFloat()) } if v.OverflowUint(n) { d.saveError(&DecodeConvertError{kind, v.Type()}) return } v.SetUint(n) }
func unmarshalQuoted(s string, v reflect.Value) { switch v.Kind() { case reflect.Bool: b, err := strconv.ParseBool(s) if err != nil { panic(err) } v.SetBool(b) case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: i, err := strconv.ParseInt(s, 10, 64) if err != nil { panic(err) } if v.OverflowInt(i) { goto overflowError } v.SetInt(i) case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: u, err := strconv.ParseUint(s, 10, 64) if err != nil { panic(err) } if v.OverflowUint(u) { goto overflowError } v.SetUint(u) case reflect.Float32, reflect.Float64: f, err := strconv.ParseFloat(s, 64) if err != nil { panic(err) } if v.OverflowFloat(f) { goto overflowError } v.SetFloat(f) default: panic("toml: unexpected type for quoted string") } return overflowError: panic(&UnmarshalOverflowError{"string " + strconv.Quote(s), v.Type()}) }
func setUint(rv reflect.Value, u uint64) error { switch rv.Kind() { case reflect.Ptr: return setUint(reflect.Indirect(rv), u) case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: if rv.OverflowUint(u) { return fmt.Errorf("value %d does not fit into target of type %s", u, rv.Kind().String()) } rv.SetUint(u) return nil case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: if (u == 0xffffffffffffffff) || rv.OverflowInt(int64(u)) { return fmt.Errorf("value %d does not fit into target of type %s", u, rv.Kind().String()) } rv.SetInt(int64(u)) return nil case reflect.Interface: rv.Set(reflect.ValueOf(u)) return nil default: return fmt.Errorf("cannot assign uint into Kind=%s Type=%#v %#v", rv.Kind().String(), rv.Type(), rv) } }
// literalStore decodes a literal stored in item into v. // // fromQuoted indicates whether this literal came from unwrapping a // string from the ",string" struct tag option. this is used only to // produce more helpful error messages. func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool) { // Check for unmarshaler. if len(item) == 0 { //Empty string given d.saveError(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type())) return } wantptr := item[0] == 'n' // null u, ut, pv := d.indirect(v, wantptr) if u != nil { err := u.UnmarshalJSON(item) if err != nil { d.error(err) } return } if ut != nil { if item[0] != '"' { if fromQuoted { d.saveError(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type())) } else { d.saveError(&UnmarshalTypeError{"string", v.Type()}) } } s, ok := unquoteBytes(item) if !ok { if fromQuoted { d.error(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type())) } else { d.error(errPhase) } } err := ut.UnmarshalText(s) if err != nil { d.error(err) } return } v = pv switch c := item[0]; c { case 'n': // null switch v.Kind() { case reflect.Interface, reflect.Ptr, reflect.Map, reflect.Slice: v.Set(reflect.Zero(v.Type())) // otherwise, ignore null for primitives/string } case 't', 'f': // true, false value := c == 't' switch v.Kind() { default: if fromQuoted { d.saveError(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type())) } else { d.saveError(&UnmarshalTypeError{"bool", v.Type()}) } case reflect.Bool: v.SetBool(value) case reflect.Interface: if v.NumMethod() == 0 { v.Set(reflect.ValueOf(value)) } else { d.saveError(&UnmarshalTypeError{"bool", v.Type()}) } } case '"': // string s, ok := unquoteBytes(item) if !ok { if fromQuoted { d.error(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type())) } else { d.error(errPhase) } } switch v.Kind() { default: d.saveError(&UnmarshalTypeError{"string", v.Type()}) case reflect.Slice: if v.Type() != byteSliceType { d.saveError(&UnmarshalTypeError{"string", v.Type()}) break } b := make([]byte, base64.StdEncoding.DecodedLen(len(s))) n, err := base64.StdEncoding.Decode(b, s) if err != nil { d.saveError(err) break } v.Set(reflect.ValueOf(b[0:n])) case reflect.String: v.SetString(string(s)) case reflect.Interface: if v.NumMethod() == 0 { v.Set(reflect.ValueOf(string(s))) } else { d.saveError(&UnmarshalTypeError{"string", v.Type()}) } } default: // number if c != '-' && (c < '0' || c > '9') { if fromQuoted { d.error(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type())) } else { d.error(errPhase) } } s := string(item) switch v.Kind() { default: if v.Kind() == reflect.String && v.Type() == numberType { v.SetString(s) break } if fromQuoted { d.error(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type())) } else { d.error(&UnmarshalTypeError{"number", v.Type()}) } case reflect.Interface: n, err := d.convertNumber(s) if err != nil { d.saveError(err) break } if v.NumMethod() != 0 { d.saveError(&UnmarshalTypeError{"number", v.Type()}) break } v.Set(reflect.ValueOf(n)) case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: n, err := strconv.ParseInt(s, 10, 64) if err != nil || v.OverflowInt(n) { d.saveError(&UnmarshalTypeError{"number " + s, v.Type()}) break } v.SetInt(n) case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: n, err := strconv.ParseUint(s, 10, 64) if err != nil || v.OverflowUint(n) { d.saveError(&UnmarshalTypeError{"number " + s, v.Type()}) break } v.SetUint(n) case reflect.Float32, reflect.Float64: n, err := strconv.ParseFloat(s, v.Type().Bits()) if err != nil || v.OverflowFloat(n) { d.saveError(&UnmarshalTypeError{"number " + s, v.Type()}) break } v.SetFloat(n) } } }
func loadInner(codec *structCodec, structValue reflect.Value, index int, name string, p Property, requireSlice bool) string { var v reflect.Value // Traverse a struct's struct-typed fields. for { fieldIndex, ok := codec.byName[name] if !ok { return "no such struct field" } v = structValue.Field(fieldIndex) st := codec.byIndex[fieldIndex] if st.substructCodec == nil { break } if v.Kind() == reflect.Slice { for v.Len() <= index { v.Set(reflect.Append(v, reflect.New(v.Type().Elem()).Elem())) } structValue = v.Index(index) requireSlice = false } else { structValue = v } // Strip the "I." from "I.X". name = name[len(st.name):] codec = st.substructCodec } doConversion := func(v reflect.Value) (string, bool) { a := v.Addr() if conv, ok := a.Interface().(PropertyConverter); ok { err := conv.FromProperty(p) if err != nil { return err.Error(), true } return "", true } return "", false } if ret, ok := doConversion(v); ok { return ret } var slice reflect.Value if v.Kind() == reflect.Slice && v.Type().Elem().Kind() != reflect.Uint8 { slice = v v = reflect.New(v.Type().Elem()).Elem() } else if requireSlice { return "multiple-valued property requires a slice field type" } if ret, ok := doConversion(v); ok { if ret != "" { return ret } } else { knd := v.Kind() project := PTNull overflow := (func(interface{}) bool)(nil) set := (func(interface{}))(nil) switch knd { case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: project = PTInt overflow = func(x interface{}) bool { return v.OverflowInt(x.(int64)) } set = func(x interface{}) { v.SetInt(x.(int64)) } case reflect.Uint8, reflect.Uint16, reflect.Uint32: project = PTInt overflow = func(x interface{}) bool { xi := x.(int64) return xi < 0 || v.OverflowUint(uint64(xi)) } set = func(x interface{}) { v.SetUint(uint64(x.(int64))) } case reflect.Bool: project = PTBool set = func(x interface{}) { v.SetBool(x.(bool)) } case reflect.String: project = PTString set = func(x interface{}) { v.SetString(x.(string)) } case reflect.Float32, reflect.Float64: project = PTFloat overflow = func(x interface{}) bool { return v.OverflowFloat(x.(float64)) } set = func(x interface{}) { v.SetFloat(x.(float64)) } case reflect.Ptr: project = PTKey set = func(x interface{}) { if k, ok := x.(*Key); ok { v.Set(reflect.ValueOf(k)) } } case reflect.Struct: switch v.Type() { case typeOfTime: project = PTTime set = func(x interface{}) { v.Set(reflect.ValueOf(x)) } case typeOfGeoPoint: project = PTGeoPoint set = func(x interface{}) { v.Set(reflect.ValueOf(x)) } default: panic(fmt.Errorf("helper: impossible: %s", typeMismatchReason(p.Value(), v))) } case reflect.Slice: project = PTBytes set = func(x interface{}) { v.SetBytes(reflect.ValueOf(x).Bytes()) } default: panic(fmt.Errorf("helper: impossible: %s", typeMismatchReason(p.Value(), v))) } pVal, err := p.Project(project) if err != nil { return typeMismatchReason(p.Value(), v) } if overflow != nil && overflow(pVal) { return fmt.Sprintf("value %v overflows struct field of type %v", pVal, v.Type()) } set(pVal) } if slice.IsValid() { slice.Set(reflect.Append(slice, v)) } return "" }
func (d *decoder) scalar(n *node, out reflect.Value) (good bool) { var tag string var resolved interface{} if n.tag == "" && !n.implicit { tag = yaml_STR_TAG resolved = n.value } else { tag, resolved = resolve(n.tag, n.value) if tag == yaml_BINARY_TAG { data, err := base64.StdEncoding.DecodeString(resolved.(string)) if err != nil { failf("!!binary value contains invalid base64 data") } resolved = string(data) } } if resolved == nil { if out.Kind() == reflect.Map && !out.CanAddr() { resetMap(out) } else { out.Set(reflect.Zero(out.Type())) } return true } if s, ok := resolved.(string); ok && out.CanAddr() { if u, ok := out.Addr().Interface().(encoding.TextUnmarshaler); ok { err := u.UnmarshalText([]byte(s)) if err != nil { fail(err) } return true } } switch out.Kind() { case reflect.String: if tag == yaml_BINARY_TAG { out.SetString(resolved.(string)) good = true } else if resolved != nil { out.SetString(n.value) good = true } case reflect.Interface: if resolved == nil { out.Set(reflect.Zero(out.Type())) } else { out.Set(reflect.ValueOf(resolved)) } good = true case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: switch resolved := resolved.(type) { case int: if !out.OverflowInt(int64(resolved)) { out.SetInt(int64(resolved)) good = true } case int64: if !out.OverflowInt(resolved) { out.SetInt(resolved) good = true } case uint64: if resolved <= math.MaxInt64 && !out.OverflowInt(int64(resolved)) { out.SetInt(int64(resolved)) good = true } case float64: if resolved <= math.MaxInt64 && !out.OverflowInt(int64(resolved)) { out.SetInt(int64(resolved)) good = true } case string: if out.Type() == durationType { d, err := time.ParseDuration(resolved) if err == nil { out.SetInt(int64(d)) good = true } } } case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: switch resolved := resolved.(type) { case int: if resolved >= 0 && !out.OverflowUint(uint64(resolved)) { out.SetUint(uint64(resolved)) good = true } case int64: if resolved >= 0 && !out.OverflowUint(uint64(resolved)) { out.SetUint(uint64(resolved)) good = true } case uint64: if !out.OverflowUint(uint64(resolved)) { out.SetUint(uint64(resolved)) good = true } case float64: if resolved <= math.MaxUint64 && !out.OverflowUint(uint64(resolved)) { out.SetUint(uint64(resolved)) good = true } } case reflect.Bool: switch resolved := resolved.(type) { case bool: out.SetBool(resolved) good = true } case reflect.Float32, reflect.Float64: switch resolved := resolved.(type) { case int: out.SetFloat(float64(resolved)) good = true case int64: out.SetFloat(float64(resolved)) good = true case uint64: out.SetFloat(float64(resolved)) good = true case float64: out.SetFloat(resolved) good = true } case reflect.Ptr: if out.Type().Elem() == reflect.TypeOf(resolved) { // TODO DOes this make sense? When is out a Ptr except when decoding a nil value? elem := reflect.New(out.Type().Elem()) elem.Elem().Set(reflect.ValueOf(resolved)) out.Set(elem) good = true } } if !good { d.terror(n, tag, out) } return good }
// literalStore decodes a literal stored in item into v. func (d *decodeState) literal(v reflect.Value, op int) { // Check for unmarshaler. wantptr := op == scanNull // null u, ut, pv := d.indirect(v, wantptr) if u != nil { d.off-- d.scan.undo(op) b := d.next() if err := u.UnmarshalUBJSON(b); err != nil { d.error(err) } return } if ut != nil { if op != scanString { d.saveError(&UnmarshalTypeError{"string", v.Type(), int64(d.off)}) return } s, err := d.scanString() if err != nil { glog.V(3).Infof("invalid string: %s", err) d.error(errPhase) } err = ut.UnmarshalText([]byte(s)) if err != nil { d.error(err) } return } v = pv switch op { default: d.saveError(&UnmarshalTypeError{scanToName[op], v.Type(), int64(d.off)}) case scanNull: switch v.Kind() { case reflect.Interface, reflect.Ptr, reflect.Map, reflect.Slice: v.Set(reflect.Zero(v.Type())) // otherwise, ignore null for primitives/string } case scanTrue, scanFalse: value := op == scanTrue switch v.Kind() { default: d.saveError(&UnmarshalTypeError{"bool", v.Type(), int64(d.off)}) case reflect.Bool: v.SetBool(value) case reflect.Interface: if v.NumMethod() == 0 { v.Set(reflect.ValueOf(value)) } else { d.saveError(&UnmarshalTypeError{"bool", v.Type(), int64(d.off)}) } } case scanString: s, err := d.scanString() if err != nil { glog.V(3).Infof("invalid string: %s", err) d.error(errPhase) } switch v.Kind() { default: d.saveError(&UnmarshalTypeError{"string", v.Type(), int64(d.off)}) case reflect.Slice: if v.Type().Elem().Kind() != reflect.Uint8 { d.saveError(&UnmarshalTypeError{"string", v.Type(), int64(d.off)}) break } b := []byte(s) v.Set(reflect.ValueOf(b)) case reflect.String: v.SetString(string(s)) case reflect.Interface: if v.NumMethod() == 0 { v.Set(reflect.ValueOf(string(s))) } else { d.saveError(&UnmarshalTypeError{"string", v.Type(), int64(d.off)}) } } case scanInt8, scanUint8, scanInt16, scanInt32, scanInt64: n, err := d.scanInt(op) if err != nil { d.error(err) break } switch v.Kind() { default: d.error(&UnmarshalTypeError{"number", v.Type(), int64(d.off)}) case reflect.Interface: if v.NumMethod() != 0 { d.saveError(&UnmarshalTypeError{"number", v.Type(), int64(d.off)}) break } v.Set(reflect.ValueOf(n)) case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: if v.OverflowInt(n) { d.saveError(&UnmarshalTypeError{"number", v.Type(), int64(d.off)}) break } v.SetInt(n) case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: if v.OverflowUint(uint64(n)) { d.saveError(&UnmarshalTypeError{"number ", v.Type(), int64(d.off)}) break } v.SetUint(uint64(n)) case reflect.Float32, reflect.Float64: if v.OverflowFloat(float64(n)) { d.saveError(&UnmarshalTypeError{"number ", v.Type(), int64(d.off)}) break } v.SetFloat(float64(n)) } case scanFloat32: b, err := d.scanPayload() if err != nil { d.error(err) return } var n float32 if err := binary.Read(bytes.NewBuffer(b), binary.BigEndian, &n); err != nil { d.error(err) return } switch v.Kind() { default: d.error(&UnmarshalTypeError{"number", v.Type(), int64(d.off)}) case reflect.Interface: if v.NumMethod() != 0 { d.saveError(&UnmarshalTypeError{"number", v.Type(), int64(d.off)}) break } v.Set(reflect.ValueOf(n)) case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: if v.OverflowInt(int64(n)) { d.saveError(&UnmarshalTypeError{"number", v.Type(), int64(d.off)}) break } v.SetInt(int64(n)) case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: if v.OverflowUint(uint64(n)) { d.saveError(&UnmarshalTypeError{"number ", v.Type(), int64(d.off)}) break } v.SetUint(uint64(n)) case reflect.Float32, reflect.Float64: if v.OverflowFloat(float64(n)) { d.saveError(&UnmarshalTypeError{"number ", v.Type(), int64(d.off)}) break } v.SetFloat(float64(n)) } case scanFloat64: b, err := d.scanPayload() if err != nil { d.error(err) return } var n float64 if err := binary.Read(bytes.NewBuffer(b), binary.BigEndian, &n); err != nil { d.error(err) return } switch v.Kind() { default: d.error(&UnmarshalTypeError{"number", v.Type(), int64(d.off)}) case reflect.Interface: if v.NumMethod() != 0 { d.saveError(&UnmarshalTypeError{"number", v.Type(), int64(d.off)}) break } v.Set(reflect.ValueOf(n)) case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: if v.OverflowInt(int64(n)) { d.saveError(&UnmarshalTypeError{"number", v.Type(), int64(d.off)}) break } v.SetInt(int64(n)) case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: if v.OverflowUint(uint64(n)) { d.saveError(&UnmarshalTypeError{"number ", v.Type(), int64(d.off)}) break } v.SetUint(uint64(n)) case reflect.Float32, reflect.Float64: if v.OverflowFloat(n) { d.saveError(&UnmarshalTypeError{"number ", v.Type(), int64(d.off)}) break } v.SetFloat(n) } } }
func (d *decoder) scalar(n *node, out reflect.Value) (good bool) { var tag string var resolved interface{} if n.tag == "" && !n.implicit { tag = "!!str" resolved = n.value } else { tag, resolved = resolve(n.tag, n.value) } if set := d.setter(tag, &out, &good); set != nil { defer set() } switch out.Kind() { case reflect.String: if resolved != nil { out.SetString(n.value) good = true } case reflect.Interface: if resolved == nil { out.Set(reflect.Zero(out.Type())) } else { out.Set(reflect.ValueOf(resolved)) } good = true case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: switch resolved := resolved.(type) { case int: if !out.OverflowInt(int64(resolved)) { out.SetInt(int64(resolved)) good = true } case int64: if !out.OverflowInt(resolved) { out.SetInt(resolved) good = true } case float64: if resolved < 1<<63-1 && !out.OverflowInt(int64(resolved)) { out.SetInt(int64(resolved)) good = true } case string: if out.Type() == durationType { d, err := time.ParseDuration(resolved) if err == nil { out.SetInt(int64(d)) good = true } } } case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: switch resolved := resolved.(type) { case int: if resolved >= 0 { out.SetUint(uint64(resolved)) good = true } case int64: if resolved >= 0 { out.SetUint(uint64(resolved)) good = true } case float64: if resolved < 1<<64-1 && !out.OverflowUint(uint64(resolved)) { out.SetUint(uint64(resolved)) good = true } } case reflect.Bool: switch resolved := resolved.(type) { case bool: out.SetBool(resolved) good = true } case reflect.Float32, reflect.Float64: switch resolved := resolved.(type) { case int: out.SetFloat(float64(resolved)) good = true case int64: out.SetFloat(float64(resolved)) good = true case float64: out.SetFloat(resolved) good = true } case reflect.Ptr: switch resolved.(type) { case nil: out.Set(reflect.Zero(out.Type())) good = true default: if out.Type().Elem() == reflect.TypeOf(resolved) { elem := reflect.New(out.Type().Elem()) elem.Elem().Set(reflect.ValueOf(resolved)) out.Set(elem) good = true } } } return good }
// literalStore decodes a literal stored in item into v. // // fromQuoted indicates whether this literal came from unwrapping a // string from the ",string" struct tag option. this is used only to // produce more helpful error messages. func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool) { // Check for unmarshaler. if len(item) == 0 { //Empty string given d.saveError(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type())) return } isNull := item[0] == 'n' // null u, ut, pv := d.indirect(v, isNull) if u != nil { err := u.UnmarshalJSON(item) if err != nil { d.error(err) } return } if ut != nil { if item[0] != '"' { if fromQuoted { d.saveError(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type())) } else { var val string switch item[0] { case 'n': val = "null" case 't', 'f': val = "bool" default: val = "number" } d.saveError(&UnmarshalTypeError{Value: val, Type: v.Type(), Offset: int64(d.off)}) } return } s, ok := unquoteBytes(item) if !ok { if fromQuoted { d.error(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type())) } else { d.error(errPhase) } } err := ut.UnmarshalText(s) if err != nil { d.error(err) } return } v = pv switch c := item[0]; c { case 'n': // null // The main parser checks that only true and false can reach here, // but if this was a quoted string input, it could be anything. if fromQuoted && string(item) != "null" { d.saveError(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type())) break } switch v.Kind() { case reflect.Interface, reflect.Ptr, reflect.Map, reflect.Slice: v.Set(reflect.Zero(v.Type())) // otherwise, ignore null for primitives/string } case 't', 'f': // true, false value := item[0] == 't' // The main parser checks that only true and false can reach here, // but if this was a quoted string input, it could be anything. if fromQuoted && string(item) != "true" && string(item) != "false" { d.saveError(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type())) break } switch v.Kind() { default: if fromQuoted { d.saveError(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type())) } else { d.saveError(&UnmarshalTypeError{Value: "bool", Type: v.Type(), Offset: int64(d.off)}) } case reflect.Bool: v.SetBool(value) case reflect.Interface: if v.NumMethod() == 0 { v.Set(reflect.ValueOf(value)) } else { d.saveError(&UnmarshalTypeError{Value: "bool", Type: v.Type(), Offset: int64(d.off)}) } } case '"': // string s, ok := unquoteBytes(item) if !ok { if fromQuoted { d.error(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type())) } else { d.error(errPhase) } } switch v.Kind() { default: d.saveError(&UnmarshalTypeError{Value: "string", Type: v.Type(), Offset: int64(d.off)}) case reflect.Slice: if v.Type().Elem().Kind() != reflect.Uint8 { d.saveError(&UnmarshalTypeError{Value: "string", Type: v.Type(), Offset: int64(d.off)}) break } b := make([]byte, base64.StdEncoding.DecodedLen(len(s))) n, err := base64.StdEncoding.Decode(b, s) if err != nil { d.saveError(err) break } v.SetBytes(b[:n]) case reflect.String: v.SetString(string(s)) case reflect.Interface: if v.NumMethod() == 0 { v.Set(reflect.ValueOf(string(s))) } else { d.saveError(&UnmarshalTypeError{Value: "string", Type: v.Type(), Offset: int64(d.off)}) } } default: // number if c != '-' && (c < '0' || c > '9') { if fromQuoted { d.error(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type())) } else { d.error(errPhase) } } s := string(item) switch v.Kind() { default: if v.Kind() == reflect.String && v.Type() == numberType { v.SetString(s) if !isValidNumber(s) { d.error(fmt.Errorf("json: invalid number literal, trying to unmarshal %q into Number", item)) } break } if fromQuoted { d.error(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type())) } else { d.error(&UnmarshalTypeError{Value: "number", Type: v.Type(), Offset: int64(d.off)}) } case reflect.Interface: n, err := d.convertNumber(s) if err != nil { d.saveError(err) break } if v.NumMethod() != 0 { d.saveError(&UnmarshalTypeError{Value: "number", Type: v.Type(), Offset: int64(d.off)}) break } v.Set(reflect.ValueOf(n)) case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: n, err := strconv.ParseInt(s, 10, 64) if err != nil || v.OverflowInt(n) { d.saveError(&UnmarshalTypeError{Value: "number " + s, Type: v.Type(), Offset: int64(d.off)}) break } v.SetInt(n) case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: n, err := strconv.ParseUint(s, 10, 64) if err != nil || v.OverflowUint(n) { d.saveError(&UnmarshalTypeError{Value: "number " + s, Type: v.Type(), Offset: int64(d.off)}) break } v.SetUint(n) case reflect.Float32, reflect.Float64: n, err := strconv.ParseFloat(s, v.Type().Bits()) if err != nil || v.OverflowFloat(n) { d.saveError(&UnmarshalTypeError{Value: "number " + s, Type: v.Type(), Offset: int64(d.off)}) break } v.SetFloat(n) } } }
// assignField is the main workhorse for the NewCmd function which handles // assigning the provided source value to the destination field. It supports // direct type assignments, indirection, conversion of numeric types, and // unmarshaling of strings into arrays, slices, structs, and maps via // json.Unmarshal. func assignField(paramNum int, fieldName string, dest reflect.Value, src reflect.Value) error { // Just error now when the types have no chance of being compatible. destBaseType, destIndirects := baseType(dest.Type()) srcBaseType, srcIndirects := baseType(src.Type()) if !typesMaybeCompatible(destBaseType, srcBaseType) { str := fmt.Sprintf("parameter #%d '%s' must be type %v (got "+ "%v)", paramNum, fieldName, destBaseType, srcBaseType) return makeError(ErrInvalidType, str) } // Check if it's possible to simply set the dest to the provided source. // This is the case when the base types are the same or they are both // pointers that can be indirected to be the same without needing to // create pointers for the destination field. if destBaseType == srcBaseType && srcIndirects >= destIndirects { for i := 0; i < srcIndirects-destIndirects; i++ { src = src.Elem() } dest.Set(src) return nil } // When the destination has more indirects than the source, the extra // pointers have to be created. Only create enough pointers to reach // the same level of indirection as the source so the dest can simply be // set to the provided source when the types are the same. destIndirectsRemaining := destIndirects if destIndirects > srcIndirects { indirectDiff := destIndirects - srcIndirects for i := 0; i < indirectDiff; i++ { dest.Set(reflect.New(dest.Type().Elem())) dest = dest.Elem() destIndirectsRemaining-- } } if destBaseType == srcBaseType { dest.Set(src) return nil } // Make any remaining pointers needed to get to the base dest type since // the above direct assign was not possible and conversions are done // against the base types. for i := 0; i < destIndirectsRemaining; i++ { dest.Set(reflect.New(dest.Type().Elem())) dest = dest.Elem() } // Indirect through to the base source value. for src.Kind() == reflect.Ptr { src = src.Elem() } // Perform supported type conversions. switch src.Kind() { // Source value is a signed integer of various magnitude. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: switch dest.Kind() { // Destination is a signed integer of various magnitude. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: srcInt := src.Int() if dest.OverflowInt(srcInt) { str := fmt.Sprintf("parameter #%d '%s' "+ "overflows destination type %v", paramNum, fieldName, destBaseType) return makeError(ErrInvalidType, str) } dest.SetInt(srcInt) // Destination is an unsigned integer of various magnitude. case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: srcInt := src.Int() if srcInt < 0 || dest.OverflowUint(uint64(srcInt)) { str := fmt.Sprintf("parameter #%d '%s' "+ "overflows destination type %v", paramNum, fieldName, destBaseType) return makeError(ErrInvalidType, str) } dest.SetUint(uint64(srcInt)) default: str := fmt.Sprintf("parameter #%d '%s' must be type "+ "%v (got %v)", paramNum, fieldName, destBaseType, srcBaseType) return makeError(ErrInvalidType, str) } // Source value is an unsigned integer of various magnitude. case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: switch dest.Kind() { // Destination is a signed integer of various magnitude. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: srcUint := src.Uint() if srcUint > uint64(1<<63)-1 { str := fmt.Sprintf("parameter #%d '%s' "+ "overflows destination type %v", paramNum, fieldName, destBaseType) return makeError(ErrInvalidType, str) } if dest.OverflowInt(int64(srcUint)) { str := fmt.Sprintf("parameter #%d '%s' "+ "overflows destination type %v", paramNum, fieldName, destBaseType) return makeError(ErrInvalidType, str) } dest.SetInt(int64(srcUint)) // Destination is an unsigned integer of various magnitude. case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: srcUint := src.Uint() if dest.OverflowUint(srcUint) { str := fmt.Sprintf("parameter #%d '%s' "+ "overflows destination type %v", paramNum, fieldName, destBaseType) return makeError(ErrInvalidType, str) } dest.SetUint(srcUint) default: str := fmt.Sprintf("parameter #%d '%s' must be type "+ "%v (got %v)", paramNum, fieldName, destBaseType, srcBaseType) return makeError(ErrInvalidType, str) } // Source value is a float. case reflect.Float32, reflect.Float64: destKind := dest.Kind() if destKind != reflect.Float32 && destKind != reflect.Float64 { str := fmt.Sprintf("parameter #%d '%s' must be type "+ "%v (got %v)", paramNum, fieldName, destBaseType, srcBaseType) return makeError(ErrInvalidType, str) } srcFloat := src.Float() if dest.OverflowFloat(srcFloat) { str := fmt.Sprintf("parameter #%d '%s' overflows "+ "destination type %v", paramNum, fieldName, destBaseType) return makeError(ErrInvalidType, str) } dest.SetFloat(srcFloat) // Source value is a string. case reflect.String: switch dest.Kind() { // String -> bool case reflect.Bool: b, err := strconv.ParseBool(src.String()) if err != nil { str := fmt.Sprintf("parameter #%d '%s' must "+ "parse to a %v", paramNum, fieldName, destBaseType) return makeError(ErrInvalidType, str) } dest.SetBool(b) // String -> signed integer of varying size. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: srcInt, err := strconv.ParseInt(src.String(), 0, 0) if err != nil { str := fmt.Sprintf("parameter #%d '%s' must "+ "parse to a %v", paramNum, fieldName, destBaseType) return makeError(ErrInvalidType, str) } if dest.OverflowInt(srcInt) { str := fmt.Sprintf("parameter #%d '%s' "+ "overflows destination type %v", paramNum, fieldName, destBaseType) return makeError(ErrInvalidType, str) } dest.SetInt(srcInt) // String -> unsigned integer of varying size. case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: srcUint, err := strconv.ParseUint(src.String(), 0, 0) if err != nil { str := fmt.Sprintf("parameter #%d '%s' must "+ "parse to a %v", paramNum, fieldName, destBaseType) return makeError(ErrInvalidType, str) } if dest.OverflowUint(srcUint) { str := fmt.Sprintf("parameter #%d '%s' "+ "overflows destination type %v", paramNum, fieldName, destBaseType) return makeError(ErrInvalidType, str) } dest.SetUint(srcUint) // String -> float of varying size. case reflect.Float32, reflect.Float64: srcFloat, err := strconv.ParseFloat(src.String(), 0) if err != nil { str := fmt.Sprintf("parameter #%d '%s' must "+ "parse to a %v", paramNum, fieldName, destBaseType) return makeError(ErrInvalidType, str) } if dest.OverflowFloat(srcFloat) { str := fmt.Sprintf("parameter #%d '%s' "+ "overflows destination type %v", paramNum, fieldName, destBaseType) return makeError(ErrInvalidType, str) } dest.SetFloat(srcFloat) // String -> string (typecast). case reflect.String: dest.SetString(src.String()) // String -> arrays, slices, structs, and maps via // json.Unmarshal. case reflect.Array, reflect.Slice, reflect.Struct, reflect.Map: concreteVal := dest.Addr().Interface() err := json.Unmarshal([]byte(src.String()), &concreteVal) if err != nil { str := fmt.Sprintf("parameter #%d '%s' must "+ "be valid JSON which unsmarshals to a %v", paramNum, fieldName, destBaseType) return makeError(ErrInvalidType, str) } dest.Set(reflect.ValueOf(concreteVal).Elem()) } } return nil }
func (p *untypedParamBinder) setFieldValue(target reflect.Value, defaultValue interface{}, data string) error { tpe := p.parameter.Type if p.parameter.Format != "" { tpe = p.parameter.Format } if data == "" && p.parameter.Required && p.parameter.Default == nil { return errors.Required(p.Name, p.parameter.In) } ok, err := p.tryUnmarshaler(target, defaultValue, data) if err != nil { return errors.InvalidType(p.Name, p.parameter.In, tpe, data) } if ok { return nil } defVal := reflect.Zero(target.Type()) if defaultValue != nil { defVal = reflect.ValueOf(defaultValue) } if tpe == "byte" { if data == "" { target.SetBytes(defVal.Bytes()) return nil } b, err := base64.StdEncoding.DecodeString(data) if err != nil { b, err = base64.URLEncoding.DecodeString(data) if err != nil { return errors.InvalidType(p.Name, p.parameter.In, tpe, data) } } target.SetBytes(b) return nil } switch target.Kind() { case reflect.Bool: if data == "" { target.SetBool(defVal.Bool()) return nil } b, err := swag.ConvertBool(data) if err != nil { return err } target.SetBool(b) case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: if data == "" { target.SetInt(defVal.Int()) return nil } i, err := strconv.ParseInt(data, 10, 64) if err != nil { return errors.InvalidType(p.Name, p.parameter.In, tpe, data) } if target.OverflowInt(i) { return errors.InvalidType(p.Name, p.parameter.In, tpe, data) } target.SetInt(i) case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: if data == "" { target.SetUint(defVal.Uint()) return nil } u, err := strconv.ParseUint(data, 10, 64) if err != nil { return errors.InvalidType(p.Name, p.parameter.In, tpe, data) } if target.OverflowUint(u) { return errors.InvalidType(p.Name, p.parameter.In, tpe, data) } target.SetUint(u) case reflect.Float32, reflect.Float64: if data == "" { target.SetFloat(defVal.Float()) return nil } f, err := strconv.ParseFloat(data, 64) if err != nil { return errors.InvalidType(p.Name, p.parameter.In, tpe, data) } if target.OverflowFloat(f) { return errors.InvalidType(p.Name, p.parameter.In, tpe, data) } target.SetFloat(f) case reflect.String: value := data if value == "" { value = defVal.String() } // validate string target.SetString(value) case reflect.Ptr: if data == "" && defVal.Kind() == reflect.Ptr { target.Set(defVal) return nil } newVal := reflect.New(target.Type().Elem()) if err := p.setFieldValue(reflect.Indirect(newVal), defVal, data); err != nil { return err } target.Set(newVal) default: return errors.InvalidType(p.Name, p.parameter.In, tpe, data) } return nil }
func resolve_uint(val string, v reflect.Value, useNumber bool) (string, error) { original := val val = strings.Replace(val, "_", "", -1) var value uint64 isNumberValue := v.Type() == numberType if val[0] == '-' { return "", errors.New("Unsigned int with negative value: " + original) } if val[0] == '+' { val = val[1:] } base := 10 if val == "0" { if isNumberValue { v.SetString("0") } else { v.Set(reflect.Zero(v.Type())) } return "!!int", nil } if strings.HasPrefix(val, "0b") { base = 2 val = val[2:] } else if strings.HasPrefix(val, "0x") { base = 16 val = val[2:] } else if val[0] == '0' { base = 8 val = val[1:] } else if strings.Contains(val, ":") { digits := strings.Split(val, ":") bes := uint64(1) for j := len(digits) - 1; j >= 0; j-- { n, err := strconv.ParseUint(digits[j], 10, 64) n *= bes if err != nil { return "", errors.New("Unsigned Integer: " + original) } value += n bes *= 60 } if isNumberValue { v.SetString(strconv.FormatUint(value, 10)) } else { if v.OverflowUint(value) { return "", errors.New("Unsigned Integer: " + original) } v.SetUint(value) } return "!!int", nil } value, err := strconv.ParseUint(val, base, 64) if err != nil { return "", errors.New("Unsigned Integer: " + val) } if isNumberValue { v.SetString(strconv.FormatUint(value, 10)) } else { if v.OverflowUint(value) { return "", errors.New("Unsigned Integer: " + val) } v.SetUint(value) } return "!!int", nil }
// decodeLiteral decodes the source value into the destination value. This function // is used to decode literal values. func decodeLiteral(s *decodeState, dv reflect.Value, sv reflect.Value) { dv = indirect(dv) // Special case for if sv is nil: switch sv.Kind() { case reflect.Invalid: dv.Set(reflect.Zero(dv.Type())) return } // Attempt to convert the value from the source type to the destination type switch value := sv.Interface().(type) { case nil: switch dv.Kind() { case reflect.Interface, reflect.Ptr, reflect.Map, reflect.Slice: dv.Set(reflect.Zero(dv.Type())) } case bool: switch dv.Kind() { default: s.saveError(&DecodeTypeError{"bool", dv.Type()}) return case reflect.Bool: dv.SetBool(value) case reflect.String: dv.SetString(strconv.FormatBool(value)) case reflect.Interface: if dv.NumMethod() == 0 { dv.Set(reflect.ValueOf(value)) } else { s.saveError(&DecodeTypeError{"bool", dv.Type()}) return } } case string: switch dv.Kind() { default: s.saveError(&DecodeTypeError{"string", dv.Type()}) return case reflect.String: dv.SetString(value) case reflect.Bool: b, err := strconv.ParseBool(value) if err != nil { s.saveError(&DecodeTypeError{"string", dv.Type()}) return } dv.SetBool(b) case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: n, err := strconv.ParseInt(value, 10, 64) if err != nil || dv.OverflowInt(n) { s.saveError(&DecodeTypeError{"string", dv.Type()}) return } dv.SetInt(n) case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: n, err := strconv.ParseUint(value, 10, 64) if err != nil || dv.OverflowUint(n) { s.saveError(&DecodeTypeError{"string", dv.Type()}) return } dv.SetUint(n) case reflect.Float32, reflect.Float64: n, err := strconv.ParseFloat(value, 64) if err != nil || dv.OverflowFloat(n) { s.saveError(&DecodeTypeError{"string", dv.Type()}) return } dv.SetFloat(n) case reflect.Interface: if dv.NumMethod() == 0 { dv.Set(reflect.ValueOf(string(value))) } else { s.saveError(&DecodeTypeError{"string", dv.Type()}) return } } case int, int8, int16, int32, int64: switch dv.Kind() { default: s.saveError(&DecodeTypeError{"int", dv.Type()}) return case reflect.Interface: if dv.NumMethod() != 0 { s.saveError(&DecodeTypeError{"int", dv.Type()}) return } dv.Set(reflect.ValueOf(value)) case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: dv.SetInt(int64(reflect.ValueOf(value).Int())) case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: dv.SetUint(uint64(reflect.ValueOf(value).Int())) case reflect.Float32, reflect.Float64: dv.SetFloat(float64(reflect.ValueOf(value).Int())) case reflect.String: dv.SetString(strconv.FormatInt(int64(reflect.ValueOf(value).Int()), 10)) } case uint, uint8, uint16, uint32, uint64: switch dv.Kind() { default: s.saveError(&DecodeTypeError{"uint", dv.Type()}) return case reflect.Interface: if dv.NumMethod() != 0 { s.saveError(&DecodeTypeError{"uint", dv.Type()}) return } dv.Set(reflect.ValueOf(value)) case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: dv.SetInt(int64(reflect.ValueOf(value).Uint())) case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: dv.SetUint(uint64(reflect.ValueOf(value).Uint())) case reflect.Float32, reflect.Float64: dv.SetFloat(float64(reflect.ValueOf(value).Uint())) case reflect.String: dv.SetString(strconv.FormatUint(uint64(reflect.ValueOf(value).Uint()), 10)) } case float32, float64: switch dv.Kind() { default: s.saveError(&DecodeTypeError{"float", dv.Type()}) return case reflect.Interface: if dv.NumMethod() != 0 { s.saveError(&DecodeTypeError{"float", dv.Type()}) return } dv.Set(reflect.ValueOf(value)) case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: dv.SetInt(int64(reflect.ValueOf(value).Float())) case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: dv.SetUint(uint64(reflect.ValueOf(value).Float())) case reflect.Float32, reflect.Float64: dv.SetFloat(float64(reflect.ValueOf(value).Float())) case reflect.String: dv.SetString(strconv.FormatFloat(float64(reflect.ValueOf(value).Float()), 'g', -1, 64)) } default: s.saveError(&DecodeTypeError{sv.Type().String(), dv.Type()}) return } return }
func (state *unmarshalState) unmarshalValue(cfObj cfTypeRef, v reflect.Value) error { vType := v.Type() var unmarshaler Unmarshaler if u, ok := v.Interface().(Unmarshaler); ok { unmarshaler = u } else if vType.Kind() != reflect.Ptr && vType.Name() != "" && v.CanAddr() { // matching the encoding/json behavior here // If v is a named type and is addressable, check its address for Unmarshaler. vA := v.Addr() if u, ok := vA.Interface().(Unmarshaler); ok { unmarshaler = u } } if unmarshaler != nil { // flip over to the dumb conversion routine so we have something to give UnmarshalPlist() plist, err := convertCFTypeToInterface(cfObj) if err != nil { return err } if vType.Kind() == reflect.Ptr && v.IsNil() { v.Set(reflect.New(vType.Elem())) unmarshaler = v.Interface().(Unmarshaler) } return unmarshaler.UnmarshalPlist(plist) } if vType.Kind() == reflect.Ptr { if v.IsNil() { v.Set(reflect.New(vType.Elem())) } return state.unmarshalValue(cfObj, v.Elem()) } typeID := C.CFGetTypeID(C.CFTypeRef(cfObj)) vSetter := v // receiver of any Set* calls vAddr := v.Addr() // used for re-setting v for maps/slices if vType.Kind() == reflect.Interface { if v.IsNil() { // pick an appropriate type based on the cfobj var typ reflect.Type if typeID == cfNumberTypeID { typ = cfNumberTypeToType(C.CFNumberGetType(C.CFNumberRef(cfObj))) } else { var ok bool typ, ok = cfTypeMap[typeID] if !ok { return &UnknownCFTypeError{typeID} } } if !typ.AssignableTo(vType) { // v must be some interface that our object doesn't conform to state.recordError(&UnmarshalTypeError{cfTypeNames[typeID], vType}) return nil } vSetter.Set(reflect.Zero(typ)) } vAddr = v v = v.Elem() vType = v.Type() } switch typeID { case cfArrayTypeID: if vType.Kind() != reflect.Slice && vType.Kind() != reflect.Array { state.recordError(&UnmarshalTypeError{cfTypeNames[typeID], vType}) return nil } return convertCFArrayToSliceHelper(C.CFArrayRef(cfObj), func(elem cfTypeRef, idx, count int) (bool, error) { if idx == 0 && vType.Kind() == reflect.Slice { vSetter.Set(reflect.MakeSlice(vType, count, count)) v = vAddr.Elem() } else if vType.Kind() == reflect.Array && idx >= v.Len() { return false, nil } if err := state.unmarshalValue(elem, v.Index(idx)); err != nil { return false, err } return true, nil }) case cfBooleanTypeID: if vType.Kind() != reflect.Bool { state.recordError(&UnmarshalTypeError{cfTypeNames[typeID], vType}) return nil } vSetter.Set(reflect.ValueOf(C.CFBooleanGetValue(C.CFBooleanRef(cfObj)) != C.false)) return nil case cfDataTypeID: if !byteSliceType.AssignableTo(vType) { state.recordError(&UnmarshalTypeError{cfTypeNames[typeID], vType}) return nil } vSetter.Set(reflect.ValueOf(convertCFDataToBytes(C.CFDataRef(cfObj)))) return nil case cfDateTypeID: if !timeType.AssignableTo(vType) { state.recordError(&UnmarshalTypeError{cfTypeNames[typeID], vType}) return nil } vSetter.Set(reflect.ValueOf(convertCFDateToTime(C.CFDateRef(cfObj)))) return nil case cfDictionaryTypeID: if vType.Kind() == reflect.Map { // it's a map. Check its key type first if !stringType.AssignableTo(vType.Key()) { state.recordError(&UnmarshalTypeError{cfTypeNames[cfStringTypeID], vType.Key()}) return nil } if v.IsNil() { vSetter.Set(reflect.MakeMap(vType)) v = vAddr.Elem() } return convertCFDictionaryToMapHelper(C.CFDictionaryRef(cfObj), func(key string, value cfTypeRef, count int) error { keyVal := reflect.ValueOf(key) val := reflect.New(vType.Elem()) if err := state.unmarshalValue(value, val); err != nil { return err } v.SetMapIndex(keyVal, val.Elem()) return nil }) } else if vType.Kind() == reflect.Struct { return convertCFDictionaryToMapHelper(C.CFDictionaryRef(cfObj), func(key string, value cfTypeRef, count int) error { // we need to iterate the fields because the tag might rename the key var f reflect.StructField var ok bool for i := 0; i < vType.NumField(); i++ { sf := vType.Field(i) tag := sf.Tag.Get("plist") if tag == "-" { // Pretend this field doesn't exist continue } if sf.Anonymous { // Match encoding/json's behavior here and pretend it doesn't exist continue } name, _ := parseTag(tag) if name == key { f = sf ok = true // This is unambiguously the right match break } if sf.Name == key { f = sf ok = true } // encoding/json does a case-insensitive match. Lets do that too if !ok && strings.EqualFold(sf.Name, key) { f = sf ok = true } } if ok { if f.PkgPath != "" { // this is an unexported field return &UnmarshalFieldError{key, vType, f} } vElem := v.FieldByIndex(f.Index) if err := state.unmarshalValue(value, vElem); err != nil { return err } } return nil }) } state.recordError(&UnmarshalTypeError{cfTypeNames[typeID], vType}) return nil case cfNumberTypeID: switch vType.Kind() { case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: i := convertCFNumberToInt64(C.CFNumberRef(cfObj)) if v.OverflowInt(i) { state.recordError(&UnmarshalTypeError{cfTypeNames[typeID] + " " + strconv.FormatInt(i, 10), vType}) return nil } if vSetter.Kind() == reflect.Interface { vSetter.Set(reflect.ValueOf(i)) } else { vSetter.SetInt(i) } return nil case reflect.Uint, reflect.Uintptr, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: u := uint64(convertCFNumberToUInt32(C.CFNumberRef(cfObj))) if v.OverflowUint(u) { state.recordError(&UnmarshalTypeError{cfTypeNames[typeID] + " " + strconv.FormatUint(u, 10), vType}) return nil } if vSetter.Kind() == reflect.Interface { vSetter.Set(reflect.ValueOf(u)) } else { vSetter.SetUint(u) } return nil case reflect.Float32, reflect.Float64: f := convertCFNumberToFloat64(C.CFNumberRef(cfObj)) if v.OverflowFloat(f) { state.recordError(&UnmarshalTypeError{cfTypeNames[typeID] + " " + strconv.FormatFloat(f, 'f', -1, 64), vType}) return nil } if vSetter.Kind() == reflect.Interface { vSetter.Set(reflect.ValueOf(f)) } else { vSetter.SetFloat(f) } return nil } state.recordError(&UnmarshalTypeError{cfTypeNames[typeID], vType}) return nil case cfStringTypeID: if vType.Kind() != reflect.String { state.recordError(&UnmarshalTypeError{cfTypeNames[typeID], vType}) return nil } vSetter.Set(reflect.ValueOf(convertCFStringToString(C.CFStringRef(cfObj)))) return nil } return &UnknownCFTypeError{typeID} }
// literalStore decodes a literal stored in item into v. func (d *decodeState) literalStore(item []byte, v reflect.Value) { // Check for unmarshaler. wantptr := item[0] == 'n' // null unmarshaler, pv := d.indirect(v, wantptr) if unmarshaler != nil { err := unmarshaler.UnmarshalJSON(item) if err != nil { d.error(err) } return } v = pv switch c := item[0]; c { case 'n': // null switch v.Kind() { default: d.saveError(&UnmarshalTypeError{"null", v.Type()}) case reflect.Interface, reflect.Ptr, reflect.Map: v.Set(reflect.Zero(v.Type())) } case 't', 'f': // true, false value := c == 't' switch v.Kind() { default: d.saveError(&UnmarshalTypeError{"bool", v.Type()}) case reflect.Bool: v.SetBool(value) case reflect.Interface: v.Set(reflect.ValueOf(value)) } case '"': // string s, ok := unquoteBytes(item) if !ok { d.error(errPhase) } switch v.Kind() { default: d.saveError(&UnmarshalTypeError{"string", v.Type()}) case reflect.Slice: if v.Type() != byteSliceType { d.saveError(&UnmarshalTypeError{"string", v.Type()}) break } b := make([]byte, base64.StdEncoding.DecodedLen(len(s))) n, err := base64.StdEncoding.Decode(b, s) if err != nil { d.saveError(err) break } v.Set(reflect.ValueOf(b[0:n])) case reflect.String: v.SetString(string(s)) case reflect.Interface: v.Set(reflect.ValueOf(string(s))) } default: // number if c != '-' && (c < '0' || c > '9') { d.error(errPhase) } s := string(item) switch v.Kind() { default: d.error(&UnmarshalTypeError{"number", v.Type()}) case reflect.Interface: n, err := strconv.Atof64(s) if err != nil { d.saveError(&UnmarshalTypeError{"number " + s, v.Type()}) break } v.Set(reflect.ValueOf(n)) case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: n, err := strconv.Atoi64(s) if err != nil || v.OverflowInt(n) { d.saveError(&UnmarshalTypeError{"number " + s, v.Type()}) break } v.SetInt(n) case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: n, err := strconv.Atoui64(s) if err != nil || v.OverflowUint(n) { d.saveError(&UnmarshalTypeError{"number " + s, v.Type()}) break } v.SetUint(n) case reflect.Float32, reflect.Float64: n, err := strconv.AtofN(s, v.Type().Bits()) if err != nil || v.OverflowFloat(n) { d.saveError(&UnmarshalTypeError{"number " + s, v.Type()}) break } v.SetFloat(n) } } }