class RustyJson::Parser

Parser is the base class that actually parses JSON into Rust structs

Example: “‘ruby name = ’Test’ json = ‘{“hello”: “world”}’ parser = Parser.new(name, json) parser.parse “‘

Public Class Methods

new(name, json) click to toggle source

@param name [String] the name of the returned root JSON struct @param json [String] the JSON string to parse into a Rust struct

# File lib/rusty_json/parser.rb, line 18
def initialize(name, json)
  @name = name
  @json = json
  @structs = Set.new
end

Public Instance Methods

parse() click to toggle source

parse takes the given JSON string and turns it into a string of Rust structs, suitable for use with rustc_serialize.

# File lib/rusty_json/parser.rb, line 26
def parse
  (type, subtype) = parse_object([@name], JSON.parse(@json))
  (subtype || type).to_s.gsub(/\n\n$/, "\n")
end

Private Instance Methods

clean_name(name) click to toggle source
# File lib/rusty_json/parser.rb, line 33
def clean_name(name)
  name.gsub('-', '_').gsub(':', '_').gsub('__', '_')
end
densify_array(array) click to toggle source
# File lib/rusty_json/parser.rb, line 84
def densify_array(array)
  # Try to get rid of as much ambiguity, as possible:
  object = array.first
  array.each do |hash|
    hash.each do |key, value|
      object[key] ||= value
    end
  end
  object
end
parse_array(key_path, array) click to toggle source
# File lib/rusty_json/parser.rb, line 71
def parse_array(key_path, array)
  if Set.new(array.map(&:class)).count > 1
    fail('Cannot handle multi-typed arrays')
  end
  object = (array.first.is_a? Hash) ? densify_array(array) : array.first
  subtype = array.empty? ? nil : parse_object(key_path, object).first
  [Array, subtype]
end
parse_hash(key_path, hash) click to toggle source
# File lib/rusty_json/parser.rb, line 60
def parse_hash(key_path, hash)
  name = ActiveSupport::Inflector.singularize(key_path.map { |key| parse_name(key) }.join(''))
  struct = RustStruct.new(name)
  hash.each do |key, value|
    val = *parse_object(key_path + [key], value)
    val[0] = possible_new_struct(val[0]) if val[0].is_a? RustStruct
    struct.add_value(clean_name(key), *val)
  end
  [struct, nil]
end
parse_name(name) click to toggle source
# File lib/rusty_json/parser.rb, line 37
def parse_name(name)
  clean_name(name).split('_').map(&:capitalize).join
end
parse_object(key_path, object) click to toggle source
# File lib/rusty_json/parser.rb, line 41
def parse_object(key_path, object)
  if object.is_a? Array
    parse_array(key_path, object)
  elsif object.is_a? Hash
    parse_hash(key_path, object)
  else
    parse_value(key_path, object)
  end
end
parse_value(_key_path, value) click to toggle source
# File lib/rusty_json/parser.rb, line 80
def parse_value(_key_path, value)
  [value.class, nil]
end
possible_new_struct(s) click to toggle source
# File lib/rusty_json/parser.rb, line 51
def possible_new_struct(s)
  match = @structs.find{|st| s == st}
  s = match || s
  if match.nil?
    @structs << s
  end
  s
end