func validateBitType(sqlType string, goType reflect.Type) bool { bits := 0 if n, err := fmt.Sscanf(sqlType, "bit(%d)", &bits); err != nil { return false } else if n != 1 { return false } requiredBits := []int{8, 16, 32, 64} i := sort.SearchInts(requiredBits, bits) if i >= len(requiredBits) { return false } bits = requiredBits[i] switch goType.Kind() { case reflect.Int, reflect.Uint: fallthrough case reflect.Int8, reflect.Uint8: fallthrough case reflect.Int16, reflect.Uint16: fallthrough case reflect.Int32, reflect.Uint32: fallthrough case reflect.Int64, reflect.Uint64: return bits == goType.Bits() } return false }
func makeUnsignedSinglePacker(typ reflect.Type, ilsb uint64, width uint8) packer { firstByte := ilsb / 8 lsb := uint8(ilsb % 8) canOverflow := width != uint8(typ.Bits()) maxVal := (uint64(1) << width) - 1 switch { case lsb+width <= 8: if canOverflow { return func(b []byte, field reflect.Value) { u := field.Uint() if u > maxVal { panic(Error{fmt.Errorf("gopack: value out of range: max %v; got %v", maxVal, u)}) } b[firstByte] |= byte(u << lsb) } } else { return func(b []byte, field reflect.Value) { b[firstByte] |= byte(field.Uint() << lsb) } } case lsb+width <= 16: if canOverflow { return func(b []byte, field reflect.Value) { u := field.Uint() if u > maxVal { panic(Error{fmt.Errorf("gopack: value out of range: max %v; got %v", maxVal, u)}) } *(*uint16)(unsafe.Pointer(&b[firstByte])) |= uint16(u << lsb) } } else { return func(b []byte, field reflect.Value) { *(*uint16)(unsafe.Pointer(&b[firstByte])) |= uint16(field.Uint() << lsb) } }
func validateIntType(bits int, sqlType string, goType reflect.Type) bool { if strings.HasSuffix(sqlType, " unsigned") { switch goType.Kind() { case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: return bits == goType.Bits() } } else { switch goType.Kind() { case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: return bits == goType.Bits() } } return false }
// makeMapKeyFromString takes the key type for a map, and a string // representing the key, it then tries to convert the string // representation into a value of the correct type. func makeMapKeyFromString(mapKeyType reflect.Type, pointer string) (reflect.Value, bool) { valp := reflect.New(mapKeyType) val := reflect.Indirect(valp) switch mapKeyType.Kind() { case reflect.String: return reflect.ValueOf(pointer), true case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int: iv, err := strconv.ParseInt(pointer, 10, mapKeyType.Bits()) if err == nil { val.SetInt(iv) return val, true } case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint: iv, err := strconv.ParseUint(pointer, 10, mapKeyType.Bits()) if err == nil { val.SetUint(iv) return val, true } case reflect.Float32, reflect.Float64: fv, err := strconv.ParseFloat(pointer, mapKeyType.Bits()) if err == nil { val.SetFloat(fv) return val, true } } return reflect.ValueOf(nil), false }
func toCtype(data interface{}) (p unsafe.Pointer, t C.GLenum, ts int, s uintptr) { v := reflect.ValueOf(data) var et reflect.Type switch v.Type().Kind() { case reflect.Slice, reflect.Array: if !v.IsNil() { p = unsafe.Pointer(v.Index(0).UnsafeAddr()) s = uintptr(v.Len()) } et = v.Type().Elem() default: panic("not a pointer or slice") } switch et.Kind() { case reflect.Uint8: t = UNSIGNED_BYTE case reflect.Int8: t = BYTE case reflect.Uint16: t = UNSIGNED_SHORT case reflect.Int16: t = SHORT case reflect.Uint32: t = UNSIGNED_INT case reflect.Int32: t = INT case reflect.Float32: t = FLOAT case reflect.Float64: t = DOUBLE default: panic("unknown type: " + reflect.TypeOf(v).String()) } ts = et.Bits() / 8 s *= uintptr(et.Bits() / 8) return }
// Append value to target or return a new value of type typ. func appendValue(typ reflect.Type, target reflect.Value, value string) (result reflect.Value, err error) { if target.IsValid() { typ = target.Type() } if typ.Kind() == reflect.Interface { typ = reflect.TypeOf([]string{}) } switch typ.Kind() { case reflect.Bool: if parsed, err2 := strconv.ParseBool(value); err2 != nil { err = &UnmarshalTypeError{Value: value, Type: typ} } else if target.IsValid() && target.CanSet() { target.SetBool(parsed) } else { result = reflect.ValueOf(parsed) } case reflect.Float32, reflect.Float64: if parsed, err2 := strconv.ParseFloat(value, typ.Bits()); err2 != nil { err = &UnmarshalTypeError{Value: value, Type: typ} } else if target.IsValid() && target.CanSet() { target.SetFloat(parsed) } else { switch typ.Kind() { case reflect.Float32: result = reflect.ValueOf(float32(parsed)) default: result = reflect.ValueOf(parsed) } } case reflect.Int, reflect.Int16, reflect.Int32, reflect.Int64: if parsed, err2 := strconv.ParseInt(value, 10, typ.Bits()); err2 != nil { err = &UnmarshalTypeError{Value: value, Type: typ} } else if target.IsValid() && target.CanSet() { target.SetInt(parsed) } else { switch typ.Kind() { case reflect.Int: result = reflect.ValueOf(int(parsed)) case reflect.Int16: result = reflect.ValueOf(int16(parsed)) case reflect.Int32: result = reflect.ValueOf(int32(parsed)) default: result = reflect.ValueOf(parsed) } } case reflect.Uint, reflect.Uint16, reflect.Uint32, reflect.Uint64: if parsed, err2 := strconv.ParseUint(value, 10, typ.Bits()); err2 != nil { err = &UnmarshalTypeError{Value: value, Type: typ} } else if target.IsValid() && target.CanSet() { target.SetUint(parsed) } else { switch typ.Kind() { case reflect.Uint: result = reflect.ValueOf(uint(parsed)) case reflect.Uint16: result = reflect.ValueOf(uint16(parsed)) case reflect.Uint32: result = reflect.ValueOf(uint32(parsed)) default: result = reflect.ValueOf(parsed) } } case reflect.Ptr: result = reflect.New(typ.Elem()) var elem reflect.Value if elem, err = appendValue(typ.Elem(), elem, value); err == nil { result.Elem().Set(elem) } case reflect.String: result = reflect.ValueOf(value) case reflect.Slice: var next reflect.Value next, err = appendValue(typ.Elem(), next, value) if err == nil && next.IsValid() { result = target if result.IsValid() && result.Type().Kind() == reflect.Interface { result = reflect.ValueOf(result.Interface()) } if !result.IsValid() { result = reflect.MakeSlice(typ, 0, 4) } result = reflect.Append(result, next) } default: err = &UnmarshalTypeError{ Value: value, Type: typ, } } return }
// Convert an untyped constant to a typed constant. If the types from and to are // incompatible, ErrBadConstConversion is returned along with an invalid value. // If the types were compatible but other errors are present, such as integer // overflows or floating truncations, the conversion will continue and a valid // value will be returned. Therefore, if a valid value is returned, the const // type is assignable to the reflect.Type. This can be checked using // // reflect.Value(constValue).IsValid() // func convertConstToTyped(from ConstType, c constValue, to reflect.Type, isTypeCast bool, expr Expr) ( constValue, []error) { v := hackedNew(to).Elem() switch from.(type) { case ConstShiftedIntType: switch to.Kind() { case reflect.Float32, reflect.Float64, reflect.Complex64, reflect.Complex128: return constValue{}, []error{ErrBadConstConversion{expr, from, to}} } return convertConstToTyped(ConstInt, c, to, isTypeCast, expr) case ConstIntType, ConstRuneType, ConstFloatType, ConstComplexType: underlying := reflect.Value(c).Interface().(*ConstNumber) switch to.Kind() { case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: var errs []error i, truncation, overflow := underlying.Value.Int(to.Bits()) if truncation { errs = append(errs, ErrTruncatedConstant{expr, ConstInt, underlying}) } if overflow { errs = append(errs, ErrOverflowedConstant{expr, from, to, underlying}) } // For some reason, the errors produced are "complex -> int" then "complex -> real" _, truncation = underlying.Value.Real() if truncation { errs = append(errs, ErrTruncatedConstant{expr, ConstFloat, underlying}) } v.SetInt(i) return constValue(v), errs case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: var errs []error u, truncation, overflow := underlying.Value.Uint(to.Bits()) if truncation { errs = append(errs, ErrTruncatedConstant{expr, ConstInt, underlying}) } if overflow { errs = append(errs, ErrOverflowedConstant{expr, from, to, underlying}) } // For some reason, the erros produced are "complex -> int" then "complex -> real" _, truncation = underlying.Value.Real() if truncation { errs = append(errs, ErrTruncatedConstant{expr, ConstFloat, underlying}) } v.SetUint(u) return constValue(v), errs case reflect.Float32, reflect.Float64: var errs []error f, truncation, _ := underlying.Value.Float64() if truncation { errs = []error{ErrTruncatedConstant{expr, ConstFloat, underlying}} } v.SetFloat(f) return constValue(v), errs case reflect.Complex64, reflect.Complex128: cmplx, _ := underlying.Value.Complex128() v.SetComplex(cmplx) return constValue(v), nil // string(97) is legal, equivalent of string('a'), but this // conversion is not automatic. "abc" + 10 is illegal. case reflect.String: if isTypeCast && from.IsIntegral() { i, _, overflow := underlying.Value.Int(32) if overflow { err := ErrOverflowedConstant{expr, from, ConstString, underlying} return constValue{}, []error{err} } v.SetString(string(i)) return constValue(v), nil } // consts can satisfy the empty interface only case reflect.Interface: if to == emptyInterface { to = underlying.Type.DefaultPromotion() cv, _ := convertConstToTyped(from, c, to, isTypeCast, expr) v.Set(reflect.Value(cv).Convert(emptyInterface)) return constValue(v), nil } } case ConstStringType: if to.Kind() == reflect.String { v.SetString(reflect.Value(c).String()) return constValue(v), nil } else if to == emptyInterface { v.Set(reflect.Value(c).Convert(emptyInterface)) return constValue(v), nil } else if isTypeCast && to == byteSlice || to == runeSlice { v = reflect.Value(c).Convert(to) return constValue(v), nil } case ConstBoolType: if to.Kind() == reflect.Bool { v.SetBool(reflect.Value(c).Bool()) return constValue(v), nil } else if to == emptyInterface { v.Set(reflect.Value(c).Convert(emptyInterface)) return constValue(v), nil } case ConstNilType: // Unfortunately there is no reflect.Type.CanNil() if isNillable(to) { // v is already nil return constValue(v), nil } } return constValue{}, []error{ErrBadConstConversion{expr, from, to}} }
func getNumberSize(typ reflect.Type) string { return fmt.Sprintf("%d", typ.Bits()) }
func convertConstToTyped(ctx *Ctx, from ConstType, c constValue, to reflect.Type, expr Expr) ( constValue, []error) { v := hackedNew(to).Elem() switch from.(type) { case ConstIntType, ConstRuneType, ConstFloatType, ConstComplexType: underlying := reflect.Value(c).Interface().(*ConstNumber) switch to.Kind() { case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: var errs []error i, truncation, overflow := underlying.Value.Int(to.Bits()) if truncation { errs = append(errs, ErrTruncatedConstant{at(ctx, expr), ConstInt, underlying}) } if overflow { errs = append(errs, ErrOverflowedConstant{at(ctx, expr), from, to, underlying}) } // For some reason, the erros produced are "complex -> int" then "complex -> real" _, truncation = underlying.Value.Real() if truncation { errs = append(errs, ErrTruncatedConstant{at(ctx, expr), ConstFloat, underlying}) } v.SetInt(i) return constValue(v), errs case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: var errs []error u, truncation, overflow := underlying.Value.Uint(to.Bits()) if truncation { errs = append(errs, ErrTruncatedConstant{at(ctx, expr), ConstInt, underlying}) } if overflow { errs = append(errs, ErrOverflowedConstant{at(ctx, expr), from, to, underlying}) } // For some reason, the erros produced are "complex -> int" then "complex -> real" _, truncation = underlying.Value.Real() if truncation { errs = append(errs, ErrTruncatedConstant{at(ctx, expr), ConstFloat, underlying}) } v.SetUint(u) return constValue(v), errs case reflect.Float32, reflect.Float64: var errs []error f, truncation, _ := underlying.Value.Float64() if truncation { errs = []error{ErrTruncatedConstant{at(ctx, expr), ConstFloat, underlying}} } v.SetFloat(f) return constValue(v), errs case reflect.Complex64, reflect.Complex128: cmplx, _ := underlying.Value.Complex128() v.SetComplex(cmplx) return constValue(v), nil // string(97) is legal, equivalent of string('a') case reflect.String: if from.IsIntegral() { i, _, overflow := underlying.Value.Int(32) if overflow { err := ErrOverflowedConstant{at(ctx, expr), from, ConstString, underlying} return constValue{}, []error{err} } v.SetString(string(i)) return constValue(v), nil } } case ConstStringType: if v.Type().Kind() == reflect.String { v.SetString(reflect.Value(c).String()) return constValue(v), nil } case ConstBoolType: if to.Kind() == reflect.Bool { v.SetBool(reflect.Value(c).Bool()) return constValue(v), nil } case ConstNilType: // Unfortunately there is no reflect.Type.CanNil() switch to.Kind() { case reflect.Chan, reflect.Func, reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice: // v is already nil return constValue(v), nil } } return constValue{}, []error{ErrBadConstConversion{at(ctx, expr), from, to, reflect.Value(c)}} }
func (v *Value) ToRealNumber(nv json.Number, valueType reflect.Type) interface{} { switch valueType.Kind() { case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: n, err := strconv.ParseInt(string(nv), 10, 64) if err != nil { return fmt.Errorf("Can not use number %v as %s patch failure err: %v", nv, valueType, err) } switch k := valueType.Kind(); k { default: panic(&reflect.ValueError{"Transform to int failure, err: %v", valueType.Kind()}) case reflect.Int: return int(n) case reflect.Int8: return int8(n) case reflect.Int16: return int16(n) case reflect.Int32: return int32(n) case reflect.Int64: return n } return n case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: n, err := strconv.ParseUint(string(nv), 10, 64) if err != nil { return fmt.Errorf("Can not use number %v as %s patch failure err: %v", nv, valueType, err) } switch k := valueType.Kind(); k { default: panic(&reflect.ValueError{"Transform to uint failure, err: %v", valueType.Kind()}) case reflect.Uint: return uint(n) case reflect.Uint8: return uint8(n) case reflect.Uint16: return uint16(n) case reflect.Uint32: return uint32(n) case reflect.Uint64: return n case reflect.Uintptr: return uintptr(n) } return n case reflect.Float32, reflect.Float64: n, err := strconv.ParseFloat(string(nv), valueType.Bits()) if err != nil { return fmt.Errorf("Can not use number %v as %s patch failure err: %v", valueType, valueType, err) } switch k := valueType.Kind(); k { default: panic(&reflect.ValueError{"Transform to float failure, err: %v", valueType.Kind()}) case reflect.Float32: return int32(n) case reflect.Float64: return n } return n default: return fmt.Errorf("Can not use use value %v to patch %s type", valueType, valueType.Kind()) } return nil }
func traverse(v reflect.Value, t reflect.Type) (match bool) { switch v.Kind() { case reflect.Map: // TODO: Logic here bit messy, needs cleaning // Idea: fieldNames are must, omitEmpty means that JSON can't have zero val- // ues in golang sense for such fields because fields with omit and empty // values will not be present in resulting json fieldNames, omitEmpty := getJSONFieldNames(t) if len(fieldNames) != len(v.MapKeys()) { return false } for _, key := range v.MapKeys() { must := fieldNames[key.String()] omit := omitEmpty[key.String()] value := v.MapIndex(key).Interface() if must == "" && omit == "" { return false } if omit != "" { if value == nil || isZero(reflect.ValueOf(value)) { return false } must = omit } f, _ := t.FieldByName(must) ok := traverse(reflect.ValueOf(value), f.Type) if !ok { return false } } case reflect.Slice: if t.Kind() != reflect.Slice { return false } trueType := t.Elem() for i := 0; i < v.Len(); i++ { ok := traverse(reflect.ValueOf(v.Index(i).Interface()), trueType) if !ok { return false } } case reflect.Bool: return t.Kind() == reflect.Bool case reflect.String: // If number var number json.Number if v.Type() == reflect.TypeOf(number) { switch t.Kind() { case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: _, err := strconv.ParseInt(v.String(), 10, t.Bits()) return err == nil case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: _, err := strconv.ParseUint(v.String(), 10, t.Bits()) return err == nil case reflect.Float32, reflect.Float64: _, err := strconv.ParseFloat(v.String(), t.Bits()) return err == nil default: return false } } return t.Kind() == reflect.String } return true }
// getParser returns back a FieldParser instance for the given type func getParser(t reflect.Type, k reflect.Kind) (parser *fieldParser) { switch k { case reflect.String: parser = &fieldParser{ Parse: func(v string) (interface{}, error) { return v, nil }, Set: func(f *reflect.Value, v interface{}) { f.SetString(v.(string)) }, } case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: parser = &fieldParser{ Parse: func(v string) (interface{}, error) { intValue, err := strconv.ParseInt(v, 0, t.Bits()) if err != nil { return nil, err } return intValue, nil }, Set: func(f *reflect.Value, v interface{}) { f.SetInt(v.(int64)) }, } case reflect.Bool: parser = &fieldParser{ Parse: func(v string) (interface{}, error) { boolValue, err := strconv.ParseBool(v) if err != nil { return nil, err } return boolValue, nil }, Set: func(f *reflect.Value, v interface{}) { f.SetBool(v.(bool)) }, } case reflect.Float32, reflect.Float64: parser = &fieldParser{ Parse: func(v string) (interface{}, error) { floatValue, err := strconv.ParseFloat(v, t.Bits()) if err != nil { return nil, err } return floatValue, nil }, Set: func(f *reflect.Value, v interface{}) { f.SetFloat(v.(float64)) }, } case reflect.Slice: parser = &fieldParser{ Parse: func(v string) (interface{}, error) { elemType := t.Elem() parser := getParser(elemType, elemType.Kind()) strValues := strings.Split(v, ",") slice := reflect.MakeSlice(reflect.SliceOf(elemType), 0, 0) for i := range strValues { value, err := parser.Parse(strValues[i]) if err != nil { return nil, err } itmValue := reflect.ValueOf(value) itmValue = itmValue.Convert(elemType) slice = reflect.Append(slice, itmValue) } return slice.Interface(), nil }, Set: func(f *reflect.Value, v interface{}) { f.Set(reflect.ValueOf(v)) }, } } return }
// unmarshallString parses string s to in vto func unmarshallString(vto reflect.Value, tto reflect.Type, s string) error { // custom handlers for non-builtin types: switch tto.String() { case "time.Duration": d, e := time.ParseDuration(s) if e != nil { return e } vto.Set(reflect.ValueOf(d)) return nil } // handle builtin types: switch vto.Kind() { case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: ival, err := strconv.ParseInt(s, 10, tto.Bits()) if err != nil { // try again looking for B/K/M/G/T ival, err = getBytes(s, err) if err != nil { return err } } vto.SetInt(ival) return nil case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: uval, err := strconv.ParseUint(s, 10, tto.Bits()) if err != nil { // try again looking for B/K/M/G/T ival, e := getBytes(s, err) if e != nil { return e } uval = uint64(ival) } vto.SetUint(uval) return nil case reflect.Float32, reflect.Float64: fval, err := strconv.ParseFloat(s, tto.Bits()) if err != nil { return err } vto.SetFloat(fval) return nil } return fmt.Errorf("don't know how to unmarshall string to %v\n", tto) }