class FileDescriptorToD

Constants

TYPE_MAPPING

Public Class Methods

new(descriptor) click to toggle source
Calls superclass method
# File lib/protocol_buffers/compiler/file_descriptor_to_d.rb, line 9
def initialize(descriptor)
  super
  @module = descriptor.package_
  @ns = []
end

Public Instance Methods

class_name(klass) click to toggle source
# File lib/protocol_buffers/compiler/file_descriptor_to_d.rb, line 19
def class_name(klass)
  klass
end
module_name() click to toggle source
# File lib/protocol_buffers/compiler/file_descriptor_to_d.rb, line 15
def module_name
  @module
end
write(io) click to toggle source
# File lib/protocol_buffers/compiler/file_descriptor_to_d.rb, line 23
  def write(io)
    @io = io

    @io.write <<HEADER
// Generated by the protocol buffer compiler. DO NOT EDIT!

static import std.string;
import protocol_buffers.message;

HEADER

    descriptor.message_type.each do |message|
      dump_message(message)
    end
  end

Protected Instance Methods

capfirst(s) click to toggle source
# File lib/protocol_buffers/compiler/file_descriptor_to_d.rb, line 183
def capfirst(s)
  "#{s[0,1].capitalize}#{s[1..-1]}" if s
end
default_value(field) click to toggle source
# File lib/protocol_buffers/compiler/file_descriptor_to_d.rb, line 152
def default_value(field)
  typename = field_typename(field)

  if field.default_value && field.default_value != ""
    case field.type
    when TYPE_STRING, TYPE_BYTES
      %{"#{field.default_value}"}
    when TYPE_BOOL
      field.default_value || "false"
    when TYPE_ENUM
      %{#{typename}.#{field.default_value}}
    else
      field.default_value || "0"
    end
  else
      %{(#{typename}).init}
  end
end
define_field(field, repeated) click to toggle source
# File lib/protocol_buffers/compiler/file_descriptor_to_d.rb, line 102
def define_field(field, repeated)
  typename = field_typename(field)
  if repeated
    line "private #{typename}[] _#{field.name};"
    line "#{typename}[] #{field.name}() { return _#{field.name}; }"
  else
    line "private #{typename} _#{field.name};"
    line "#{typename} #{field.name}() { return _#{field.name}; }"
  end

  if !repeated
    line "static const #{typename} default_#{field.name} = #{default_value(field)};"
    line "bool has_#{field.name}() { return _check_bit(__bits.#{field.name}); }"
    line "void #{field.name}(#{typename} val) { _set_bit(__bits.#{field.name}); _#{field.name} = val; }"
  end

  if repeated
    line "void clear_#{field.name}() { _#{field.name} = []; }"
  else
    line "void clear_#{field.name}() { _clear_bit(__bits.#{field.name}); _#{field.name} = default_#{field.name}; }"
  end
  line
end
dump_enum(enum) click to toggle source
# File lib/protocol_buffers/compiler/file_descriptor_to_d.rb, line 126
def dump_enum(enum)
  in_namespace("enum", enum.name) do
    enum.value.each do |value|
      line %{#{value.name} = #{value.number},}
    end
  end
end
dump_message(message) click to toggle source
# File lib/protocol_buffers/compiler/file_descriptor_to_d.rb, line 41
  def dump_message(message)
    in_namespace("final class", class_name(message.name), " : Message") do

      line %{static const #{class_name(message.name)} default_instance;}
      line %{string typeName() { return "#{class_name(message.name)}"; }}

      line %{// nested messages} unless message.nested_type.empty?
      message.nested_type.each { |inner| dump_message(inner) }

      line %{// nested enums} unless message.enum_type.empty?
      message.enum_type.each { |inner| dump_enum(inner) }

      singular_fields = message.field.find_all { |f|
        f.label == LABEL_OPTIONAL || f.label == LABEL_REQUIRED }
      repeated_fields = message.field.find_all { |f| f.label == LABEL_REPEATED }

      line

      singular_fields.each { |f| define_field(f, false) }
      repeated_fields.each { |f| define_field(f, true) }

      line %{enum __tags { #{message.field.map { |f| "#{f.name} = #{f.number}" }.join(", ")} }}

      unless singular_fields.empty?
        in_namespace("private", "") do
          line "ubyte[(#{singular_fields.size}/32)+1] _tags;"
          line %{void _set_bit(uint idx)   { _tags[idx / 32] |= (1u << (idx % 32)); }}
          line %{void _clear_bit(uint idx) { _tags[idx / 32] &= ~(1u << (idx % 32)); }}
          line %{bool _check_bit(uint idx) { return (_tags[idx / 32] & (1u << (idx % 32))) != 0; }}
        end
        line %{enum __bits { #{m=0; singular_fields.map { |f| "#{f.name} = #{m+=1}" }.join(", ")} }} unless singular_fields.empty?
      end

      in_namespace("void clear()", "") do
        message.field.each { |f| line %{clear_#{f.name}();} }
      end

      in_namespace("bool mergeFromString(string s)", "") do
        body = <<-BODY
        uint i;
        while(i < s.length) {
          long nextTag = decodeVarint(s[i++]);
          long tag = nextTag >> 3;
          uint wire_type = nextTag & 0b111;
          switch(tag) {
          }
        }
        return true;
        BODY

        body.each_line { |l| line(l.sub("        ", '').chomp) }
      end

      line
    end
  end
field_typename(field) click to toggle source
# File lib/protocol_buffers/compiler/file_descriptor_to_d.rb, line 98
def field_typename(field)
  (TYPE_MAPPING[field.type] || field.type_name).sub(/^.#{module_name}/, '')
end
in_namespace(type, name, rest = "") { || ... } click to toggle source
# File lib/protocol_buffers/compiler/file_descriptor_to_d.rb, line 171
def in_namespace(type, name, rest = "")
  if !name
    yield
  else
    line "#{type} #{capfirst(name)}#{rest} {"
    @ns.push name
    yield
    @ns.pop
    line "}"
  end
end
line(str = nil) click to toggle source
# File lib/protocol_buffers/compiler/file_descriptor_to_d.rb, line 187
def line(str = nil)
  if str
    @ns.size.times { @io.write("  ") }
    @io.write(str)
  end
  @io.write("\n")
end