order.go raw

   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  
   5  package order
   6  
   7  import (
   8  	"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.
  13  type FieldOrder func(x, y protoreflect.FieldDescriptor) bool
  14  
  15  var (
  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 protoreflect.FieldDescriptor) bool {
  22  		ox, oy := x.ContainingOneof(), y.ContainingOneof()
  23  		inOneof := func(od protoreflect.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 inOneof(ox) && inOneof(oy) && 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 protoreflect.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 protoreflect.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.
  67  type KeyOrder func(x, y protoreflect.MapKey) bool
  68  
  69  var (
  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 protoreflect.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  )
  90