Browse Source

codec: fix helper_unsafe for correct string-to-byte conversion (without copy)

Update #142
Ugorji Nwoke 9 years ago
parent
commit
9f21f8ea30
3 changed files with 12 additions and 7 deletions
  1. 2 2
      codec/decode.go
  2. 1 0
      codec/helper.go
  3. 9 5
      codec/helper_unsafe.go

+ 2 - 2
codec/decode.go

@@ -1546,7 +1546,6 @@ func (d *Decoder) decode(iv interface{}) {
 		d.decodeValueNotNil(v.Elem(), nil)
 
 	case *string:
-
 		*v = d.d.DecodeString()
 	case *bool:
 		*v = d.d.DecodeBool()
@@ -1796,12 +1795,13 @@ func (d *Decoder) getDecFn(rt reflect.Type, checkFastpath, checkCodecSelfer bool
 }
 
 func (d *Decoder) structFieldNotFound(index int, rvkencname string) {
+	// NOTE: rvkencname may be a stringView, so don't pass it to another function.
 	if d.h.ErrorIfNoField {
 		if index >= 0 {
 			d.errorf("no matching struct field found when decoding stream array at index %v", index)
 			return
 		} else if rvkencname != "" {
-			d.errorf("no matching struct field found when decoding stream map with key %s", rvkencname)
+			d.errorf("no matching struct field found when decoding stream map with key " + rvkencname)
 			return
 		}
 	}

+ 1 - 0
codec/helper.go

@@ -734,6 +734,7 @@ type typeInfo struct {
 }
 
 func (ti *typeInfo) indexForEncName(name string) int {
+	// NOTE: name may be a stringView, so don't pass it to another function.
 	//tisfi := ti.sfi
 	const binarySearchThreshold = 16
 	if sfilen := len(ti.sfi); sfilen < binarySearchThreshold {

+ 9 - 5
codec/helper_unsafe.go

@@ -16,7 +16,7 @@ type unsafeString struct {
 	Len  int
 }
 
-type unsafeBytes struct {
+type unsafeSlice struct {
 	Data uintptr
 	Len  int
 	Cap  int
@@ -29,8 +29,10 @@ func stringView(v []byte) string {
 	if len(v) == 0 {
 		return ""
 	}
-	x := unsafeString{uintptr(unsafe.Pointer(&v[0])), len(v)}
-	return *(*string)(unsafe.Pointer(&x))
+
+	bx := (*unsafeSlice)(unsafe.Pointer(&v))
+	sx := unsafeString{bx.Data, bx.Len}
+	return *(*string)(unsafe.Pointer(&sx))
 }
 
 // bytesView returns a view of the string as a []byte.
@@ -40,6 +42,8 @@ func bytesView(v string) []byte {
 	if len(v) == 0 {
 		return zeroByteSlice
 	}
-	x := unsafeBytes{uintptr(unsafe.Pointer(&v)), len(v), len(v)}
-	return *(*[]byte)(unsafe.Pointer(&x))
+
+	sx := (*unsafeString)(unsafe.Pointer(&v))
+	bx := unsafeSlice{sx.Data, sx.Len, sx.Len}
+	return *(*[]byte)(unsafe.Pointer(&bx))
 }