You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

90 lines
2.9 KiB

  1. // 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. package order
  5. import (
  6. "google.golang.org/protobuf/reflect/protoreflect"
  7. )
  8. // FieldOrder specifies the ordering to visit message fields.
  9. // It is a function that reports whether x is ordered before y.
  10. type FieldOrder func(x, y protoreflect.FieldDescriptor) bool
  11. var (
  12. // AnyFieldOrder specifies no specific field ordering.
  13. AnyFieldOrder FieldOrder = nil
  14. // LegacyFieldOrder sorts fields in the same ordering as emitted by
  15. // wire serialization in the github.com/golang/protobuf implementation.
  16. LegacyFieldOrder FieldOrder = func(x, y protoreflect.FieldDescriptor) bool {
  17. ox, oy := x.ContainingOneof(), y.ContainingOneof()
  18. inOneof := func(od protoreflect.OneofDescriptor) bool {
  19. return od != nil && !od.IsSynthetic()
  20. }
  21. // Extension fields sort before non-extension fields.
  22. if x.IsExtension() != y.IsExtension() {
  23. return x.IsExtension() && !y.IsExtension()
  24. }
  25. // Fields not within a oneof sort before those within a oneof.
  26. if inOneof(ox) != inOneof(oy) {
  27. return !inOneof(ox) && inOneof(oy)
  28. }
  29. // Fields in disjoint oneof sets are sorted by declaration index.
  30. if ox != nil && oy != nil && ox != oy {
  31. return ox.Index() < oy.Index()
  32. }
  33. // Fields sorted by field number.
  34. return x.Number() < y.Number()
  35. }
  36. // NumberFieldOrder sorts fields by their field number.
  37. NumberFieldOrder FieldOrder = func(x, y protoreflect.FieldDescriptor) bool {
  38. return x.Number() < y.Number()
  39. }
  40. // IndexNameFieldOrder sorts non-extension fields before extension fields.
  41. // Non-extensions are sorted according to their declaration index.
  42. // Extensions are sorted according to their full name.
  43. IndexNameFieldOrder FieldOrder = func(x, y protoreflect.FieldDescriptor) bool {
  44. // Non-extension fields sort before extension fields.
  45. if x.IsExtension() != y.IsExtension() {
  46. return !x.IsExtension() && y.IsExtension()
  47. }
  48. // Extensions sorted by fullname.
  49. if x.IsExtension() && y.IsExtension() {
  50. return x.FullName() < y.FullName()
  51. }
  52. // Non-extensions sorted by declaration index.
  53. return x.Index() < y.Index()
  54. }
  55. )
  56. // KeyOrder specifies the ordering to visit map entries.
  57. // It is a function that reports whether x is ordered before y.
  58. type KeyOrder func(x, y protoreflect.MapKey) bool
  59. var (
  60. // AnyKeyOrder specifies no specific key ordering.
  61. AnyKeyOrder KeyOrder = nil
  62. // GenericKeyOrder sorts false before true, numeric keys in ascending order,
  63. // and strings in lexicographical ordering according to UTF-8 codepoints.
  64. GenericKeyOrder KeyOrder = func(x, y protoreflect.MapKey) bool {
  65. switch x.Interface().(type) {
  66. case bool:
  67. return !x.Bool() && y.Bool()
  68. case int32, int64:
  69. return x.Int() < y.Int()
  70. case uint32, uint64:
  71. return x.Uint() < y.Uint()
  72. case string:
  73. return x.String() < y.String()
  74. default:
  75. panic("invalid map key type")
  76. }
  77. }
  78. )