Module: SchemaRegistry::Output::ProtoText

Defined in:
lib/schema_registry_client/output/proto_text.rb

Defined Under Namespace

Classes: ParseInfo, Writer

Class Method Summary collapse

Class Method Details

.fetch(message_name) ⇒ Object



44
45
46
47
# File 'lib/schema_registry_client/output/proto_text.rb', line 44

def fetch(message_name)
  name = message_name.start_with?(".") ? message_name[1..] : message_name
  Google::Protobuf::DescriptorPool.generated_pool.lookup(name)
end

.field_type(info, field_type) ⇒ Object



156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
# File 'lib/schema_registry_client/output/proto_text.rb', line 156

def field_type(info, field_type)
  case field_type.type
  when :TYPE_INT32
    "int32"
  when :TYPE_INT64
    "int64"
  when :TYPE_UINT32
    "uint32"
  when :TYPE_UINT64
    "uint64"
  when :TYPE_SINT32
    "sint32"
  when :TYPE_SINT64
    "sint64"
  when :TYPE_FIXED32
    "fixed32"
  when :TYPE_FIXED64
    "fixed64"
  when :TYPE_SFIXED32
    "sfixed32"
  when :TYPE_SFIXED64
    "sfixed64"
  when :TYPE_FLOAT
    "float"
  when :TYPE_DOUBLE
    "double"
  when :TYPE_BOOL
    "bool"
  when :TYPE_STRING
    "string"
  when :TYPE_BYTES
    "bytes"
  when :TYPE_ENUM, :TYPE_MESSAGE
    # remove leading .
    type = fetch(field_type.type_name[1..])
    name = type.name.sub("#{info.package}.#{info.message.name}.", "")
    name.sub("#{info.package}.", "")
  end
end

.method_type(package, name) ⇒ Object



261
262
263
264
265
# File 'lib/schema_registry_client/output/proto_text.rb', line 261

def method_type(package, name)
  output = name.sub("#{package}.", "")
  output = output[1..] if output.start_with?(".")
  output
end

.output(file_descriptor) ⇒ Object



49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
# File 'lib/schema_registry_client/output/proto_text.rb', line 49

def output(file_descriptor)
  writer = Writer.new
  info = ParseInfo.new(writer, file_descriptor.package)
  writer.write_line("syntax = \"#{file_descriptor.syntax}\";", 2)
  writer.write_line("package #{file_descriptor.package};")
  writer.writenl
  found = false
  file_descriptor.options.to_h.each do |name, value|
    found = true
    writer.write_line("option #{name} = #{value.to_json};")
  end
  writer.writenl if found

  found = false
  file_descriptor.dependency.each do |dependency|
    found = true
    writer.write_line("import \"#{dependency}\";")
  end
  writer.writenl if found

  writer.writenl if write_options(info, file_descriptor)
  writer.writenl if write_extensions(info, file_descriptor)

  file_descriptor.enum_type.each do |enum_type|
    write_enum(info, enum_type)
  end
  file_descriptor.message_type.each do |message_type|
    write_message(info, message_type)
  end
  file_descriptor.service.each do |service|
    write_service(info, service)
  end
  writer.string
end

.write_enum(info, enum_type) ⇒ Object



247
248
249
250
251
252
253
254
255
256
257
258
259
# File 'lib/schema_registry_client/output/proto_text.rb', line 247

def write_enum(info, enum_type)
  info.write("enum ")
  info.write("#{enum_type.name} {")
  info.writenl
  info.indent
  write_reserved(info, enum_type)
  enum_type.value.each do |value|
    info.write_line("#{value.name} = #{value.number};")
  end
  info.dedent
  info.write_line("}")
  info.writenl
end

.write_extensions(info, descriptor) ⇒ Object



84
85
86
87
88
89
90
91
92
93
# File 'lib/schema_registry_client/output/proto_text.rb', line 84

def write_extensions(info, descriptor)
  descriptor.extension.each do |extension|
    info.write_line("extend #{extension.extendee[1..]} {")
    info.indent
    write_field(info, extension)
    info.dedent
    info.write_line("}")
  end
  descriptor.extension.any?
end

.write_field(info, field, oneof: false) ⇒ Object



196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
# File 'lib/schema_registry_client/output/proto_text.rb', line 196

def write_field(info, field, oneof: false)
  return if !oneof && field.has_oneof_index?

  info.write_indent("")

  klass = nil
  klass = fetch(field.type_name).to_proto if field.type_name && field.type_name != ""

  if field.proto3_optional
    info.write("optional ")
  elsif field.label == :LABEL_REPEATED && !klass&.options&.map_entry
    info.write("repeated ")
  end

  if klass&.options&.map_entry
    info.write("map<#{field_type(info, klass.field[0])}, #{field_type(info, klass.field[1])}>")
  else
    info.write(field_type(info, field).to_s)
  end
  info.write(" #{field.name} = #{field.number}")

  write_field_options(info, field)
  info.write(";")
  info.writenl
