discord: ContainerComponents.Unmarshal for number types

This commit adds int*, uint* and float* parsing support into
ContainerComponents.Unmarshal.
This commit is contained in:
diamondburned 2022-08-20 09:39:24 -07:00
parent 6412cf74ff
commit 7961d18278
No known key found for this signature in database
GPG Key ID: D78C4471CE776659
2 changed files with 50 additions and 3 deletions

View File

@ -3,6 +3,7 @@ package discord
import (
"fmt"
"reflect"
"strconv"
"strings"
"github.com/diamondburned/arikawa/v3/internal/rfutil"
@ -71,6 +72,7 @@ func (c *ContainerComponents) Find(customID ComponentID) Component {
// The following types are supported:
//
// - string (SelectComponent if range = [n, 1], TextInputComponent)
// - int*, uint*, float* (uses Parse{Int,Uint,Float}, SelectComponent if range = [n, 1], TextInputComponent)
// - bool (ButtonComponent or any component, true if present)
// - []string (SelectComponent)
//
@ -128,11 +130,14 @@ func (c *ContainerComponents) Unmarshal(v interface{}) error {
return fmt.Errorf("component %q is required but not found", name)
}
switch fieldt.Kind() {
switch fieldk := fieldt.Kind(); fieldk {
case reflect.Bool:
// Intended for ButtonComponents.
fieldv.Set(reflect.ValueOf(true).Convert(fieldt))
case reflect.String:
case reflect.String,
reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64,
reflect.Float32, reflect.Float64:
var v string
switch component := component.(type) {
@ -151,7 +156,30 @@ func (c *ContainerComponents) Unmarshal(v interface{}) error {
return fmt.Errorf("component %q is of unsupported type %T", name, component)
}
fieldv.Set(reflect.ValueOf(v).Convert(fieldt))
switch fieldk {
case reflect.String:
fieldv.Set(reflect.ValueOf(v).Convert(fieldt))
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
i, err := strconv.ParseInt(v, 10, rfutil.KindBits(fieldk))
if err != nil {
return fmt.Errorf("component %q has invalid integer: %v", name, err)
}
fieldv.Set(reflect.ValueOf(i).Convert(fieldt))
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
u, err := strconv.ParseUint(v, 10, rfutil.KindBits(fieldk))
if err != nil {
return fmt.Errorf("component %q has invalid unsigned (positive) integer: %v", name, err)
}
fieldv.Set(reflect.ValueOf(u).Convert(fieldt))
case reflect.Float32, reflect.Float64:
f, err := strconv.ParseFloat(v, rfutil.KindBits(fieldk))
if err != nil {
return fmt.Errorf("component %q has invalid floating-point number: %v", name, err)
}
fieldv.Set(reflect.ValueOf(f).Convert(fieldt))
default:
panic("unreachable")
}
case reflect.Slice:
elemt := fieldt.Elem()

View File

@ -2,6 +2,7 @@ package rfutil
import (
"errors"
"math/bits"
"reflect"
)
@ -24,3 +25,21 @@ func StructRValue(rv reflect.Value) (reflect.Value, reflect.Type, error) {
return rv, rt, nil
}
// KindBits works on int*, uint* and float* only.
func KindBits(k reflect.Kind) int {
switch k {
case reflect.Int, reflect.Uint:
return bits.UintSize
case reflect.Int8, reflect.Uint8:
return 8
case reflect.Int16, reflect.Uint16:
return 16
case reflect.Int32, reflect.Uint32, reflect.Float32:
return 32
case reflect.Int64, reflect.Uint64, reflect.Float64:
return 64
default:
panic("unknown kind " + k.String())
}
}