reflect: Convert() for integer and float types
Этот коммит содержится в:
родитель
13fb5aa7e7
коммит
72c7adf94a
2 изменённых файлов: 100 добавлений и 1 удалений
|
@ -1074,7 +1074,97 @@ func (v Value) CanConvert(t Type) bool {
|
|||
}
|
||||
|
||||
func (v Value) Convert(t Type) Value {
|
||||
panic("unimplemented: (reflect.Value).Convert()")
|
||||
if v, ok := convertOp(v, t); ok {
|
||||
return v
|
||||
}
|
||||
|
||||
panic("reflect.Value.Convert: value of type " + v.typecode.String() + " cannot be converted to type " + t.String())
|
||||
}
|
||||
|
||||
func convertOp(src Value, typ Type) (Value, bool) {
|
||||
switch src.Kind() {
|
||||
case Int, Int8, Int16, Int32, Int64:
|
||||
switch rtype := typ.(*rawType); rtype.Kind() {
|
||||
case Int, Int8, Int16, Int32, Int64, Uint, Uint8, Uint16, Uint32, Uint64, Uintptr:
|
||||
return cvtInt(src, rtype), true
|
||||
case Float32, Float64:
|
||||
return cvtIntFloat(src, rtype), true
|
||||
case String:
|
||||
return cvtIntString(src, rtype), true
|
||||
}
|
||||
|
||||
case Uint, Uint8, Uint16, Uint32, Uint64:
|
||||
switch rtype := typ.(*rawType); rtype.Kind() {
|
||||
case Int, Int8, Int16, Int32, Int64, Uint, Uint8, Uint16, Uint32, Uint64, Uintptr:
|
||||
return cvtUint(src, rtype), true
|
||||
case Float32, Float64:
|
||||
return cvtUintFloat(src, rtype), true
|
||||
case String:
|
||||
return cvtUintString(src, rtype), true
|
||||
}
|
||||
}
|
||||
|
||||
return Value{}, false
|
||||
}
|
||||
|
||||
func cvtInt(v Value, t *rawType) Value {
|
||||
return makeInt(v.flags, uint64(v.Int()), t)
|
||||
}
|
||||
|
||||
func cvtUint(v Value, t *rawType) Value {
|
||||
return makeInt(v.flags, v.Uint(), t)
|
||||
}
|
||||
|
||||
func cvtIntFloat(v Value, t *rawType) Value {
|
||||
return makeFloat(v.flags, float64(v.Int()), t)
|
||||
}
|
||||
|
||||
func cvtUintFloat(v Value, t *rawType) Value {
|
||||
return makeFloat(v.flags, float64(v.Uint()), t)
|
||||
}
|
||||
|
||||
func makeInt(flags valueFlags, bits uint64, t *rawType) Value {
|
||||
size := t.Size()
|
||||
ptr := alloc(size, nil)
|
||||
switch size {
|
||||
case 1:
|
||||
*(*uint8)(ptr) = uint8(bits)
|
||||
case 2:
|
||||
*(*uint16)(ptr) = uint16(bits)
|
||||
case 4:
|
||||
*(*uint32)(ptr) = uint32(bits)
|
||||
case 8:
|
||||
*(*uint64)(ptr) = bits
|
||||
}
|
||||
return Value{
|
||||
typecode: t,
|
||||
value: ptr,
|
||||
flags: flags | valueFlagIndirect,
|
||||
}
|
||||
}
|
||||
|
||||
func makeFloat(flags valueFlags, v float64, t *rawType) Value {
|
||||
size := t.Size()
|
||||
ptr := alloc(size, nil)
|
||||
switch size {
|
||||
case 4:
|
||||
*(*float32)(ptr) = float32(v)
|
||||
case 8:
|
||||
*(*float64)(ptr) = v
|
||||
}
|
||||
return Value{
|
||||
typecode: t,
|
||||
value: ptr,
|
||||
flags: flags | valueFlagIndirect,
|
||||
}
|
||||
}
|
||||
|
||||
func cvtIntString(src Value, t *rawType) Value {
|
||||
panic("cvtUintString: unimplemented")
|
||||
}
|
||||
|
||||
func cvtUintString(src Value, t *rawType) Value {
|
||||
panic("cvtUintString: unimplemented")
|
||||
}
|
||||
|
||||
//go:linkname slicePanic runtime.slicePanic
|
||||
|
|
|
@ -572,6 +572,15 @@ func TestAssignableTo(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestConvert(t *testing.T) {
|
||||
v := ValueOf(int64(3))
|
||||
c := v.Convert(TypeOf(byte(0)))
|
||||
|
||||
if c.Type().Kind() != Uint8 || c.Uint() != 3 {
|
||||
t.Errorf("Conver(uint64 -> byte failed: kind=%v, value=%d", c.Type().Kind().String(), c.Uint())
|
||||
}
|
||||
}
|
||||
|
||||
func equal[T comparable](a, b []T) bool {
|
||||
if len(a) != len(b) {
|
||||
return false
|
||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче