diff --git a/lib/protobuf/generators/group_generator.rb b/lib/protobuf/generators/group_generator.rb index 33e7b5be..a6f4241a 100644 --- a/lib/protobuf/generators/group_generator.rb +++ b/lib/protobuf/generators/group_generator.rb @@ -4,6 +4,7 @@ require 'protobuf/generators/message_generator' require 'protobuf/generators/option_generator' require 'protobuf/generators/service_generator' +require 'protobuf/generators/oneof_group_generator' module Protobuf module Generators @@ -27,6 +28,12 @@ def add_options(option_descriptor) @groups[:options] << OptionGenerator.new(option_descriptor, indent_level) end + def add_oneof_groups(field_descriptors, msg_descriptor) + return unless msg_descriptor.oneof_decl.length > 0 + + @groups[:oneof_group] << OneofGroupGenerator.new(msg_descriptor.oneof_decl, field_descriptors, indent_level) + end + def add_enums(enum_descriptors, options) enum_descriptors.each do |enum_descriptor| @groups[:enum] << EnumGenerator.new(enum_descriptor, indent_level, options) diff --git a/lib/protobuf/generators/message_generator.rb b/lib/protobuf/generators/message_generator.rb index bbaf84d5..c38b49d4 100644 --- a/lib/protobuf/generators/message_generator.rb +++ b/lib/protobuf/generators/message_generator.rb @@ -44,6 +44,9 @@ def compile_message group.add_messages(descriptor.nested_type, :extension_fields => @extension_fields, :namespace => type_namespace) group.add_comment(:options, 'Message Options') group.add_options(descriptor.options) if options? + group.add_oneof_groups(descriptor.field, descriptor) + group.add_comment(:oneof_group, 'Oneof Groups') + group.add_message_fields(descriptor.field, descriptor) self.class.validate_tags(fully_qualified_type_namespace, descriptor.field.map(&:number)) @@ -54,7 +57,7 @@ def compile_message group.add_extension_fields(message_extension_fields) - group.order = [:message, :options, :field, :extension_range, :extension_field] + group.order = [:message, :options, :oneof_group, :field, :extension_range, :extension_field] print group.to_s end end diff --git a/lib/protobuf/generators/oneof_group_generators.rb b/lib/protobuf/generators/oneof_group_generators.rb new file mode 100644 index 00000000..b8ce86a5 --- /dev/null +++ b/lib/protobuf/generators/oneof_group_generators.rb @@ -0,0 +1,29 @@ +require 'protobuf/generators/base' + +module Protobuf + module Generators + class OneofGroupGenerator < Base + def initialize(oneof_decl, field_descriptors, indent_level, options = {}) + super(oneof_decl, indent_level, options) + @field_descriptors = field_descriptors + end + + def compile + run_once(:compile) do + descriptor.each_with_index do |oneof_descriptor, idx| + puts build_value(oneof_descriptor.name, idx) + end + puts + end + end + + def build_value(name, oneof_index) + oneof_fields = @field_descriptors.select { |field_descriptor| field_descriptor.oneof_index == oneof_index } + + "oneof_group :#{name.strip}, [:#{oneof_fields.map(&:name).join(', :')}]" + end + end + end +end + + diff --git a/lib/protobuf/message.rb b/lib/protobuf/message.rb index a13c0d19..3f12d5be 100644 --- a/lib/protobuf/message.rb +++ b/lib/protobuf/message.rb @@ -1,5 +1,6 @@ require 'protobuf/message/fields' require 'protobuf/message/serialization' +require 'protobuf/message/oneof_groups' require 'protobuf/varint' module Protobuf @@ -10,6 +11,7 @@ class Message # extend ::Protobuf::Message::Fields + extend ::Protobuf::Message::OneofGroups include ::Protobuf::Message::Serialization ::Protobuf::Optionable.inject(self) { ::Google::Protobuf::MessageOptions } diff --git a/lib/protobuf/message/oneof_groups.rb b/lib/protobuf/message/oneof_groups.rb new file mode 100644 index 00000000..74e3451d --- /dev/null +++ b/lib/protobuf/message/oneof_groups.rb @@ -0,0 +1,31 @@ +module Protobuf + class Message + module OneofGroups + def self.extended(other) + other.extend(ClassMethods) + end + + module ClassMethods + # Define a oneOf group + # + def oneof_group(group_name, field_names) + oneof_groups[group_name] = field_names + end + + def get_oneof_group(group_name) + oneof_groups[group_name] + end + + def raise_if_oneof_group_name_collision(group_name) + if get_oneof_group(group_name) + fail DuplicateOneofGroupNameError, %(Oneof group name #{group_name} has already been used in "#{name}".) + end + end + + def oneof_groups + @oneof_groups ||= {} + end + end + end + end +end