class Beefcake::Generator

Constants

L
T

Attributes

c[R]

Public Class Methods

compile(req) click to toggle source
# File lib/beefcake/generator.rb, line 143
def self.compile(req)
  file = req.proto_file.map do |file|
    g = new(StringIO.new)
    g.compile(file)

    g.c.rewind
    CodeGeneratorResponse::File.new(
      :name => File.basename(file.name, ".proto") + ".pb.rb",
      :content => g.c.read
    )
  end

  CodeGeneratorResponse.new(:file => file)
end
new(c) click to toggle source
# File lib/beefcake/generator.rb, line 160
def initialize(c)
  @c = c
  @n = 0
end

Public Instance Methods

camelize(term) click to toggle source
# File lib/beefcake/generator.rb, line 304
def camelize(term)
  string = term.to_s
  if /^[A-Z\d]+(?:_[A-Z\d]+)+$/ =~ string
    # Do not mess with SNAKE_CONSTANTS
    string
  else
    string = string.sub(/^[a-z\d]*/) { $&.capitalize }
    string.gsub!(/(?:_|(\/))([a-z\d]*)/i) { "#{$1}#{$2.capitalize}" }
    string.gsub!('/', '::')
    string
  end
end
compile(file) click to toggle source
# File lib/beefcake/generator.rb, line 263
def compile(file)
  package_part = file.package ? "for #{file.package}" : ''
  puts "## Generated from #{file.name} #{package_part}".strip
  puts "require \"beefcake\""
  puts

  ns!(file.package.split('.').map { |v| camelize(v) }) do
    Array(file.enum_type).each do |et|
      enum!(et)
    end

    file.message_type.each do |mt|
      define! mt
    end

    file.message_type.each do |mt|
      message!(file.package, mt)
    end
  end
end
define!(mt) click to toggle source
# File lib/beefcake/generator.rb, line 175
def define!(mt)
  puts
  puts "class #{mt.name}"

  indent do
    puts "include Beefcake::Message"

    ## Enum Types
    Array(mt.enum_type).each do |et|
      enum!(et)
    end

    ## Nested Types
    Array(mt.nested_type).each do |nt|
      define!(nt)
    end
  end
  puts "end"
end
enum!(et) click to toggle source
# File lib/beefcake/generator.rb, line 214
def enum!(et)
  puts
  puts "module #{et.name}"
  indent do
    et.value.each do |v|
      puts "%s = %d" % [v.name, v.number]
    end
  end
  puts "end"
end
field!(pkg, f) click to toggle source
# File lib/beefcake/generator.rb, line 225
def field!(pkg, f)
  # Turn the label into Ruby
  label = name_for(f, L, f.label)

  # Turn the name into a Ruby
  name = ":#{f.name}"

  # Determine the type-name and convert to Ruby
  type = if f.type_name
    t = f.type_name.gsub(/^\.*/, "").split('.').map { |v| camelize(v) } * '::'
  else
    ":#{name_for(f, T, f.type)}"
  end

  # Finally, generate the declaration
  out = "%s %s, %s, %d" % [label, name, type, f.number]

  if f.default_value
    v = case f.type
    when T::TYPE_ENUM
      "%s::%s" % [type, f.default_value]
    when T::TYPE_STRING, T::TYPE_BYTES
      '"%s"' % [f.default_value.gsub('"', '\"')]
    else
      f.default_value
    end

    out += ", :default => #{v}"
  end

  puts out
end
indent(&blk) click to toggle source
# File lib/beefcake/generator.rb, line 165
def indent(&blk)
  @n += 1
  blk.call
  @n -= 1
end
indent!(n) click to toggle source
# File lib/beefcake/generator.rb, line 171
def indent!(n)
  @n = n
end
message!(pkg, mt) click to toggle source
# File lib/beefcake/generator.rb, line 195
def message!(pkg, mt)
  puts
  puts "class #{mt.name}"

  indent do
    ## Generate Types
    Array(mt.nested_type).each do |nt|
      message!(pkg, nt)
    end

    ## Generate Fields
    Array(mt.field).each do |f|
      field!(pkg, f)
    end
  end

  puts "end"
end
name_for(b, mod, val) click to toggle source

Determines the name for a

# File lib/beefcake/generator.rb, line 259
def name_for(b, mod, val)
  b.name_for(mod, val).to_s.gsub(/.*_/, "").downcase
end
ns!(modules, &blk) click to toggle source
# File lib/beefcake/generator.rb, line 284
def ns!(modules, &blk)
  if modules.empty?
    blk.call
  else
    puts "module #{modules.first}"
    indent do
      ns!(modules[1..-1], &blk)
    end
    puts "end"
  end
end
puts(msg=nil) click to toggle source
# File lib/beefcake/generator.rb, line 296
def puts(msg=nil)
  if msg
    c.puts(("  " * @n) + msg)
  else
    c.puts
  end
end