blob: 2a24953f6a47a856a905cafe688c2480fc5333c2 [file] [log] [blame]
khenaidoo106c61a2021-08-11 18:05:46 -04001// Copyright 2020 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package order
6
7import (
8 pref "google.golang.org/protobuf/reflect/protoreflect"
9)
10
11// FieldOrder specifies the ordering to visit message fields.
12// It is a function that reports whether x is ordered before y.
13type FieldOrder func(x, y pref.FieldDescriptor) bool
14
15var (
16 // AnyFieldOrder specifies no specific field ordering.
17 AnyFieldOrder FieldOrder = nil
18
19 // LegacyFieldOrder sorts fields in the same ordering as emitted by
20 // wire serialization in the github.com/golang/protobuf implementation.
21 LegacyFieldOrder FieldOrder = func(x, y pref.FieldDescriptor) bool {
22 ox, oy := x.ContainingOneof(), y.ContainingOneof()
23 inOneof := func(od pref.OneofDescriptor) bool {
24 return od != nil && !od.IsSynthetic()
25 }
26
27 // Extension fields sort before non-extension fields.
28 if x.IsExtension() != y.IsExtension() {
29 return x.IsExtension() && !y.IsExtension()
30 }
31 // Fields not within a oneof sort before those within a oneof.
32 if inOneof(ox) != inOneof(oy) {
33 return !inOneof(ox) && inOneof(oy)
34 }
35 // Fields in disjoint oneof sets are sorted by declaration index.
36 if ox != nil && oy != nil && ox != oy {
37 return ox.Index() < oy.Index()
38 }
39 // Fields sorted by field number.
40 return x.Number() < y.Number()
41 }
42
43 // NumberFieldOrder sorts fields by their field number.
44 NumberFieldOrder FieldOrder = func(x, y pref.FieldDescriptor) bool {
45 return x.Number() < y.Number()
46 }
47
48 // IndexNameFieldOrder sorts non-extension fields before extension fields.
49 // Non-extensions are sorted according to their declaration index.
50 // Extensions are sorted according to their full name.
51 IndexNameFieldOrder FieldOrder = func(x, y pref.FieldDescriptor) bool {
52 // Non-extension fields sort before extension fields.
53 if x.IsExtension() != y.IsExtension() {
54 return !x.IsExtension() && y.IsExtension()
55 }
56 // Extensions sorted by fullname.
57 if x.IsExtension() && y.IsExtension() {
58 return x.FullName() < y.FullName()
59 }
60 // Non-extensions sorted by declaration index.
61 return x.Index() < y.Index()
62 }
63)
64
65// KeyOrder specifies the ordering to visit map entries.
66// It is a function that reports whether x is ordered before y.
67type KeyOrder func(x, y pref.MapKey) bool
68
69var (
70 // AnyKeyOrder specifies no specific key ordering.
71 AnyKeyOrder KeyOrder = nil
72
73 // GenericKeyOrder sorts false before true, numeric keys in ascending order,
74 // and strings in lexicographical ordering according to UTF-8 codepoints.
75 GenericKeyOrder KeyOrder = func(x, y pref.MapKey) bool {
76 switch x.Interface().(type) {
77 case bool:
78 return !x.Bool() && y.Bool()
79 case int32, int64:
80 return x.Int() < y.Int()
81 case uint32, uint64:
82 return x.Uint() < y.Uint()
83 case string:
84 return x.String() < y.String()
85 default:
86 panic("invalid map key type")
87 }
88 }
89)