parent
d6895b548e
commit
8f882e7f3d
8 changed files with 645 additions and 2 deletions
@ -0,0 +1,104 @@ |
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include "google/protobuf/compiler/retention.h" |
||||
|
||||
#include <memory> |
||||
#include <string> |
||||
#include <vector> |
||||
|
||||
#include "google/protobuf/descriptor.h" |
||||
#include "google/protobuf/dynamic_message.h" |
||||
|
||||
namespace google { |
||||
namespace protobuf { |
||||
namespace compiler { |
||||
|
||||
namespace { |
||||
// Recursively strips any options with source retention from the message.
|
||||
void StripMessage(Message& m) { |
||||
const Reflection* reflection = m.GetReflection(); |
||||
std::vector<const FieldDescriptor*> fields; |
||||
reflection->ListFields(m, &fields); |
||||
for (const FieldDescriptor* field : fields) { |
||||
if (field->options().retention() == FieldOptions::RETENTION_SOURCE) { |
||||
reflection->ClearField(&m, field); |
||||
} else if (field->type() == FieldDescriptor::TYPE_MESSAGE) { |
||||
if (field->is_repeated()) { |
||||
int field_size = reflection->FieldSize(m, field); |
||||
for (int i = 0; i < field_size; ++i) { |
||||
StripMessage(*reflection->MutableRepeatedMessage(&m, field, i)); |
||||
} |
||||
} else { |
||||
StripMessage(*reflection->MutableMessage(&m, field)); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} // namespace
|
||||
|
||||
FileDescriptorProto StripSourceRetentionOptions(const FileDescriptor& file) { |
||||
FileDescriptorProto file_proto; |
||||
file.CopyTo(&file_proto); |
||||
|
||||
// We need to look up the descriptor in file.pool() so that we can get a
|
||||
// descriptor which knows about any custom options that were used in the
|
||||
// .proto file.
|
||||
const Descriptor* descriptor = |
||||
file.pool()->FindMessageTypeByName(FileDescriptorProto().GetTypeName()); |
||||
|
||||
if (descriptor == nullptr) { |
||||
// If the pool does not contain the descriptor for FileDescriptorProto,
|
||||
// then this proto file does not transitively depend on descriptor.proto,
|
||||
// in which case we know there are no custom options to worry about.
|
||||
StripMessage(file_proto); |
||||
} else { |
||||
// The options message may have custom options set on it, and these would
|
||||
// ordinarily appear as unknown fields since they are not linked into
|
||||
// protoc. Using a dynamic message allows us to see these custom options.
|
||||
// To convert back and forth between the generated type and the dynamic
|
||||
// message, we have to serialize one and parse that into the other.
|
||||
DynamicMessageFactory factory; |
||||
std::unique_ptr<Message> dynamic_message( |
||||
factory.GetPrototype(descriptor)->New()); |
||||
std::string serialized; |
||||
ABSL_CHECK(file_proto.SerializeToString(&serialized)); |
||||
ABSL_CHECK(dynamic_message->ParseFromString(serialized)); |
||||
StripMessage(*dynamic_message); |
||||
ABSL_CHECK(dynamic_message->SerializeToString(&serialized)); |
||||
ABSL_CHECK(file_proto.ParseFromString(serialized)); |
||||
} |
||||
|
||||
return file_proto; |
||||
} |
||||
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
@ -0,0 +1,49 @@ |
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_COMPILER_RETENTION_H__ |
||||
#define GOOGLE_PROTOBUF_COMPILER_RETENTION_H__ |
||||
|
||||
#include "google/protobuf/descriptor.h" |
||||
#include "google/protobuf/descriptor.pb.h" |
||||
|
||||
namespace google { |
||||
namespace protobuf { |
||||
namespace compiler { |
||||
|
||||
// Returns a FileDescriptorProto for this file, with all RETENTION_SOURCE
|
||||
// options stripped out.
|
||||
FileDescriptorProto StripSourceRetentionOptions(const FileDescriptor& file); |
||||
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_COMPILER_RETENTION_H__
|
@ -0,0 +1,246 @@ |
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include "google/protobuf/compiler/retention.h" |
||||
|
||||
#include <memory> |
||||
#include <string> |
||||
#include <vector> |
||||
|
||||
#include "google/protobuf/descriptor.pb.h" |
||||
#include <gtest/gtest.h> |
||||
#include "absl/strings/substitute.h" |
||||
#include "google/protobuf/compiler/parser.h" |
||||
#include "google/protobuf/dynamic_message.h" |
||||
#include "google/protobuf/io/tokenizer.h" |
||||
#include "google/protobuf/io/zero_copy_stream_impl_lite.h" |
||||
#include "google/protobuf/text_format.h" |
||||
#include "google/protobuf/unittest_retention.pb.h" |
||||
#include "google/protobuf/util/message_differencer.h" |
||||
|
||||
namespace google { |
||||
namespace protobuf { |
||||
namespace internal { |
||||
namespace { |
||||
|
||||
TEST(RetentionTest, DirectOptions) { |
||||
const google::protobuf::FileOptions& file_options = |
||||
OptionsMessage::descriptor()->file()->options(); |
||||
EXPECT_EQ(file_options.GetExtension(plain_option), 1); |
||||
EXPECT_EQ(file_options.GetExtension(runtime_retention_option), 2); |
||||
// RETENTION_SOURCE option should be stripped.
|
||||
EXPECT_FALSE(file_options.HasExtension(source_retention_option)); |
||||
EXPECT_EQ(file_options.GetExtension(source_retention_option), 0); |
||||
} |
||||
|
||||
void CheckOptionsMessageIsStrippedCorrectly(const OptionsMessage& options) { |
||||
EXPECT_EQ(options.plain_field(), 1); |
||||
EXPECT_EQ(options.runtime_retention_field(), 2); |
||||
// RETENTION_SOURCE field should be stripped.
|
||||
EXPECT_FALSE(options.has_source_retention_field()); |
||||
EXPECT_EQ(options.source_retention_field(), 0); |
||||
} |
||||
|
||||
TEST(RetentionTest, FieldsNestedInRepeatedMessage) { |
||||
const google::protobuf::FileOptions& file_options = |
||||
OptionsMessage::descriptor()->file()->options(); |
||||
ASSERT_EQ(1, file_options.ExtensionSize(repeated_options)); |
||||
const OptionsMessage& options_message = |
||||
file_options.GetRepeatedExtension(repeated_options)[0]; |
||||
CheckOptionsMessageIsStrippedCorrectly(options_message); |
||||
} |
||||
|
||||
TEST(RetentionTest, File) { |
||||
CheckOptionsMessageIsStrippedCorrectly( |
||||
OptionsMessage::descriptor()->file()->options().GetExtension( |
||||
file_option)); |
||||
} |
||||
|
||||
TEST(RetentionTest, TopLevelMessage) { |
||||
CheckOptionsMessageIsStrippedCorrectly( |
||||
TopLevelMessage::descriptor()->options().GetExtension(message_option)); |
||||
} |
||||
|
||||
TEST(RetentionTest, NestedMessage) { |
||||
CheckOptionsMessageIsStrippedCorrectly( |
||||
TopLevelMessage::NestedMessage::descriptor()->options().GetExtension( |
||||
message_option)); |
||||
} |
||||
|
||||
TEST(RetentionTest, TopLevelEnum) { |
||||
CheckOptionsMessageIsStrippedCorrectly( |
||||
TopLevelEnum_descriptor()->options().GetExtension(enum_option)); |
||||
} |
||||
|
||||
TEST(RetentionTest, NestedEnum) { |
||||
CheckOptionsMessageIsStrippedCorrectly( |
||||
TopLevelMessage::NestedEnum_descriptor()->options().GetExtension( |
||||
enum_option)); |
||||
} |
||||
|
||||
TEST(RetentionTest, EnumEntry) { |
||||
CheckOptionsMessageIsStrippedCorrectly( |
||||
TopLevelEnum_descriptor()->value(0)->options().GetExtension( |
||||
enum_entry_option)); |
||||
} |
||||
|
||||
TEST(RetentionTest, TopLevelExtension) { |
||||
CheckOptionsMessageIsStrippedCorrectly(TopLevelMessage::descriptor() |
||||
->file() |
||||
->FindExtensionByName("i") |
||||
->options() |
||||
.GetExtension(field_option)); |
||||
} |
||||
|
||||
TEST(RetentionTest, NestedExtension) { |
||||
CheckOptionsMessageIsStrippedCorrectly( |
||||
TopLevelMessage::descriptor()->extension(0)->options().GetExtension( |
||||
field_option)); |
||||
} |
||||
|
||||
TEST(RetentionTest, Field) { |
||||
CheckOptionsMessageIsStrippedCorrectly( |
||||
TopLevelMessage::descriptor()->field(0)->options().GetExtension( |
||||
field_option)); |
||||
} |
||||
|
||||
TEST(RetentionTest, Oneof) { |
||||
CheckOptionsMessageIsStrippedCorrectly( |
||||
TopLevelMessage::descriptor()->oneof_decl(0)->options().GetExtension( |
||||
oneof_option)); |
||||
} |
||||
|
||||
TEST(RetentionTest, ExtensionRange) { |
||||
CheckOptionsMessageIsStrippedCorrectly( |
||||
TopLevelMessage::descriptor()->extension_range(0)->options_->GetExtension( |
||||
extension_range_option)); |
||||
} |
||||
|
||||
TEST(RetentionTest, Service) { |
||||
CheckOptionsMessageIsStrippedCorrectly( |
||||
TopLevelMessage::descriptor()->file()->service(0)->options().GetExtension( |
||||
service_option)); |
||||
} |
||||
|
||||
TEST(RetentionTest, Method) { |
||||
CheckOptionsMessageIsStrippedCorrectly(TopLevelMessage::descriptor() |
||||
->file() |
||||
->service(0) |
||||
->method(0) |
||||
->options() |
||||
.GetExtension(method_option)); |
||||
} |
||||
|
||||
TEST(RetentionTest, StripSourceRetentionOptions) { |
||||
// The tests above make assertions against the generated code, but this test
|
||||
// case directly examines the result of the StripSourceRetentionOptions()
|
||||
// function instead.
|
||||
std::string proto_file = |
||||
absl::Substitute(R"( |
||||
syntax = "proto2"; |
||||
|
||||
package google.protobuf.internal; |
||||
|
||||
import "$0"; |
||||
|
||||
option (source_retention_option) = 123; |
||||
option (options) = { |
||||
i1: 123 |
||||
i2: 456 |
||||
c { s: "abc" } |
||||
rc { s: "abc" } |
||||
}; |
||||
option (repeated_options) = { |
||||
i1: 111 i2: 222 |
||||
}; |
||||
|
||||
message Options { |
||||
optional int32 i1 = 1 [retention = RETENTION_SOURCE]; |
||||
optional int32 i2 = 2; |
||||
message ChildMessage { |
||||
optional string s = 1 [retention = RETENTION_SOURCE]; |
||||
} |
||||
optional ChildMessage c = 3; |
||||
repeated ChildMessage rc = 4; |
||||
} |
||||
|
||||
extend google.protobuf.FileOptions { |
||||
optional int32 source_retention_option = 50000 [retention = RETENTION_SOURCE]; |
||||
optional Options options = 50001; |
||||
repeated Options repeated_options = 50002; |
||||
})", |
||||
FileDescriptorSet::descriptor()->file()->name()); |
||||
io::ArrayInputStream input_stream(proto_file.data(), |
||||
static_cast<int>(proto_file.size())); |
||||
io::ErrorCollector error_collector; |
||||
io::Tokenizer tokenizer(&input_stream, &error_collector); |
||||
compiler::Parser parser; |
||||
FileDescriptorProto file_descriptor; |
||||
ASSERT_TRUE(parser.Parse(&tokenizer, &file_descriptor)); |
||||
file_descriptor.set_name("retention.proto"); |
||||
|
||||
DescriptorPool pool; |
||||
FileDescriptorProto descriptor_proto_descriptor; |
||||
FileDescriptorSet::descriptor()->file()->CopyTo(&descriptor_proto_descriptor); |
||||
pool.BuildFile(descriptor_proto_descriptor); |
||||
pool.BuildFile(file_descriptor); |
||||
|
||||
FileDescriptorProto stripped_file = compiler::StripSourceRetentionOptions( |
||||
*pool.FindFileByName("retention.proto")); |
||||
|
||||
// We use a dynamic message to generate the expected options proto. This lets
|
||||
// us parse the custom options in text format.
|
||||
const Descriptor* file_options_descriptor = |
||||
pool.FindMessageTypeByName(FileOptions().GetTypeName()); |
||||
DynamicMessageFactory factory; |
||||
std::unique_ptr<Message> dynamic_message( |
||||
factory.GetPrototype(file_options_descriptor)->New()); |
||||
ASSERT_TRUE(TextFormat::ParseFromString( |
||||
R"([google.protobuf.internal.options] { |
||||
i2: 456 |
||||
c {} |
||||
rc {} |
||||
} |
||||
[google.protobuf.internal.repeated_options] { |
||||
i2: 222 |
||||
})", |
||||
dynamic_message.get())); |
||||
FileOptions expected_options; |
||||
ASSERT_TRUE( |
||||
expected_options.ParseFromString(dynamic_message->SerializeAsString())); |
||||
|
||||
EXPECT_TRUE(util::MessageDifferencer::Equals(stripped_file.options(), |
||||
expected_options)); |
||||
} |
||||
|
||||
} // namespace
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
@ -0,0 +1,206 @@ |
||||
// Protocol Buffers - Google's data interchange format |
||||
// Copyright 2008 Google Inc. All rights reserved. |
||||
// https://developers.google.com/protocol-buffers/ |
||||
// |
||||
// Redistribution and use in source and binary forms, with or without |
||||
// modification, are permitted provided that the following conditions are |
||||
// met: |
||||
// |
||||
// * Redistributions of source code must retain the above copyright |
||||
// notice, this list of conditions and the following disclaimer. |
||||
// * Redistributions in binary form must reproduce the above |
||||
// copyright notice, this list of conditions and the following disclaimer |
||||
// in the documentation and/or other materials provided with the |
||||
// distribution. |
||||
// * Neither the name of Google Inc. nor the names of its |
||||
// contributors may be used to endorse or promote products derived from |
||||
// this software without specific prior written permission. |
||||
// |
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
|
||||
syntax = "proto2"; |
||||
|
||||
package google.protobuf.internal; |
||||
|
||||
import "google/protobuf/descriptor.proto"; |
||||
|
||||
// Retention attributes set directly on custom options |
||||
extend google.protobuf.FileOptions { |
||||
optional int32 plain_option = 505092806; |
||||
optional int32 runtime_retention_option = 505039132 |
||||
[retention = RETENTION_RUNTIME]; |
||||
optional int32 source_retention_option = 504878676 |
||||
[retention = RETENTION_SOURCE]; |
||||
} |
||||
|
||||
option (plain_option) = 1; |
||||
option (runtime_retention_option) = 2; |
||||
option (source_retention_option) = 3; |
||||
|
||||
// Retention attributes set on fields nested within a message |
||||
message OptionsMessage { |
||||
optional int32 plain_field = 1; |
||||
optional int32 runtime_retention_field = 2 [retention = RETENTION_RUNTIME]; |
||||
optional int32 source_retention_field = 3 [retention = RETENTION_SOURCE]; |
||||
} |
||||
|
||||
extend google.protobuf.FileOptions { |
||||
optional OptionsMessage file_option = 504871168; |
||||
} |
||||
|
||||
option (file_option) = { |
||||
plain_field: 1 |
||||
runtime_retention_field: 2 |
||||
source_retention_field: 3 |
||||
}; |
||||
|
||||
// Retention attribute nested inside a repeated message field |
||||
extend google.protobuf.FileOptions { |
||||
repeated OptionsMessage repeated_options = 504823570; |
||||
} |
||||
|
||||
option (repeated_options) = { |
||||
plain_field: 1 |
||||
runtime_retention_field: 2 |
||||
source_retention_field: 3 |
||||
}; |
||||
|
||||
extend google.protobuf.ExtensionRangeOptions { |
||||
optional OptionsMessage extension_range_option = 504822148; |
||||
} |
||||
|
||||
extend google.protobuf.MessageOptions { |
||||
optional OptionsMessage message_option = 504820819; |
||||
} |
||||
|
||||
extend google.protobuf.FieldOptions { |
||||
optional OptionsMessage field_option = 504589219; |
||||
} |
||||
|
||||
extend google.protobuf.OneofOptions { |
||||
optional OptionsMessage oneof_option = 504479153; |
||||
} |
||||
|
||||
extend google.protobuf.EnumOptions { |
||||
optional OptionsMessage enum_option = 504451567; |
||||
} |
||||
|
||||
extend google.protobuf.EnumValueOptions { |
||||
optional OptionsMessage enum_entry_option = 504450522; |
||||
} |
||||
|
||||
extend google.protobuf.ServiceOptions { |
||||
optional OptionsMessage service_option = 504387709; |
||||
} |
||||
|
||||
extend google.protobuf.MethodOptions { |
||||
optional OptionsMessage method_option = 504349420; |
||||
} |
||||
|
||||
message Extendee { |
||||
extensions 1, 2; |
||||
} |
||||
|
||||
extend Extendee { |
||||
optional int32 i = 1 [(field_option) = { |
||||
plain_field: 1 |
||||
runtime_retention_field: 2 |
||||
source_retention_field: 3 |
||||
}]; |
||||
} |
||||
|
||||
message TopLevelMessage { |
||||
option (message_option) = { |
||||
plain_field: 1 |
||||
runtime_retention_field: 2 |
||||
source_retention_field: 3 |
||||
}; |
||||
|
||||
message NestedMessage { |
||||
option (message_option) = { |
||||
plain_field: 1 |
||||
runtime_retention_field: 2 |
||||
source_retention_field: 3 |
||||
}; |
||||
} |
||||
|
||||
enum NestedEnum { |
||||
option (enum_option) = { |
||||
plain_field: 1 |
||||
runtime_retention_field: 2 |
||||
source_retention_field: 3 |
||||
}; |
||||
|
||||
NESTED_UNKNOWN = 0; |
||||
} |
||||
|
||||
optional float f = 1 [(field_option) = { |
||||
plain_field: 1 |
||||
runtime_retention_field: 2 |
||||
source_retention_field: 3 |
||||
}]; |
||||
|
||||
oneof o { |
||||
option (oneof_option) = { |
||||
plain_field: 1 |
||||
runtime_retention_field: 2 |
||||
source_retention_field: 3 |
||||
}; |
||||
|
||||
int64 i = 2; |
||||
} |
||||
|
||||
extensions 10 to 100 [(extension_range_option) = { |
||||
plain_field: 1 |
||||
runtime_retention_field: 2 |
||||
source_retention_field: 3 |
||||
}]; |
||||
|
||||
extend Extendee { |
||||
optional string s = 2 [(field_option) = { |
||||
plain_field: 1 |
||||
runtime_retention_field: 2 |
||||
source_retention_field: 3 |
||||
}]; |
||||
} |
||||
} |
||||
|
||||
enum TopLevelEnum { |
||||
option (enum_option) = { |
||||
plain_field: 1 |
||||
runtime_retention_field: 2 |
||||
source_retention_field: 3 |
||||
}; |
||||
|
||||
TOP_LEVEL_UNKNOWN = 0 [(enum_entry_option) = { |
||||
plain_field: 1 |
||||
runtime_retention_field: 2 |
||||
source_retention_field: 3 |
||||
}]; |
||||
} |
||||
|
||||
service Service { |
||||
option (service_option) = { |
||||
plain_field: 1 |
||||
runtime_retention_field: 2 |
||||
source_retention_field: 3 |
||||
}; |
||||
|
||||
rpc DoStuff(TopLevelMessage) returns (TopLevelMessage) { |
||||
option (method_option) = { |
||||
plain_field: 1 |
||||
runtime_retention_field: 2 |
||||
source_retention_field: 3 |
||||
}; |
||||
} |
||||
} |
Loading…
Reference in new issue