rusty_json 1.2.2 → 1.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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