proto_turf 0.0.3 → 0.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9af9eb4df4dd0323090363e65378d08d4b9a55050eb0a08ea6ddfe2cd7bd8b59
4
- data.tar.gz: 32fb8b5f560d5e49978930f5e863d5851efc17b288f75c26e45ee7d1cf8e98dd
3
+ metadata.gz: 8239512fca1dd5698211d880f8af935172d618df491a556593328dc3fcf6962b
4
+ data.tar.gz: 76922a13957798957fbffb8bcfad086a850d4a0f4d76d019401bca2fcf073c0f
5
5
  SHA512:
6
- metadata.gz: 3286859be78192d3495c3dc58e15dad50273aed4d611ddf579b9b27a16b01bbf0652d17af367192ed6dd9154a693a1991342439d53bde14777a5e61e5402a036
7
- data.tar.gz: e8d941d3a7b153345e407ed62fb4e6201b93a65e01810f06cacb4fa616bbbf3c93b1456be349f3f53fd8e41d5a7f4fc4fcd0fad9fc380f8c7ff4ea101678fc18
6
+ metadata.gz: 62e0dc2021649ed6404dfa4aff7b55008922dcad1bd405bab49e8c8bd6e813f6a4633b75f1822a359c799d97c50bfc8454bcd0be6159a2b1805dab1b5c505c2e
7
+ data.tar.gz: e78d7140868439556d6be3a3e39844e27c3b408e7eccbc92fde258bd3b411b0264f91017b02894bbb8144295bc278844028101a0cce15dc452e6ecc64956870c
@@ -0,0 +1,18 @@
1
+ name: Lint
2
+
3
+ on: [push, pull_request]
4
+
5
+ jobs:
6
+ build:
7
+
8
+ runs-on: ubuntu-latest
9
+
10
+ steps:
11
+ - uses: actions/checkout@v3
12
+ - name: Set up Ruby ${{ matrix.ruby }}
13
+ uses: ruby/setup-ruby@v1
14
+ with:
15
+ ruby-version: 3.4
16
+ bundler-cache: true
17
+ - name: Run standardrb
18
+ run: bundle exec standardrb
@@ -0,0 +1,31 @@
1
+ name: Release Gem
2
+ on:
3
+ push:
4
+ branches:
5
+ - main
6
+ tags:
7
+ - 'v*.*.*' # Matches semantic versioning tags like v1.0.0
8
+ workflow_dispatch: # Allows manual triggering of the workflow
9
+
10
+ jobs:
11
+ push:
12
+ name: Push gem to RubyGems.org
13
+ runs-on: ubuntu-latest
14
+
15
+ permissions:
16
+ id-token: write # IMPORTANT: this permission is mandatory for trusted publishing
17
+ contents: write # IMPORTANT: this permission is required for `rake release` to push the release tag
18
+
19
+ steps:
20
+ # Set up
21
+ - uses: actions/checkout@v4
22
+ with:
23
+ persist-credentials: false
24
+ - name: Set up Ruby
25
+ uses: ruby/setup-ruby@v1
26
+ with:
27
+ bundler-cache: true
28
+ ruby-version: ruby
29
+
30
+ # Release
31
+ - uses: rubygems/release-gem@v1
@@ -0,0 +1,22 @@
1
+ name: Test
2
+
3
+ on: [push, pull_request]
4
+
5
+ jobs:
6
+ build:
7
+
8
+ runs-on: ubuntu-latest
9
+ strategy:
10
+ fail-fast: false
11
+ matrix:
12
+ ruby: [3.1, 3.2, 3.3, 3.4]
13
+
14
+ steps:
15
+ - uses: actions/checkout@v3
16
+ - name: Set up Ruby ${{ matrix.ruby }}
17
+ uses: ruby/setup-ruby@v1
18
+ with:
19
+ ruby-version: ${{ matrix.ruby }}
20
+ bundler-cache: true
21
+ - name: Build and test with RSpec
22
+ run: bundle exec rspec
data/CHANGELOG.md CHANGED
@@ -7,6 +7,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## UNRELEASED
9
9
 
10
- # 0.0.3 - 2025-8-15
10
+ # 0.0.5 - 2025-08-20
11
+
12
+ * Minor fixes.
13
+
14
+ # 0.0.4 - 2025-08-19
15
+
16
+ * Changed emitting of protobuf schemas from file-based to generated from descriptors.
17
+
18
+ # 0.0.3 - 2025-08-15
11
19
 
12
20
  * Initial release.
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- proto_turf (0.0.2)
4
+ proto_turf (0.0.5)
5
5
  excon
6
6
  google-protobuf
7
7
 
@@ -21,6 +21,9 @@ GEM
21
21
  google-protobuf (4.30.2-arm64-darwin)
22
22
  bigdecimal
23
23
  rake (>= 13)
24
+ google-protobuf (4.30.2-x86_64-linux)
25
+ bigdecimal
26
+ rake (>= 13)
24
27
  hashdiff (1.2.0)
25
28
  json (2.13.2)
26
29
  language_server-protocol (3.17.0.5)
