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:
|
||||
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
|
||||
|
@ -1123,6 +1149,30 @@ func cvtUintFloat(v Value, t *rawType) Value {
|
|||
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 {
|
||||
size := t.Size()
|
||||
ptr := alloc(size, nil)
|
||||
|
@ -1167,6 +1217,14 @@ func cvtUintString(src Value, t *rawType) Value {
|
|||
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
|
||||
func slicePanic()
|
||||
|
||||
|
|
|
@ -579,6 +579,14 @@ func TestConvert(t *testing.T) {
|
|||
if c.Type().Kind() != Uint8 || c.Uint() != 3 {
|
||||
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 {
|
||||
|
|
|
@ -77,6 +77,16 @@ func stringFromBytes(x struct {
|
|||
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.
|
||||
func stringToBytes(x _string) (slice struct {
|
||||
ptr *byte
|
||||
|
@ -91,6 +101,12 @@ func stringToBytes(x _string) (slice struct {
|
|||
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.
|
||||
func stringFromRunes(runeSlice []rune) (s _string) {
|
||||
// Count the number of characters that will be in the string.
|
||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче