serde 0.0.1 → 0.0.2

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
  SHA256:
3
- metadata.gz: 56ecad527ba63b8bab91bf3c1f6f69db7b47a2154e61d79163a5a998683682d0
4
- data.tar.gz: 36c782fa69b87ed6e44273b11a73d136665b2e66194d4d6a42d9a9c6f180518e
3
+ metadata.gz: 6451590c25809fc93d4d9a1bcfd3b0792078c0921b6031ec31ce65892ba41c0e
4
+ data.tar.gz: 4efaecacfadf090538b228274d4555781b04c65ee9a07cef4e6266ec7a5b9400
5
5
  SHA512:
6
- metadata.gz: 403cd1c381aeb30ee51cb793ee4fb16b07768d982d6e6654ef498840c66c48584263f7e7590077a43ad31a157341b9f274d8377c102f762714f63ee47b9993ee
7
- data.tar.gz: ae956ed2dd8d82640ea69cc8011308ec904c71019e910136d41cd989d1ebe7c43e09f263d7eb1abee3feeb08c3fcaa1486fefef0b818af331fcd1d8f94d55ba0
6
+ metadata.gz: db9fc2fa1159029b2387ff37768bdde5f008d56dc7a40bf5a6e6bee90650ed01fd5185abd0438aa7fc0b155e68cdb2620db37551e448b6e9f1b1a3ef4e493023
7
+ data.tar.gz: 473f65a45fdebe1d0ed38349441d7810cb4eec559efdf47316f7ce41c4d4bae0da8c691158e9b3503f10467b8ba7ebef6ae8e4f9855d36cabc931940f03e8f61
data/.gitignore CHANGED
@@ -1,3 +1,7 @@
1
+ /.rustc
2
+ /bin/rustc
1
3
  /tmp
2
- /_target_
3
4
  /serde-*.gem
5
+ .ruby-version
6
+ Gemfile.lock
7
+ examples/app/Gemfile.lock
data/.rubocop.yml ADDED
@@ -0,0 +1,29 @@
1
+ inherit_gem:
2
+ armitage-rubocop:
3
+ - lib/rubocop.general.yml
4
+ - lib/rubocop.rspec.yml
5
+
6
+ AllCops:
7
+ TargetRubyVersion: 2.5.3
8
+ Include:
9
+ - serde.gemspec
10
+ - lib/**/*.rb
11
+ - spec/**/*.rb
12
+ - Gemfile
13
+ - examples/**/*.rb
14
+
15
+ Style/TrailingCommaInArguments:
16
+ EnforcedStyleForMultiline: comma
17
+
18
+ Style/TrailingCommaInArrayLiteral:
19
+ EnforcedStyleForMultiline: comma
20
+
21
+ Style/TrailingCommaInHashLiteral:
22
+ EnforcedStyleForMultiline: comma
23
+
24
+ Metrics/AbcSize:
25
+ Max: 40
26
+
27
+ Naming/FileName:
28
+ Exclude:
29
+ - examples/app/Gemfile
data/Gemfile CHANGED
@@ -1,7 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  source 'https://rubygems.org'
2
- gemspec
3
4
 
4
- group :development, :test do
5
- gem 'surrealist'
6
- gem 'benchmark-ips'
7
- end
5
+ git_source(:github) { |repo_name| "https://github.com/#{repo_name}" }
6
+
7
+ gemspec
data/README.md CHANGED
@@ -5,15 +5,17 @@ WIP
5
5
  # TODO:
6
6
 
7
7
  - [ ] Write the README
8
- - [ ] Use a temporary directory instead of `_target_`
8
+ - [x] Use a temporary directory instead of `_target_`
9
9
  - [ ] Write specs
10
- - [ ] Set up rubocop
10
+ - [x] Set up rubocop
11
11
  - [ ] Set up CI
12
12
  - [ ] Reuse Rust crate, but generate sources in a temp dir
13
13
  - [ ] Cover all basic types (Integer, String, Float, Boolean)
14
14
  - [ ] Nullable types
15
15
  - [ ] Composite types (ArrayOf, HashMap?, Enum)
16
16
  - [ ] Vendor `rustc` with the gem
17
- - [ ] Write benchmarks, compare with Surrealist
17
+ - [x] Write benchmarks, compare with Surrealist
18
+ - [ ] Support any serde-compatible format
19
+ - [ ] Deserialization
18
20
  - [ ] Allow dynamic hashes?
19
21
  - [ ] Type checks and coercions?
data/Rakefile ADDED
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/gem_tasks'
4
+ require 'rspec/core/rake_task'
5
+ require 'rubocop'
6
+ require 'rubocop-rspec'
7
+ require 'rubocop/rake_task'
8
+
9
+ RuboCop::RakeTask.new(:rubocop) do |t|
10
+ config_path = File.expand_path(File.join('.rubocop.yml'), __dir__)
11
+
12
+ t.options = ['--config', config_path]
13
+ t.requires << 'rubocop-rspec'
14
+ end
15
+
16
+ RSpec::Core::RakeTask.new(:rspec)
17
+
18
+ task :run_example do
19
+ require_relative 'examples/app/new.rb'
20
+ end
21
+
22
+ task :bench do
23
+ require_relative 'bench/bench.rb'
24
+ end
25
+
26
+ task default: :rspec
data/bench/bench.rb ADDED
@@ -0,0 +1,115 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/setup'
4
+
5
+ require 'benchmark/ips'
6
+ require 'serde'
7
+ require 'surrealist'
8
+
9
+ class User
10
+ attr_reader :id, :first_name, :last_name, :email, :age
11
+
12
+ def initialize(id, first_name, last_name, email, age)
13
+ @id = id
14
+ @first_name = first_name
15
+ @last_name = last_name
16
+ @email = email
17
+ @age = age
18
+ end
19
+ end
20
+
21
+ class UserSerdeSerializer < Serde::Serializer
22
+ schema(
23
+ id: Integer,
24
+ first_name: String,
25
+ last_name: String,
26
+ email: String,
27
+ age: Integer
28
+ )
29
+ end
30
+
31
+ class UserSurrealistSerializer < Surrealist::Serializer
32
+ json_schema do
33
+ {
34
+ id: Integer,
35
+ first_name: String,
36
+ last_name: String,
37
+ email: String,
38
+ age: Integer
39
+ }
40
+ end
41
+ end
42
+
43
+ class UserOjSerializer
44
+ def initialize(user)
45
+ @user = user
46
+ end
47
+
48
+ def to_json
49
+ Oj.dump(
50
+ id: @user.id,
51
+ first_name: @user.first_name,
52
+ last_name: @user.last_name,
53
+ email: @user.email,
54
+ age: @user.age
55
+ )
56
+ end
57
+ end
58
+
59
+ user = User.new(1, 'Pavel', 'Yakimov', 'mrpavel@example.com', 24)
60
+ serde_serializer = UserSerdeSerializer.new(user)
61
+ surrealist_serializer = UserSurrealistSerializer.new(user)
62
+ oj_serializer = UserOjSerializer.new(user)
63
+
64
+ puts "-------\nSerialize to JSON\n-------"
65
+ Benchmark.ips do |x|
66
+ x.report('serde') { serde_serializer.to_json }
67
+ x.report('Surrealist') { surrealist_serializer.surrealize }
68
+ x.report('Oj') { oj_serializer.to_json }
69
+
70
+ x.compare!
71
+ end
72
+
73
+ puts "-------\nInitialize + serialize to JSON\n-------"
74
+ Benchmark.ips do |x|
75
+ x.report('serde') { UserSerdeSerializer.new(user).to_json }
76
+ x.report('Surrealist') { UserSurrealistSerializer.new(user).surrealize }
77
+ x.report('Oj') { UserOjSerializer.new(user).to_json }
78
+
79
+ x.compare!
80
+ end
81
+
82
+ # -------
83
+ # Serialize to JSON
84
+ # -------
85
+ # Warming up --------------------------------------
86
+ # serde 76.802k i/100ms
87
+ # Surrealist 3.064k i/100ms
88
+ # Oj 51.183k i/100ms
89
+ # Calculating -------------------------------------
90
+ # serde 898.268k (± 5.1%) i/s - 4.531M in 5.058080s
91
+ # Surrealist 36.268k (± 3.2%) i/s - 183.840k in 5.074885s
92
+ # Oj 689.594k (± 3.4%) i/s - 3.480M in 5.053357s
93
+
94
+ # Comparison:
95
+ # serde: 898267.9 i/s
96
+ # Oj: 689593.9 i/s - 1.30x slower
97
+ # Surrealist: 36268.1 i/s - 24.77x slower
98
+
99
+ # -------
100
+ # Initialize + serialize to JSON
101
+ # -------
102
+ # Warming up --------------------------------------
103
+ # serde 41.158k i/100ms
104
+ # Surrealist 3.087k i/100ms
105
+ # Oj 51.710k i/100ms
106
+ # Calculating -------------------------------------
107
+ # serde 451.324k (± 1.4%) i/s - 2.264M in 5.016647s
108
+ # Surrealist 33.478k (± 6.8%) i/s - 166.698k in 5.003821s
109
+ # Oj 635.098k (± 2.9%) i/s - 3.206M in 5.052618s
110
+
111
+ # Comparison:
112
+ # Oj: 635097.9 i/s
113
+ # serde: 451323.7 i/s - 1.41x slower
114
+ # Surrealist: 33478.1 i/s - 18.97x slower
115
+
data/bin/.keep ADDED
File without changes
data/examples/app/new.rb CHANGED
@@ -3,20 +3,43 @@
3
3
  require 'bundler/setup'
4
4
  require 'serde'
5
5
 
6
- class CowSerializer < Serde::Serializer
7
- schema(
8
- id: Integer,
9
- name: String,
10
- )
6
+ module Kek
7
+ class Cow
8
+ attr_reader :id, :name
9
+
10
+ def initialize(id, name)
11
+ @id = id
12
+ @name = name
13
+ end
14
+ end
15
+
16
+ class CowSerializer < Serde::Serializer
17
+ schema(
18
+ id: Integer,
19
+ name: String,
20
+ )
21
+ end
11
22
  end
12
23
 
13
- class Cow
14
- attr_reader :id, :name
24
+ module Pek
25
+ class Car
26
+ attr_reader :id, :brand, :model
27
+
28
+ def initialize(id, brand, model)
29
+ @id = id
30
+ @brand = brand
31
+ @model = model
32
+ end
33
+ end
15
34
 
16
- def initialize(id, name)
17
- @id = id
18
- @name = name
35
+ class CarSerializer < Serde::Serializer
36
+ schema(
37
+ id: Integer,
38
+ brand: String,
39
+ model: String,
40
+ )
19
41
  end
20
42
  end
21
43
 
22
- puts CowSerializer.new(Cow.new(1, 'Ковыч')).to_json
44
+ puts Kek::CowSerializer.new(Kek::Cow.new(1, 'Ковыч')).to_json
45
+ puts Pek::CarSerializer.new(Pek::Car.new(1, 'Mazda', '6')).to_json
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ Gem.post_install do
4
+ puts 'installing rustc'
5
+ require_relative 'rustc_installer.rb'
6
+ end
@@ -0,0 +1,96 @@
1
+ # frozen_string_literal: true
2
+
3
+ # TODO: test on different systems and architectures
4
+
5
+ require 'tmpdir'
6
+ require 'net/http'
7
+ require 'fileutils'
8
+ require 'rubygems/package'
9
+ require 'zlib'
10
+
11
+ # https://github.com/rust-lang/rustup.rs/blob/243e3d5889a58116fb7eb910e8508b9d0d0a0b04/rustup-init.sh#L172
12
+ # not considering android and mips for now
13
+ ostype = `uname -s`.chomp
14
+ cputype = `uname -m`.chomp
15
+
16
+ if ostype == 'Darwin' && cputype == 'i386' && !`sysctl hw.optional.x86_64 | grep -q ': 1'`.nil?
17
+ cputype = 'x86_64'
18
+ end
19
+
20
+ ostype =
21
+ case ostype
22
+ when 'Linux' then 'unknown-linux-gnu'
23
+ when 'FreeBSD' then 'unknown-freebsd'
24
+ when 'NetBSD' then 'unknown-netbsd'
25
+ when 'DragonFly' then 'unknown-dragonfly'
26
+ when 'Darwin' then 'apple-darwin'
27
+ when /MINGW/, /MSYS/, /CYGWIN/ then 'pc-windows-gnu'
28
+ else raise "unrecognized OS type: #{ostype}"
29
+ end
30
+
31
+ cputype =
32
+ case cputype
33
+ when 'i386', 'i486', 'i686', 'i786', 'x86' then 'i686'
34
+ when 'xscale', 'arm' then 'arm'
35
+ when 'armv6l' then 'armeabihf'
36
+ when 'armv7l', 'armv8l' then 'armv7eabihf'
37
+ when 'aarch64' then 'aarch64'
38
+ when 'x86_64', 'x86-64', 'x64', 'amd64' then 'x86_64'
39
+ when 'ppc' then 'powerpc'
40
+ when 'ppc64' then 'powerpc64'
41
+ when 'ppc64le' then 'powerpc64le'
42
+ else raise "unknown CPU type: #{cputype}"
43
+ end
44
+
45
+ rustc_name = "rustc-beta-#{cputype}-#{ostype}"
46
+ ruststd_name = "rust-std-beta-#{cputype}-#{ostype}"
47
+ TAR_LONGLINK = '././@LongLink'
48
+ DESTINATION = File.expand_path('../.rustc', __dir__)
49
+
50
+ def download_and_extract(name) # rubocop:disable Metrics/MethodLength
51
+ File.write(
52
+ "#{name}.tar.gz",
53
+ Net::HTTP.get(URI("https://static.rust-lang.org/dist/2018-11-27/#{name}.tar.gz")),
54
+ )
55
+
56
+ # https://stackoverflow.com/a/19139114
57
+ Gem::Package::TarReader.new(Zlib::GzipReader.open("#{name}.tar.gz")) do |tar|
58
+ dest = nil
59
+ tar.each do |entry|
60
+ if entry.full_name == TAR_LONGLINK
61
+ dest = File.join DESTINATION, entry.read.strip
62
+ next
63
+ end
64
+ dest ||= File.join DESTINATION, entry.full_name
65
+ if entry.directory?
66
+ File.delete dest if File.file? dest
67
+ FileUtils.mkdir_p dest, mode: entry.header.mode, verbose: false
68
+ elsif entry.file?
69
+ FileUtils.rm_rf dest if File.directory? dest
70
+ File.open dest, 'wb' do |f|
71
+ f.print entry.read
72
+ end
73
+ FileUtils.chmod entry.header.mode, dest, verbose: false
74
+ elsif entry.header.typeflag == '2' # Symlink!
75
+ File.symlink entry.header.linkname, dest
76
+ end
77
+ dest = nil
78
+ end
79
+ end
80
+ end
81
+
82
+ Dir.mktmpdir do |dir|
83
+ Dir.chdir(dir) do
84
+ # manifest = Net::HTTP.get(URI('https://static.rust-lang.org/dist/channel-rust-beta.toml'))
85
+ # puts manifest
86
+
87
+ download_and_extract(rustc_name)
88
+ download_and_extract(ruststd_name)
89
+
90
+ # TODO: windows?
91
+ FileUtils.ln_s(
92
+ "#{DESTINATION}/#{rustc_name}/rustc/bin/rustc",
93
+ File.expand_path('../bin/rustc', __dir__),
94
+ )
95
+ end
96
+ end
@@ -1,14 +1,16 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'erb'
2
4
 
3
- def generate_serializers
4
- def underscore(str)
5
- str.tr('::', '/')
6
- .gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
7
- .gsub(/([a-z\d])([A-Z])/, '\1_\2')
8
- .tr('-', '_')
9
- .downcase
10
- end
5
+ def underscore(str)
6
+ str.tr('::', '/')
7
+ .gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
8
+ .gsub(/([a-z\d])([A-Z])/, '\1_\2')
9
+ .tr('-', '_')
10
+ .downcase
11
+ end
11
12
 
13
+ def generate_serializers # rubocop:disable Metrics/MethodLength
12
14
  modules = []
13
15
 
14
16
  Serde.subclasses.each do |klass|
@@ -32,7 +34,7 @@ def generate_serializers
32
34
  fields: fields,
33
35
  joint_fields: fields.map do |field|
34
36
  "#{field[:name]}: #{field[:type]}"
35
- end.join(', ')
37
+ end.join(', '),
36
38
  }
37
39
 
38
40
  mod_template = ERB.new(File.read('./rust_template/mod.rs.erb'))
@@ -44,7 +46,7 @@ def generate_serializers
44
46
  lib_template = ERB.new(File.read('./rust_template/lib.rs.erb'))
45
47
  compiled_template = lib_template.result(binding)
46
48
 
