rusty_json 1.2.2 → 1.2.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 8229cb337a37bcc8564b5a89faea33d555df6baf
4
- data.tar.gz: a59744de5deffd9f5e4574c9d2851da6b57a7552
3
+ metadata.gz: 80f45d09c233b8bd9a51eb44b6b1d494c50e5f6b
4
+ data.tar.gz: b90b6666fde5e38f12031528ce5f4051594d6790
5
5
  SHA512:
6
- metadata.gz: feb861a20062c7e8fec5dd896dbd3783215568e8730a2c4e2e943f074020fa14876de0ecc19ce00ad8462f550768786d03e7318e6dd2a04dd8672fc95f8f04ee
7
- data.tar.gz: b83f60923de006bffe464f745bccb756a898950161712ef37c3635b5ff5a59fb77c4ea20dade8b721d296b5b22ae1022823fd666fef90b8892e00e67f22bfc39
6
+ metadata.gz: 97bd1d4de345fd9da6052628fe12f8c2aa1026380d35bd5c4121c4d26912289fe8489e804520accbf9675856d4cedec138c1b2d50ebf230b317a42d6f5390778
7
+ data.tar.gz: 11f8b29588bafd836a4b557ee7c09e1b69e75a7e68419a390bfcdaddca72f101f77c0bbff66bd9a48949355ed05e77aa2b5e672ad35d6f02dcbfc6b6cc6e686c
data/.travis.yml CHANGED
@@ -11,4 +11,6 @@ matrix:
11
11
  before_install: gem install bundler -v 1.10.6
12
12
  addons:
13
13
  code_climate:
14
- repo_token: 34d0d282f871aa2247e5b461141fcec4ef02fcf0a952476f33216dec59091827
14
+ repo_token: 34d0d282f871aa2247e5b461141fcec4ef02fcf0a952476f33216dec59091827
15
+ notifications:
16
+ email: false
data/bin/rusty_json ADDED
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "rusty_json"
4
+
5
+ if $stdin.tty? && ARGV.empty?
6
+ puts "USAGE: $ echo '{\"test\":64}' | rusty_json"
7
+ puts "USAGE: $ rusty_json path/to/file.json"
8
+ else
9
+ puts RustyJson.parse(ARGF.read)
10
+ end
@@ -1,5 +1,6 @@
1
1
  require 'json'
2
2
  require 'set'
3
+ require 'active_support/inflector'
3
4
 
4
5
  module RustyJson
5
6
  # Parser is the base class that actually parses JSON into Rust structs
@@ -11,98 +12,72 @@ module RustyJson
11
12
  # parser = Parser.new(name, json)
12
13
  # parser.parse
13
14
  # ```
14
-
15
15
  class Parser
16
- # BASE_TYPES are merely Rust base types that we use before adding our own
17
- # Structs to them.
18
- BASE_TYPES = {
19
- String => 'String',
20
- Fixnum => 'i64',
21
- Float => 'f64',
22
- }
23
-
24
16
  # @param name [String] the name of the returned root JSON struct
25
17
  # @param json [String] the JSON string to parse into a Rust struct
26
18
  def initialize(name, json)
27
19
  @name = name
28
20
  @json = json
29
- @struct_names = Set.new
30
- @structs = Set.new
31
21
  end
32
22
 
33
23
  # parse takes the given JSON string and turns it into a string of
34
24
  # Rust structs, suitable for use with rustc_serialize.
35
25
  def parse
36
- @parsed = JSON.parse(@json)
37
- if @parsed.is_a? Hash
38
- struct = parse_hash(@name, @parsed)
39
- end
40
- struct.to_s
26
+ (type, subtype) = parse_object([@name], JSON.parse(@json))
27
+ (subtype || type).to_s.gsub(/\n\n$/, "\n")
41
28
  end
42
29
 
43
30
  private
44
31
 
45
- def parse_name(n)
46
- n = n.split('_').collect(&:capitalize).join
47
-
48
- if @struct_names.include? n
49
- i = 2
50
- while @struct_names.include? "#{n}_#{i}"
51
- i += 1
52
- end
53
- "#{n}_#{i}"
54
- else
55
- n
56
- end
32
+ def clean_name(name)
33
+ name.gsub('-', '_').gsub(':', '_').gsub('__', '_')
57
34
  end
58
35
 
59
- def possible_new_struct(s)
60
- match = @structs.find{|st| s == st}
61
- s = match || s
62
- if match.nil?
63
- @structs << s
64
- end
65
- s
36
+ def parse_name(name)
37
+ clean_name(name).split('_').map(&:capitalize).join
66
38
  end
67
39
 
68
- def parse_parts(name, values, struct)
69
- name = name.gsub('-', '_').gsub(':', '_').gsub('__', '_')
70
- if values.is_a? Array
71
- struct = parse_array(name, values, struct)
72
- elsif values.is_a? Hash
73
- n = parse_name(name)
74
- @struct_names << n
75
- s = possible_new_struct( parse_hash(n, values) )
76
- struct.add_value(name, s)
40
+ def parse_object(key_path, object)
41
+ if object.is_a? Array
42
+ parse_array(key_path, object)
43
+ elsif object.is_a? Hash
44
+ parse_hash(key_path, object)
77
45
  else
78
- struct = parse_value(name, values, struct)
46
+ parse_value(key_path, object)
79
47
  end
80
- struct
81
48
  end
82
49
 
83
- def parse_hash(n, hash)
84
- struct = RustStruct.new(n)
85
- @struct_names << n
86
- hash.each do |name, values|
87
- struct = parse_parts(name, values, struct)
50
+ def parse_hash(key_path, hash)
51
+ name = ActiveSupport::Inflector.singularize(key_path.map { |key| parse_name(key) }.join(''))
52
+ struct = RustStruct.new(name)
53
+ hash.each do |key, value|
54
+ struct.add_value(clean_name(key), *parse_object(key_path + [key], value))
88
55
  end
89
- struct
56
+ [struct, nil]
90
57
  end
91
58
 
92
- def parse_array(name, values, struct)
93
- # binding.pry
94
- types = Set.new
95
- values.each do |v|
96
- types << v.class
59
+ def parse_array(key_path, array)
60
+ if Set.new(array.map(&:class)).count > 1
61
+ fail('Cannot handle multi-typed arrays')
97
62
  end
98
- fail("Cannot handle multi typed arrays") if types.count > 1
99
- struct.add_value(name, Array, types.to_a.first)
100
- struct
63
+ object = (array.first.is_a? Hash) ? densify_array(array) : array.first
64
+ subtype = array.empty? ? nil : parse_object(key_path, object).first
65
+ [Array, subtype]
66
+ end
67
+
68
+ def parse_value(_key_path, value)
69
+ [value.class, nil]
101
70
  end
102
71
 
103
- def parse_value(name, value, struct)
104
- struct.add_value(name, value.class)
105
- struct
72
+ def densify_array(array)
73
+ # Try to get rid of as much ambiguity, as possible:
74
+ object = array.first
75
+ array.each do |hash|
76
+ hash.each do |key, value|
77
+ object[key] ||= value
78
+ end
79
+ end
80
+ object
106
81
  end
107
82
  end
108
- end
83
+ end
@@ -16,7 +16,10 @@ module RustyJson
16
16
  String => 'String',
17
17
  Fixnum => 'i64',
18
18
  Float => 'f64',
19
+ TrueClass => 'bool',
20
+ FalseClass => 'bool',
19
21
  Array => 'Vec',
22
+ NilClass => 'Option<?>'
20
23
  }
21
24
  # @param name [String] the name of the returned struct
22
25
  # @param root [Boolean] is this the root struct
@@ -35,9 +38,7 @@ module RustyJson
35
38
  # input JSON
36
39
  def reset
37
40
  @printed = false
38
- @structs.each do |s|
39
- s.reset
40
- end
41
+ @structs.each(&:reset)
41
42
  end
42
43
 
43
44
  # Add Value is how we add keys to the resulting Struct
@@ -56,64 +57,51 @@ module RustyJson
56
57
 
57
58
  def add_value(name, type, subtype = nil)
58
59
  if type.class == RustyJson::RustStruct || subtype.class == RustyJson::RustStruct
59
- struct = if type.class == RustyJson::RustStruct
60
+ if type.class == RustyJson::RustStruct
60
61
  t = type
61
62
  type = type.name
62
- t
63
+ struct = t
63
64
  elsif subtype.class == RustyJson::RustStruct
64
65
  s = subtype
65
66
  subtype = subtype.name
66
- s
67
+ struct = s
67
68
  end
68
69
  @structs << struct
