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 setFloat(v reflect.Value, x interface{}) error { xx := x.(float64) if v.OverflowFloat(xx) { return fmt.Errorf("bigquery: value %v overflows struct field of type %v", xx, v.Type()) } v.SetFloat(xx) return nil }
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 resolve_float(val string, v reflect.Value, useNumber bool) (string, error) { val = strings.Replace(val, "_", "", -1) var value float64 isNumberValue := v.Type() == numberType typeBits := 64 if !isNumberValue { typeBits = v.Type().Bits() } sign := 1 if val[0] == '-' { sign = -1 val = val[1:] } else if val[0] == '+' { val = val[1:] } valLower := strings.ToLower(val) if valLower == ".inf" { value = math.Inf(sign) } else if valLower == ".nan" { value = math.NaN() } else if strings.Contains(val, ":") { digits := strings.Split(val, ":") bes := float64(1) for j := len(digits) - 1; j >= 0; j-- { n, err := strconv.ParseFloat(digits[j], typeBits) n *= bes if err != nil { return "", errors.New("Float: " + val) } value += n bes *= 60 } value *= float64(sign) } else { var err error value, err = strconv.ParseFloat(val, typeBits) value *= float64(sign) if err != nil { return "", errors.New("Float: " + val) } } if isNumberValue { v.SetString(strconv.FormatFloat(value, 'g', -1, typeBits)) } else { if v.OverflowFloat(value) { return "", errors.New("Float: " + val) } v.SetFloat(value) } return "!!float", nil }
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 decodeFloat(rval reflect.Value, arg string) error { v, err := strconv.ParseFloat(arg, 64) if err != nil { return err } if rval.OverflowFloat(v) { return fmt.Errorf("value %f 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 unmarshalFloat(f float64, v reflect.Value) { switch v.Kind() { case reflect.Float32, reflect.Float64: if v.OverflowFloat(f) { panic(&UnmarshalOverflowError{"float " + strconv.FormatFloat(f, 'g', -1, 64), v.Type()}) } v.SetFloat(f) case reflect.Interface: if v.NumMethod() == 0 { v.Set(reflect.ValueOf(f)) return } fallthrough default: panic(&UnmarshalTypeError{"float " + strconv.FormatFloat(f, 'g', -1, 64), v.Type()}) } }
func resolve_float(val string, v reflect.Value, useNumber bool, event yaml_event_t) (string, error) { val = strings.Replace(val, "_", "", -1) var value float64 isNumberValue := v.Type() == numberType typeBits := 64 if !isNumberValue { typeBits = v.Type().Bits() } sign := 1 if val[0] == '-' { sign = -1 val = val[1:] } else if val[0] == '+' { val = val[1:] } valLower := strings.ToLower(val) if valLower == ".inf" { value = math.Inf(sign) } else if valLower == ".nan" { value = math.NaN() } else { var err error value, err = strconv.ParseFloat(val, typeBits) value *= float64(sign) if err != nil { return "", fmt.Errorf("Invalid float: '%s' at %s", val, event.start_mark) } } if isNumberValue { v.SetString(strconv.FormatFloat(value, 'g', -1, typeBits)) } else { if v.OverflowFloat(value) { return "", fmt.Errorf("Invalid float: '%s' at %s", val, event.start_mark) } v.SetFloat(value) } return yaml_FLOAT_TAG, nil }
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) } }
func setFloat(fv reflect.Value, v *ast.Float) error { f, err := v.Float() if err != nil { return err } switch fv.Kind() { case reflect.Float32, reflect.Float64: if fv.OverflowFloat(f) { return &errorOutOfRange{fv.Kind(), f} } fv.SetFloat(f) case reflect.Interface: fv.Set(reflect.ValueOf(f)) default: return fmt.Errorf("`%v' is not float32 or float64", fv.Type()) } return nil }
func decodeFloat(d *decodeState, kind int, v reflect.Value) { var f float64 switch kind { default: d.saveErrorAndSkip(kind, v.Type()) return case kindFloat: f = d.scanFloat() case kindInt64: f = float64(d.scanInt64()) case kindInt32: f = float64(d.scanInt32()) } if v.OverflowFloat(f) { d.saveError(&DecodeConvertError{kind, v.Type()}) return } v.SetFloat(f) }
// 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 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 resolve_float(val string, v reflect.Value) error { val = strings.Replace(val, "_", "", -1) var value float64 sign := 1 if val[0] == '-' { sign = -1 val = val[1:] } else if val[0] == '+' { val = val[1:] } valLower := strings.ToLower(val) if valLower == ".inf" { value = math.Inf(sign) } else if valLower == ".nan" { value = math.NaN() } else if strings.Contains(val, ":") { digits := strings.Split(val, ":") bes := float64(1) for j := len(digits) - 1; j >= 0; j-- { n, err := strconv.ParseFloat(digits[j], v.Type().Bits()) n *= bes if err != nil || v.OverflowFloat(n) { return errors.New("Float: " + val) } value += n bes *= 60 } value *= float64(sign) } else { var err error value, err = strconv.ParseFloat(val, v.Type().Bits()) value *= float64(sign) if err != nil || v.OverflowFloat(value) { return errors.New("Float: " + val) } } v.SetFloat(value) return nil }
func (d *decoder) unmarshalFloat64(size uint, offset uint, result reflect.Value) (uint, error) { if size != 8 { return 0, newInvalidDatabaseError("the MaxMind DB file's data section contains bad data (float 64 size of %v)", size) } value, newOffset, err := d.decodeFloat64(size, offset) if err != nil { return 0, err } switch result.Kind() { default: return newOffset, newUnmarshalTypeError(value, result.Type()) case reflect.Float32, reflect.Float64: if result.OverflowFloat(value) { return 0, newUnmarshalTypeError(value, result.Type()) } result.SetFloat(value) return newOffset, nil case reflect.Interface: result.Set(reflect.ValueOf(value)) return newOffset, nil } }
// setVal sets v to the value pValue. func setVal(v reflect.Value, pValue interface{}) string { switch v.Kind() { case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: x, ok := pValue.(int64) if !ok && pValue != nil { return typeMismatchReason(pValue, v) } if v.OverflowInt(x) { return fmt.Sprintf("value %v overflows struct field of type %v", x, v.Type()) } v.SetInt(x) case reflect.Bool: x, ok := pValue.(bool) if !ok && pValue != nil { return typeMismatchReason(pValue, v) } v.SetBool(x) case reflect.String: switch x := pValue.(type) { case appengine.BlobKey: v.SetString(string(x)) case ByteString: v.SetString(string(x)) case string: v.SetString(x) default: if pValue != nil { return typeMismatchReason(pValue, v) } } case reflect.Float32, reflect.Float64: x, ok := pValue.(float64) if !ok && pValue != nil { return typeMismatchReason(pValue, v) } if v.OverflowFloat(x) { return fmt.Sprintf("value %v overflows struct field of type %v", x, v.Type()) } v.SetFloat(x) case reflect.Ptr: x, ok := pValue.(*Key) if !ok && pValue != nil { return typeMismatchReason(pValue, v) } if _, ok := v.Interface().(*Key); !ok { return typeMismatchReason(pValue, v) } v.Set(reflect.ValueOf(x)) case reflect.Struct: switch v.Type() { case typeOfTime: x, ok := pValue.(time.Time) if !ok && pValue != nil { return typeMismatchReason(pValue, v) } v.Set(reflect.ValueOf(x)) case typeOfGeoPoint: x, ok := pValue.(appengine.GeoPoint) if !ok && pValue != nil { return typeMismatchReason(pValue, v) } v.Set(reflect.ValueOf(x)) default: ent, ok := pValue.(*Entity) if !ok { return typeMismatchReason(pValue, v) } // Recursively load nested struct pls, err := newStructPLS(v.Addr().Interface()) if err != nil { return err.Error() } // if ent has a Key value and our struct has a Key field, // load the Entity's Key value into the Key field on the struct. if ent.Key != nil && pls.codec.keyField != -1 { pls.v.Field(pls.codec.keyField).Set(reflect.ValueOf(ent.Key)) } err = pls.Load(ent.Properties) if err != nil { return err.Error() } } case reflect.Slice: x, ok := pValue.([]byte) if !ok { if y, yok := pValue.(ByteString); yok { x, ok = []byte(y), true } } if !ok && pValue != nil { return typeMismatchReason(pValue, v) } if v.Type().Elem().Kind() != reflect.Uint8 { return typeMismatchReason(pValue, v) } v.SetBytes(x) default: return typeMismatchReason(pValue, v) } return "" }
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 }
// 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 (l *propertyLoader) load(codec *structCodec, structValue reflect.Value, p Property, prev map[string]struct{}) string { var sliceOk bool var v reflect.Value // Traverse a struct's struct-typed fields. for name := p.Name; ; { decoder, ok := codec.byName[name] if !ok { return "no such struct field" } v = structValue.Field(decoder.index) if !v.IsValid() { return "no such struct field" } if !v.CanSet() { return "cannot set struct field" } if decoder.substructCodec == nil { break } if v.Kind() == reflect.Slice { if l.m == nil { l.m = make(map[string]int) } index := l.m[p.Name] l.m[p.Name] = index + 1 for v.Len() <= index { v.Set(reflect.Append(v, reflect.New(v.Type().Elem()).Elem())) } structValue = v.Index(index) sliceOk = true } else { structValue = v } // Strip the "I." from "I.X". name = name[len(codec.byIndex[decoder.index].name):] codec = decoder.substructCodec } 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 _, ok := prev[p.Name]; ok && !sliceOk { // Zero the field back out that was set previously, turns out its a slice and we don't know what to do with it v.Set(reflect.Zero(v.Type())) return "multiple-valued property requires a slice field type" } prev[p.Name] = struct{}{} pValue := p.Value switch v.Kind() { case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: x, ok := pValue.(int64) if !ok && pValue != nil { return typeMismatchReason(p, v) } if v.OverflowInt(x) { return fmt.Sprintf("value %v overflows struct field of type %v", x, v.Type()) } v.SetInt(x) case reflect.Bool: x, ok := pValue.(bool) if !ok && pValue != nil { return typeMismatchReason(p, v) } v.SetBool(x) case reflect.String: x, ok := pValue.(string) if !ok && pValue != nil { return typeMismatchReason(p, v) } v.SetString(x) case reflect.Float32, reflect.Float64: x, ok := pValue.(float64) if !ok && pValue != nil { return typeMismatchReason(p, v) } if v.OverflowFloat(x) { return fmt.Sprintf("value %v overflows struct field of type %v", x, v.Type()) } v.SetFloat(x) case reflect.Ptr: x, ok := pValue.(*Key) if !ok && pValue != nil { return typeMismatchReason(p, v) } if _, ok := v.Interface().(*Key); !ok { return typeMismatchReason(p, v) } v.Set(reflect.ValueOf(x)) case reflect.Struct: switch v.Type() { case typeOfTime: x, ok := pValue.(time.Time) if !ok && pValue != nil { return typeMismatchReason(p, v) } v.Set(reflect.ValueOf(x)) default: return typeMismatchReason(p, v) } case reflect.Slice: x, ok := pValue.([]byte) if !ok && pValue != nil { return typeMismatchReason(p, v) } if v.Type().Elem().Kind() != reflect.Uint8 { return typeMismatchReason(p, v) } v.SetBytes(x) default: return typeMismatchReason(p, v) } if slice.IsValid() { slice.Set(reflect.Append(slice, v)) } return "" }
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 (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} }
// 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 }
// 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) } } }
// 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) } } }
func (l *propertyLoader) load(codec *structCodec, structValue reflect.Value, p Property, requireSlice bool) string { var v reflect.Value // Traverse a struct's struct-typed fields. for name := p.Name; ; { decoder, ok := codec.byName[name] if !ok { return "no such struct field" } v = structValue.Field(decoder.index) if !v.IsValid() { return "no such struct field" } if !v.CanSet() { return "cannot set struct field" } if decoder.substructCodec == nil { break } if v.Kind() == reflect.Slice { if l.m == nil { l.m = make(map[string]int) } index := l.m[p.Name] l.m[p.Name] = index + 1 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(codec.byIndex[decoder.index].name):] codec = decoder.substructCodec } var slice reflect.Value if v.Kind() == reflect.Slice && v.Type() != typeOfByteSlice { slice = v v = reflect.New(v.Type().Elem()).Elem() } else if requireSlice { return "multiple-valued property requires a slice field type" } // Convert indexValues to a Go value with a meaning derived from the // destination type. pValue := p.Value if iv, ok := pValue.(indexValue); ok { meaning := pb.Property_NO_MEANING switch v.Type() { case typeOfBlobKey: meaning = pb.Property_BLOBKEY case typeOfByteSlice: meaning = pb.Property_BLOB case typeOfTime: meaning = pb.Property_GD_WHEN } var err error pValue, err = propValue(iv.value, meaning) if err != nil { return err.Error() } } switch v.Kind() { case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: x, ok := pValue.(int64) if !ok && pValue != nil { return typeMismatchReason(p, v) } if v.OverflowInt(x) { return fmt.Sprintf("value %v overflows struct field of type %v", x, v.Type()) } v.SetInt(x) case reflect.Bool: x, ok := pValue.(bool) if !ok && pValue != nil { return typeMismatchReason(p, v) } v.SetBool(x) case reflect.String: if x, ok := pValue.(appengine.BlobKey); ok { v.SetString(string(x)) break } x, ok := pValue.(string) if !ok && pValue != nil { return typeMismatchReason(p, v) } v.SetString(x) case reflect.Float32, reflect.Float64: x, ok := pValue.(float64) if !ok && pValue != nil { return typeMismatchReason(p, v) } if v.OverflowFloat(x) { return fmt.Sprintf("value %v overflows struct field of type %v", x, v.Type()) } v.SetFloat(x) case reflect.Ptr: x, ok := pValue.(*Key) if !ok && pValue != nil { return typeMismatchReason(p, v) } if _, ok := v.Interface().(*Key); !ok { return typeMismatchReason(p, v) } v.Set(reflect.ValueOf(x)) case reflect.Struct: x, ok := pValue.(time.Time) if !ok && pValue != nil { return typeMismatchReason(p, v) } if _, ok := v.Interface().(time.Time); !ok { return typeMismatchReason(p, v) } v.Set(reflect.ValueOf(x)) case reflect.Slice: x, ok := pValue.([]byte) if !ok && pValue != nil { return typeMismatchReason(p, v) } if _, ok := v.Interface().([]byte); !ok { return typeMismatchReason(p, v) } v.Set(reflect.ValueOf(x)) default: return typeMismatchReason(p, v) } if slice.IsValid() { slice.Set(reflect.Append(slice, v)) } return "" }
// 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 }
// 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) } } }
// setVal sets 'v' to the value of the Property 'p'. func setVal(v reflect.Value, p Property) string { pValue := p.Value switch v.Kind() { case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: x, ok := pValue.(int64) if !ok && pValue != nil { return typeMismatchReason(p, v) } if v.OverflowInt(x) { return fmt.Sprintf("value %v overflows struct field of type %v", x, v.Type()) } v.SetInt(x) case reflect.Bool: x, ok := pValue.(bool) if !ok && pValue != nil { return typeMismatchReason(p, v) } v.SetBool(x) case reflect.String: x, ok := pValue.(string) if !ok && pValue != nil { return typeMismatchReason(p, v) } v.SetString(x) case reflect.Float32, reflect.Float64: x, ok := pValue.(float64) if !ok && pValue != nil { return typeMismatchReason(p, v) } if v.OverflowFloat(x) { return fmt.Sprintf("value %v overflows struct field of type %v", x, v.Type()) } v.SetFloat(x) case reflect.Ptr: x, ok := pValue.(*Key) if !ok && pValue != nil { return typeMismatchReason(p, v) } if _, ok := v.Interface().(*Key); !ok { return typeMismatchReason(p, v) } v.Set(reflect.ValueOf(x)) case reflect.Struct: switch v.Type() { case typeOfTime: x, ok := pValue.(time.Time) if !ok && pValue != nil { return typeMismatchReason(p, v) } v.Set(reflect.ValueOf(x)) case typeOfGeoPoint: x, ok := pValue.(GeoPoint) if !ok && pValue != nil { return typeMismatchReason(p, v) } v.Set(reflect.ValueOf(x)) default: ent, ok := pValue.(*Entity) if !ok { return typeMismatchReason(p, v) } // Recursively load nested struct pls, err := newStructPLS(v.Addr().Interface()) if err != nil { return err.Error() } // if ent has a Key value and our struct has a Key field, // load the Entity's Key value into the Key field on the struct. keyField := pls.codec.Match(keyFieldName) if keyField != nil && ent.Key != nil { pls.v.FieldByIndex(keyField.Index).Set(reflect.ValueOf(ent.Key)) } err = pls.Load(ent.Properties) if err != nil { return err.Error() } } case reflect.Slice: x, ok := pValue.([]byte) if !ok && pValue != nil { return typeMismatchReason(p, v) } if v.Type().Elem().Kind() != reflect.Uint8 { return typeMismatchReason(p, v) } v.SetBytes(x) default: return typeMismatchReason(p, v) } return "" }
func unmarshallAttribute(a *Attribute, v reflect.Value) error { switch v.Kind() { case reflect.Bool: n, err := strconv.ParseInt(a.Value, 10, 64) if err != nil { return fmt.Errorf("UnmarshalTypeError (bool) %#v: %#v", a.Value, err) } v.SetBool(n != 0) case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: n, err := strconv.ParseInt(a.Value, 10, 64) if err != nil || v.OverflowInt(n) { return fmt.Errorf("UnmarshalTypeError (number) %#v: %#v", a.Value, err) } v.SetInt(n) case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: n, err := strconv.ParseUint(a.Value, 10, 64) if err != nil || v.OverflowUint(n) { return fmt.Errorf("UnmarshalTypeError (number) %#v: %#v", a.Value, err) } v.SetUint(n) case reflect.Float32, reflect.Float64: n, err := strconv.ParseFloat(a.Value, v.Type().Bits()) if err != nil || v.OverflowFloat(n) { return fmt.Errorf("UnmarshalTypeError (number) %#v: %#v", a.Value, err) } v.SetFloat(n) case reflect.String: v.SetString(a.Value) case reflect.Slice: if v.Type().Elem().Kind() == reflect.Uint8 { // byte arrays are a special case b := make([]byte, base64.StdEncoding.DecodedLen(len(a.Value))) n, err := base64.StdEncoding.Decode(b, []byte(a.Value)) if err != nil { return fmt.Errorf("UnmarshalTypeError (byte) %#v: %#v", a.Value, err) } v.Set(reflect.ValueOf(b[0:n])) break } if a.SetType() { // Special NS and SS types should be correctly handled nativeSetCreated := false switch v.Type().Elem().Kind() { case reflect.Bool: nativeSetCreated = true arry := reflect.MakeSlice(v.Type(), len(a.SetValues), len(a.SetValues)) for i, aval := range a.SetValues { n, err := strconv.ParseInt(aval, 10, 64) if err != nil { return fmt.Errorf("UnmarshalSetTypeError (bool) %#v: %#v", aval, err) } arry.Index(i).SetBool(n != 0) } v.Set(arry) case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: nativeSetCreated = true arry := reflect.MakeSlice(v.Type(), len(a.SetValues), len(a.SetValues)) for i, aval := range a.SetValues { n, err := strconv.ParseInt(aval, 10, 64) if err != nil || arry.Index(i).OverflowInt(n) { return fmt.Errorf("UnmarshalSetTypeError (number) %#v: %#v", aval, err) } arry.Index(i).SetInt(n) } v.Set(arry) case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: nativeSetCreated = true arry := reflect.MakeSlice(v.Type(), len(a.SetValues), len(a.SetValues)) for i, aval := range a.SetValues { n, err := strconv.ParseUint(aval, 10, 64) if err != nil || arry.Index(i).OverflowUint(n) { return fmt.Errorf("UnmarshalSetTypeError (number) %#v: %#v", aval, err) } arry.Index(i).SetUint(n) } v.Set(arry) case reflect.Float32, reflect.Float64: nativeSetCreated = true arry := reflect.MakeSlice(v.Type(), len(a.SetValues), len(a.SetValues)) for i, aval := range a.SetValues { n, err := strconv.ParseFloat(aval, arry.Index(i).Type().Bits()) if err != nil || arry.Index(i).OverflowFloat(n) { return fmt.Errorf("UnmarshalSetTypeError (number) %#v: %#v", aval, err) } arry.Index(i).SetFloat(n) } v.Set(arry) case reflect.String: nativeSetCreated = true arry := reflect.MakeSlice(v.Type(), len(a.SetValues), len(a.SetValues)) for i, aval := range a.SetValues { arry.Index(i).SetString(aval) } v.Set(arry) } if nativeSetCreated { break } } // Slices can be marshalled as nil, but otherwise are handled // as arrays. fallthrough case reflect.Array, reflect.Struct, reflect.Map, reflect.Interface, reflect.Ptr: unmarshalled := reflect.New(v.Type()) err := json.Unmarshal([]byte(a.Value), unmarshalled.Interface()) if err != nil { return err } v.Set(unmarshalled.Elem()) default: return fmt.Errorf("UnsupportedTypeError %#v", v.Type()) } return nil }