@@ -93,6 +96,7 @@ GEM
93
96
 
94
97
  PLATFORMS
95
98
  arm64-darwin
99
+ x86_64-linux
96
100
 
97
101
  DEPENDENCIES
98
102
  bundler (~> 2.0)
data/README.md CHANGED
@@ -36,10 +36,6 @@ encoded = proto_turf.encode(message, subject: 'my-subject')
36
36
  decoded_proto_message = proto_turf.decode(encoded_string)
37
37
  ```
38
38
 
39
- If you're using [buf](https://buf.build/) to manage your Protobuf definitions, you should run `buf export` before using `proto_turf` to ensure that all the dependencies are available as `.proto` files in your project. The actual proto text is needed when registering the schema with the Schema Registry.
40
-
41
- Because `buf export` overwrites/deletes existing files, you should run it into a different directory and provide both as `schema_paths` to the `ProtoTurf` constructor.
42
-
43
39
  ## Notes about usage
44
40
 
45
41
  * When decoding, this library does *not* attempt to fully parse the Proto definition stored on the schema registry and generate dynamic classes. Instead, it simply parses out the package and message and assumes that the reader has the message available in the descriptor pool. Any compatibility issues should be detected through normal means, i.e. just by instantiating the message and seeing if any errors are raised.
@@ -49,4 +45,4 @@ Run the following to regenerate:
49
45
 
50
46
  ```sh
51
47
  protoc -I spec/schemas --ruby_out=spec/gen --ruby_opt=paths=source_relative spec/schemas/**/*.proto
52
- ```
48
+ ```
data/Rakefile ADDED
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
@@ -0,0 +1,319 @@
1
+ class ProtoTurf
2
+ module ProtoText
3
+ ParseInfo = Struct.new(:writer, :package, :message) do
4
+ %i[write write_indent write_line writenl indent dedent].each do |method|
5
+ define_method(method) do |*args|
6
+ writer.send(method, *args)
7
+ end
8
+ end
9
+ end
10
+
11
+ class Writer < StringIO
12
+ def initialize(...)
13
+ super
14
+ @indent = 0
15
+ end
16
+
17
+ def write_indent(str)
18
+ @indent.times { write(" ") }
19
+ write(str)
20
+ end
21
+
22
+ def write_line(line, nl = 1)
23
+ write_indent(line)
24
+ nl.times { writenl }
25
+ end
26
+
27
+ def writenl
28
+ write("\n")
29
+ end
30
+
31
+ def indent
32
+ @indent += 2
33
+ end
34
+
35
+ def dedent
36
+ @indent -= 2
37
+ end
38
+ end
39
+
40
+ class << self
41
+ def fetch(message_name)
42
+ name = message_name.start_with?(".") ? message_name[1..] : message_name
43
+ Google::Protobuf::DescriptorPool.generated_pool.lookup(name)
44
+ end
45
+
46
+ def output(file_descriptor)
47
+ writer = Writer.new
48
+ info = ParseInfo.new(writer, file_descriptor.package)
49
+ writer.write_line("syntax = \"#{file_descriptor.syntax}\";", 2)
50
+ writer.write_line("package #{file_descriptor.package};")
51
+ writer.writenl
52
+ found = false
53
+ file_descriptor.options.to_h.each do |name, value|
54
+ found = true
55
+ writer.write_line("option #{name} = #{value.to_json};")
56
+ end
57
+ writer.writenl if found
58
+
59
+ found = false
60
+ file_descriptor.dependency.each do |dependency|
61
+ found = true
62
+ writer.write_line("import \"#{dependency}\";")
63
+ end
64
+ writer.writenl if found
65
+
66
+ writer.writenl if write_options(info, file_descriptor)
67
+ writer.writenl if write_extensions(info, file_descriptor)
68
+
69
+ file_descriptor.enum_type.each do |enum_type|
70
+ write_enum(info, enum_type)
71
+ end
72
+ file_descriptor.message_type.each do |message_type|
73
+ write_message(info, message_type)
74
+ end
75
+ file_descriptor.service.each do |service|
76
+ write_service(info, service)
77
+ end
78
+ writer.string
79
+ end
80
+
81
+ def write_extensions(info, descriptor)
82
+ descriptor.extension.each do |extension|
83
+ info.write_line("extend #{extension.extendee[1..]} {")
84
+ info.indent
85
+ write_field(info, extension)
86
+ info.dedent
87
+ info.write_line("}")
88
+ end
89
+ descriptor.extension.any?
90
+ end
91
+
92
+ def write_reserved(writer, descriptor)
93
+ reserved = descriptor.reserved_range.map do |range|
94
+ (range.start == range.end - 1) ? range.start.to_s : "#{range.start} to #{range.end - 1}"
95
+ end
96
+ found = false
97
+ if reserved.any?
98
+ found = true
99
+ writer.write_line("reserved #{reserved.join(", ")};")
100
+ end
101
+ if descriptor.reserved_name.any?
102
+ found = true
103
+ writer.write_line("reserved #{descriptor.reserved_name.map(&:to_json).join(", ")};")
104
+ end
105
+ writer.writenl if found
106
+ end
107
+
108
+ def write_imports(writer, file_descriptor)
109
+ writer.writenl
110
+ file_descriptor.dependency.each do |dependency|
111
+ writer.write_line("import \"#{dependency}\";")
112
+ end
113
+ file_descriptor.public_dependency.each do |public_dependency|
114
+ writer.write_line("import public \"#{public_dependency}\";")
115
+ end
116
+ file_descriptor.option_dependency.each do |option_dependency|
117
+ writer.write_line("import weak \"#{option_dependency}\";")
118
+ end
119
+ writer.writenl
120
+ end
121
+
122
+ def write_message(info, message_type)
123
+ info.message = message_type
124
+ info.write_indent("message ")
125
+ info.write("#{message_type.name} {")
126
+ info.writenl
127
+ info.indent
128
+
129
+ write_options(info, message_type)
130
+ write_reserved(info, message_type)
131
+
132
+ message_type.enum_type.each do |enum|
133
+ info.writenl
134
+ write_enum(info, enum)
135
+ end
136
+ message_type.field.each do |field|
137
+ write_field(info, field)
138
+ end
139
+ message_type.extension.each do |extension|
140
+ write_field(info, extension)
141
+ end
142
+ write_oneofs(info, message_type)
143
+ message_type.nested_type.each do |subtype|
144
+ next if subtype.options&.map_entry
145
+
146
+ info.writenl
147
+ write_message(info, subtype)
148
+ end
149
+ info.dedent
150
+ info.write_line("}")
151
+ end
152
+
153
+ def field_type(info, field_type)
154
+ case field_type.type
155
+ when :TYPE_INT32
156
+ "int32"
157
+ when :TYPE_INT64
158
+ "int64"
159
+ when :TYPE_UINT32
160
+ "uint32"
161
+ when :TYPE_UINT64
162
+ "uint64"
163
+ when :TYPE_SINT32
164
+ "sint32"
165
+ when :TYPE_SINT64
166
+ "sint64"
167
+ when :TYPE_FIXED32
168
+ "fixed32"
169
+ when :TYPE_FIXED64
170
+ "fixed64"
171
+ when :TYPE_SFIXED32
172
+ "sfixed32"
173
+ when :TYPE_SFIXED64
174
+ "sfixed64"
175
+ when :TYPE_FLOAT
176
+ "float"
177
+ when :TYPE_DOUBLE
178
+ "double"
179
+ when :TYPE_BOOL
180
+ "bool"
181
+ when :TYPE_STRING
182
+ "string"
183
+ when :TYPE_BYTES
184
+ "bytes"
185
+ when :TYPE_ENUM, :TYPE_MESSAGE
186
+ # remove leading .
187
+ type = fetch(field_type.type_name[1..])
188
+ name = type.name.sub("#{info.package}.#{info.message.name}.", "")
189
+ name.sub("#{info.package}.", "")
190
+ end
191
+ end
192
+
193
+ def write_field(info, field, oneof: false)
194
+ return if !oneof && field.has_oneof_index?
195
+ info.write_indent("")
196
+
197
+ klass = nil
198
+ if field.type_name && field.type_name != ""
199
+ klass = fetch(field.type_name).to_proto
200
+ end
201
+
202
+ if field.proto3_optional
203
+ info.write("optional ")
204
+ elsif field.label == :LABEL_REPEATED && !klass&.options&.map_entry
205
+ info.write("repeated ")
206
+ end
207
+
208
+ if klass&.options&.map_entry
209
+ info.write("map<#{field_type(info, klass.field[0])}, #{field_type(info, klass.field[1])}>")
210
+ else
211
+ info.write(field_type(info, field).to_s)
212
+ end
213
+ info.write(" #{field.name} = #{field.number}")
214
+
215
+ write_field_options(info, field)
216
+ info.write(";")
217
+ info.writenl
218
+ end
219
+
220
+ def write_field_options(info, field)
221
+ return unless field.options
222
+
223
+ info.write(" [")
224
+ info.write(field.options.to_h.map { |name, value| "#{name} = #{value}" }.join(", "))
225
+ write_options(info, field, include_option_label: false)
226
+ info.write("]")
227
+ end
228
+
229
+ def write_oneofs(info, message)
230
+ message.oneof_decl.each_with_index do |oneof, i|
231
+ # synthetic oneof for proto3 optional fields
232
+ next if oneof.name.start_with?("_") &&
233
+ message.field.any? { |f| f.proto3_optional && f.name == oneof.name[1..] }
234
+
235
+ info.write_line("oneof #{oneof.name} {")
236
+ info.indent
237
+ message.field.select { |f| f.has_oneof_index? && f.oneof_index == i }.each do |field|
238
+ write_field(info, field, oneof: true)
239
+ end
240
+ info.dedent
241
+ info.write_line("}")
242
+ end
243
+ end
244
+
245
+ def write_enum(info, enum_type)
246
+ info.write("enum ")
247
+ info.write("#{enum_type.name} {")
248
+ info.writenl
249
+ info.indent
250
+ write_reserved(info, enum_type)
251
+ enum_type.value.each do |value|
252
+ info.write_line("#{value.name} = #{value.number};")
253
+ end
254
+ info.dedent
255
+ info.write_line("}")
256
+ info.writenl
257
+ end
258
+
259
+ def method_type(package, name)
260
+ output = name.sub("#{package}.", "")
261
+ output = output[1..] if output.start_with?(".")
262
+ output
263
+ end
264
+
265
+ def write_service(info, service)
266
+ info.write_line("service #{service.name} {")
267
+ info.indent
268
+ service["method"].each do |method|
269
+ info.write_indent("rpc #{method.name}(#{method_type(info.package, method.input_type)}) ")
270
+ info.write("returns (#{method_type(info.package, method.output_type)}) {")
271
+ info.writenl
272
+ info.indent
273
+ if method.options
274
+ write_options(info, method)
275
+ end
276
+ info.dedent
277
+ info.write_line("};")
278
+ end
279
+ info.dedent
280
+ info.write_line("}")
281
+ end
282
+
283
+ # @return [Boolean] true if any options were written
284
+ def write_options(info, descriptor, include_option_label: true)
285
+ # unfortunately there doesn't seem to be a way to get the full list of options without
286
+ # resorting to to_json.
287
+ json = JSON.parse(descriptor.options.to_json)
288
+ return if !json || json.empty?
289
+
290
+ found = false
291
+ json.keys.each do |name|
292
+ option_name = name.tr("[]", "")
293
+ ext = fetch(option_name)
294
+ next if ext.nil?
295
+
296
+ found = true
297
+ options = ext.get(descriptor.options)
298
+ if include_option_label
299
+ info.write_indent("option (#{option_name}) =")
300
+ else
301
+ info.write("(#{option_name}) = ")
302
+ end
303
+ if options.respond_to?(:to_h)
304
+ lines = JSON.pretty_generate(options.to_h).lines(chomp: true)
305
+ lines.each_with_index do |line, i|
306
+ info.write_indent(line)
307
+ info.writenl if i < lines.length - 1
308
+ end
309
+ info.write(";")
310
+ else
311
+ info.write(options.to_json)
312
+ end
313
+ info.writenl
314
+ end
315
+ found
316
+ end
317
+ end
318
+ end
319
+ end
@@ -1,3 +1,3 @@
1
1
  class ProtoTurf
