mirror of
https://github.com/rocky-linux/peridot.git
synced 2024-11-28 07:56:25 +00:00
178 lines
5.9 KiB
Go
178 lines
5.9 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 protodesc
|
||
|
|
||
|
import (
|
||
|
_ "embed"
|
||
|
"fmt"
|
||
|
"os"
|
||
|
"sync"
|
||
|
|
||
|
"google.golang.org/protobuf/internal/filedesc"
|
||
|
"google.golang.org/protobuf/proto"
|
||
|
"google.golang.org/protobuf/types/descriptorpb"
|
||
|
)
|
||
|
|
||
|
const (
|
||
|
SupportedEditionsMinimum = descriptorpb.Edition_EDITION_PROTO2
|
||
|
SupportedEditionsMaximum = descriptorpb.Edition_EDITION_2023
|
||
|
)
|
||
|
|
||
|
//go:embed editions_defaults.binpb
|
||
|
var binaryEditionDefaults []byte
|
||
|
var defaults = &descriptorpb.FeatureSetDefaults{}
|
||
|
var defaultsCacheMu sync.Mutex
|
||
|
var defaultsCache = make(map[filedesc.Edition]*descriptorpb.FeatureSet)
|
||
|
|
||
|
func init() {
|
||
|
err := proto.Unmarshal(binaryEditionDefaults, defaults)
|
||
|
if err != nil {
|
||
|
fmt.Fprintf(os.Stderr, "unmarshal editions defaults: %v\n", err)
|
||
|
os.Exit(1)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func fromEditionProto(epb descriptorpb.Edition) filedesc.Edition {
|
||
|
return filedesc.Edition(epb)
|
||
|
}
|
||
|
|
||
|
func toEditionProto(ed filedesc.Edition) descriptorpb.Edition {
|
||
|
switch ed {
|
||
|
case filedesc.EditionUnknown:
|
||
|
return descriptorpb.Edition_EDITION_UNKNOWN
|
||
|
case filedesc.EditionProto2:
|
||
|
return descriptorpb.Edition_EDITION_PROTO2
|
||
|
case filedesc.EditionProto3:
|
||
|
return descriptorpb.Edition_EDITION_PROTO3
|
||
|
case filedesc.Edition2023:
|
||
|
return descriptorpb.Edition_EDITION_2023
|
||
|
default:
|
||
|
panic(fmt.Sprintf("unknown value for edition: %v", ed))
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func getFeatureSetFor(ed filedesc.Edition) *descriptorpb.FeatureSet {
|
||
|
defaultsCacheMu.Lock()
|
||
|
defer defaultsCacheMu.Unlock()
|
||
|
if def, ok := defaultsCache[ed]; ok {
|
||
|
return def
|
||
|
}
|
||
|
edpb := toEditionProto(ed)
|
||
|
if defaults.GetMinimumEdition() > edpb || defaults.GetMaximumEdition() < edpb {
|
||
|
// This should never happen protodesc.(FileOptions).New would fail when
|
||
|
// initializing the file descriptor.
|
||
|
// This most likely means the embedded defaults were not updated.
|
||
|
fmt.Fprintf(os.Stderr, "internal error: unsupported edition %v (did you forget to update the embedded defaults (i.e. the bootstrap descriptor proto)?)\n", edpb)
|
||
|
os.Exit(1)
|
||
|
}
|
||
|
fs := defaults.GetDefaults()[0].GetFeatures()
|
||
|
// Using a linear search for now.
|
||
|
// Editions are guaranteed to be sorted and thus we could use a binary search.
|
||
|
// Given that there are only a handful of editions (with one more per year)
|
||
|
// there is not much reason to use a binary search.
|
||
|
for _, def := range defaults.GetDefaults() {
|
||
|
if def.GetEdition() <= edpb {
|
||
|
fs = def.GetFeatures()
|
||
|
} else {
|
||
|
break
|
||
|
}
|
||
|
}
|
||
|
defaultsCache[ed] = fs
|
||
|
return fs
|
||
|
}
|
||
|
|
||
|
func resolveFeatureHasFieldPresence(fileDesc *filedesc.File, fieldDesc *descriptorpb.FieldDescriptorProto) bool {
|
||
|
fs := fieldDesc.GetOptions().GetFeatures()
|
||
|
if fs == nil || fs.FieldPresence == nil {
|
||
|
return fileDesc.L1.EditionFeatures.IsFieldPresence
|
||
|
}
|
||
|
return fs.GetFieldPresence() == descriptorpb.FeatureSet_LEGACY_REQUIRED ||
|
||
|
fs.GetFieldPresence() == descriptorpb.FeatureSet_EXPLICIT
|
||
|
}
|
||
|
|
||
|
func resolveFeatureRepeatedFieldEncodingPacked(fileDesc *filedesc.File, fieldDesc *descriptorpb.FieldDescriptorProto) bool {
|
||
|
fs := fieldDesc.GetOptions().GetFeatures()
|
||
|
if fs == nil || fs.RepeatedFieldEncoding == nil {
|
||
|
return fileDesc.L1.EditionFeatures.IsPacked
|
||
|
}
|
||
|
return fs.GetRepeatedFieldEncoding() == descriptorpb.FeatureSet_PACKED
|
||
|
}
|
||
|
|
||
|
func resolveFeatureEnforceUTF8(fileDesc *filedesc.File, fieldDesc *descriptorpb.FieldDescriptorProto) bool {
|
||
|
fs := fieldDesc.GetOptions().GetFeatures()
|
||
|
if fs == nil || fs.Utf8Validation == nil {
|
||
|
return fileDesc.L1.EditionFeatures.IsUTF8Validated
|
||
|
}
|
||
|
return fs.GetUtf8Validation() == descriptorpb.FeatureSet_VERIFY
|
||
|
}
|
||
|
|
||
|
func resolveFeatureDelimitedEncoding(fileDesc *filedesc.File, fieldDesc *descriptorpb.FieldDescriptorProto) bool {
|
||
|
fs := fieldDesc.GetOptions().GetFeatures()
|
||
|
if fs == nil || fs.MessageEncoding == nil {
|
||
|
return fileDesc.L1.EditionFeatures.IsDelimitedEncoded
|
||
|
}
|
||
|
return fs.GetMessageEncoding() == descriptorpb.FeatureSet_DELIMITED
|
||
|
}
|
||
|
|
||
|
// initFileDescFromFeatureSet initializes editions related fields in fd based
|
||
|
// on fs. If fs is nil it is assumed to be an empty featureset and all fields
|
||
|
// will be initialized with the appropriate default. fd.L1.Edition must be set
|
||
|
// before calling this function.
|
||
|
func initFileDescFromFeatureSet(fd *filedesc.File, fs *descriptorpb.FeatureSet) {
|
||
|
dfs := getFeatureSetFor(fd.L1.Edition)
|
||
|
if fs == nil {
|
||
|
fs = &descriptorpb.FeatureSet{}
|
||
|
}
|
||
|
|
||
|
var fieldPresence descriptorpb.FeatureSet_FieldPresence
|
||
|
if fp := fs.FieldPresence; fp != nil {
|
||
|
fieldPresence = *fp
|
||
|
} else {
|
||
|
fieldPresence = *dfs.FieldPresence
|
||
|
}
|
||
|
fd.L1.EditionFeatures.IsFieldPresence = fieldPresence == descriptorpb.FeatureSet_LEGACY_REQUIRED ||
|
||
|
fieldPresence == descriptorpb.FeatureSet_EXPLICIT
|
||
|
|
||
|
var enumType descriptorpb.FeatureSet_EnumType
|
||
|
if et := fs.EnumType; et != nil {
|
||
|
enumType = *et
|
||
|
} else {
|
||
|
enumType = *dfs.EnumType
|
||
|
}
|
||
|
fd.L1.EditionFeatures.IsOpenEnum = enumType == descriptorpb.FeatureSet_OPEN
|
||
|
|
||
|
var respeatedFieldEncoding descriptorpb.FeatureSet_RepeatedFieldEncoding
|
||
|
if rfe := fs.RepeatedFieldEncoding; rfe != nil {
|
||
|
respeatedFieldEncoding = *rfe
|
||
|
} else {
|
||
|
respeatedFieldEncoding = *dfs.RepeatedFieldEncoding
|
||
|
}
|
||
|
fd.L1.EditionFeatures.IsPacked = respeatedFieldEncoding == descriptorpb.FeatureSet_PACKED
|
||
|
|
||
|
var isUTF8Validated descriptorpb.FeatureSet_Utf8Validation
|
||
|
if utf8val := fs.Utf8Validation; utf8val != nil {
|
||
|
isUTF8Validated = *utf8val
|
||
|
} else {
|
||
|
isUTF8Validated = *dfs.Utf8Validation
|
||
|
}
|
||
|
fd.L1.EditionFeatures.IsUTF8Validated = isUTF8Validated == descriptorpb.FeatureSet_VERIFY
|
||
|
|
||
|
var messageEncoding descriptorpb.FeatureSet_MessageEncoding
|
||
|
if me := fs.MessageEncoding; me != nil {
|
||
|
messageEncoding = *me
|
||
|
} else {
|
||
|
messageEncoding = *dfs.MessageEncoding
|
||
|
}
|
||
|
fd.L1.EditionFeatures.IsDelimitedEncoded = messageEncoding == descriptorpb.FeatureSet_DELIMITED
|
||
|
|
||
|
var jsonFormat descriptorpb.FeatureSet_JsonFormat
|
||
|
if jf := fs.JsonFormat; jf != nil {
|
||
|
jsonFormat = *jf
|
||
|
} else {
|
||
|
jsonFormat = *dfs.JsonFormat
|
||
|
}
|
||
|
fd.L1.EditionFeatures.IsJSONCompliant = jsonFormat == descriptorpb.FeatureSet_ALLOW
|
||
|
}
|