47
- File.open("./src/lib.rs", 'w') { |f| f.write(compiled_template) }
49
+ File.open('./src/lib.rs', 'w') { |f| f.write(compiled_template) }
48
50
 
49
51
  `rake build`
50
52
  end
@@ -1,11 +1,15 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'fileutils'
3
4
  require 'erb'
4
5
 
5
6
  module Serde
6
7
  module SerializerGenerator
7
8
  class << self
8
- def call(klass)
9
+ # rubocop:disable Metrics/MethodLength, Metrics/AbcSize, Metrics/CyclomaticComplexity
10
+ def call(dir, klass)
11
+ FileUtils.cp_r(Dir.glob(File.expand_path('../../templates/extension/*', __dir__)), '.')
12
+
9
13
  schema = klass.instance_variable_get(:@schema)
10
14
 
11
15
  name = underscore(klass.name)
@@ -37,6 +41,18 @@ module Serde
37
41
  { name: k, type: type, rctype: rctype, cdecl: cdecl, ctype: ctype }
38
42
  end
39
43
 
44
+ rust_extras = []
45
+
46
+ schema.each do |k, v|
47
+ next unless v.to_s == 'String'
48
+
49
+ rust_extras.push(<<~RUST)
50
+ let #{k} = unsafe {
51
+ CStr::from_ptr(#{k}).to_string_lossy().into_owned()
52
+ };
53
+ RUST
54
+ end
55
+
40
56
  serializer = {
41
57
  class_name: klass.name,
42
58
  name: name,
@@ -50,28 +66,30 @@ module Serde
50
66
  joint_fields_c: fields.map do |field|
51
67
  "#{field[:ctype]} #{field[:name]}"
52
68
  end.join(', '),
69
+ rust_extras: rust_extras,
53
70
  }
54
71
 
55
- mod_template = ERB.new(File.read('./templates/rust/mod.rs'))
72
+ mod_template = ERB.new(File.read(File.expand_path('../../templates/rust/mod.rs', __dir__)))
56
73
  compiled_template = mod_template.result(binding)
57
74
 
58
- File.write("./rust/src/#{name}.rs", compiled_template)
75
+ File.write(File.expand_path("../../rust/src/#{name}.rs", __dir__), compiled_template)
59
76
 
60
- c_template = ERB.new(File.read('./templates/c/serde_rb.c'))
77
+ c_template = ERB.new(File.read(File.expand_path('../../templates/c/serde_rb.c', __dir__)))
61
78
  compiled_template = c_template.result(binding)
62
79
 
63
- File.write('./_target_/serde_rb/serde_rb.c', compiled_template)
80
+ File.write('./serde_rb/serde_rb.c', compiled_template)
64
81
 
65
- lib_template = ERB.new(File.read('./templates/rust/lib.rs'))
82
+ lib_template = ERB.new(File.read(File.expand_path('../../templates/rust/lib.rs', __dir__)))
66
83
  compiled_template = lib_template.result(binding)
67
84
 
68
- File.write("./rust/src/lib.rs", compiled_template)
85
+ File.write(File.expand_path('../../rust/src/lib.rs', __dir__), compiled_template)
69
86
  end
87
+ # rubocop:enable Metrics/MethodLength, Metrics/AbcSize, Metrics/CyclomaticComplexity
70
88
 
71
89
  private
72
90
 
73
91
  def underscore(str)
74
- str.tr('::', '/')
92
+ str.tr('::', '__')
75
93
  .gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
76
94
  .gsub(/([a-z\d])([A-Z])/, '\1_\2')
77
95
  .tr('-', '_')
data/lib/serde.rb CHANGED
@@ -1,20 +1,54 @@
1
- require 'fileutils'
1
+ # frozen_string_literal: true
2
+
3
+ require 'tmpdir'
2
4
  require_relative 'serde/serializer_generator.rb'
3
5
 
4
- FileUtils.rm_r(Dir.glob('_target_/*'))
5
- FileUtils.cp_r(Dir.glob('templates/extension/*'), '_target_')
6
+ trace = TracePoint.new(:end) do |tp|
7
+ klass = tp.self
8
+ if Serde::Serializer.descendants.include?(klass)
9
+ klass.compile!
10
+ end
11
+ end
12
+ trace.enable
6
13
 
