internal/order: add a package for ordered iteration over messages and maps
The order package replaces the mapsort and fieldsort packages.
It presents a common API for ordered iteration over message fields
and map fields.
It has a number of pre-defined orderings.
Change-Id: Ie6cd423da30b4757864c352cb04454f21fe07ee2
Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/239837
Reviewed-by: Herbie Ong <herbie@google.com>
diff --git a/internal/msgfmt/format.go b/internal/msgfmt/format.go
index 9547a53..f01cf60 100644
--- a/internal/msgfmt/format.go
+++ b/internal/msgfmt/format.go
@@ -20,7 +20,7 @@
"google.golang.org/protobuf/encoding/protowire"
"google.golang.org/protobuf/internal/detrand"
"google.golang.org/protobuf/internal/genid"
- "google.golang.org/protobuf/internal/mapsort"
+ "google.golang.org/protobuf/internal/order"
"google.golang.org/protobuf/proto"
"google.golang.org/protobuf/reflect/protoreflect"
"google.golang.org/protobuf/reflect/protoregistry"
@@ -64,25 +64,8 @@
return b2
}
- var fds []protoreflect.FieldDescriptor
- m.Range(func(fd protoreflect.FieldDescriptor, _ protoreflect.Value) bool {
- fds = append(fds, fd)
- return true
- })
- sort.Slice(fds, func(i, j int) bool {
- fdi, fdj := fds[i], fds[j]
- switch {
- case !fdi.IsExtension() && !fdj.IsExtension():
- return fdi.Index() < fdj.Index()
- case fdi.IsExtension() && fdj.IsExtension():
- return fdi.FullName() < fdj.FullName()
- default:
- return !fdi.IsExtension() && fdj.IsExtension()
- }
- })
-
b = append(b, '{')
- for _, fd := range fds {
+ order.RangeFields(m, order.IndexNameFieldOrder, func(fd protoreflect.FieldDescriptor, v protoreflect.Value) bool {
k := string(fd.Name())
if fd.IsExtension() {
k = string("[" + fd.FullName() + "]")
@@ -90,9 +73,10 @@
b = append(b, k...)
b = append(b, ':')
- b = appendValue(b, m.Get(fd), fd)
+ b = appendValue(b, v, fd)
b = append(b, delim()...)
- }
+ return true
+ })
b = appendUnknown(b, m.GetUnknown())
b = bytes.TrimRight(b, delim())
b = append(b, '}')
@@ -247,19 +231,14 @@
}
func appendMap(b []byte, v protoreflect.Map, fd protoreflect.FieldDescriptor) []byte {
- var ks []protoreflect.MapKey
- mapsort.Range(v, fd.MapKey().Kind(), func(k protoreflect.MapKey, _ protoreflect.Value) bool {
- ks = append(ks, k)
- return true
- })
-
b = append(b, '{')
- for _, k := range ks {
+ order.RangeEntries(v, order.GenericKeyOrder, func(k protoreflect.MapKey, v protoreflect.Value) bool {
b = appendValue(b, k.Value(), fd.MapKey())
b = append(b, ':')
- b = appendValue(b, v.Get(k), fd.MapValue())
+ b = appendValue(b, v, fd.MapValue())
b = append(b, delim()...)
- }
+ return true
+ })
b = bytes.TrimRight(b, delim())
b = append(b, '}')
return b