reflect: add Convert() for string -> []byte and []byte -> string
Этот коммит содержится в:
родитель
72c7adf94a
коммит
0b6bb12e9e
3 изменённых файлов: 82 добавлений и 0 удалений
|
@ -1102,6 +1102,32 @@ func convertOp(src Value, typ Type) (Value, bool) {
|
||||||
case String:
|
case String:
|
||||||
return cvtUintString(src, rtype), true
|
return cvtUintString(src, rtype), true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case Slice:
|
||||||
|
if typ.Kind() == String && !src.typecode.elem().isNamed() {
|
||||||
|
rtype := typ.(*rawType)
|
||||||
|
|
||||||
|
switch src.Type().Elem().Kind() {
|
||||||
|
case Uint8:
|
||||||
|
return cvtBytesString(src, rtype), true
|
||||||
|
case Int32:
|
||||||
|
return cvtRunesString(src, rtype), true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(dgryski): Implement other cases
|
||||||
|
|
||||||
|
case String:
|
||||||
|
rtype := typ.(*rawType)
|
||||||
|
if typ.Kind() == Slice && !rtype.elem().isNamed() {
|
||||||
|
switch typ.Elem().Kind() {
|
||||||
|
case Uint8:
|
||||||
|
return cvtStringBytes(src, rtype), true
|
||||||
|
case Int32:
|
||||||
|
return cvtStringRunes(src, rtype), true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return Value{}, false
|
return Value{}, false
|
||||||
|
@ -1123,6 +1149,30 @@ func cvtUintFloat(v Value, t *rawType) Value {
|
||||||
return makeFloat(v.flags, float64(v.Uint()), t)
|
return makeFloat(v.flags, float64(v.Uint()), t)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//go:linkname stringToBytes runtime.stringToBytesTyped
|
||||||
|
func stringToBytes(x string) []byte
|
||||||
|
|
||||||
|
func cvtStringBytes(v Value, t *rawType) Value {
|
||||||
|
b := stringToBytes(*(*string)(v.value))
|
||||||
|
return Value{
|
||||||
|
typecode: t,
|
||||||
|
value: unsafe.Pointer(&b),
|
||||||
|
flags: v.flags,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//go:linkname stringFromBytes runtime.stringFromBytesTyped
|
||||||
|
func stringFromBytes(x []byte) string
|
||||||
|
|
||||||
|
func cvtBytesString(v Value, t *rawType) Value {
|
||||||
|
s := stringFromBytes(*(*[]byte)(v.value))
|
||||||
|
return Value{
|
||||||
|
typecode: t,
|
||||||
|
value: unsafe.Pointer(&s),
|
||||||
|
flags: v.flags,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func makeInt(flags valueFlags, bits uint64, t *rawType) Value {
|
func makeInt(flags valueFlags, bits uint64, t *rawType) Value {
|
||||||
size := t.Size()
|
size := t.Size()
|
||||||
ptr := alloc(size, nil)
|
ptr := alloc(size, nil)
|
||||||
|
@ -1167,6 +1217,14 @@ func cvtUintString(src Value, t *rawType) Value {
|
||||||
panic("cvtUintString: unimplemented")
|
panic("cvtUintString: unimplemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func cvtStringRunes(src Value, t *rawType) Value {
|
||||||
|
panic("cvsStringRunes: unimplemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
func cvtRunesString(src Value, t *rawType) Value {
|
||||||
|
panic("cvsRunesString: unimplemented")
|
||||||
|
}
|
||||||
|
|
||||||
//go:linkname slicePanic runtime.slicePanic
|
//go:linkname slicePanic runtime.slicePanic
|
||||||
func slicePanic()
|
func slicePanic()
|
||||||
|
|
||||||
|
|
|
@ -579,6 +579,14 @@ func TestConvert(t *testing.T) {
|
||||||
if c.Type().Kind() != Uint8 || c.Uint() != 3 {
|
if c.Type().Kind() != Uint8 || c.Uint() != 3 {
|
||||||
t.Errorf("Conver(uint64 -> byte failed: kind=%v, value=%d", c.Type().Kind().String(), c.Uint())
|
t.Errorf("Conver(uint64 -> byte failed: kind=%v, value=%d", c.Type().Kind().String(), c.Uint())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
v = ValueOf("hello")
|
||||||
|
c = v.Convert(TypeOf([]byte("")))
|
||||||
|
|
||||||
|
if c.Type().Kind() != Slice || c.Type().Elem().Kind() != Uint8 && c.Len() != 5 && string(c.Bytes()) != "hello" {
|
||||||
|
t.Errorf("Conver(string -> []byte")
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func equal[T comparable](a, b []T) bool {
|
func equal[T comparable](a, b []T) bool {
|
||||||
|
|
|
@ -77,6 +77,16 @@ func stringFromBytes(x struct {
|
||||||
return _string{ptr: (*byte)(buf), length: x.len}
|
return _string{ptr: (*byte)(buf), length: x.len}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func stringFromBytesTyped(x []byte) string {
|
||||||
|
slice := *(*struct {
|
||||||
|
ptr *byte
|
||||||
|
len uintptr
|
||||||
|
cap uintptr
|
||||||
|
})(unsafe.Pointer(&x))
|
||||||
|
s := stringFromBytes(slice)
|
||||||
|
return *(*string)(unsafe.Pointer(&s))
|
||||||
|
}
|
||||||
|
|
||||||
// Convert a string to a []byte slice.
|
// Convert a string to a []byte slice.
|
||||||
func stringToBytes(x _string) (slice struct {
|
func stringToBytes(x _string) (slice struct {
|
||||||
ptr *byte
|
ptr *byte
|
||||||
|
@ -91,6 +101,12 @@ func stringToBytes(x _string) (slice struct {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func stringToBytesTyped(x string) []byte {
|
||||||
|
s := *(*_string)(unsafe.Pointer(&x))
|
||||||
|
slice := stringToBytes(s)
|
||||||
|
return *(*[]byte)(unsafe.Pointer(&slice))
|
||||||
|
}
|
||||||
|
|
||||||
// Convert a []rune slice to a string.
|
// Convert a []rune slice to a string.
|
||||||
func stringFromRunes(runeSlice []rune) (s _string) {
|
func stringFromRunes(runeSlice []rune) (s _string) {
|
||||||
// Count the number of characters that will be in the string.
|
// Count the number of characters that will be in the string.
|
||||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче