Browse Source

codec: add support for go 1.12 MapRange

Ugorji Nwoke 6 years ago
parent
commit
5950f00715
3 changed files with 54 additions and 9 deletions
  1. 11 9
      codec/encode.go
  2. 14 0
      codec/goversion_maprange_gte_go112.go
  3. 29 0
      codec/goversion_maprange_lt_go112.go

+ 11 - 9
codec/encode.go

@@ -855,10 +855,9 @@ func (e *Encoder) kMap(f *codecFnInfo, rv reflect.Value) {
 	if rtval.Kind() != reflect.Interface {
 	if rtval.Kind() != reflect.Interface {
 		valFn = e.h.fn(rtval)
 		valFn = e.h.fn(rtval)
 	}
 	}
-	mks := rv.MapKeys()
 
 
 	if e.h.Canonical {
 	if e.h.Canonical {
-		e.kMapCanonical(f.ti.key, rv, mks, valFn)
+		e.kMapCanonical(f.ti.key, rv, valFn)
 		e.mapEnd()
 		e.mapEnd()
 		return
 		return
 	}
 	}
@@ -875,28 +874,31 @@ func (e *Encoder) kMap(f *codecFnInfo, rv reflect.Value) {
 		}
 		}
 	}
 	}
 
 
-	// for j, lmks := 0, len(mks); j < lmks; j++ {
-	for j := range mks {
+	it := mapRange(rv)
+	for it.Next() {
 		e.mapElemKey()
 		e.mapElemKey()
 		if keyTypeIsString {
 		if keyTypeIsString {
 			if e.h.StringToRaw {
 			if e.h.StringToRaw {
-				e.e.EncodeStringBytesRaw(bytesView(mks[j].String()))
+				e.e.EncodeStringBytesRaw(bytesView(it.Key().String()))
 			} else {
 			} else {
-				e.e.EncodeStringEnc(cUTF8, mks[j].String())
+				e.e.EncodeStringEnc(cUTF8, it.Key().String())
 			}
 			}
 		} else {
 		} else {
-			e.encodeValue(mks[j], keyFn)
+			e.encodeValue(it.Key(), keyFn)
 		}
 		}
 		e.mapElemValue()
 		e.mapElemValue()
-		e.encodeValue(rv.MapIndex(mks[j]), valFn)
+		e.encodeValue(it.Value(), valFn)
 	}
 	}
+
 	e.mapEnd()
 	e.mapEnd()
 }
 }
 
 
-func (e *Encoder) kMapCanonical(rtkey reflect.Type, rv reflect.Value, mks []reflect.Value, valFn *codecFn) {
+func (e *Encoder) kMapCanonical(rtkey reflect.Type, rv reflect.Value, valFn *codecFn) {
 	// we previously did out-of-band if an extension was registered.
 	// we previously did out-of-band if an extension was registered.
 	// This is not necessary, as the natural kind is sufficient for ordering.
 	// This is not necessary, as the natural kind is sufficient for ordering.
 
 
+	mks := rv.MapKeys()
+
 	switch rtkey.Kind() {
 	switch rtkey.Kind() {
 	case reflect.Bool:
 	case reflect.Bool:
 		mksv := make([]boolRv, len(mks))
 		mksv := make([]boolRv, len(mks))

+ 14 - 0
codec/goversion_maprange_gte_go112.go

@@ -0,0 +1,14 @@
+// Copyright (c) 2012-2018 Ugorji Nwoke. All rights reserved.
+// Use of this source code is governed by a MIT license found in the LICENSE file.
+
+// +build go1.12
+
+// add support for reflect.Value.MapRange.
+
+package codec
+
+import "reflect"
+
+func mapRange(rv reflect.Value) *reflect.MapIter {
+	return rv.MapRange()
+}

+ 29 - 0
codec/goversion_maprange_lt_go112.go

@@ -0,0 +1,29 @@
+// Copyright (c) 2012-2018 Ugorji Nwoke. All rights reserved.
+// Use of this source code is governed by a MIT license found in the LICENSE file.
+
+// +build !go1.12
+
+package codec
+
+import "reflect"
+
+type mapRanger struct {
+	rv  reflect.Value
+	mks []reflect.Value
+	j   int
+}
+
+func (x *mapRanger) Next() bool {
+	x.j++
+	return x.j < len(x.mks)
+}
+func (x *mapRanger) Key() reflect.Value {
+	return x.mks[x.j]
+}
+func (x *mapRanger) Value() reflect.Value {
+	return x.rv.MapIndex(x.mks[x.j])
+}
+
+func mapRange(rv reflect.Value) (g *mapRanger) {
+	return &mapRanger{rv: rv, mks: rv.MapKeys(), j: -1}
+}