7
14
  module Serde
8
15
  class Serializer
16
+ @descendants = []
17
+ @compiled = false
18
+
9
19
  class << self
20
+ attr_reader :descendants
21
+
22
+ def inherited(klass)
23
+ @descendants << klass
24
+ end
25
+
10
26
  def schema(**attrs)
11
27
  @schema = attrs
12
- SerializerGenerator.call(self)
13
- Dir.chdir(File.expand_path('../_target_', __dir__)) do
14
- `make`
28
+ end
29
+
30
+ def compile!
31
+ raise 'already compiled' if @compiled
32
+
33
+ Dir.mktmpdir do |dir|
34
+ Dir.chdir(dir) do
35
+ SerializerGenerator.call(dir, self)
36
+
37
+ root_path = File.expand_path('..', __dir__)
38
+ rust_path = File.expand_path('../rust', __dir__)
39
+ bin_path = File.expand_path('../bin', __dir__)
40
+
41
+ # rubocop:disable Metrics/LineLength
42
+ `cd #{rust_path}; #{bin_path}/rustc --edition=2018 --crate-name serde_rb src/lib.rs --crate-type staticlib --crate-type cdylib --emit=dep-info,link -C opt-level=3 -C metadata=aff563bf4af79579 --out-dir /Users/cow/projects/serde/rust/target/release -L dependency=/Users/cow/projects/serde/rust/target/release/deps --extern serde=/Users/cow/projects/serde/rust/target/release/deps/libserde-6a9e4ab445963d7f.rlib --extern serde_derive=/Users/cow/projects/serde/rust/target/release/deps/libserde_derive-20596753c2ed9015.dylib --extern serde_json=/Users/cow/projects/serde/rust/target/release/deps/libserde_json-489658cb61f64325.rlib -L #{root_path}/.rustc/rust-std-beta-x86_64-apple-darwin/rust-std-x86_64-apple-darwin/lib/rustlib/x86_64-apple-darwin/lib`
43
+ # rubocop:enable Metrics/LineLength
44
+ `cp #{rust_path}/target/release/libserde_rb*.a #{dir}/serde_rb/libserde_rb.a`
45
+ `cd #{dir}/serde_rb; ruby extconf.rb; make clean; make`
46
+
47
+ require_relative "#{dir}/serde_rb/serde_rb"
48
+ end
15
49
  end
16
50
 
17
- require_relative '../_target_/serde_rb/serde_rb'
51
+ @compiled = true
18
52
  end
19
53
 
20
54
  def get_schema
data/serde.gemspec CHANGED
@@ -4,17 +4,17 @@ lib = File.expand_path('../lib', __dir__)
4
4
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
5
 
6
6
  Gem::Specification.new do |spec|
7
- spec.required_ruby_version = '>= 2.5.0'
7
+ spec.required_ruby_version = '>= 2.5.3'
8
8
 
9
- spec.name = 'serde'
10
- spec.version = '0.0.1'
9
+ spec.name = 'serde'
10
+ spec.version = '0.0.2'
11
11
  spec.authors = ['Alexander Komarov']
12
- spec.email = %w[ak@akxcv.com]
12
+ spec.email = %w[ak@akxcv.com]
13
13
 
14
- spec.summary = %q(Fast, compiled serializers for Ruby.)
15
- spec.description = %q(Fast, compiled serializers for Ruby. Powered by serde.rs.)
16
- spec.homepage = 'https://github.com/akxcv/serde.rb'
17
- spec.license = 'MIT'
14
+ spec.summary = 'Fast, compiled serializers for Ruby.'
15
+ spec.description = 'Fast, compiled serializers for Ruby. Powered by serde.rs.'
16
+ spec.homepage = 'https://github.com/akxcv/serde.rb'
17
+ spec.license = 'MIT'
18
18
 
19
19
  spec.require_paths = %w[lib]
20
20
 
@@ -22,8 +22,10 @@ Gem::Specification.new do |spec|
22
22
  f.match(%r{^(test|spec|features)/})
23
23
  end
24
24
 