2
- VERSION = "0.0.3"
2
+ VERSION = "0.0.5"
3
3
  end
data/lib/proto_turf.rb CHANGED
@@ -5,8 +5,11 @@ require "google/protobuf/descriptor_pb"
5
5
  require "json"
6
6
  require "proto_turf/confluent_schema_registry"
7
7
  require "proto_turf/cached_confluent_schema_registry"
8
+ require "proto_turf/proto_text"
8
9
 
9
10
  class ProtoTurf
11
+ class SchemaNotFoundError < StandardError; end
12
+
10
13
  # Provides a way to encode and decode messages without having to embed schemas
11
14
  # in the encoded data. Confluent's Schema Registry[1] is used to register
12
15
  # a schema when encoding a message -- the registry will issue a schema id that
@@ -25,7 +28,6 @@ class ProtoTurf
25
28
  # ProtoTurf::ConfluentSchemaRegistry interface.
26
29
  # registry_url - The String URL of the schema registry that should be used.
27
30
  # schema_context - Schema registry context name (optional)
28
- # schema_paths - The String file system path where local schemas are stored.
29
31
  # registry_path_prefix - The String URL path prefix used to namespace schema registry requests (optional).
30
32
  # logger - The Logger that should be used to log information (optional).
31
33
  # proxy - Forward the request via proxy (optional).
@@ -43,7 +45,6 @@ class ProtoTurf
43
45
  registry: nil,
44
46
  registry_url: nil,
45
47
  schema_context: nil,
46
- schema_paths: nil,
47
48
  registry_path_prefix: nil,
48
49
  logger: nil,
49
50
  proxy: nil,
@@ -60,7 +61,6 @@ class ProtoTurf
60
61
  retry_limit: nil
61
62
  )
62
63
  @logger = logger || Logger.new($stderr)
