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. | ||||||
|  |  | ||||||
		Загрузка…
	
	Создание таблицы
		
		Сослаться в новой задаче
	
	 Damian Gryski
						Damian Gryski