Prechádzať zdrojové kódy

codec: encode []byte as nil if nil, and handle decoding a []byte from a container containing uint8's

Ugorji Nwoke 8 rokov pred
rodič
commit
bb71fe2c0a
5 zmenil súbory, kde vykonal 61 pridanie a 33 odobranie
  1. 9 0
      codec/binc.go
  2. 8 16
      codec/cbor.go
  3. 12 0
      codec/json.go
  4. 24 16
      codec/msgpack.go
  5. 8 1
      codec/simple.go

+ 9 - 0
codec/binc.go

@@ -276,6 +276,10 @@ func (e *bincEncDriver) EncodeSymbol(v string) {
 }
 
 func (e *bincEncDriver) EncodeStringBytes(c charEncoding, v []byte) {
+	if v == nil {
+		e.EncodeNil()
+		return
+	}
 	l := uint64(len(v))
 	e.encBytesLen(c, l)
 	if l > 0 {
@@ -750,6 +754,11 @@ func (d *bincDecDriver) DecodeBytes(bs []byte, zerocopy bool) (bsOut []byte) {
 		d.bdRead = false
 		return nil
 	}
+	// check if an "array" of uint8's (see ContainerType for how to infer if an array)
+	if d.vd == bincVdArray {
+		bsOut, _ = fastpathTV.DecSliceUint8V(bs, true, d.d)
+		return
+	}
 	var clen int
 	if d.vd == bincVdString || d.vd == bincVdByteArray {
 		clen = d.decLen()

+ 8 - 16
codec/cbor.go

@@ -133,20 +133,12 @@ func (e *cborEncDriver) EncodeTime(t time.Time) {
 		e.EncodeString(cUTF8, t.Format(time.RFC3339Nano))
 	} else {
 		e.encUint(1, cborBaseTag)
-		// fmt.Printf(">>>> - encoding time: %v\n", t)
 		t = t.UTC().Round(0).Round(time.Microsecond)
-		// fmt.Printf(">>>> - encoding time: %v\n", t)
 		sec, nsec := t.Unix(), uint64(t.Nanosecond())
 		if nsec == 0 {
 			e.EncodeInt(sec)
-			// fmt.Printf(">>>> i encoding time using: %v\n", sec)
 		} else {
 			e.EncodeFloat64(float64(sec) + float64(nsec)/1e9)
-			// round nsec to microseconds, so it fits into float64 without losing resolution
-			// e.EncodeFloat64(float64(sec) + round(float64(nsec)/1e3)/1e6)
-			// e.EncodeFloat64(float64(sec) + float64(nsec/1e3)/1e6)
-			// fmt.Printf(">>>> f encoding time using: %v + %v = %v, nsec: %v, \n",
-			// 	float64(sec), round(float64(nsec)/1e3)/1e6, float64(sec)+round(float64(nsec)/1e3)/1e6, nsec)
 		}
 	}
 }
@@ -208,7 +200,9 @@ func (e *cborEncDriver) EncodeString(c charEncoding, v string) {
 }
 
 func (e *cborEncDriver) EncodeStringBytes(c charEncoding, v []byte) {
-	if c == cRAW {
+	if v == nil {
+		e.EncodeNil()
+	} else if c == cRAW {
 		e.encStringBytesS(cborBaseBytes, stringView(v))
 	} else {
 		e.encStringBytesS(cborBaseString, stringView(v))
@@ -502,6 +496,11 @@ func (d *cborDecDriver) DecodeBytes(bs []byte, zerocopy bool) (bsOut []byte) {
 		}
 		return d.decAppendIndefiniteBytes(bs[:0])
 	}
+	// check if an "array" of uint8's (see ContainerType for how to infer if an array)
+	if d.bd == cborBdIndefiniteArray || (d.bd >= cborBaseArray && d.bd < cborBaseMap) {
+		bsOut, _ = fastpathTV.DecSliceUint8V(bs, true, d.d)
+		return
+	}
 	clen := d.decLen()
 	d.bdRead = false
 	if zerocopy {
@@ -547,19 +546,12 @@ func (d *cborDecDriver) decodeTime(xtag uint64) (t time.Time) {
 		switch {
 		case d.bd == cborBdFloat16, d.bd == cborBdFloat32:
 			f1, f2 := math.Modf(d.DecodeFloat(true))
-			// t = time.Unix(int64(f1), int64(round(f2*1e6))*1e3).Round(time.Microsecond).UTC()
 			t = time.Unix(int64(f1), int64(f2*1e9))
 		case d.bd == cborBdFloat64:
 			f1, f2 := math.Modf(d.DecodeFloat(false))
-			// fmt.Printf(">>>> f decoding time using: %v + %v --> %v %v\n",
-			//   f1, f2, int64(f2*1e9), int64(round(f2*1e6))*1e3)
-			// t = time.Unix(int64(f1), (int64(f2*1e9)/1e3)*1e3).UTC()
-			// t = time.Unix(int64(f1), int64(round(f2*1e6))*1e3).Round(time.Microsecond).UTC()
 			t = time.Unix(int64(f1), int64(f2*1e9))
-			// fmt.Printf(">>>> f decoding time using: %v + %v = %v\n", t.Unix(), t.Nanosecond(), t)
 		case d.bd >= cborBaseUint && d.bd < cborBaseNegInt, d.bd >= cborBaseNegInt && d.bd < cborBaseBytes:
 			t = time.Unix(d.DecodeInt(64), 0)
-			// fmt.Printf(">>>> i decoding time using: %v + %v = %v\n", t.Unix(), t.Nanosecond(), t)
 		default:
 			d.d.errorf("cbor: time.Time can only be decoded from a number (or RFC3339 string)")
 		}

+ 12 - 0
codec/json.go

@@ -387,6 +387,10 @@ func (e *jsonEncDriver) EncodeSymbol(v string) {
 
 func (e *jsonEncDriver) EncodeStringBytes(c charEncoding, v []byte) {
 	// if encoding raw bytes and RawBytesExt is configured, use it to encode
+	if v == nil {
+		e.EncodeNil()
+		return
+	}
 	if c == cRAW {
 		if e.se.i != nil {
 			e.EncodeExt(v, 0, &e.se, e.e)
@@ -779,6 +783,14 @@ func (d *jsonDecDriver) DecodeBytes(bs []byte, zerocopy bool) (bsOut []byte) {
 		d.DecodeExt(&bsOut, 0, &d.se)
 		return
 	}
+	if d.tok == 0 {
+		d.tok = d.r.skip(&jsonCharWhitespaceSet)
+	}
+	// check if an "array" of uint8's (see ContainerType for how to infer if an array)
+	if d.tok == '[' {
+		bsOut, _ = fastpathTV.DecSliceUint8V(bs, true, d.d)
+		return
+	}
 	d.appendStringAsBytes()
 	// base64 encodes []byte{} as "", and we encode nil []byte as null.
 	// Consequently, base64 should decode null as a nil []byte, and "" as an empty []byte{}.

+ 24 - 16
codec/msgpack.go

@@ -292,6 +292,10 @@ func (e *msgpackEncDriver) EncodeSymbol(v string) {
 }
 
 func (e *msgpackEncDriver) EncodeStringBytes(c charEncoding, bs []byte) {
+	if bs == nil {
+		e.EncodeNil()
+		return
+	}
 	slen := len(bs)
 	if c == cRAW && e.h.WriteExt {
 		e.writeContainerLen(msgpackContainerBin, slen)
@@ -592,13 +596,15 @@ func (d *msgpackDecDriver) DecodeBytes(bs []byte, zerocopy bool) (bsOut []byte)
 		d.readNextBd()
 	}
 
+	// check if an "array" of uint8's (see ContainerType for how to infer if an array)
+	bd := d.bd
 	// DecodeBytes could be from: bin str fixstr fixarray array ...
 	var clen int
 	vt := d.ContainerType()
 	switch vt {
 	case valueTypeBytes:
 		// valueTypeBytes may be a mpBin or an mpStr container
-		if bd := d.bd; bd == mpBin8 || bd == mpBin16 || bd == mpBin32 {
+		if bd == mpBin8 || bd == mpBin16 || bd == mpBin32 {
 			clen = d.readContainerLen(msgpackContainerBin)
 		} else {
 			clen = d.readContainerLen(msgpackContainerStr)
@@ -606,21 +612,23 @@ func (d *msgpackDecDriver) DecodeBytes(bs []byte, zerocopy bool) (bsOut []byte)
 	case valueTypeString:
 		clen = d.readContainerLen(msgpackContainerStr)
 	case valueTypeArray:
-		clen = d.readContainerLen(msgpackContainerList)
-		// ensure everything after is one byte each
-		for i := 0; i < clen; i++ {
-			d.readNextBd()
-			if d.bd == mpNil {
-				bs = append(bs, 0)
-			} else if d.bd == mpUint8 {
-				bs = append(bs, d.r.readn1())
-			} else {
-				d.d.errorf("cannot read non-byte into a byte array")
-				return
-			}
-		}
-		d.bdRead = false
-		return bs
+		bsOut, _ = fastpathTV.DecSliceUint8V(bs, true, d.d)
+		return
+		// clen = d.readContainerLen(msgpackContainerList)
+		// // ensure everything after is one byte each
+		// for i := 0; i < clen; i++ {
+		// 	d.readNextBd()
+		// 	if d.bd == mpNil {
+		// 		bs = append(bs, 0)
+		// 	} else if d.bd == mpUint8 {
+		// 		bs = append(bs, d.r.readn1())
+		// 	} else {
+		// 		d.d.errorf("cannot read non-byte into a byte array")
+		// 		return
+		// 	}
+		// }
+		// d.bdRead = false
+		// return bs
 	default:
 		d.d.errorf("invalid container type: expecting bin|str|array, got: 0x%x", uint8(vt))
 		return

+ 8 - 1
codec/simple.go

@@ -189,7 +189,8 @@ func (e *simpleEncDriver) EncodeSymbol(v string) {
 }
 
 func (e *simpleEncDriver) EncodeStringBytes(c charEncoding, v []byte) {
-	if e.h.EncZeroValuesAsNil && e.c != containerMapKey && v == nil {
+	// if e.h.EncZeroValuesAsNil && e.c != containerMapKey && v == nil {
+	if v == nil {
 		e.EncodeNil()
 		return
 	}
@@ -465,6 +466,12 @@ func (d *simpleDecDriver) DecodeBytes(bs []byte, zerocopy bool) (bsOut []byte) {
 		d.bdRead = false
 		return
 	}
+	// check if an "array" of uint8's (see ContainerType for how to infer if an array)
+	if d.bd >= simpleVdArray && d.bd <= simpleVdMap+4 {
+		bsOut, _ = fastpathTV.DecSliceUint8V(bs, true, d.d)
+		return
+	}
+
 	clen := d.decLen()
 	d.bdRead = false
 	if zerocopy {