69
70
  RustStruct.add_type(struct.name, struct.name)
70
- @values[name] = [type, subtype]
71
- else
72
- @values[name] = [type, subtype]
73
71
  end
72
+ @values[name] = [type, subtype]
74
73
  true
75
74
  end
76
75
 
77
76
  # two Rust structs are equal if all of their keys / value types are the same
78
- def == other
79
- self.values == other.values
77
+ def ==(other)
78
+ values == other.values
80
79
  end
81
80
 
82
81
  # to_s controlls how to display the RustStruct as a Rust Struct
83
82
  def to_s
84
- return "" if @printed
83
+ return '' if @printed
85
84
  @printed = true
86
85
  struct = required_structs
87
- # binding.pry
88
- struct << <<-RUST
89
- struct #{@name} {
90
- RUST
91
- @values.each do |attr_name, type|
92
- if type[1] == nil
93
- struct += " #{attr_name}: #{RustStruct.type_name(type[0])}"
94
- else
95
- struct += " #{attr_name}: #{RustStruct.type_name(type[0])}<#{RustStruct.type_name(type[1])}>"
96
- end
97
- struct += ",\n"
98
- end
99
- struct << <<-RUST
100
- }
101
- RUST
102
- if @root
103
- reset
86
+ members = @values.map do |key, value|
87
+ type = RustStruct.type_name(value[0])
88
+ subtype = RustStruct.type_name(value[1])
89
+ member = " #{key}: #{type}"
90
+ member << "<#{subtype}>" unless value[1].nil?
91
+ member
104
92
  end
93
+ struct << "struct #{@name} {\n" + members.join(",\n") + ",\n}\n\n"
94
+ struct = struct.gsub("\n\n\n", "\n\n")
95
+ reset if @root
105
96
  struct
106
97
  end
107
98
 
108
99
  private
109
100
 
110
101
  def required_structs
111
- struct = ""
112
- # binding.pry
113
- @structs.to_a.each do |nested_struct|
114
- struct << nested_struct.to_s + "\n"
115
- end
116
- struct
102
+ s = @structs.map(&:to_s).join("\n")
103
+ return "" if s == "\n"
104
+ s
117
105
  end
118
106
 
119
107
  def self.add_type(name, value)
@@ -124,4 +112,4 @@ struct #{@name} {
124
112
  @@types[type]
125
113
  end
126
114
  end
127
- end
115
+ end
@@ -1,3 +1,3 @@
1
1
  module RustyJson
2
- VERSION = "1.2.2"
2
+ VERSION = "1.2.3"
3
3
  end
data/rusty_json.gemspec CHANGED
@@ -14,8 +14,8 @@ Gem::Specification.new do |spec|
14
14
  spec.license = "MIT"
15
15
 
16
16
  spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
17
- spec.bindir = "exe"
18
- spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
17
+ spec.bindir = "bin"
18
+ spec.executables = ["rusty_json"] # spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
19
19
  spec.require_paths = ["lib"]
20
20
 
21
21
  spec.add_development_dependency "bundler", "~> 1.10"
@@ -24,4 +24,5 @@ Gem::Specification.new do |spec|
24
24
  spec.add_development_dependency "pry"
25
25
  spec.add_development_dependency 'codeclimate-test-reporter'
26
26
  spec.add_dependency "json"
27
+ spec.add_dependency "activesupport"
27
28
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rusty_json
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.2
4
+ version: 1.2.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chris MacNaughton
8
8
  autorequire:
9
- bindir: exe
9
+ bindir: bin
10
10
  cert_chain: []
11
- date: 2015-10-22 00:00:00.000000000 Z
11
+ date: 2015-10-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -94,10 +94,25 @@ dependencies:
94
94
  - - ">="
95
95
  - !ruby/object:Gem::Version
96
96
  version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: activesupport
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :runtime
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
97
111
  description:
98
112
  email:
99
113
  - chmacnaughton@gmail.com
100
- executables: []
114
+ executables:
115
+ - rusty_json
101
116
  extensions: []
102
117
  extra_rdoc_files: []
103
118
  files:
@@ -109,6 +124,7 @@ files:
109
124
  - README.md
110
125
  - Rakefile
111
126
  - bin/console
127
+ - bin/rusty_json
112
128
  - bin/setup
113
129
  - lib/rusty_json.rb
114
130
  - lib/rusty_json/parser.rb