altsv 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 6dabb0913e3f6ee313714b955983a1b52a6ca3dfd3a567287cb08397184a8ffa
4
+ data.tar.gz: '090396592332217d2c087c8e8944b1b5cad271a08f5f2231de01b41002fc1422'
5
+ SHA512:
6
+ metadata.gz: a799aae3dd58843d7b7e70ebfdc5f48099e850fbff88d92e003e9615a1d9e86597ea9da95703ccc1377264bea9a3a5790bfb521761640e0b5d40775318d89175
7
+ data.tar.gz: 0516ea9c4d4b019309c7dca87a3016856bfe6e760d937a67b17b3382c61f34aae0d1e9aacd7a7d960ea14db63029cad4e1ec2e7d9dcc01d8b62471cacbaf2e65
@@ -0,0 +1,57 @@
1
+ *.gem
2
+ *.rbc
3
+ /.config
4
+ /coverage/
5
+ /InstalledFiles
6
+ /pkg/
7
+ /spec/reports/
8
+ /spec/examples.txt
9
+ /test/tmp/
10
+ /test/version_tmp/
11
+ /tmp/
12
+
13
+ # Used by dotenv library to load environment variables.
14
+ # .env
15
+
16
+ ## Specific to RubyMotion:
17
+ .dat*
18
+ .repl_history
19
+ build/
20
+ *.bridgesupport
21
+ build-iPhoneOS/
22
+ build-iPhoneSimulator/
23
+
24
+ ## Specific to RubyMotion (use of CocoaPods):
25
+ #
26
+ # We recommend against adding the Pods directory to your .gitignore. However
27
+ # you should judge for yourself, the pros and cons are mentioned at:
28
+ # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
29
+ #
30
+ # vendor/Pods/
31
+
32
+ ## Documentation cache and generated files:
33
+ /.yardoc/
34
+ /_yardoc/
35
+ /doc/
36
+ /rdoc/
37
+
38
+ ## Environment normalization:
39
+ /.bundle/
40
+ /vendor/bundle
41
+ /lib/bundler/man/
42
+
43
+ # for a library or gem, you might want to ignore these files since the code is
44
+ # intended to run in multiple environments; otherwise, check them in:
45
+ # Gemfile.lock
46
+ # .ruby-version
47
+ # .ruby-gemset
48
+
49
+ # unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
50
+ .rvmrc
51
+
52
+ /.idea/
53
+
54
+ # Avoid the merging of the build intermediates
55
+ /target/
56
+
57
+ /lib/altsv/native.bundle
@@ -0,0 +1,7 @@
1
+ ---
2
+ sudo: false
3
+ language: ruby
4
+ cache: bundler
5
+ rvm:
6
+ - 2.6.0
7
+ before_install: gem install bundler -v 1.17.2
@@ -0,0 +1,41 @@
1
+ [[package]]
2
+ name = "altsv"
3
+ version = "0.0.1"
4
+ dependencies = [
5
+ "helix 0.7.5 (registry+https://github.com/rust-lang/crates.io-index)",
6
+ "libcruby-sys 0.7.5 (registry+https://github.com/rust-lang/crates.io-index)",
7
+ ]
8
+
9
+ [[package]]
10
+ name = "cstr-macro"
11
+ version = "0.1.0"
12
+ source = "registry+https://github.com/rust-lang/crates.io-index"
13
+
14
+ [[package]]
15
+ name = "helix"
16
+ version = "0.7.5"
17
+ source = "registry+https://github.com/rust-lang/crates.io-index"
18
+ dependencies = [
19
+ "cstr-macro 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
20
+ "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)",
21
+ "libcruby-sys 0.7.5 (registry+https://github.com/rust-lang/crates.io-index)",
22
+ ]
23
+
24
+ [[package]]
25
+ name = "libc"
26
+ version = "0.2.48"
27
+ source = "registry+https://github.com/rust-lang/crates.io-index"
28
+
29
+ [[package]]
30
+ name = "libcruby-sys"
31
+ version = "0.7.5"
32
+ source = "registry+https://github.com/rust-lang/crates.io-index"
33
+ dependencies = [
34
+ "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)",
35
+ ]
36
+
37
+ [metadata]
38
+ "checksum cstr-macro 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "db53fddba18cdd35477a7213a3ef6acfbfa333c31b42ce019e544c4a1420a06f"
39
+ "checksum helix 0.7.5 (registry+https://github.com/rust-lang/crates.io-index)" = "49a017e3e798ad9386e0a0584e66fd6c04a80ccc1242eb8f689c62ce6f408240"
40
+ "checksum libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)" = "e962c7641008ac010fa60a7dfdc1712449f29c44ef2d4702394aea943ee75047"
41
+ "checksum libcruby-sys 0.7.5 (registry+https://github.com/rust-lang/crates.io-index)" = "fef6028cdce0c8d55676fd1d66bb810facef8cade0dd71d28511d375e84da4c0"
@@ -0,0 +1,11 @@
1
+ [package]
2
+ name = "altsv"
3
+ version = "0.0.1"
4
+ edition = "2018"
5
+
6
+ [lib]
7
+ crate-type = ["cdylib"]
8
+
9
+ [dependencies]
10
+ helix = "0.7.5"
11
+ libcruby-sys = "0.7.5"
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source "https://rubygems.org"
2
+
3
+ git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
4
+
5
+ # Specify your gem's dependencies in altsv.gemspec
6
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2019 condor
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,78 @@
1
+ # altsv
2
+
3
+ An ALTernative LTSV Parser / Dumper gem partially written in Rust.
4
+
5
+ ## Prerequisites
6
+
7
+ * rustc (tested with 1.32.0)
8
+ * cargo (The de-fact standard package manager for Rust)
9
+
10
+ You can install both with [rustup.rs](https://rustup.rs/)
11
+
12
+ ## Installation
13
+
14
+ Add this line to your application's Gemfile:
15
+
16
+ ```ruby
17
+ gem 'altsv'
18
+ ```
19
+
20
+ And then execute:
21
+
22
+ $ bundle
23
+
24
+ Or install it yourself as:
25
+
26
+ $ gem install altsv
27
+
28
+ ## Usage
29
+
30
+ At first, you should require altsv:
31
+
32
+ require 'altsv'
33
+
34
+ In addition, if you manage gems with bundler, you should add the statement below into your Gemfile:
35
+
36
+ gem 'altsv'
37
+
38
+
39
+ ### parsing LTSV
40
+
41
+ # parse string
42
+ string = "label1:value1\tlabel2:value2"
43
+ values = Altsv.parse(string) # => [{:label1 => "value1", :label2 => "value2"}]
44
+
45
+ # parse via stream
46
+ # content: as below
47
+ # label1_1:value1_1\tlabel1_2:value1_2
48
+ # label2_1:value2_1\tlabel2_2:value2_2
49
+ stream = File.open("some_file.ltsv", "r")
50
+ values = Altsv.parse(stream)
51
+ # => [{:label1_1 => "value1_2", :label1_2 => "value1_2"},
52
+ # {:label2_1 => "value2_2", :label2_2 => "value2_2"}]
53
+
54
+ ### loading LTSV file
55
+
56
+ # load via path
57
+ values = Altsv.load("some_path.ltsv")
58
+
59
+ # load via stream
60
+ stream = File.open("some_file.ltsv", "r")
61
+ values = Altsv.load(stream) # => same as LTSV.parse(stream)
62
+
63
+ ### dumping into LTSV
64
+
65
+ value = {label1: "value1", label2: "value2"}
66
+ dumped = Altsv.dump(value) # => "label1:value1\tlabel2:value2"
67
+
68
+ Dumped objects should respond to :to_hash.
69
+
70
+ ## Development
71
+
72
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
73
+
74
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
75
+
76
+ ## Contributing
77
+
78
+ Bug reports and pull requests are welcome on GitHub at https://github.com/condor/altsv.
@@ -0,0 +1,5 @@
1
+ require 'helix_runtime/build_task'
2
+
3
+ HelixRuntime::BuildTask.new
4
+
5
+ require "bundler/gem_tasks"
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ lib = File.expand_path("../lib", __FILE__)
4
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
+ require "altsv/version"
6
+
7
+ Gem::Specification.new do |spec|
8
+ spec.name = "altsv"
9
+ spec.version = Altsv::VERSION
10
+ spec.authors = ["condor"]
11
+ spec.email = ["condor1226@gmail.com"]
12
+
13
+ spec.summary = %q{an ALTernative ltSV parser / dumper library}
14
+ spec.description = %q{A more lightweight LTSV handler library partially written in Rust.}
15
+ spec.homepage = "https://github.com/condor/altsv"
16
+
17
+ # Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
18
+ # to allow pushing to a single host or delete this section to allow pushing to any host.
19
+ if spec.respond_to?(:metadata)
20
+ spec.metadata["homepage_uri"] = spec.homepage
21
+ spec.metadata["source_code_uri"] = "https://github.com/condor/altsv"
22
+ spec.metadata["changelog_uri"] = "https://github.com/condor/altsv/blob/master/CHANGELOG.md"
23
+ else
24
+ raise "RubyGems 2.0 or newer is required to protect against " \
25
+ "public gem pushes."
26
+ end
27
+
28
+ # Specify which files should be added to the gem when it is released.
29
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
30
+ spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
31
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
32
+ end
33
+ spec.bindir = "exe"
34
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
35
+ spec.require_paths = ["lib"]
36
+ spec.extensions = %w(ext/altsv/extconf.rb)
37
+
38
+ spec.add_dependency 'helix_runtime', '~> 0.7.5'
39
+
40
+ spec.add_development_dependency 'pry'
41
+ spec.add_development_dependency "bundler", "~> 1.17"
42
+ spec.add_development_dependency "rake", "~> 10.0"
43
+ spec.add_development_dependency "rspec", "~> 3.8", '< 4.0'
44
+ spec.add_development_dependency 'ltsv'
45
+ end
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "altsv"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start(__FILE__)
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,25 @@
1
+ RAKEFILE = 'native.rake'
2
+
3
+ def command_exists(command, *extra_test_arguments)
4
+ raise "Command #{command} not found. exitting..." unless system(command, *extra_test_arguments)
5
+ end
6
+
7
+ command_exists('cargo', '--version')
8
+ command_exists('rustc', '--version')
9
+
10
+ File.open('Makefile', 'w') do |makefile|
11
+ makefile.puts <<~MAKEFILE
12
+ clean:
13
+ \trake -f #{RAKEFILE} clobber
14
+ install:
15
+ \trake -f #{RAKEFILE} build
16
+ MAKEFILE
17
+ end
18
+
19
+ File.open(RAKEFILE, 'w') do |rakefile|
20
+ rakefile.puts <<~RUBY
21
+ require 'helix_runtime/build_task'
22
+
23
+ HelixRuntime::BuildTask.new
24
+ RUBY
25
+ end
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+ require 'helix_runtime'
3
+ require 'altsv/native'
4
+
5
+ require "altsv/version"
6
+
7
+ class Altsv
8
+ class Error < StandardError; end
9
+ # Your code goes here...
10
+
11
+ class << self
12
+ def parse(input)
13
+ case input
14
+ when String
15
+ parse_native input
16
+ when StringIO
17
+ parse_native input.string
18
+ when IO
19
+ input.each_line.map{|line| parse_line_native line}
20
+ end
21
+ end
22
+
23
+ def load(path_or_io)
24
+ case path_or_io
25
+ when String
26
+ File.open(path_or_io){|f| parse f}
27
+ when IO
28
+ parse(path_or_io)
29
+ else
30
+ raise ArgumentError, "#{name}.#{__method__} only accepts IO or path."
31
+ end
32
+ end
33
+
34
+ def dump(value)
35
+ dump_native value
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,3 @@
1
+ class Altsv
2
+ VERSION = "0.0.2"
3
+ end
@@ -0,0 +1,356 @@
1
+ use std::collections::HashMap;
2
+ use std::ffi::CString;
3
+
4
+ use libcruby_sys::*;
5
+
6
+ use helix::*;
7
+
8
+ const BUFFER_SIZE_KEY: usize = 64usize;
9
+ const BUFFER_SIZE_VALUE: usize = 128usize;
10
+
11
+ struct HashMapWrapper {
12
+ map: HashMap<Symbol, Option<CString>>,
13
+ }
14
+
15
+ impl HashMapWrapper {
16
+ fn with_capacity(capacity: usize) -> Self {
17
+ HashMapWrapper {
18
+ map: HashMap::with_capacity(capacity)
19
+ }
20
+ }
21
+
22
+ fn insert(&mut self, key: &String, value: &str) {
23
+ let value_to_insert: Option<CString>;
24
+ if value.is_empty() {
25
+ value_to_insert = None;
26
+ } else {
27
+ value_to_insert = Some(CString::new(value).expect("This must success since it is from String"))
28
+ }
29
+ let key_to_insert = Symbol::from_string(key.clone());
30
+
31
+ self.map.insert(key_to_insert, value_to_insert);
32
+ }
33
+
34
+ fn inner(self) -> HashMap<Symbol, Option<CString>> {
35
+ self.map
36
+ }
37
+ }
38
+
39
+ impl ToRuby for HashMapWrapper {
40
+ fn to_ruby(self) -> ToRubyResult {
41
+ let hash: VALUE;
42
+ unsafe {
43
+ hash = rb_hash_new();
44
+
45
+ for (key, value) in self.inner().into_iter() {
46
+ let key_ruby = key.to_ruby().expect("This must success since it is from String");
47
+ let value_ruby = match value {
48
+ None => Qnil,
49
+ Some(v) => rb_utf8_str_new(v.as_ptr(), v.as_bytes().len() as i64),
50
+ };
51
+ rb_hash_aset(hash, key_ruby, value_ruby);
52
+ }
53
+ }
54
+
55
+ return Ok(hash);
56
+ }
57
+ }
58
+
59
+ fn parse_line(input: &str) -> HashMapWrapper {
60
+ let mut key = String::with_capacity(BUFFER_SIZE_KEY);
61
+ let mut value = String::with_capacity(BUFFER_SIZE_VALUE);
62
+ let mut in_value = false;
63
+ let mut escaping = false;
64
+
65
+ // First: count the key-value pairs.
66
+ let mut count = 0usize;
67
+ let mut chars = input.chars();
68
+ loop {
69
+ match chars.next() {
70
+ None => break,
71
+ Some(c) => {
72
+ match c {
73
+ '\t' => count += 1,
74
+ _ => {}
75
+ }
76
+ }
77
+ }
78
+ }
79
+
80
+ let mut line= HashMapWrapper::with_capacity(count);
81
+
82
+ // start actual parsing
83
+ let mut chars = input.chars();
84
+ loop {
85
+ match chars.next() {
86
+ None => {
87
+ if !key.is_empty() {
88
+ line.insert(&key, &value);
89
+ }
90
+ break;
91
+ }
92
+ Some(c) => {
93
+ if c == '\r' || c == '\n' {
94
+ if !key.is_empty() {
95
+ line.insert(&key, &value);
96
+ }
97
+ break;
98
+ }
99
+
100
+ let current_char: char;
101
+ if escaping {
102
+ match c {
103
+ 'n' => current_char = '\n',
104
+ 'r' => current_char = '\r',
105
+ 't' => current_char = '\t',
106
+ '\\' => current_char = '\\',
107
+ _ => {
108
+ current_char = c;
109
+ if in_value {
110
+ value.push('\\')
111
+ }else {
112
+ key.push('\\')
113
+ }
114
+ },
115
+ }
116
+ escaping = false;
117
+ } else {
118
+ match c {
119
+ '\\' => {
120
+ escaping = true;
121
+ continue;
122
+ },
123
+ ':' => {
124
+ // key-value separator(only when not separated)
125
+ if !in_value {
126
+ in_value = true;
127
+ continue;
128
+ }
129
+ }
130
+ '\t' => {
131
+ // field separator
132
+ if !key.is_empty() {
133
+ // TODO: Whether OR NOT the empty label should cause error?
134
+ line.insert(&key, &value);
135
+ }
136
+ key.clear();
137
+ value.clear();
138
+ in_value = false;
139
+ continue;
140
+ }
141
+ _ => {}
142
+ }
143
+ current_char = c;
144
+ }
145
+
146
+ if in_value {
147
+ value.push(current_char)
148
+ } else {
149
+ key.push(current_char)
150
+ }
151
+ }
152
+ }
153
+ }
154
+
155
+ line
156
+ }
157
+
158
+ const METHOD_NAME_RESPOND_TO: &[u8] = b"respond_to?\0`";
159
+ const METHOD_NAME_TO_H: &[u8] = b"to_h\0";
160
+ const METHOD_NAME_TO_HASH: &[u8] = b"to_hash\0";
161
+ const METHOD_NAME_TO_S: &[u8] = b"to_s\0";
162
+
163
+ const CLASS_NAME_ARGUMENT_ERROR: &str = "ArgumentError";
164
+
165
+ const MESSAGE_DUMP_ERROR: &'static str = "Argument does not respond to neither :to_h nor :to_hash";
166
+
167
+ unsafe fn rb_intern_u8(method_name: &[u8]) -> ID {
168
+ use std::mem;
169
+ rb_intern(mem::transmute::<&u8, c_string>(&method_name[0]))
170
+ }
171
+
172
+ unsafe fn respond_to(object: VALUE, name: ID) -> bool {
173
+ let respond_to = rb_intern_u8(METHOD_NAME_RESPOND_TO);
174
+ let method = rb_id2sym(name);
175
+
176
+ rb_funcall(object, respond_to, 1, method) == Qtrue
177
+ }
178
+
179
+ extern "C" fn join_hash(key: VALUE, value: VALUE, farg: *mut void) -> st_retval {
180
+ use std::mem;
181
+
182
+ let s = unsafe {mem::transmute::<*mut void, *mut DumpResult>(farg) };
183
+
184
+ match unsafe{ (*s).push_value(key, true) } {
185
+ None => {}
186
+ Some(error) => {
187
+ unsafe{ (*s).set_error(error) };
188
+ return st_retval::ST_STOP;
189
+ }
190
+ }
191
+
192
+ unsafe { (*s).push_char(':') };
193
+
194
+ match unsafe{ (*s).push_value(value, false) } {
195
+ None => {}
196
+ Some(error) => {
197
+ unsafe{ (*s).set_error(error) };
198
+ return st_retval::ST_STOP;
199
+ }
200
+ }
201
+ unsafe { (*s).push_char('\t') };
202
+
203
+ st_retval::ST_CONTINUE
204
+ }
205
+
206
+ struct DumpResult {
207
+ error: Option<Error>,
208
+ buffer: String,
209
+ }
210
+
211
+ impl DumpResult {
212
+ fn new(item_count: usize) -> Self{
213
+ DumpResult {
214
+ buffer: String::with_capacity(item_count * (BUFFER_SIZE_KEY + BUFFER_SIZE_VALUE)),
215
+ error: None,
216
+ }
217
+ }
218
+ fn push_value(&mut self, v: VALUE, for_key: bool) -> Option<Error>{
219
+ match unsafe {
220
+ if RB_TYPE_P(v, T_SYMBOL) {
221
+ String::from_ruby(rb_id2str(rb_sym2id(v)))
222
+ } else if RB_TYPE_P(v, T_STRING) {
223
+ String::from_ruby(v)
224
+ } else {
225
+ let to_s = rb_intern_u8(&METHOD_NAME_TO_S);
226
+ String::from_ruby(rb_funcall(v, to_s, 0))
227
+ }
228
+ } {
229
+ Ok(checked) => {
230
+ use helix::Error;
231
+
232
+ for c in String::from_checked(checked).chars() {
233
+ match c {
234
+ '\r' => self.buffer.push_str("\\r"),
235
+ '\n' => self.buffer.push_str("\\n"),
236
+ '\t' => self.buffer.push_str("\\t"),
237
+ ':' => {
238
+ if for_key {
239
+ return Some(Error::with_c_string(CString::new("Key should not include ':'").unwrap().as_ptr()));
240
+ }
241
+ self.buffer.push(c)
242
+ },
243
+ _ => self.buffer.push(c),
244
+ }
245
+ }
246
+ None
247
+ },
248
+ Err(e) => Some(e),
249
+ }
250
+ }
251
+
252
+ fn push_char(&mut self, c: char) {
253
+ self.buffer.push(c);
254
+ }
255
+
256
+ fn set_error(&mut self, e: Error) {
257
+ self.error = Some(e);
258
+ }
259
+
260
+ fn extract(self) -> Result<String, Error> {
261
+ match self.error {
262
+ Some(e) => Err(e),
263
+ None => Ok(String::from(self.buffer.trim_end())),
264
+ }
265
+ }
266
+ }
267
+
268
+ struct DumpArgument {
269
+ inner: VALUE,
270
+ count: usize,
271
+ }
272
+
273
+ impl DumpArgument {
274
+ pub unsafe fn from_hash(inner: VALUE) -> Self{
275
+ let count = RHASH_SIZE(inner) as usize;
276
+
277
+ DumpArgument{
278
+ inner,
279
+ count,
280
+ }
281
+ }
282
+ pub fn dump(&self) -> Result<String, Error> {
283
+ use std::mem;
284
+
285
+ let mut dump_result = DumpResult::new(self.count);
286
+ unsafe{
287
+ rb_hash_foreach(
288
+ self.inner,
289
+ join_hash,
290
+ mem::transmute::<&mut DumpResult, *mut void>(&mut dump_result)
291
+ )
292
+ };
293
+
294
+ dump_result.extract()
295
+ }
296
+ }
297
+
298
+ impl FromRuby for DumpArgument {
299
+ type Checked = CheckedValue<DumpArgument>;
300
+
301
+ fn from_ruby(value: VALUE) -> CheckResult<CheckedValue<DumpArgument>> {
302
+ unsafe {
303
+ if RB_TYPE_P(value, T_HASH) {
304
+ return Ok(CheckedValue::new(value));
305
+ }
306
+
307
+ let hashed_value: VALUE;
308
+ let to_h = rb_intern_u8(METHOD_NAME_TO_H);
309
+ if respond_to(value, to_h) {
310
+ hashed_value = rb_funcall(value, to_h, 0);
311
+ return Ok(CheckedValue::new(hashed_value));
312
+ }
313
+
314
+ let hashed_value: VALUE;
315
+ let to_h = rb_intern_u8(METHOD_NAME_TO_HASH);
316
+ if respond_to(value, to_h) {
317
+ hashed_value = rb_funcall(value, to_h, 0);
318
+ return Ok(CheckedValue::new(hashed_value));
319
+ }
320
+ }
321
+
322
+ let argument_error = unsafe {
323
+ let id_argument_error = rb_intern(CString::new(CLASS_NAME_ARGUMENT_ERROR).unwrap().as_ptr());
324
+ rb_const_get(rb_cObject, id_argument_error)
325
+ };
326
+ let argument_error_class = unsafe{ Class::from_value(argument_error) };
327
+ raise!(argument_error_class, MESSAGE_DUMP_ERROR);
328
+ }
329
+
330
+ fn from_checked(checked: CheckedValue<DumpArgument>) -> DumpArgument {
331
+ unsafe{ DumpArgument::from_hash(checked.to_value())}
332
+ }
333
+ }
334
+
335
+ ruby! {
336
+ class Altsv {
337
+ def parse_native(input: String) -> Vec<HashMapWrapper> {
338
+ let mut hashes: Vec<HashMapWrapper> = Vec::new();
339
+ let mut lines = input.lines();
340
+ loop {
341
+ match lines.next() {
342
+ Some(line) => hashes.push(parse_line(line)),
343
+ None => break,
344
+ }
345
+ }
346
+ hashes
347
+ }
348
+ def parse_line_native(input: String) -> HashMapWrapper {
349
+ parse_line(&input)
350
+ }
351
+
352
+ def dump_native(value: DumpArgument) -> Result<String, Error> {
353
+ value.dump()
354
+ }
355
+ }
356
+ }
metadata ADDED
@@ -0,0 +1,151 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: altsv
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ platform: ruby
6
+ authors:
7
+ - condor
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2019-03-19 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: helix_runtime
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 0.7.5
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 0.7.5
27
+ - !ruby/object:Gem::Dependency
28
+ name: pry
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: bundler
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.17'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '1.17'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rake
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '10.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '10.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rspec
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '3.8'
76
+ - - "<"
77
+ - !ruby/object:Gem::Version
78
+ version: '4.0'
79
+ type: :development
80
+ prerelease: false
81
+ version_requirements: !ruby/object:Gem::Requirement
82
+ requirements:
83
+ - - "~>"
84
+ - !ruby/object:Gem::Version
85
+ version: '3.8'
86
+ - - "<"
87
+ - !ruby/object:Gem::Version
88
+ version: '4.0'
89
+ - !ruby/object:Gem::Dependency
90
+ name: ltsv
91
+ requirement: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - ">="
94
+ - !ruby/object:Gem::Version
95
+ version: '0'
96
+ type: :development
97
+ prerelease: false
98
+ version_requirements: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - ">="
101
+ - !ruby/object:Gem::Version
102
+ version: '0'
103
+ description: A more lightweight LTSV handler library partially written in Rust.
104
+ email:
105
+ - condor1226@gmail.com
106
+ executables: []
107
+ extensions:
108
+ - ext/altsv/extconf.rb
109
+ extra_rdoc_files: []
110
+ files:
111
+ - ".gitignore"
112
+ - ".travis.yml"
113
+ - Cargo.lock
114
+ - Cargo.toml
115
+ - Gemfile
116
+ - LICENSE
117
+ - README.md
118
+ - Rakefile
119
+ - altsv.gemspec
120
+ - bin/console
121
+ - bin/setup
122
+ - ext/altsv/extconf.rb
123
+ - lib/altsv.rb
124
+ - lib/altsv/version.rb
125
+ - src/lib.rs
126
+ homepage: https://github.com/condor/altsv
127
+ licenses: []
128
+ metadata:
129
+ homepage_uri: https://github.com/condor/altsv
130
+ source_code_uri: https://github.com/condor/altsv
131
+ changelog_uri: https://github.com/condor/altsv/blob/master/CHANGELOG.md
132
+ post_install_message:
133
+ rdoc_options: []
134
+ require_paths:
135
+ - lib
136
+ required_ruby_version: !ruby/object:Gem::Requirement
137
+ requirements:
138
+ - - ">="
139
+ - !ruby/object:Gem::Version
140
+ version: '0'
141
+ required_rubygems_version: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - ">="
144
+ - !ruby/object:Gem::Version
145
+ version: '0'
146
+ requirements: []
147
+ rubygems_version: 3.0.3
148
+ signing_key:
149
+ specification_version: 4
150
+ summary: an ALTernative ltSV parser / dumper library
151
+ test_files: []