package bind import ( "fmt" "reflect" "strconv" "strings" ) func intParse[T any](parse func(string, int, int) (T, error), s string, byteSize int) (T, error) { bitSize := byteSize * 8 switch { case strings.HasPrefix(s, "0b"): return parse(s[2:], 2, bitSize) case strings.HasPrefix(s, "0x"): return parse(s[2:], 16, bitSize) case strings.HasPrefix(s, "0"): return parse(s[1:], 8, bitSize) default: return parse(s, 10, bitSize) } } func parseInt(s string, byteSize int) (int64, error) { return intParse(strconv.ParseInt, s, byteSize) } func parseUint(s string, byteSize int) (uint64, error) { return intParse(strconv.ParseUint, s, byteSize) } func scanConvert(t reflect.Type, v any) (any, bool) { r := reflect.ValueOf(v) if !r.CanConvert(t) { return nil, false } return r.Convert(t).Interface(), true } func scanString(t reflect.Type, s string) (any, bool) { var ( v any err error ) switch t.Kind() { case reflect.Bool: v, err = strconv.ParseBool(s) case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: v, err = parseInt(s, int(t.Size())) case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: v, err = parseUint(s, int(t.Size())) case reflect.Float32, reflect.Float64: v, err = strconv.ParseFloat(s, int(t.Size())*8) case reflect.String: v = s default: return nil, false } if err != nil { return nil, false } p := reflect.New(t) p.Elem().Set(reflect.ValueOf(v).Convert(t)) return p.Elem().Interface(), true } func scan(t reflect.Type, v any) (any, bool) { // time and duration support if vv, ok := scanConvert(t, v); ok { return vv, true } r := reflect.ValueOf(v) if r.Kind() != reflect.String { return nil, false } return scanString(t, fmt.Sprint(v)) }