mirror of
https://github.com/protocolbuffers/protobuf-go.git
synced 2025-01-04 02:38:50 +00:00
01c0e8d680
The v1 wire marshaler sorts fields as follows: - All extensions, sorted by field number. - All non-oneof fields, sorted by field number. - All oneof fields, in indeterminate order. We already make some steps toward supporting this ordering: The fast path encoder places extensions in sorted order at the start of the message. This commit moves oneof fields to the end of the message, makes the reflection-based encoder use this ordering when deterministic marshaling is enabled, and adds a test to catch unintentional changes to the ordering. Users SHOULD NOT depend on stability of the marshal output. It is subject to change over time. Without deterministic marshaling enabled, it is subject to change over calls to Marshal. Change-Id: I6cfd89090d790a3bb50785f32b94d2781d7d08db Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/206800 Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
41 lines
1.1 KiB
Go
41 lines
1.1 KiB
Go
// Copyright 2019 The Go Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
// Package fieldsort defines an ordering of fields.
|
|
//
|
|
// The ordering defined by this package matches the historic behavior of the proto
|
|
// package, placing extensions first and oneofs last.
|
|
//
|
|
// There is no guarantee about stability of the wire encoding, and users should not
|
|
// depend on the order defined in this package as it is subject to change without
|
|
// notice.
|
|
package fieldsort
|
|
|
|
import (
|
|
"google.golang.org/protobuf/reflect/protoreflect"
|
|
)
|
|
|
|
// Less returns true if field a comes before field j in ordered wire marshal output.
|
|
func Less(a, b protoreflect.FieldDescriptor) bool {
|
|
ea := a.IsExtension()
|
|
eb := b.IsExtension()
|
|
oa := a.ContainingOneof()
|
|
ob := b.ContainingOneof()
|
|
switch {
|
|
case ea != eb:
|
|
return ea
|
|
case oa != nil && ob != nil:
|
|
if oa == ob {
|
|
return a.Number() < b.Number()
|
|
}
|
|
return oa.Index() < ob.Index()
|
|
case oa != nil:
|
|
return false
|
|
case ob != nil:
|
|
return true
|
|
default:
|
|
return a.Number() < b.Number()
|
|
}
|
|
}
|