7 |
7 |
8 import ( |
8 import ( |
9 "sort" |
9 "sort" |
10 "sync" |
10 "sync" |
11 |
11 |
12 pref "google.golang.org/protobuf/reflect/protoreflect" |
12 "google.golang.org/protobuf/reflect/protoreflect" |
13 ) |
13 ) |
14 |
14 |
15 type messageField struct { |
15 type messageField struct { |
16 fd pref.FieldDescriptor |
16 fd protoreflect.FieldDescriptor |
17 v pref.Value |
17 v protoreflect.Value |
18 } |
18 } |
19 |
19 |
20 var messageFieldPool = sync.Pool{ |
20 var messageFieldPool = sync.Pool{ |
21 New: func() interface{} { return new([]messageField) }, |
21 New: func() interface{} { return new([]messageField) }, |
22 } |
22 } |
23 |
23 |
24 type ( |
24 type ( |
25 // FieldRnger is an interface for visiting all fields in a message. |
25 // FieldRnger is an interface for visiting all fields in a message. |
26 // The protoreflect.Message type implements this interface. |
26 // The protoreflect.Message type implements this interface. |
27 FieldRanger interface{ Range(VisitField) } |
27 FieldRanger interface{ Range(VisitField) } |
28 // VisitField is called everytime a message field is visited. |
28 // VisitField is called every time a message field is visited. |
29 VisitField = func(pref.FieldDescriptor, pref.Value) bool |
29 VisitField = func(protoreflect.FieldDescriptor, protoreflect.Value) bool |
30 ) |
30 ) |
31 |
31 |
32 // RangeFields iterates over the fields of fs according to the specified order. |
32 // RangeFields iterates over the fields of fs according to the specified order. |
33 func RangeFields(fs FieldRanger, less FieldOrder, fn VisitField) { |
33 func RangeFields(fs FieldRanger, less FieldOrder, fn VisitField) { |
34 if less == nil { |
34 if less == nil { |
45 messageFieldPool.Put(p) |
45 messageFieldPool.Put(p) |
46 } |
46 } |
47 }() |
47 }() |
48 |
48 |
49 // Collect all fields in the message and sort them. |
49 // Collect all fields in the message and sort them. |
50 fs.Range(func(fd pref.FieldDescriptor, v pref.Value) bool { |
50 fs.Range(func(fd protoreflect.FieldDescriptor, v protoreflect.Value) bool { |
51 fields = append(fields, messageField{fd, v}) |
51 fields = append(fields, messageField{fd, v}) |
52 return true |
52 return true |
53 }) |
53 }) |
54 sort.Slice(fields, func(i, j int) bool { |
54 sort.Slice(fields, func(i, j int) bool { |
55 return less(fields[i].fd, fields[j].fd) |
55 return less(fields[i].fd, fields[j].fd) |
62 } |
62 } |
63 } |
63 } |
64 } |
64 } |
65 |
65 |
66 type mapEntry struct { |
66 type mapEntry struct { |
67 k pref.MapKey |
67 k protoreflect.MapKey |
68 v pref.Value |
68 v protoreflect.Value |
69 } |
69 } |
70 |
70 |
71 var mapEntryPool = sync.Pool{ |
71 var mapEntryPool = sync.Pool{ |
72 New: func() interface{} { return new([]mapEntry) }, |
72 New: func() interface{} { return new([]mapEntry) }, |
73 } |
73 } |
74 |
74 |
75 type ( |
75 type ( |
76 // EntryRanger is an interface for visiting all fields in a message. |
76 // EntryRanger is an interface for visiting all fields in a message. |
77 // The protoreflect.Map type implements this interface. |
77 // The protoreflect.Map type implements this interface. |
78 EntryRanger interface{ Range(VisitEntry) } |
78 EntryRanger interface{ Range(VisitEntry) } |
79 // VisitEntry is called everytime a map entry is visited. |
79 // VisitEntry is called every time a map entry is visited. |
80 VisitEntry = func(pref.MapKey, pref.Value) bool |
80 VisitEntry = func(protoreflect.MapKey, protoreflect.Value) bool |
81 ) |
81 ) |
82 |
82 |
83 // RangeEntries iterates over the entries of es according to the specified order. |
83 // RangeEntries iterates over the entries of es according to the specified order. |
84 func RangeEntries(es EntryRanger, less KeyOrder, fn VisitEntry) { |
84 func RangeEntries(es EntryRanger, less KeyOrder, fn VisitEntry) { |
85 if less == nil { |
85 if less == nil { |
96 mapEntryPool.Put(p) |
96 mapEntryPool.Put(p) |
97 } |
97 } |
98 }() |
98 }() |
99 |
99 |
100 // Collect all entries in the map and sort them. |
100 // Collect all entries in the map and sort them. |
101 es.Range(func(k pref.MapKey, v pref.Value) bool { |
101 es.Range(func(k protoreflect.MapKey, v protoreflect.Value) bool { |
102 entries = append(entries, mapEntry{k, v}) |
102 entries = append(entries, mapEntry{k, v}) |
103 return true |
103 return true |
104 }) |
104 }) |
105 sort.Slice(entries, func(i, j int) bool { |
105 sort.Slice(entries, func(i, j int) bool { |
106 return less(entries[i].k, entries[j].k) |
106 return less(entries[i].k, entries[j].k) |