end

.write_field_options(info, field) ⇒ Object



222
223
224
225
226
227
228
229
# File 'lib/schema_registry_client/output/proto_text.rb', line 222

def write_field_options(info, field)
  return unless field.options

  info.write(" [")
  info.write(field.options.to_h.map { |name, value| "#{name} = #{value}" }.join(", "))
  write_options(info, field, include_option_label: false)
  info.write("]")
end

.write_imports(writer, file_descriptor) ⇒ Object



111
112
113
114
115
116
117
118
119
120
121
122
123
# File 'lib/schema_registry_client/output/proto_text.rb', line 111

def write_imports(writer, file_descriptor)
  writer.writenl
  file_descriptor.dependency.each do |dependency|
    writer.write_line("import \"#{dependency}\";")
  end
  file_descriptor.public_dependency.each do |public_dependency|
    writer.write_line("import public \"#{public_dependency}\";")
  end
  file_descriptor.option_dependency.each do |option_dependency|
    writer.write_line("import weak \"#{option_dependency}\";")
  end
  writer.writenl
end

.write_message(info, message_type) ⇒ Object



125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
# File 'lib/schema_registry_client/output/proto_text.rb', line 125

def write_message(info, message_type)
  info.message = message_type
  info.write_indent("message ")
  info.write("#{message_type.name} {")
  info.writenl
  info.indent

  write_options(info, message_type)
  write_reserved(info, message_type)

  message_type.enum_type.each do |enum|
    info.writenl
    write_enum(info, enum)
  end
  message_type.field.each do |field|
    write_field(info, field)
  end
  message_type.extension.each do |extension|
    write_field(info, extension)
  end
  write_oneofs(info, message_type)
  message_type.nested_type.each do |subtype|
    next if subtype.options&.map_entry

    info.writenl
    write_message(info, subtype)
  end
  info.dedent
  info.write_line("}")
end

.write_oneofs(info, message) ⇒ Object



231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
# File 'lib/schema_registry_client/output/proto_text.rb', line 231

def write_oneofs(info, message)
  message.oneof_decl.each_with_index do |oneof, i|
    # synthetic oneof for proto3 optional fields
    next if oneof.name.start_with?("_") &&
      message.field.any? { |f| f.proto3_optional && f.name == oneof.name[1..] }

    info.write_line("oneof #{oneof.name} {")
    info.indent
    message.field.select { |f| f.has_oneof_index? && f.oneof_index == i }.each do |field|
      write_field(info, field, oneof: true)
    end
    info.dedent
    info.write_line("}")
  end
end

.write_options(info, descriptor, include_option_label: true) ⇒ Boolean

Returns true if any options were written.

Returns:

  • (Boolean)

    true if any options were written



284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
# File 'lib/schema_registry_client/output/proto_text.rb', line 284

def write_options(info, descriptor, include_option_label: true)
  # unfortunately there doesn't seem to be a way to get the full list of options without
  # resorting to to_json.
  json = JSON.parse(descriptor.options.to_json)
  return if !json || json.empty?

  found = false
  json.each_key do |name|
    option_name = name.tr("[]", "")
    ext = fetch(option_name)
    next if ext.nil?

    found = true
    options = ext.get(descriptor.options)
    if include_option_label
      info.write_indent("option (#{option_name}) =")
    else
      info.write("(#{option_name}) = ")
    end
    if options.respond_to?(:to_h)
      lines = JSON.pretty_generate(options.to_h).lines(chomp: true)
      lines.each_with_index do |line, i|
        info.write_indent(line)
        info.writenl if i < lines.length - 1
      end
      info.write(";")
    else
      info.write(options.to_json)
    end
    info.writenl
  end
  found
end

.write_reserved(writer, descriptor) ⇒ Object



95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
# File 'lib/schema_registry_client/output/proto_text.rb', line 95

def write_reserved(writer, descriptor)
  reserved = descriptor.reserved_range.map do |range|
    (range.start == range.end - 1) ? range.start.to_s : "#{range.start} to #{range.end - 1}"
  end
  found = false
  if reserved.any?
    found = true
    writer.write_line("reserved #{reserved.join(", ")};")
  end
  if descriptor.reserved_name.any?
    found = true
    writer.write_line("reserved #{descriptor.reserved_name.map(&:to_json).join(", ")};")
  end
  writer.writenl if found
end

.write_service(info, service) ⇒ Object



267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
# File 'lib/schema_registry_client/output/proto_text.rb', line 267

def write_service(info, service)
  info.write_line("service #{service.name} {")
  info.indent
  service["method"].each do |method|
    info.write_indent("rpc #{method.name}(#{method_type(info.package, method.input_type)}) ")
    info.write("returns (#{method_type(info.package, method.output_type)}) {")
    info.writenl
    info.indent
    write_options(info, method) if method.options
    info.dedent
    info.write_line("};")
  end
  info.dedent
  info.write_line("}")
end