From 2725b9dc073fac9782366eeaf1491c97352f380a Mon Sep 17 00:00:00 2001 From: Michael Heilmann Date: Fri, 16 Jan 2026 16:53:10 -0500 Subject: [PATCH] generate representative proto definitions --- priv/protos/common_types.proto | 38 ++++++ priv/protos/custom_prefix_service.proto | 46 ++----- priv/protos/edge_cases.proto | 153 ++++++++++++++++++++++++ priv/protos/empty_service.proto | 5 - priv/protos/helloworld.proto | 27 ----- priv/protos/imports_test.proto | 63 ++++++++++ priv/protos/nested_messages.proto | 90 ++++++++++++++ priv/protos/no_package.proto | 16 +++ priv/protos/package_a.proto | 14 +++ priv/protos/package_b.proto | 20 ++++ priv/protos/proto2_features.proto | 94 +++++++++++++++ priv/protos/scalar_types.proto | 64 ++++++++++ priv/protos/streaming_service.proto | 54 +++++++++ priv/protos/test_service_v2.proto | 41 ------- priv/protos/test_service_v3.proto | 52 -------- priv/protos/well_known_types.proto | 66 ++++++++++ 16 files changed, 683 insertions(+), 160 deletions(-) create mode 100644 priv/protos/common_types.proto create mode 100644 priv/protos/edge_cases.proto delete mode 100644 priv/protos/empty_service.proto delete mode 100644 priv/protos/helloworld.proto create mode 100644 priv/protos/imports_test.proto create mode 100644 priv/protos/nested_messages.proto create mode 100644 priv/protos/no_package.proto create mode 100644 priv/protos/package_a.proto create mode 100644 priv/protos/package_b.proto create mode 100644 priv/protos/proto2_features.proto create mode 100644 priv/protos/scalar_types.proto create mode 100644 priv/protos/streaming_service.proto delete mode 100644 priv/protos/test_service_v2.proto delete mode 100644 priv/protos/test_service_v3.proto create mode 100644 priv/protos/well_known_types.proto diff --git a/priv/protos/common_types.proto b/priv/protos/common_types.proto new file mode 100644 index 0000000..a639319 --- /dev/null +++ b/priv/protos/common_types.proto @@ -0,0 +1,38 @@ +syntax = "proto3"; + +package common; + +// Common messages to be imported by other proto files + +message Address { + string street = 1; + string city = 2; + string state = 3; + string postal_code = 4; + string country = 5; +} + +message Coordinates { + double latitude = 1; + double longitude = 2; + double altitude = 3; +} + +message Money { + string currency_code = 1; + int64 units = 2; + int32 nanos = 3; +} + +enum Priority { + PRIORITY_UNSPECIFIED = 0; + LOW = 1; + MEDIUM = 2; + HIGH = 3; + CRITICAL = 4; +} + +message TimeRange { + int64 start_time = 1; + int64 end_time = 2; +} diff --git a/priv/protos/custom_prefix_service.proto b/priv/protos/custom_prefix_service.proto index 5e1b834..ccc09f2 100644 --- a/priv/protos/custom_prefix_service.proto +++ b/priv/protos/custom_prefix_service.proto @@ -1,44 +1,20 @@ -syntax = "proto2"; +syntax = "proto3"; -import "google/protobuf/timestamp.proto"; -import "google/protobuf/any.proto"; - -package testserviceV2; +package custom_prefix; +// This proto demonstrates Elixir-specific custom module prefix option import "elixirpb.proto"; -option (elixirpb.file).module_prefix = "HLW"; - -service TestService { - rpc CallFunction (TestRequest) returns (TestReply) {} -} - -message TestRequest { - required string name = 1; - optional Enum enum = 2; - oneof test_oneof { - string label = 3; - int32 value = 4; - } - map g = 5; - repeated google.protobuf.Any instrument = 6; - extensions 10 to 20; -} - -message Location { - optional double latitude = 1; - optional double longitude = 2; -} +option (elixirpb.file).module_prefix = "CustomPrefix"; -extend TestRequest { - optional string data = 10; - optional Location location = 11; +// Simple service to test custom module prefix generation +service PrefixService { + rpc Echo (EchoRequest) returns (EchoResponse) {} } -message TestReply { - required google.protobuf.Timestamp today = 2; +message EchoRequest { + string message = 1; } -enum Enum { - A = 0; - B = 1; +message EchoResponse { + string reply = 1; } \ No newline at end of file diff --git a/priv/protos/edge_cases.proto b/priv/protos/edge_cases.proto new file mode 100644 index 0000000..633b931 --- /dev/null +++ b/priv/protos/edge_cases.proto @@ -0,0 +1,153 @@ +syntax = "proto3"; + +package edge_cases; + +// Empty service (no methods) - edge case +service EmptyService { +} + +// Service with unusual but valid patterns +service EdgeCaseService { + // Method names with underscores and different conventions + rpc process_data (Request) returns (Response) {} + rpc ProcessData (Request) returns (Response) {} + rpc PROCESS_DATA (Request) returns (Response) {} + + // Empty request or response + rpc EmptyInput (EmptyMessage) returns (Response) {} + rpc EmptyOutput (Request) returns (EmptyMessage) {} + rpc BothEmpty (EmptyMessage) returns (EmptyMessage) {} +} + +message EmptyMessage { + // Intentionally empty message +} + +message Request { + string data = 1; +} + +message Response { + string result = 1; +} + +// Unusual field numbering +message SparseFieldNumbers { + string field_1 = 1; + string field_536870911 = 536870911; // Max field number (2^29 - 1) +} + +// Many fields +message ManyFields { + string field_001 = 1; + string field_002 = 2; + string field_003 = 3; + string field_004 = 4; + string field_005 = 5; + string field_006 = 6; + string field_007 = 7; + string field_008 = 8; + string field_009 = 9; + string field_010 = 10; + string field_011 = 11; + string field_012 = 12; + string field_013 = 13; + string field_014 = 14; + string field_015 = 15; + string field_016 = 16; + string field_017 = 17; + string field_018 = 18; + string field_019 = 19; + string field_020 = 20; +} + +// Complex enum +enum DetailedStatus { + // Enum with zero value (required in proto3) + DETAILED_STATUS_UNSPECIFIED = 0; + + // Various naming patterns + status_active = 1; + STATUS_INACTIVE = 2; + Status_Pending = 3; + + // Negative enum values (valid but unusual) + ERROR_STATE = -1; + CRITICAL_ERROR = -100; + + // Large enum values + MAX_STATUS = 2147483647; // Max int32 +} + +// Multiple oneofs in one message +message MultipleOneofs { + oneof first_choice { + string option_a1 = 1; + int32 option_a2 = 2; + } + + oneof second_choice { + string option_b1 = 3; + int32 option_b2 = 4; + } + + oneof third_choice { + string option_c1 = 5; + int32 option_c2 = 6; + } + + string regular_field = 7; +} + +// Nested maps +message NestedMaps { + map outer_map = 1; + map int_key_map = 2; + map numeric_map = 3; + map bool_key_map = 4; +} + +message InnerMap { + map data = 1; + map counts = 2; +} + +// Circular reference patterns (different from recursive_message.proto) +message CircularA { + CircularB b_field = 1; + string data = 2; +} + +message CircularB { + CircularC c_field = 1; + string data = 2; +} + +message CircularC { + CircularA a_field = 1; + string data = 2; +} + +// Reserved with various patterns +message WithReservedFields { + string active_field_1 = 1; + + reserved 2, 15, 9 to 11; + reserved "foo", "bar", "old_field"; + + string active_field_16 = 16; + + reserved 100 to max; +} + +// Unicode and special characters in comments +message UnicodeTest { + // Field with emoji in comment: 🚀 rocket + string rocket_field = 1; + + // Mathematical symbols: ∑ ∫ π + double pi_field = 2; + + // Various languages: 你好 مرحبا שלום + string greeting = 3; +} diff --git a/priv/protos/empty_service.proto b/priv/protos/empty_service.proto deleted file mode 100644 index 7af1e8f..0000000 --- a/priv/protos/empty_service.proto +++ /dev/null @@ -1,5 +0,0 @@ -syntax = "proto2"; - -service EmptyService { - -} \ No newline at end of file diff --git a/priv/protos/helloworld.proto b/priv/protos/helloworld.proto deleted file mode 100644 index 1284998..0000000 --- a/priv/protos/helloworld.proto +++ /dev/null @@ -1,27 +0,0 @@ -syntax = "proto3"; - -option java_multiple_files = true; -option java_package = "io.grpc.examples.helloworld"; -option java_outer_classname = "HelloWorldProto"; -option objc_class_prefix = "HLW"; - -import "google/protobuf/timestamp.proto"; - -package helloworld; - -// The greeting service definition. -service Greeter { - // Sends a greeting - rpc SayHello (HelloRequest) returns (HelloReply) {} -} - -// The request message containing the user's name. -message HelloRequest { - string name = 1; -} - -// The response message containing the greetings -message HelloReply { - string message = 1; - google.protobuf.Timestamp today = 2; -} diff --git a/priv/protos/imports_test.proto b/priv/protos/imports_test.proto new file mode 100644 index 0000000..336b402 --- /dev/null +++ b/priv/protos/imports_test.proto @@ -0,0 +1,63 @@ +syntax = "proto3"; + +package imports_test; + +// Import from local proto file +import "common_types.proto"; + +// Import from google protos +import "google/protobuf/timestamp.proto"; + +// Service demonstrating cross-file type usage +service ImportTestService { + rpc CreateUser (UserRequest) returns (UserResponse) {} + rpc UpdateLocation (LocationUpdate) returns (LocationResponse) {} +} + +message UserRequest { + string name = 1; + string email = 2; + + // Using imported type from common_types.proto + common.Address address = 3; + common.Coordinates location = 4; + + // Using imported google type + google.protobuf.Timestamp registered_at = 5; +} + +message UserResponse { + string user_id = 1; + common.Priority priority = 2; + google.protobuf.Timestamp created_at = 3; + + // Nested message that uses imported types + message Profile { + common.Address billing_address = 1; + common.Address shipping_address = 2; + repeated common.Coordinates recent_locations = 3; + } + + Profile profile = 4; +} + +message LocationUpdate { + string user_id = 1; + common.Coordinates new_location = 2; + google.protobuf.Timestamp timestamp = 3; +} + +message LocationResponse { + bool success = 1; + common.Coordinates confirmed_location = 2; + + // Map using imported types + map visit_history = 3; +} + +// Message demonstrating repeated imported types +message BulkOperation { + repeated common.Address addresses = 1; + repeated common.Money transactions = 2; + map task_priorities = 3; +} diff --git a/priv/protos/nested_messages.proto b/priv/protos/nested_messages.proto new file mode 100644 index 0000000..58bb549 --- /dev/null +++ b/priv/protos/nested_messages.proto @@ -0,0 +1,90 @@ +syntax = "proto3"; + +package nested; + +// Service with deeply nested message structures +service NestedService { + rpc ProcessNested (OuterMessage) returns (OuterResponse) {} +} + +// Deeply nested message structure +message OuterMessage { + string outer_field = 1; + + message MiddleMessage { + string middle_field = 1; + + message InnerMessage { + string inner_field = 1; + + message DeepMessage { + string deep_field = 1; + + message VeryDeepMessage { + string very_deep_field = 1; + repeated int32 values = 2; + } + + VeryDeepMessage very_deep = 2; + } + + DeepMessage deep = 2; + } + + InnerMessage inner = 2; + repeated InnerMessage inner_list = 3; + } + + MiddleMessage middle = 2; + repeated MiddleMessage middle_list = 3; + + // Map with nested message value + map nested_map = 4; + + // Oneof with nested messages + oneof nested_oneof { + MiddleMessage option_a = 5; + MiddleMessage.InnerMessage option_b = 6; + string simple_option = 7; + } +} + +message OuterResponse { + // Message referencing nested types from request + OuterMessage.MiddleMessage.InnerMessage.DeepMessage deep_result = 1; + repeated OuterMessage.MiddleMessage middle_results = 2; +} + +// Multiple services in the same file +service AnotherNestedService { + rpc ProcessOuter (OuterMessage) returns (OuterResponse) {} + rpc ProcessMiddle (OuterMessage.MiddleMessage) returns (OuterMessage.MiddleMessage) {} + rpc ProcessInner (OuterMessage.MiddleMessage.InnerMessage) returns (OuterMessage.MiddleMessage.InnerMessage) {} +} + +// Complex message with multiple nested enums +message ComplexNested { + enum Status { + UNKNOWN = 0; + ACTIVE = 1; + INACTIVE = 2; + } + + message Node { + enum NodeType { + LEAF = 0; + BRANCH = 1; + ROOT = 2; + } + + string id = 1; + NodeType type = 2; + repeated Node children = 3; + Node parent = 4; + map named_children = 5; + } + + Status status = 1; + Node root = 2; + repeated Node all_nodes = 3; +} diff --git a/priv/protos/no_package.proto b/priv/protos/no_package.proto new file mode 100644 index 0000000..abb1846 --- /dev/null +++ b/priv/protos/no_package.proto @@ -0,0 +1,16 @@ +syntax = "proto3"; + +// File with no package declaration - valid but unusual +// Messages and services are in the global namespace + +service GlobalService { + rpc GlobalMethod (GlobalRequest) returns (GlobalResponse) {} +} + +message GlobalRequest { + string data = 1; +} + +message GlobalResponse { + string result = 1; +} diff --git a/priv/protos/package_a.proto b/priv/protos/package_a.proto new file mode 100644 index 0000000..7fcb19d --- /dev/null +++ b/priv/protos/package_a.proto @@ -0,0 +1,14 @@ +syntax = "proto3"; + +package package_a; + +message MessageA { + string field_a = 1; + int32 count = 2; +} + +enum EnumA { + ENUM_A_UNSPECIFIED = 0; + OPTION_1 = 1; + OPTION_2 = 2; +} diff --git a/priv/protos/package_b.proto b/priv/protos/package_b.proto new file mode 100644 index 0000000..098e20d --- /dev/null +++ b/priv/protos/package_b.proto @@ -0,0 +1,20 @@ +syntax = "proto3"; + +package package_b; + +import "package_a.proto"; + +message MessageB { + string field_b = 1; + package_a.MessageA message_from_a = 2; + package_a.EnumA enum_from_a = 3; +} + +service ServiceB { + rpc ProcessB (MessageB) returns (ResponseB) {} + rpc ProcessA (package_a.MessageA) returns (package_a.MessageA) {} +} + +message ResponseB { + repeated package_a.MessageA results = 1; +} diff --git a/priv/protos/proto2_features.proto b/priv/protos/proto2_features.proto new file mode 100644 index 0000000..d077f37 --- /dev/null +++ b/priv/protos/proto2_features.proto @@ -0,0 +1,94 @@ +syntax = "proto2"; + +package proto2_features; + +import "google/protobuf/any.proto"; +import "google/protobuf/timestamp.proto"; + +// Service demonstrating proto2-specific features +service Proto2Service { + rpc ProcessProto2 (Proto2Request) returns (Proto2Response) {} +} + +message Proto2Request { + // Required fields (proto2 only) + required string required_field = 1; + required int32 required_id = 2; + + // Optional fields (explicit in proto2) + optional string optional_field = 3; + optional int32 optional_id = 4; + + // Default values (proto2 only) + optional string name = 5 [default = "unknown"]; + optional int32 port = 6 [default = 8080]; + optional bool enabled = 7 [default = true]; + optional Status status = 8 [default = ACTIVE]; + + // Oneof in proto2 + oneof proto2_oneof { + string oneof_string = 9; + int32 oneof_int = 13; + } + + // Groups (proto2 only, deprecated but still valid) + repeated group Result = 10 { + required string url = 11; + optional string title = 12; + } + + // Map in proto2 (added in proto2 v3.0.0) + map metadata_map = 14; + + // Repeated Any in proto2 + repeated google.protobuf.Any any_values = 15; + + // Extensions range + extensions 100 to 199; +} + +enum Status { + UNKNOWN = 0; + ACTIVE = 1; + INACTIVE = 2; +} + +// Extension of Proto2Request +extend Proto2Request { + optional string extended_field = 100; + optional int64 extended_timestamp = 101; + optional ExtensionData extension_data = 102; + optional google.protobuf.Timestamp timestamp_extension = 103; +} + +message ExtensionData { + optional string key = 1; + optional string value = 2; +} + +message Proto2Response { + required bool success = 1; + optional string message = 2; + repeated Proto2Request.Result results = 3; +} + +// Message with extension and nested types +message ExtendableMessage { + required string id = 1; + extensions 1000 to max; + + message NestedInExtendable { + optional string data = 1; + } + + enum ExtendableEnum { + OPTION_A = 0; + OPTION_B = 1; + } +} + +extend ExtendableMessage { + optional string meta_info = 1000; + optional ExtendableMessage.NestedInExtendable nested_extension = 1001; + optional ExtendableMessage.ExtendableEnum enum_extension = 1002; +} diff --git a/priv/protos/scalar_types.proto b/priv/protos/scalar_types.proto new file mode 100644 index 0000000..ef3b66d --- /dev/null +++ b/priv/protos/scalar_types.proto @@ -0,0 +1,64 @@ +syntax = "proto3"; + +package scalar_types; + +// Service demonstrating all scalar field types +service ScalarService { + rpc ProcessScalars (ScalarRequest) returns (ScalarReply) {} +} + +// Message containing all protobuf scalar types +message ScalarRequest { + // Numeric types + double double_field = 1; + float float_field = 2; + int32 int32_field = 3; + int64 int64_field = 4; + uint32 uint32_field = 5; + uint64 uint64_field = 6; + sint32 sint32_field = 7; + sint64 sint64_field = 8; + fixed32 fixed32_field = 9; + fixed64 fixed64_field = 10; + sfixed32 sfixed32_field = 11; + sfixed64 sfixed64_field = 12; + + // Boolean type + bool bool_field = 13; + + // String types + string string_field = 14; + bytes bytes_field = 15; + + // Proto3 optional (added in protobuf 3.15) - generates presence tracking + optional string optional_string = 18; + optional int32 optional_int = 19; + + // Large field numbers to test range handling + string sparse_field_1 = 100; + string sparse_field_2 = 1000; + string sparse_field_3 = 10000; + + // Reserved fields and ranges + reserved 16, 17, 20 to 25; + reserved "old_field", "deprecated_field"; +} + +message ScalarReply { + // Repeated scalars + repeated double double_list = 1; + repeated float float_list = 2; + repeated int32 int32_list = 3; + repeated int64 int64_list = 4; + repeated uint32 uint32_list = 5; + repeated uint64 uint64_list = 6; + repeated sint32 sint32_list = 7; + repeated sint64 sint64_list = 8; + repeated fixed32 fixed32_list = 9; + repeated fixed64 fixed64_list = 10; + repeated sfixed32 sfixed32_list = 11; + repeated sfixed64 sfixed64_list = 12; + repeated bool bool_list = 13; + repeated string string_list = 14; + repeated bytes bytes_list = 15; +} diff --git a/priv/protos/streaming_service.proto b/priv/protos/streaming_service.proto new file mode 100644 index 0000000..5dfbde2 --- /dev/null +++ b/priv/protos/streaming_service.proto @@ -0,0 +1,54 @@ +syntax = "proto3"; + +package streaming; + +// Service demonstrating all four RPC streaming patterns +service StreamingService { + // Unary RPC: single request, single response + rpc UnaryCall (StreamRequest) returns (StreamResponse) {} + + // Server streaming: single request, stream of responses + rpc ServerStreamingCall (StreamRequest) returns (stream StreamResponse) {} + + // Client streaming: stream of requests, single response + rpc ClientStreamingCall (stream StreamRequest) returns (StreamResponse) {} + + // Bidirectional streaming: stream of requests and responses + rpc BidirectionalStreamingCall (stream StreamRequest) returns (stream StreamResponse) {} +} + +message StreamRequest { + string message = 1; + int32 sequence = 2; +} + +message StreamResponse { + string result = 1; + int32 sequence = 2; + bool is_final = 3; +} + +// Service with multiple streaming methods showing different patterns +service MultiStreamService { + rpc UploadData (stream DataChunk) returns (UploadStatus) {} + rpc DownloadData (DownloadRequest) returns (stream DataChunk) {} + rpc SyncData (stream DataChunk) returns (stream DataChunk) {} +} + +message DataChunk { + bytes data = 1; + int64 offset = 2; + int32 size = 3; +} + +message UploadStatus { + bool success = 1; + int64 total_bytes = 2; + string checksum = 3; +} + +message DownloadRequest { + string file_id = 1; + int64 start_offset = 2; + int64 max_bytes = 3; +} diff --git a/priv/protos/test_service_v2.proto b/priv/protos/test_service_v2.proto deleted file mode 100644 index 859ccd3..0000000 --- a/priv/protos/test_service_v2.proto +++ /dev/null @@ -1,41 +0,0 @@ -syntax = "proto2"; - -import "google/protobuf/timestamp.proto"; -import "google/protobuf/any.proto"; - -package testserviceV2; - -service TestService { - rpc CallFunction (TestRequest) returns (TestReply) {} -} - -message TestRequest { - required string name = 1; - optional Enum enum = 2; - oneof test_oneof { - string label = 3; - int32 value = 4; - } - map g = 5; - repeated google.protobuf.Any instrument = 6; - extensions 10 to 20; -} - -message Location { - optional double latitude = 1; - optional double longitude = 2; -} - -extend TestRequest { - optional string data = 10; - optional Location location = 11; -} - -message TestReply { - required google.protobuf.Timestamp today = 2; -} - -enum Enum { - A = 0; - B = 1; -} \ No newline at end of file diff --git a/priv/protos/test_service_v3.proto b/priv/protos/test_service_v3.proto deleted file mode 100644 index 2d56b66..0000000 --- a/priv/protos/test_service_v3.proto +++ /dev/null @@ -1,52 +0,0 @@ -syntax = "proto3"; - -import "google/protobuf/timestamp.proto"; -import "google/protobuf/any.proto"; -import "google/protobuf/wrappers.proto"; - -package testserviceV3; - -service TestService { - rpc CallFunction (TestRequest) returns (TestReply) {} -} - -message TestRequest { - string name = 1; - Enum enum = 2; - oneof test_oneof { - string label = 3; - int32 value = 4; - } - map g = 5; - google.protobuf.Any instrument = 6; - - message Payload { - google.protobuf.StringValue data = 1; - - message Location { - double latitude = 1; - double longitude = 2; - } - - Location location = 2; - Token token = 3; - } - - message Token { - string vaule = 1; - } - - Payload payload = 7; -} - -message TestReply { - google.protobuf.Timestamp today = 2; - - google.protobuf.StringValue ext_1 = 3; - google.protobuf.StringValue ext_2 = 4; -} - -enum Enum { - A = 0; - B = 1; -} \ No newline at end of file diff --git a/priv/protos/well_known_types.proto b/priv/protos/well_known_types.proto new file mode 100644 index 0000000..6130da1 --- /dev/null +++ b/priv/protos/well_known_types.proto @@ -0,0 +1,66 @@ +syntax = "proto3"; + +package well_known_types; + +import "google/protobuf/any.proto"; +import "google/protobuf/timestamp.proto"; +import "google/protobuf/duration.proto"; +import "google/protobuf/empty.proto"; +import "google/protobuf/struct.proto"; +import "google/protobuf/wrappers.proto"; +import "google/protobuf/field_mask.proto"; + +// Service demonstrating all common google.protobuf well-known types +service WellKnownTypesService { + rpc ProcessWellKnownTypes (WellKnownRequest) returns (WellKnownResponse) {} + rpc EmptyMethod (google.protobuf.Empty) returns (google.protobuf.Empty) {} +} + +message WellKnownRequest { + // Any type - can hold any message + google.protobuf.Any payload = 1; + repeated google.protobuf.Any items = 2; + + // Timestamp - point in time + google.protobuf.Timestamp created_at = 3; + google.protobuf.Timestamp updated_at = 4; + + // Duration - span of time + google.protobuf.Duration timeout = 5; + google.protobuf.Duration retry_delay = 6; + + // Struct - arbitrary JSON-like structure + google.protobuf.Struct metadata = 7; + google.protobuf.Value dynamic_value = 8; + google.protobuf.ListValue list_value = 9; + + // Wrappers - nullable scalar types + google.protobuf.StringValue nullable_string = 10; + google.protobuf.Int32Value nullable_int32 = 11; + google.protobuf.Int64Value nullable_int64 = 12; + google.protobuf.UInt32Value nullable_uint32 = 13; + google.protobuf.UInt64Value nullable_uint64 = 14; + google.protobuf.FloatValue nullable_float = 15; + google.protobuf.DoubleValue nullable_double = 16; + google.protobuf.BoolValue nullable_bool = 17; + google.protobuf.BytesValue nullable_bytes = 18; + + // FieldMask - specify which fields to return/update + google.protobuf.FieldMask field_mask = 19; +} + +message WellKnownResponse { + google.protobuf.Timestamp processed_at = 1; + google.protobuf.Duration elapsed_time = 2; + google.protobuf.Struct result = 3; + + // Repeated wrappers + repeated google.protobuf.StringValue string_values = 4; + repeated google.protobuf.Int32Value int_values = 5; +} + +// Message to be packed into Any +message CustomPayload { + string data = 1; + int32 version = 2; +}