25
- spec.add_development_dependency 'bundler', '~> 1.17'
26
- spec.add_development_dependency 'pry', '~> 0.12'
27
- spec.add_development_dependency 'rspec', '~> 3.8'
28
- spec.add_development_dependency 'rubocop', '~> 0.60'
25
+ spec.add_development_dependency 'surrealist', '~> 1.3'
26
+ spec.add_development_dependency 'benchmark-ips', '~> 2.7'
27
+ spec.add_development_dependency 'rspec', '~> 3.8'
28
+ spec.add_development_dependency 'armitage-rubocop', '~> 0.12'
29
+ spec.add_development_dependency 'bundler', '~> 1.17'
30
+ spec.add_development_dependency 'pry', '~> 0.12'
29
31
  end
@@ -9,7 +9,11 @@ VALUE c_to_json(VALUE _instance, <%= serializer[:fields].map { |f| "VALUE #{f[:n
9
9
  }
10
10
 
11
11
  void Init_serde_rb(void) {
12
- VALUE klass = rb_const_get(rb_cObject, rb_intern("<%= serializer[:class_name] %>"));
12
+ VALUE klass = rb_eval_string("Object.const_get('<%= serializer[:class_name] %>')");
13
+ /**
14
+ * FIXME: `rb_const_get` doesn't work with nested modules
15
+ */
16
+ // VALUE klass = rb_const_get(rb_cObject, rb_intern("<%= serializer[:class_name] %>"));
13
17
 
14
18
  rb_define_method(klass, "internal_to_json", c_to_json, <%= serializer[:fields].length %>);
15
19
  }
@@ -1,7 +1,5 @@
1
- extern crate serde;
2
- #[macro_use]
3
- extern crate serde_derive;
4
- extern crate serde_json;
1
+ #![allow(non_snake_case)]
2
+
5
3
  use std::os::raw::c_char;
6
4
  use std::ffi::CStr;
7
5
 
@@ -9,13 +7,11 @@ mod <%= serializer[:name] %>;
9
7
 
10
8
  #[no_mangle]
11
9
  pub extern "C" fn serde_rb_rs_<%= serializer[:name] %> (<%= serializer[:joint_fields_rctype] %>) -> *const u8 {
12
- let name = unsafe {
13
- CStr::from_ptr(name).to_string_lossy().into_owned()
14
- };
10
+ <%= serializer[:rust_extras].join("\n") %>
15
11
  let instance = <%= serializer[:name] %>::Struct {
16
12
  <% serializer[:fields].each do |field| %>
17
13
  <%= field[:name] %>,
18
14
  <% end %>
19
15
  };
20
- serde_json::to_string(&instance).unwrap().as_ptr()
16
+ (serde_json::to_string(&instance).unwrap() + "\0").as_ptr()
21
17
  }
@@ -1,3 +1,5 @@
1
+ use serde_derive::Serialize;
2
+
1
3
  #[derive(Serialize)]
2
4
  pub struct Struct {
3
5
  <% fields.each do |field| %>
metadata CHANGED
@@ -1,43 +1,43 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: serde
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alexander Komarov
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-11-28 00:00:00.000000000 Z
11
+ date: 2018-11-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: bundler
14
+ name: surrealist
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '1.17'
19
+ version: '1.3'
20
20
  type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '1.17'
26
+ version: '1.3'
27
27
  - !ruby/object:Gem::Dependency
28
- name: pry
28
+ name: benchmark-ips
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '0.12'
33
+ version: '2.7'
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: '0.12'
40
+ version: '2.7'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: rspec
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -53,19 +53,47 @@ dependencies:
53
53
  - !ruby/object:Gem::Version
54
54
  version: '3.8'
55
55
  - !ruby/object:Gem::Dependency
56
- name: rubocop
56
+ name: armitage-rubocop
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '0.12'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '0.12'
69
+ - !ruby/object:Gem::Dependency
70
+ name: bundler
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '1.17'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '1.17'
83
+ - !ruby/object:Gem::Dependency
84
+ name: pry
57
85
  requirement: !ruby/object:Gem::Requirement
58
86
  requirements:
59
87
  - - "~>"
60
88
  - !ruby/object:Gem::Version
61
- version: '0.60'
89
+ version: '0.12'
62
90
  type: :development
63
91
  prerelease: false
64
92
  version_requirements: !ruby/object:Gem::Requirement
65
93
  requirements:
66
94
  - - "~>"
67
95
  - !ruby/object:Gem::Version
68
- version: '0.60'
96
+ version: '0.12'
69
97
  description: Fast, compiled serializers for Ruby. Powered by serde.rs.
70
98
  email:
71
99
  - ak@akxcv.com
@@ -74,13 +102,16 @@ extensions: []
74
102
  extra_rdoc_files: []
75
103
  files:
76
104
  - ".gitignore"
105
+ - ".rubocop.yml"
77
106
  - Gemfile
78
- - Gemfile.lock
79
107
  - LICENSE
80
108
  - README.md
81
- - examples/app/Gemfile
82
- - examples/app/Gemfile.lock
109
+ - Rakefile
110
+ - bench/bench.rb
111
+ - bin/.keep
83
112
  - examples/app/new.rb
113
+ - lib/rubygems_plugin.rb
114
+ - lib/rustc_installer.rb
84
115
  - lib/serde.rb
85
116
  - lib/serde/generate.rb
86
117
  - lib/serde/serializer_generator.rb
@@ -105,7 +136,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
105
136
  requirements:
106
137
  - - ">="
107
138
  - !ruby/object:Gem::Version
108
- version: 2.5.0
139
+ version: 2.5.3
109
140
  required_rubygems_version: !ruby/object:Gem::Requirement
110
141
  requirements:
111
142
  - - ">="
data/Gemfile.lock DELETED
@@ -1,63 +0,0 @@
1
- PATH
2
- remote: .
3
- specs:
4
- serde (0.1.0)
5
-
6
- GEM
7
- remote: https://rubygems.org/
8
- specs:
9
- ast (2.4.0)
10
- benchmark-ips (2.7.2)
11
- coderay (1.1.2)
12
- diff-lcs (1.3)
13
- jaro_winkler (1.5.1)
14
- method_source (0.9.2)
15
- oj (3.7.1)
16
- parallel (1.12.1)
17
- parser (2.5.3.0)
18
- ast (~> 2.4.0)
19
- powerpack (0.1.2)
20
- pry (0.12.2)
21
- coderay (~> 1.1.0)
22
- method_source (~> 0.9.0)
23
- rainbow (3.0.0)
24
- rspec (3.8.0)
25
- rspec-core (~> 3.8.0)
26
- rspec-expectations (~> 3.8.0)
27
- rspec-mocks (~> 3.8.0)
28
- rspec-core (3.8.0)
29
- rspec-support (~> 3.8.0)
30
- rspec-expectations (3.8.2)
31
- diff-lcs (>= 1.2.0, < 2.0)
32
- rspec-support (~> 3.8.0)
33
- rspec-mocks (3.8.0)
34
- diff-lcs (>= 1.2.0, < 2.0)
35
- rspec-support (~> 3.8.0)
36
- rspec-support (3.8.0)
37
- rubocop (0.60.0)
38
- jaro_winkler (~> 1.5.1)
39
- parallel (~> 1.10)
40
- parser (>= 2.5, != 2.5.1.1)
41
- powerpack (~> 0.1)
42
- rainbow (>= 2.2.2, < 4.0)
43
- ruby-progressbar (~> 1.7)
44
- unicode-display_width (~> 1.4.0)
45
- ruby-progressbar (1.10.0)
46
- surrealist (1.3.1)
47
- oj (~> 3.0)
48
- unicode-display_width (1.4.0)
49
-
50
- PLATFORMS
51
- ruby
52
-
53
- DEPENDENCIES
54
- benchmark-ips
55
- bundler (~> 1.17)
56
- pry (~> 0.12)
57
- rspec (~> 3.8)
58
- rubocop (~> 0.60)
59
- serde!
60
- surrealist
61
-
62
- BUNDLED WITH
63
- 1.17.1
data/examples/app/Gemfile DELETED
@@ -1 +0,0 @@
1
- gem 'serde', path: '../..'
@@ -1,16 +0,0 @@
1
- PATH
2
- remote: ../..
3
- specs:
4
- serde (0.1.0)
5
-
6
- GEM
7
- specs:
8
-
9
- PLATFORMS
10
- ruby
11
-
12
- DEPENDENCIES
13
- serde!
14
-
15
- BUNDLED WITH
16
- 1.17.1