63
- @paths = Array(schema_paths)
64
64
  @registry = registry || ProtoTurf::CachedConfluentSchemaRegistry.new(
65
65
  ProtoTurf::ConfluentSchemaRegistry.new(
66
66
  registry_url,
@@ -117,12 +117,6 @@ class ProtoTurf
117
117
  stream.write(message.to_proto)
118
118
 
119
119
  stream.string
120
- rescue Excon::Error::NotFound
121
- if schema_id
122
- raise SchemaNotFoundError.new("Schema with id: #{schema_id} is not found on registry")
123
- else
124
- raise SchemaNotFoundError.new("Schema with subject: `#{subject}` version: `#{version}` is not found on registry")
125
- end
126
120
  end
127
121
 
128
122
  # Decodes data into the original message.
@@ -252,19 +246,12 @@ class ProtoTurf
252
246
  end
253
247
 
254
248
  def schema_text(file_descriptor)
255
- @paths.each do |path|
256
- filename = "#{path}/#{file_descriptor.name}"
257
- return File.read(filename) if File.exist?(filename)
258
- end
259
- ""
249
+ ProtoTurf::ProtoText.output(file_descriptor.to_proto)
260
250
  end
261
251
 
262
252
  def load_schemas!
263
- all_messages = ObjectSpace.each_object(Class).select do |o|
264
- o < Google::Protobuf.const_get(:AbstractMessage)
265
- end.to_a
266
- all_messages.each do |m|
267
- file_desc = m.descriptor.file_descriptor
253
+ all_files = ObjectSpace.each_object(Google::Protobuf::FileDescriptor).to_a
254
+ all_files.each do |file_desc|
268
255
  file_path = file_desc.name
269
256
  next if file_path.start_with?("google/protobuf/") # skip built-in protos
270
257
 
@@ -1,8 +1,7 @@
1
1
  RSpec.describe "encoding" do
2
2
  let(:proto_turf) do
3
3
  ProtoTurf.new(
4
- registry_url: "http://localhost:8081",
5
- schema_paths: ["spec/schemas"]
4
+ registry_url: "http://localhost:8081"
6
5
  )
7
6
  end
8
7
 
@@ -1,8 +1,7 @@
1
1
  RSpec.describe "encoding" do
2
2
  let(:proto_turf) do
3
3
  ProtoTurf.new(
4
- registry_url: "http://localhost:8081",
5
- schema_paths: ["spec/schemas"]
4
+ registry_url: "http://localhost:8081"
6
5
  )
7
6
  end
8
7
 
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Generated by the protocol buffer compiler. DO NOT EDIT!
4
+ # source: everything/everything.proto
5
+
6
+ require "google/protobuf"
7
+
8
+ require "simple/simple_pb"
9
+ require "google/protobuf/descriptor_pb"
10
+
11
+ descriptor_data = "\n\x1b\x65verything/everything.proto\x12\reverything.v1\x1a\x13simple/simple.proto\x1a google/protobuf/descriptor.proto\"*\n\x0e\x46oreignMessage\x12\n\n\x02id\x18\x01 \x01(\x05\x12\x0c\n\x04name\x18\x02 \x01(\t\"\xc0\x12\n\x0cTestAllTypes\x12\x16\n\x0eoptional_int32\x18\x01 \x01(\x05\x12\x16\n\x0eoptional_int64\x18\x02 \x01(\x03\x12\x17\n\x0foptional_uint32\x18\x03 \x01(\r\x12\x17\n\x0foptional_uint64\x18\x04 \x01(\x04\x12\x17\n\x0foptional_sint32\x18\x05 \x01(\x11\x12\x17\n\x0foptional_sint64\x18\x06 \x01(\x12\x12\x18\n\x10optional_fixed32\x18\x07 \x01(\x07\x12\x18\n\x10optional_fixed64\x18\x08 \x01(\x06\x12\x19\n\x11optional_sfixed32\x18\t \x01(\x0f\x12\x19\n\x11optional_sfixed64\x18\n \x01(\x10\x12\x16\n\x0eoptional_float\x18\x0b \x01(\x02\x12\x17\n\x0foptional_double\x18\x0c \x01(\x01\x12\x15\n\roptional_bool\x18\r \x01(\x08\x12\x17\n\x0foptional_string\x18\x0e \x01(\t\x12\x16\n\x0eoptional_bytes\x18\x0f \x01(\x0c\x12J\n\x17optional_nested_message\x18\x12 \x01(\x0b\x32).everything.v1.TestAllTypes.NestedMessage\x12?\n\x18optional_foreign_message\x18\x13 \x01(\x0b\x32\x1d.everything.v1.ForeignMessage\x12\x39\n\x17optional_import_message\x18\x14 \x01(\x0b\x32\x18.simple.v1.SimpleMessage\x12\x44\n\x14optional_nested_enum\x18\x15 \x01(\x0e\x32&.everything.v1.TestAllTypes.NestedEnum\x12\x39\n\x15optional_foreign_enum\x18\x16 \x01(\x0e\x32\x1a.everything.v1.ForeignEnum\x12\x33\n\x14optional_import_enum\x18\x17 \x01(\x0e\x32\x15.simple.v1.SimpleEnum\x12!\n\x15optional_string_piece\x18\x18 \x01(\tB\x02\x08\x02\x12\x19\n\roptional_cord\x18\x19 \x01(\tB\x02\x08\x01\x12\x1f\n\x13optional_bytes_cord\x18V \x01(\x0c\x42\x02\x08\x01\x12L\n\x15optional_lazy_message\x18\x1b \x01(\x0b\x32).everything.v1.TestAllTypes.NestedMessageB\x02(\x01\x12W\n optional_unverified_lazy_message\x18\x1c \x01(\x0b\x32).everything.v1.TestAllTypes.NestedMessageB\x02x\x01\x12\x16\n\x0erepeated_int32\x18\x1f \x03(\x05\x12\x16\n\x0erepeated_int64\x18 \x03(\x03\x12\x17\n\x0frepeated_uint32\x18! \x03(\r\x12\x17\n\x0frepeated_uint64\x18\" \x03(\x04\x12\x17\n\x0frepeated_sint32\x18# \x03(\x11\x12\x17\n\x0frepeated_sint64\x18$ \x03(\x12\x12\x18\n\x10repeated_fixed32\x18% \x03(\x07\x12\x18\n\x10repeated_fixed64\x18& \x03(\x06\x12\x19\n\x11repeated_sfixed32\x18' \x03(\x0f\x12\x19\n\x11repeated_sfixed64\x18( \x03(\x10\x12\x16\n\x0erepeated_float\x18) \x03(\x02\x12\x17\n\x0frepeated_double\x18* \x03(\x01\x12\x15\n\rrepeated_bool\x18+ \x03(\x08\x12\x17\n\x0frepeated_string\x18, \x03(\t\x12\x16\n\x0erepeated_bytes\x18- \x03(\x0c\x12J\n\x17repeated_nested_message\x18\x30 \x03(\x0b\x32).everything.v1.TestAllTypes.NestedMessage\x12?\n\x18repeated_foreign_message\x18\x31 \x03(\x0b\x32\x1d.everything.v1.ForeignMessage\x12\x39\n\x17repeated_import_message\x18\x32 \x03(\x0b\x32\x18.simple.v1.SimpleMessage\x12\x44\n\x14repeated_nested_enum\x18\x33 \x03(\x0e\x32&.everything.v1.TestAllTypes.NestedEnum\x12\x39\n\x15repeated_foreign_enum\x18\x34 \x03(\x0e\x32\x1a.everything.v1.ForeignEnum\x12\x33\n\x14repeated_import_enum\x18\x35 \x03(\x0e\x32\x15.simple.v1.SimpleEnum\x12!\n\x15repeated_string_piece\x18\x36 \x03(\tB\x02\x08\x02\x12\x19\n\rrepeated_cord\x18\x37 \x03(\tB\x02\x08\x01\x12L\n\x15repeated_lazy_message\x18\x39 \x03(\x0b\x32).everything.v1.TestAllTypes.NestedMessageB\x02(\x01\x12\x16\n\x0coneof_uint32\x18o \x01(\rH\x00\x12I\n\x14oneof_nested_message\x18p \x01(\x0b\x32).everything.v1.TestAllTypes.NestedMessageH\x00\x12\x16\n\x0coneof_string\x18q \x01(\tH\x00\x12\x15\n\x0boneof_bytes\x18r \x01(\x0cH\x00\x12\x18\n\noneof_cord\x18s \x01(\tB\x02\x08\x01H\x00\x12 \n\x12oneof_string_piece\x18t \x01(\tB\x02\x08\x02H\x00\x12R\n\x19oneof_lazy_nested_message\x18u \x01(\x0b\x32).everything.v1.TestAllTypes.NestedMessageB\x02(\x01H\x00\x1a\"\n\rNestedMessage\x12\x11\n\x02\x62\x62\x18\x01 \x01(\x05\x42\x05\x90\x82\x19\xd2\t\x1a\x1a\n\rOptionalGroup\x12\t\n\x01\x61\x18\x11 \x01(\x05\x1a\x1a\n\rRepeatedGroup\x12\t\n\x01\x61\x18/ \x01(\x05\"'\n\nNestedEnum\x12\x07\n\x03\x46OO\x10\x00\x12\x07\n\x03\x42\x41R\x10\x02\x12\x07\n\x03\x42\x41Z\x10\x03\x42\r\n\x0boneof_field*/\n\x0b\x46oreignEnum\x12\x0f\n\x0b\x46OREIGN_FOO\x10\x00\x12\x0f\n\x0b\x46OREIGN_BAR\x10\x01\x32Y\n\x0bTestService\x12J\n\nTestMethod\x12\x1b.everything.v1.TestAllTypes\x1a\x1d.everything.v1.ForeignMessage\"\x00:4\n\x0bsome_option\x12\x1d.google.protobuf.FieldOptions\x18\xa2\x90\x03 \x01(\x05\x62\x06proto3"
12
+
13
+ pool = Google::Protobuf::DescriptorPool.generated_pool
14
+ pool.add_serialized_file(descriptor_data)
15
+
16
+ module Everything
17
+ module V1
18
+ ForeignMessage = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("everything.v1.ForeignMessage").msgclass
19
+ TestAllTypes = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("everything.v1.TestAllTypes").msgclass
20
+ TestAllTypes::NestedMessage = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("everything.v1.TestAllTypes.NestedMessage").msgclass
21
+ TestAllTypes::OptionalGroup = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("everything.v1.TestAllTypes.OptionalGroup").msgclass
22
+ TestAllTypes::RepeatedGroup = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("everything.v1.TestAllTypes.RepeatedGroup").msgclass
23
+ TestAllTypes::NestedEnum = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("everything.v1.TestAllTypes.NestedEnum").enummodule
24
+ ForeignEnum = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("everything.v1.ForeignEnum").enummodule
25
+ end
26
+ end
@@ -5,7 +5,7 @@
5
5
 
6
6
  require "google/protobuf"
7
7
 
8
- descriptor_data = "\n\x13simple/simple.proto\x12\tsimple.v1\"\x1d\n\rSimpleMessage\x12\x0c\n\x04name\x18\x01 \x01(\tb\x06proto3"
8
+ descriptor_data = "\n\x13simple/simple.proto\x12\tsimple.v1\"\x1d\n\rSimpleMessage\x12\x0c\n\x04name\x18\x01 \x01(\t*,\n\nSimpleEnum\x12\x0e\n\nSIMPLE_FOO\x10\x00\x12\x0e\n\nSIMPLE_BAR\x10\x01\x62\x06proto3"
9
9
 
10
10
  pool = Google::Protobuf::DescriptorPool.generated_pool
11
11
  pool.add_serialized_file(descriptor_data)
@@ -13,5 +13,6 @@ pool.add_serialized_file(descriptor_data)
13
13
  module Simple
14
14
  module V1
15
15
  SimpleMessage = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("simple.v1.SimpleMessage").msgclass
16
+ SimpleEnum = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("simple.v1.SimpleEnum").enummodule
16
17
  end
17
18
  end
@@ -0,0 +1,8 @@
1
+ RSpec.describe ProtoTurf::ProtoText do
2
+ it "should output as expected" do
3
+ output = described_class.output(Everything::V1::TestAllTypes.descriptor.file_descriptor.to_proto)
4
+
5
+ expected = File.read("#{__dir__}/schemas/everything/everything.proto")
6
+ expect(output).to eq(expected)
7
+ end
8
+ end
@@ -0,0 +1,105 @@
1
+ syntax = "proto3";
2
+
3
+ package everything.v1;
4
+
5
+ import "simple/simple.proto";
6
+ import "google/protobuf/descriptor.proto";
7
+
8
+ extend google.protobuf.FieldOptions {
9
+ int32 some_option = 51234;
10
+ }
11
+
12
+ enum ForeignEnum {
13
+ FOREIGN_FOO = 0;
14
+ FOREIGN_BAR = 1;
15
+ }
16
+
17
+ message ForeignMessage {
18
+ int32 id = 1;
19
+ string name = 2;
20
+ }
21
+ message TestAllTypes {
22
+
23
+ enum NestedEnum {
24
+ FOO = 0;
25
+ BAR = 2;
26
+ BAZ = 3;
27
+ }
28
+
29
+ int32 optional_int32 = 1;
30
+ int64 optional_int64 = 2;
31
+ uint32 optional_uint32 = 3;
32
+ uint64 optional_uint64 = 4;
33
+ sint32 optional_sint32 = 5;
34
+ sint64 optional_sint64 = 6;
35
+ fixed32 optional_fixed32 = 7;
36
+ fixed64 optional_fixed64 = 8;
37
+ sfixed32 optional_sfixed32 = 9;
38
+ sfixed64 optional_sfixed64 = 10;
39
+ float optional_float = 11;
40
+ double optional_double = 12;
41
+ bool optional_bool = 13;
42
+ string optional_string = 14;
43
+ bytes optional_bytes = 15;
44
+ NestedMessage optional_nested_message = 18;
45
+ ForeignMessage optional_foreign_message = 19;
46
+ simple.v1.SimpleMessage optional_import_message = 20;
47
+ NestedEnum optional_nested_enum = 21;
48
+ ForeignEnum optional_foreign_enum = 22;
49
+ simple.v1.SimpleEnum optional_import_enum = 23;
50
+ string optional_string_piece = 24 [ctype = STRING_PIECE];
51
+ string optional_cord = 25 [ctype = CORD];
52
+ bytes optional_bytes_cord = 86 [ctype = CORD];
53
+ NestedMessage optional_lazy_message = 27 [lazy = true];
54
+ NestedMessage optional_unverified_lazy_message = 28 [unverified_lazy = true];
55
+ repeated int32 repeated_int32 = 31;
56
+ repeated int64 repeated_int64 = 32;
57
+ repeated uint32 repeated_uint32 = 33;
58
+ repeated uint64 repeated_uint64 = 34;
59
+ repeated sint32 repeated_sint32 = 35;
60
+ repeated sint64 repeated_sint64 = 36;
61
+ repeated fixed32 repeated_fixed32 = 37;
62
+ repeated fixed64 repeated_fixed64 = 38;
63
+ repeated sfixed32 repeated_sfixed32 = 39;
64
+ repeated sfixed64 repeated_sfixed64 = 40;
65
+ repeated float repeated_float = 41;
66
+ repeated double repeated_double = 42;
67
+ repeated bool repeated_bool = 43;
68
+ repeated string repeated_string = 44;
69
+ repeated bytes repeated_bytes = 45;
70
+ repeated NestedMessage repeated_nested_message = 48;
71
+ repeated ForeignMessage repeated_foreign_message = 49;
72
+ repeated simple.v1.SimpleMessage repeated_import_message = 50;
73
+ repeated NestedEnum repeated_nested_enum = 51;
74
+ repeated ForeignEnum repeated_foreign_enum = 52;
75
+ repeated simple.v1.SimpleEnum repeated_import_enum = 53;
76
+ repeated string repeated_string_piece = 54 [ctype = STRING_PIECE];
77
+ repeated string repeated_cord = 55 [ctype = CORD];
78
+ repeated NestedMessage repeated_lazy_message = 57 [lazy = true];
79
+ oneof oneof_field {
80
+ uint32 oneof_uint32 = 111;
81
+ NestedMessage oneof_nested_message = 112;
82
+ string oneof_string = 113;
83
+ bytes oneof_bytes = 114;
84
+ string oneof_cord = 115 [ctype = CORD];
85
+ string oneof_string_piece = 116 [ctype = STRING_PIECE];
86
+ NestedMessage oneof_lazy_nested_message = 117 [lazy = true];
87
+ }
88
+
89
+ message NestedMessage {
90
+ int32 bb = 1 [(everything.v1.some_option) = 1234
91
+ ];
92
+ }
93
+
94
+ message OptionalGroup {
95
+ int32 a = 17;
96
+ }
97
+
98
+ message RepeatedGroup {
99
+ int32 a = 47;
100
+ }
101
+ }
102
+ service TestService {
103
+ rpc TestMethod(TestAllTypes) returns (ForeignMessage) {
104
+ };
105
+ }
@@ -1,23 +1,27 @@
1
1
  syntax = "proto3";
2
2
 
3
3
  package referenced.v1;
4
+
4
5
  import "simple/simple.proto";
5
6
 
6
7
  message MessageA {
8
+
7
9
  message MessageAA {
8
10
  string name = 1;
9
11
  simple.v1.SimpleMessage simple = 2;
10
12
  }
13
+
11
14
  message MessageAB {
12
15
  string name = 1;
13
16
  }
14
17
  }
15
-
16
18
  message MessageB {
19
+
17
20
  message MessageBA {
18
21
  string name = 1;
19
22
  simple.v1.SimpleMessage simple = 2;
20
23
  }
24
+
21
25
  message MessageBB {
22
26
  string name = 1;
23
27
  }
@@ -2,6 +2,11 @@ syntax = "proto3";
2
2
 
3
3
  package simple.v1;
4
4
 
5
+ enum SimpleEnum {
6
+ SIMPLE_FOO = 0;
7
+ SIMPLE_BAR = 1;
8
+ }
9
+
5
10
  message SimpleMessage {
6
11
  string name = 1;
7
12
  }
metadata CHANGED
@@ -1,14 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: proto_turf
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.0.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Daniel Orner
8
- autorequire:
9
8
  bindir: bin
10
9
  cert_chain: []
11
- date: 2025-08-15 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
14
13
  name: google-protobuf
@@ -108,28 +107,35 @@ dependencies:
108
107
  - - ">="
109
108
  - !ruby/object:Gem::Version
110
109
  version: '0'
111
- description:
112
110
  email:
113
111
  - daniel.orner@flipp.com
114
112
  executables: []
115
113
  extensions: []
116
114
  extra_rdoc_files: []
117
115
  files:
116
+ - ".github/workflows/lint.yml"
117
+ - ".github/workflows/release.yml"
118
+ - ".github/workflows/test.yml"
118
119
  - ".rspec"
119
120
  - CHANGELOG.md
120
121
  - Gemfile
121
122
  - Gemfile.lock
122
123
  - LICENSE
123
124
  - README.md
125
+ - Rakefile
124
126
  - lib/proto_turf.rb
125
127
  - lib/proto_turf/cached_confluent_schema_registry.rb
126
128
  - lib/proto_turf/confluent_schema_registry.rb
129
+ - lib/proto_turf/proto_text.rb
127
130
  - lib/proto_turf/version.rb
128
131
  - proto_turf.gemspec
129
132
  - spec/decoding_spec.rb
130
133
  - spec/encoding_spec.rb
134
+ - spec/gen/everything/everything_pb.rb
131
135
  - spec/gen/referenced/referer_pb.rb
132
136
  - spec/gen/simple/simple_pb.rb
137
+ - spec/proto_text_spec.rb
138
+ - spec/schemas/everything/everything.proto
133
139
  - spec/schemas/referenced/referer.proto
134
140
  - spec/schemas/simple/simple.proto
135
141
  - spec/spec_helper.rb
@@ -138,7 +144,6 @@ licenses:
138
144
  - MIT
139
145
  metadata:
140
146
  rubygems_mfa_required: 'true'
141
- post_install_message:
142
147
  rdoc_options: []
143
148
  require_paths:
144
149
  - lib
@@ -153,8 +158,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
153
158
  - !ruby/object:Gem::Version
154
159
  version: '0'
155
160
  requirements: []
156
- rubygems_version: 3.4.10
157
- signing_key:
161
+ rubygems_version: 3.6.9
158
162
  specification_version: 4
159
163
  summary: Support for Protobuf files in Confluent Schema Registry
160
164
  test_files: []