ruston 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: cf5c0f1352fca5ac06d4941ed73e96eaf9f7094e2cc87e48ac731224e9756850
4
+ data.tar.gz: 7774865e19f036dc54fcd0f087ff8dff7af7ee3a291f04f7a541796ace67a8d1
5
+ SHA512:
6
+ metadata.gz: b8ba536beb1a1b3a18af9061ab073622edee3222161281a3146e18d28eda1872fe404371891cc45f82dea28c89ceb6172ceac4b0d29e55da3b69b23cf400b134
7
+ data.tar.gz: 263de613a6e15a1179fc2ab3e9e4d877c0266ffa8ed3da1ae697b0b9f251ac214fd7b6adb527e344618a95f7c382dc609491367b059bbf63e2e417edf65c1d36
data/.gitignore ADDED
@@ -0,0 +1,12 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
9
+
10
+ /target/
11
+
12
+ *.gem
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 3.1.1
data/Cargo.lock ADDED
@@ -0,0 +1,398 @@
1
+ # This file is automatically @generated by Cargo.
2
+ # It is not intended for manual editing.
3
+ version = 3
4
+
5
+ [[package]]
6
+ name = "aho-corasick"
7
+ version = "0.7.18"
8
+ source = "registry+https://github.com/rust-lang/crates.io-index"
9
+ checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f"
10
+ dependencies = [
11
+ "memchr",
12
+ ]
13
+
14
+ [[package]]
15
+ name = "ansi_term"
16
+ version = "0.12.1"
17
+ source = "registry+https://github.com/rust-lang/crates.io-index"
18
+ checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2"
19
+ dependencies = [
20
+ "winapi",
21
+ ]
22
+
23
+ [[package]]
24
+ name = "atty"
25
+ version = "0.2.14"
26
+ source = "registry+https://github.com/rust-lang/crates.io-index"
27
+ checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
28
+ dependencies = [
29
+ "hermit-abi",
30
+ "libc",
31
+ "winapi",
32
+ ]
33
+
34
+ [[package]]
35
+ name = "bindgen"
36
+ version = "0.59.2"
37
+ source = "registry+https://github.com/rust-lang/crates.io-index"
38
+ checksum = "2bd2a9a458e8f4304c52c43ebb0cfbd520289f8379a52e329a38afda99bf8eb8"
39
+ dependencies = [
40
+ "bitflags",
41
+ "cexpr",
42
+ "clang-sys",
43
+ "clap",
44
+ "env_logger",
45
+ "lazy_static",
46
+ "lazycell",
47
+ "log",
48
+ "peeking_take_while",
49
+ "proc-macro2",
50
+ "quote",
51
+ "regex",
52
+ "rustc-hash",
53
+ "shlex",
54
+ "which",
55
+ ]
56
+
57
+ [[package]]
58
+ name = "bitflags"
59
+ version = "1.3.2"
60
+ source = "registry+https://github.com/rust-lang/crates.io-index"
61
+ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
62
+
63
+ [[package]]
64
+ name = "cc"
65
+ version = "1.0.73"
66
+ source = "registry+https://github.com/rust-lang/crates.io-index"
67
+ checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11"
68
+
69
+ [[package]]
70
+ name = "cexpr"
71
+ version = "0.6.0"
72
+ source = "registry+https://github.com/rust-lang/crates.io-index"
73
+ checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766"
74
+ dependencies = [
75
+ "nom",
76
+ ]
77
+
78
+ [[package]]
79
+ name = "cfg-if"
80
+ version = "1.0.0"
81
+ source = "registry+https://github.com/rust-lang/crates.io-index"
82
+ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
83
+
84
+ [[package]]
85
+ name = "clang-sys"
86
+ version = "1.3.3"
87
+ source = "registry+https://github.com/rust-lang/crates.io-index"
88
+ checksum = "5a050e2153c5be08febd6734e29298e844fdb0fa21aeddd63b4eb7baa106c69b"
89
+ dependencies = [
90
+ "glob",
91
+ "libc",
92
+ "libloading",
93
+ ]
94
+
95
+ [[package]]
96
+ name = "clap"
97
+ version = "2.34.0"
98
+ source = "registry+https://github.com/rust-lang/crates.io-index"
99
+ checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c"
100
+ dependencies = [
101
+ "ansi_term",
102
+ "atty",
103
+ "bitflags",
104
+ "strsim",
105
+ "textwrap",
106
+ "unicode-width",
107
+ "vec_map",
108
+ ]
109
+
110
+ [[package]]
111
+ name = "coffret"
112
+ version = "0.0.3"
113
+ source = "registry+https://github.com/rust-lang/crates.io-index"
114
+ checksum = "efb0b42fe7c89fec1939af9293f94403f32bab4ac86769dbd8362d34c40e649c"
115
+ dependencies = [
116
+ "libc",
117
+ "rb-sys",
118
+ ]
119
+
120
+ [[package]]
121
+ name = "either"
122
+ version = "1.6.1"
123
+ source = "registry+https://github.com/rust-lang/crates.io-index"
124
+ checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457"
125
+
126
+ [[package]]
127
+ name = "env_logger"
128
+ version = "0.9.0"
129
+ source = "registry+https://github.com/rust-lang/crates.io-index"
130
+ checksum = "0b2cf0344971ee6c64c31be0d530793fba457d322dfec2810c453d0ef228f9c3"
131
+ dependencies = [
132
+ "atty",
133
+ "humantime",
134
+ "log",
135
+ "regex",
136
+ "termcolor",
137
+ ]
138
+
139
+ [[package]]
140
+ name = "glob"
141
+ version = "0.3.0"
142
+ source = "registry+https://github.com/rust-lang/crates.io-index"
143
+ checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574"
144
+
145
+ [[package]]
146
+ name = "hermit-abi"
147
+ version = "0.1.19"
148
+ source = "registry+https://github.com/rust-lang/crates.io-index"
149
+ checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
150
+ dependencies = [
151
+ "libc",
152
+ ]
153
+
154
+ [[package]]
155
+ name = "humantime"
156
+ version = "2.1.0"
157
+ source = "registry+https://github.com/rust-lang/crates.io-index"
158
+ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
159
+
160
+ [[package]]
161
+ name = "lazy_static"
162
+ version = "1.4.0"
163
+ source = "registry+https://github.com/rust-lang/crates.io-index"
164
+ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
165
+
166
+ [[package]]
167
+ name = "lazycell"
168
+ version = "1.3.0"
169
+ source = "registry+https://github.com/rust-lang/crates.io-index"
170
+ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
171
+
172
+ [[package]]
173
+ name = "libc"
174
+ version = "0.2.126"
175
+ source = "registry+https://github.com/rust-lang/crates.io-index"
176
+ checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836"
177
+
178
+ [[package]]
179
+ name = "libloading"
180
+ version = "0.7.3"
181
+ source = "registry+https://github.com/rust-lang/crates.io-index"
182
+ checksum = "efbc0f03f9a775e9f6aed295c6a1ba2253c5757a9e03d55c6caa46a681abcddd"
183
+ dependencies = [
184
+ "cfg-if",
185
+ "winapi",
186
+ ]
187
+
188
+ [[package]]
189
+ name = "linkify"
190
+ version = "0.8.1"
191
+ source = "registry+https://github.com/rust-lang/crates.io-index"
192
+ checksum = "28d9967eb7d0bc31c39c6f52e8fce42991c0cd1f7a2078326f0b7a399a584c8d"
193
+ dependencies = [
194
+ "memchr",
195
+ ]
196
+
197
+ [[package]]
198
+ name = "log"
199
+ version = "0.4.17"
200
+ source = "registry+https://github.com/rust-lang/crates.io-index"
201
+ checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e"
202
+ dependencies = [
203
+ "cfg-if",
204
+ ]
205
+
206
+ [[package]]
207
+ name = "memchr"
208
+ version = "2.5.0"
209
+ source = "registry+https://github.com/rust-lang/crates.io-index"
210
+ checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
211
+
212
+ [[package]]
213
+ name = "minimal-lexical"
214
+ version = "0.2.1"
215
+ source = "registry+https://github.com/rust-lang/crates.io-index"
216
+ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
217
+
218
+ [[package]]
219
+ name = "nom"
220
+ version = "7.1.1"
221
+ source = "registry+https://github.com/rust-lang/crates.io-index"
222
+ checksum = "a8903e5a29a317527874d0402f867152a3d21c908bb0b933e416c65e301d4c36"
223
+ dependencies = [
224
+ "memchr",
225
+ "minimal-lexical",
226
+ ]
227
+
228
+ [[package]]
229
+ name = "peeking_take_while"
230
+ version = "0.1.2"
231
+ source = "registry+https://github.com/rust-lang/crates.io-index"
232
+ checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099"
233
+
234
+ [[package]]
235
+ name = "pkg-config"
236
+ version = "0.3.25"
237
+ source = "registry+https://github.com/rust-lang/crates.io-index"
238
+ checksum = "1df8c4ec4b0627e53bdf214615ad287367e482558cf84b109250b37464dc03ae"
239
+
240
+ [[package]]
241
+ name = "proc-macro2"
242
+ version = "1.0.39"
243
+ source = "registry+https://github.com/rust-lang/crates.io-index"
244
+ checksum = "c54b25569025b7fc9651de43004ae593a75ad88543b17178aa5e1b9c4f15f56f"
245
+ dependencies = [
246
+ "unicode-ident",
247
+ ]
248
+
249
+ [[package]]
250
+ name = "quote"
251
+ version = "1.0.18"
252
+ source = "registry+https://github.com/rust-lang/crates.io-index"
253
+ checksum = "a1feb54ed693b93a84e14094943b84b7c4eae204c512b7ccb95ab0c66d278ad1"
254
+ dependencies = [
255
+ "proc-macro2",
256
+ ]
257
+
258
+ [[package]]
259
+ name = "rb-sys"
260
+ version = "0.9.4"
261
+ source = "registry+https://github.com/rust-lang/crates.io-index"
262
+ checksum = "f5465c5bd695ef70959b91b4ca9cfd515e9af012f6d9f0ae46f09fa4bcc3b722"
263
+ dependencies = [
264
+ "bindgen",
265
+ "cc",
266
+ "lazy_static",
267
+ "linkify",
268
+ "pkg-config",
269
+ "shell-words",
270
+ ]
271
+
272
+ [[package]]
273
+ name = "regex"
274
+ version = "1.5.6"
275
+ source = "registry+https://github.com/rust-lang/crates.io-index"
276
+ checksum = "d83f127d94bdbcda4c8cc2e50f6f84f4b611f69c902699ca385a39c3a75f9ff1"
277
+ dependencies = [
278
+ "aho-corasick",
279
+ "memchr",
280
+ "regex-syntax",
281
+ ]
282
+
283
+ [[package]]
284
+ name = "regex-syntax"
285
+ version = "0.6.26"
286
+ source = "registry+https://github.com/rust-lang/crates.io-index"
287
+ checksum = "49b3de9ec5dc0a3417da371aab17d729997c15010e7fd24ff707773a33bddb64"
288
+
289
+ [[package]]
290
+ name = "rustc-hash"
291
+ version = "1.1.0"
292
+ source = "registry+https://github.com/rust-lang/crates.io-index"
293
+ checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
294
+
295
+ [[package]]
296
+ name = "ruston"
297
+ version = "0.1.0"
298
+ dependencies = [
299
+ "coffret",
300
+ "libc",
301
+ "rb-sys",
302
+ ]
303
+
304
+ [[package]]
305
+ name = "shell-words"
306
+ version = "1.1.0"
307
+ source = "registry+https://github.com/rust-lang/crates.io-index"
308
+ checksum = "24188a676b6ae68c3b2cb3a01be17fbf7240ce009799bb56d5b1409051e78fde"
309
+
310
+ [[package]]
311
+ name = "shlex"
312
+ version = "1.1.0"
313
+ source = "registry+https://github.com/rust-lang/crates.io-index"
314
+ checksum = "43b2853a4d09f215c24cc5489c992ce46052d359b5109343cbafbf26bc62f8a3"
315
+
316
+ [[package]]
317
+ name = "strsim"
318
+ version = "0.8.0"
319
+ source = "registry+https://github.com/rust-lang/crates.io-index"
320
+ checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
321
+
322
+ [[package]]
323
+ name = "termcolor"
324
+ version = "1.1.3"
325
+ source = "registry+https://github.com/rust-lang/crates.io-index"
326
+ checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755"
327
+ dependencies = [
328
+ "winapi-util",
329
+ ]
330
+
331
+ [[package]]
332
+ name = "textwrap"
333
+ version = "0.11.0"
334
+ source = "registry+https://github.com/rust-lang/crates.io-index"
335
+ checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
336
+ dependencies = [
337
+ "unicode-width",
338
+ ]
339
+
340
+ [[package]]
341
+ name = "unicode-ident"
342
+ version = "1.0.1"
343
+ source = "registry+https://github.com/rust-lang/crates.io-index"
344
+ checksum = "5bd2fe26506023ed7b5e1e315add59d6f584c621d037f9368fea9cfb988f368c"
345
+
346
+ [[package]]
347
+ name = "unicode-width"
348
+ version = "0.1.9"
349
+ source = "registry+https://github.com/rust-lang/crates.io-index"
350
+ checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973"
351
+
352
+ [[package]]
353
+ name = "vec_map"
354
+ version = "0.8.2"
355
+ source = "registry+https://github.com/rust-lang/crates.io-index"
356
+ checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"
357
+
358
+ [[package]]
359
+ name = "which"
360
+ version = "4.2.5"
361
+ source = "registry+https://github.com/rust-lang/crates.io-index"
362
+ checksum = "5c4fb54e6113b6a8772ee41c3404fb0301ac79604489467e0a9ce1f3e97c24ae"
363
+ dependencies = [
364
+ "either",
365
+ "lazy_static",
366
+ "libc",
367
+ ]
368
+
369
+ [[package]]
370
+ name = "winapi"
371
+ version = "0.3.9"
372
+ source = "registry+https://github.com/rust-lang/crates.io-index"
373
+ checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
374
+ dependencies = [
375
+ "winapi-i686-pc-windows-gnu",
376
+ "winapi-x86_64-pc-windows-gnu",
377
+ ]
378
+
379
+ [[package]]
380
+ name = "winapi-i686-pc-windows-gnu"
381
+ version = "0.4.0"
382
+ source = "registry+https://github.com/rust-lang/crates.io-index"
383
+ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
384
+
385
+ [[package]]
386
+ name = "winapi-util"
387
+ version = "0.1.5"
388
+ source = "registry+https://github.com/rust-lang/crates.io-index"
389
+ checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
390
+ dependencies = [
391
+ "winapi",
392
+ ]
393
+
394
+ [[package]]
395
+ name = "winapi-x86_64-pc-windows-gnu"
396
+ version = "0.4.0"
397
+ source = "registry+https://github.com/rust-lang/crates.io-index"
398
+ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
data/Cargo.toml ADDED
@@ -0,0 +1,12 @@
1
+ [package]
2
+ name = "ruston"
3
+ version = "0.1.0"
4
+ edition = "2021"
5
+
6
+ [lib]
7
+ crate-type = ["lib", "cdylib"]
8
+
9
+ [dependencies]
10
+ libc = "^0.2"
11
+ rb-sys = { version = "^0.9", features = ["link-ruby"] }
12
+ coffret = "0.0.3"
data/Gemfile ADDED
@@ -0,0 +1,9 @@
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 ruston.gemspec
6
+ gemspec
7
+
8
+ gem "bundler", ">= 1.17"
9
+ gem "rake", ">= 10.0"
data/Gemfile.lock ADDED
@@ -0,0 +1,20 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ ruston (0.0.1)
5
+
6
+ GEM
7
+ remote: https://rubygems.org/
8
+ specs:
9
+ rake (13.0.6)
10
+
11
+ PLATFORMS
12
+ arm64-darwin-21
13
+
14
+ DEPENDENCIES
15
+ bundler (>= 1.17)
16
+ rake (>= 10.0)
17
+ ruston!
18
+
19
+ BUNDLED WITH
20
+ 2.4.0.dev
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2022 Uchio Kondo
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
13
+ all 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
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,39 @@
1
+ # Ruston
2
+
3
+ Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/ruston`. To experiment with that code, run `bin/console` for an interactive prompt.
4
+
5
+ TODO: Delete this and the text above, and describe your gem
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ ```ruby
12
+ gem 'ruston'
13
+ ```
14
+
15
+ And then execute:
16
+
17
+ $ bundle
18
+
19
+ Or install it yourself as:
20
+
21
+ $ gem install ruston
22
+
23
+ ## Usage
24
+
25
+ TODO: Write usage instructions here
26
+
27
+ ## Development
28
+
29
+ After checking out the repo, run `bin/setup` to install dependencies. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
30
+
31
+ 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).
32
+
33
+ ## Contributing
34
+
35
+ Bug reports and pull requests are welcome on GitHub at https://github.com/udzura/ruston.
36
+
37
+ ## License
38
+
39
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+ task :default => :spec
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "ruston"
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__)
data/bin/setup ADDED
@@ -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
data/examples/lex.rs ADDED
@@ -0,0 +1,11 @@
1
+ extern crate ruston;
2
+
3
+ fn main() {
4
+ let json = "
5
+ {\"Hello\": true, \"world\": [1, 2, 3]}
6
+ ";
7
+ let ret = ruston::json::lexer::Lex::run(json.to_string())
8
+ .unwrap()
9
+ .tokens;
10
+ dbg!(ret);
11
+ }
@@ -0,0 +1,30 @@
1
+ extern crate ruston;
2
+
3
+ fn main() {
4
+ let ret = ruston::json::parse("true");
5
+ dbg!(ret);
6
+
7
+ let ret = ruston::json::parse("123");
8
+ dbg!(ret);
9
+
10
+ let ret = ruston::json::parse("\"Hola\"");
11
+ dbg!(ret);
12
+
13
+ let ret = ruston::json::parse("[1, 2, 3, false]");
14
+ dbg!(ret);
15
+
16
+ let ret = ruston::json::parse("{\"foo\": true, \"bar\": 123}");
17
+ dbg!(ret);
18
+
19
+ let nested = "
20
+ {
21
+ \"id\": 1,
22
+ \"user\": {
23
+ \"name\": \"Akubi\",
24
+ \"age\": 3,
25
+ }
26
+ }
27
+ ";
28
+ let ret = ruston::json::parse(nested);
29
+ dbg!(ret);
30
+ }
@@ -0,0 +1,14 @@
1
+ require 'ruston'
2
+ require 'ruston.so'
3
+
4
+ json = <<JSON
5
+ [
6
+ {"id": 1,
7
+ "name": "udzura"},
8
+ {"id": 2,
9
+ "name": "akubi"}
10
+ ]
11
+ JSON
12
+
13
+ ret = Ruston.new.parse(json)
14
+ p ret
@@ -0,0 +1,23 @@
1
+ extern crate ruston;
2
+
3
+ fn main() {
4
+ // let json = "
5
+ // {\"Hello\": true, \"world\": [1, 2, 3]}
6
+ // ";
7
+
8
+ let json = "true";
9
+ let ruby = ruston::ruby::parse_into_ruby(json.to_string()).unwrap();
10
+ unsafe { rb::rb_p(ruby) };
11
+
12
+ let json = "\"Rubyist?\"";
13
+ let ruby = ruston::ruby::parse_into_ruby(json.to_string()).unwrap();
14
+ unsafe { rb::rb_p(ruby) };
15
+
16
+ let json = "[\"Rubyist?\", 12, null]";
17
+ let ruby = ruston::ruby::parse_into_ruby(json.to_string()).unwrap();
18
+ unsafe { rb::rb_p(ruby) };
19
+
20
+ let json = "{\"Rubyist?\": true}";
21
+ let ruby = ruston::ruby::parse_into_ruby(json.to_string()).unwrap();
22
+ unsafe { rb::rb_p(ruby) };
23
+ }
@@ -0,0 +1,3 @@
1
+ class Ruston
2
+ VERSION = "0.0.1"
3
+ end
data/lib/ruston.rb ADDED
@@ -0,0 +1,7 @@
1
+ require "ruston/version"
2
+ require "ruston.so"
3
+
4
+ class Ruston
5
+ class Error < StandardError; end
6
+ # Your code goes here...
7
+ end
data/ruston.gemspec ADDED
@@ -0,0 +1,25 @@
1
+ lib = File.expand_path("../lib", __FILE__)
2
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
+ require "ruston/version"
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "ruston"
7
+ spec.version = Ruston::VERSION
8
+ spec.authors = ["Uchio Kondo"]
9
+ spec.email = ["udzura@udzura.jp"]
10
+
11
+ spec.summary = %q{Sample Rust-made gem to parse simple JSON...}
12
+ spec.description = %q{Sample Rust-made gem to parse simple JSON...}
13
+ spec.homepage = "https://github.com/udzura/ruston"
14
+ spec.license = "MIT"
15
+
16
+ # Specify which files should be added to the gem when it is released.
17
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
18
+ spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
19
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
20
+ end
21
+ # spec.bindir = "exe"
22
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
23
+ spec.require_paths = ["lib"]
24
+ spec.extensions = ["Cargo.toml"]
25
+ end
data/src/json.rs ADDED
@@ -0,0 +1,379 @@
1
+ use std::{collections::HashMap, fmt::Display, hash::Hash};
2
+
3
+ #[derive(Debug, Clone)]
4
+ pub struct Token {
5
+ pub start: usize,
6
+ pub end: usize,
7
+ pub lexeme: String,
8
+ pub ty: TokenType,
9
+ }
10
+
11
+ impl Token {
12
+ fn is(&self, ty: TokenType) -> bool {
13
+ self.ty == ty
14
+ }
15
+ }
16
+
17
+ #[derive(Debug, Copy, Clone, PartialEq, Eq)]
18
+ pub enum TokenType {
19
+ BraceOpen,
20
+ BraceClose,
21
+ BracketOpen,
22
+ BracketClose,
23
+ Colon,
24
+ Comma,
25
+ Number,
26
+ StrLit,
27
+ Null,
28
+ True,
29
+ False,
30
+
31
+ EoF,
32
+ }
33
+
34
+ #[derive(Debug, Clone, PartialEq, Eq)]
35
+ pub enum Value {
36
+ Null,
37
+ True,
38
+ False,
39
+ Int(i32),
40
+ Str(String),
41
+ Array(Vec<Value>),
42
+ Object(usize, HashMap<Value, Value>),
43
+ }
44
+
45
+ impl Hash for Value {
46
+ fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
47
+ match self {
48
+ Self::Object(val, _) => val.hash(state),
49
+ _ => core::mem::discriminant(self).hash(state),
50
+ };
51
+ }
52
+ }
53
+
54
+ #[derive(Debug, Clone)]
55
+ pub struct JsonError {
56
+ pub message: String,
57
+ }
58
+
59
+ impl JsonError {
60
+ pub fn raise(message: impl Into<String>) -> Self {
61
+ Self {
62
+ message: message.into(),
63
+ }
64
+ }
65
+ }
66
+
67
+ impl Display for JsonError {
68
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
69
+ write!(f, "{}", &self.message)
70
+ }
71
+ }
72
+
73
+ impl std::error::Error for JsonError {}
74
+
75
+ pub mod lexer {
76
+ use super::*;
77
+
78
+ #[derive(Debug, Default)]
79
+ pub struct Lex {
80
+ pub stream: String,
81
+ pub start: usize,
82
+ pub current: usize,
83
+ pub line: usize,
84
+
85
+ pub tokens: Vec<Token>,
86
+ }
87
+
88
+ impl Lex {
89
+ pub fn run(stream: String) -> Result<Self, JsonError> {
90
+ let mut lex = Self {
91
+ stream,
92
+ ..Default::default()
93
+ };
94
+
95
+ lex.process()?;
96
+ Ok(lex)
97
+ }
98
+
99
+ fn process(&mut self) -> Result<(), JsonError> {
100
+ loop {
101
+ match self.advance()? {
102
+ '{' => self.push_token(TokenType::BraceOpen),
103
+ '}' => self.push_token(TokenType::BraceClose),
104
+ '[' => self.push_token(TokenType::BracketOpen),
105
+ ']' => self.push_token(TokenType::BracketClose),
106
+ ':' => self.push_token(TokenType::Colon),
107
+ ',' => self.push_token(TokenType::Comma),
108
+ 't' => {
109
+ self.matches("rue")?;
110
+ self.push_token(TokenType::True)
111
+ }
112
+ 'f' => {
113
+ self.matches("alse")?;
114
+ self.push_token(TokenType::False)
115
+ }
116
+ 'n' => {
117
+ self.matches("ull")?;
118
+ self.push_token(TokenType::Null)
119
+ }
120
+ '"' => loop {
121
+ let c = self
122
+ .advance()
123
+ .or_else(|_| Err(JsonError::raise("quote unmet")))?;
124
+ if c == '"' {
125
+ self.push_token(TokenType::StrLit);
126
+ break;
127
+ }
128
+ },
129
+ '\n' => {
130
+ self.line += 1;
131
+ self.start = self.current
132
+ }
133
+ ' ' | '\t' => self.start = self.current,
134
+ '1'..='9' => {
135
+ while is_digit(self.peek()) {
136
+ self.advance()?;
137
+ }
138
+ self.push_token(TokenType::Number);
139
+ }
140
+ c => return Err(JsonError::raise(format!("unexpected token {}", c))),
141
+ }
142
+ if self.reached_end() {
143
+ self.push_token(TokenType::EoF);
144
+ break;
145
+ }
146
+ }
147
+ Ok(())
148
+ }
149
+
150
+ fn peek(&mut self) -> Option<char> {
151
+ self.stream
152
+ .chars()
153
+ .collect::<Vec<char>>()
154
+ .get(self.current)
155
+ .map(|c| *c)
156
+ }
157
+
158
+ fn matches(&mut self, s: &str) -> Result<(), JsonError> {
159
+ for c in s.chars() {
160
+ let c2 = self.advance()?;
161
+ if c2 != c {
162
+ return Err(JsonError::raise(format!("unexpected character {}", c2)));
163
+ }
164
+ }
165
+
166
+ Ok(())
167
+ }
168
+
169
+ fn advance(&mut self) -> Result<char, JsonError> {
170
+ let c = self.peek().ok_or_else(|| JsonError::raise("EoF"))?;
171
+ // eprintln!("process: {}", c);
172
+ self.current += 1;
173
+ Ok(c)
174
+ }
175
+
176
+ fn reached_end(&mut self) -> bool {
177
+ self.current >= self.stream.len()
178
+ }
179
+
180
+ fn push_token(&mut self, ty: TokenType) {
181
+ let token = Token {
182
+ start: self.start,
183
+ end: self.current,
184
+ lexeme: (&self.stream[self.start..self.current]).to_string(),
185
+ ty,
186
+ };
187
+
188
+ // eprintln!("pusing: {:?}: {}", &token.ty, &token.lexeme);
189
+ self.tokens.push(token);
190
+ self.start = self.current
191
+ }
192
+ }
193
+
194
+ fn is_digit(c: Option<char>) -> bool {
195
+ match c {
196
+ Some(c) => c >= '0' && c <= '9',
197
+ None => false,
198
+ }
199
+ }
200
+ }
201
+
202
+ pub mod parser {
203
+ use super::*;
204
+
205
+ #[derive(Debug)]
206
+ pub struct Parser {
207
+ pub stream: Vec<Token>,
208
+ pub current: usize,
209
+ pub value: Value,
210
+
211
+ next_object_id: usize,
212
+ }
213
+
214
+ impl Parser {
215
+ pub fn run(stream: Vec<Token>) -> Result<Self, JsonError> {
216
+ let mut parser = Self {
217
+ stream,
218
+ current: 0,
219
+ value: Value::Null,
220
+ next_object_id: (1 << 16),
221
+ };
222
+
223
+ parser.process()?;
224
+ Ok(parser)
225
+ }
226
+
227
+ fn process(&mut self) -> Result<(), JsonError> {
228
+ self.value = self.process_value()?;
229
+
230
+ if !self.reached_end()? {
231
+ return Err(JsonError::raise("JSON has continued form"));
232
+ }
233
+
234
+ Ok(())
235
+ }
236
+
237
+ fn process_value(&mut self) -> Result<Value, JsonError> {
238
+ use TokenType::*;
239
+ let token = self.succ(1)?;
240
+ let value = match &token.ty {
241
+ Null => Value::Null,
242
+ True => Value::True,
243
+ False => Value::False,
244
+ Number => Value::Int(token.lexeme.parse().unwrap()),
245
+ StrLit => {
246
+ let len = token.lexeme.len();
247
+ Value::Str((&token.lexeme[1..(len - 1)]).to_string())
248
+ }
249
+ BracketOpen => self.array()?,
250
+ BraceOpen => self.object()?,
251
+
252
+ t => {
253
+ todo!("Unexpected token: {:?}", &t)
254
+ }
255
+ };
256
+ Ok(value)
257
+ }
258
+
259
+ fn array(&mut self) -> Result<Value, JsonError> {
260
+ use TokenType::*;
261
+ let mut ar = Vec::new();
262
+ loop {
263
+ match self.peek(0) {
264
+ Some(t) => match &t.ty {
265
+ EoF => return Err(JsonError::raise("EoF")),
266
+ BracketClose => {
267
+ self.succ(1)?;
268
+ break;
269
+ }
270
+ _ => {
271
+ let v = self.process_value()?;
272
+ ar.push(v);
273
+ match self.peek(0) {
274
+ None => return Err(JsonError::raise("EoF")),
275
+ Some(t) => {
276
+ if t.is(Comma) {
277
+ self.succ(1)?;
278
+ let n = self.peek(0);
279
+ if n.is_none() {
280
+ return Err(JsonError::raise("EoF"));
281
+ }
282
+ if n.unwrap().is(BracketClose) {
283
+ return Err(JsonError::raise("Unexpected ]"));
284
+ }
285
+ }
286
+ }
287
+ }
288
+ }
289
+ },
290
+ None => return Err(JsonError::raise("EoF")),
291
+ }
292
+ }
293
+ Ok(Value::Array(ar))
294
+ }
295
+
296
+ fn object(&mut self) -> Result<Value, JsonError> {
297
+ use TokenType::*;
298
+ let mut ha = HashMap::new();
299
+ loop {
300
+ match self.peek(0) {
301
+ Some(t) => match &t.ty {
302
+ EoF => return Err(JsonError::raise("EoF")),
303
+ BraceClose => {
304
+ self.succ(1)?;
305
+ break;
306
+ }
307
+ _ => {
308
+ let k = self.process_value()?;
309
+ match self.peek(0) {
310
+ None => return Err(JsonError::raise("EoF")),
311
+ Some(t) => {
312
+ if t.is(Colon) {
313
+ self.succ(1)?;
314
+ } else {
315
+ return Err(JsonError::raise(format!(
316
+ "Unexpected token {:?}",
317
+ t.ty
318
+ )));
319
+ }
320
+ }
321
+ }
322
+ let v = self.process_value()?;
323
+ ha.insert(k, v);
324
+ match self.peek(0) {
325
+ None => return Err(JsonError::raise("EoF")),
326
+ Some(t) => match t.ty {
327
+ BraceClose => {
328
+ continue;
329
+ }
330
+ Comma => {
331
+ self.succ(1)?;
332
+ continue;
333
+ }
334
+ other => {
335
+ return Err(JsonError::raise(format!(
336
+ "Unexpected token {:?}",
337
+ other
338
+ )));
339
+ }
340
+ },
341
+ }
342
+ }
343
+ },
344
+ None => return Err(JsonError::raise("EoF")),
345
+ }
346
+ }
347
+ self.next_object_id += 1;
348
+ Ok(Value::Object(self.next_object_id, ha))
349
+ }
350
+
351
+ fn peek(&mut self, count: usize) -> Option<&Token> {
352
+ self.stream.get(self.current + count)
353
+ }
354
+
355
+ fn previous(&mut self) -> Option<&Token> {
356
+ if self.current == 0 {
357
+ return None;
358
+ }
359
+ self.stream.get(self.current - 1)
360
+ }
361
+
362
+ fn succ(&mut self, count: usize) -> Result<&Token, JsonError> {
363
+ self.current += count;
364
+ self.previous().ok_or_else(|| JsonError::raise("EoF"))
365
+ }
366
+
367
+ fn reached_end(&mut self) -> Result<bool, JsonError> {
368
+ self.peek(0)
369
+ .map(|tok| tok.is(TokenType::EoF))
370
+ .ok_or_else(|| JsonError::raise("EoF"))
371
+ }
372
+ }
373
+ }
374
+
375
+ pub fn parse(json: impl Into<String>) -> Value {
376
+ let tokens = self::lexer::Lex::run(json.into()).unwrap().tokens;
377
+ let value = self::parser::Parser::run(tokens).unwrap().value;
378
+ value
379
+ }
data/src/lib.rs ADDED
@@ -0,0 +1,81 @@
1
+ pub mod json;
2
+ pub mod ruby;
3
+
4
+ use std::slice;
5
+
6
+ use coffret::*;
7
+ use rb_sys::*;
8
+
9
+ pub struct RubyFn {
10
+ value: unsafe extern "C" fn() -> RubyValue,
11
+ }
12
+
13
+ impl From<RubyFn> for unsafe extern "C" fn() -> RubyValue {
14
+ fn from(from: RubyFn) -> Self {
15
+ from.value
16
+ }
17
+ }
18
+
19
+ impl From<unsafe extern "C" fn() -> RubyValue> for RubyFn {
20
+ fn from(from: unsafe extern "C" fn() -> RubyValue) -> Self {
21
+ RubyFn { value: from }
22
+ }
23
+ }
24
+
25
+ impl From<unsafe extern "C" fn(RubyValue) -> RubyValue> for RubyFn {
26
+ fn from(from: unsafe extern "C" fn(RubyValue) -> RubyValue) -> Self {
27
+ let value = unsafe {
28
+ std::mem::transmute::<
29
+ unsafe extern "C" fn(RubyValue) -> RubyValue,
30
+ unsafe extern "C" fn() -> RubyValue,
31
+ >(from)
32
+ };
33
+ RubyFn { value }
34
+ }
35
+ }
36
+
37
+ impl From<unsafe extern "C" fn(RubyValue, RubyValue) -> RubyValue> for RubyFn {
38
+ fn from(from: unsafe extern "C" fn(RubyValue, RubyValue) -> RubyValue) -> Self {
39
+ let value = unsafe {
40
+ std::mem::transmute::<
41
+ unsafe extern "C" fn(RubyValue, RubyValue) -> RubyValue,
42
+ unsafe extern "C" fn() -> RubyValue,
43
+ >(from)
44
+ };
45
+ RubyFn { value }
46
+ }
47
+ }
48
+
49
+ #[no_mangle]
50
+ pub unsafe extern "C" fn ruston_parse(_slf: RubyValue, json: RubyValue) -> RubyValue {
51
+ let mut json = Box::new(json);
52
+ let data: *const u8 = unsafe { rb_string_value_ptr(json.as_mut()) } as *const u8;
53
+ let len = unsafe { macros::RSTRING_LEN(json.as_ref().clone()) };
54
+
55
+ let bytes: &[u8] = unsafe { slice::from_raw_parts(data, len as usize) };
56
+ let json = String::from_utf8_lossy(bytes);
57
+
58
+ crate::ruby::parse_into_ruby(json.to_string()).unwrap()
59
+ }
60
+
61
+ fn init_ruston_internal() -> Result<(), Box<dyn std::error::Error>> {
62
+ println!("Rust loaded");
63
+
64
+ let object = class::object_class();
65
+ let klass = class::define_class("Ruston", object);
66
+
67
+ let callback: RubyFn = (ruston_parse as unsafe extern "C" fn(u64, u64) -> u64).into();
68
+
69
+ class::define_method(klass, "parse", callback.into(), 1);
70
+
71
+ Ok(())
72
+ }
73
+
74
+ #[allow(non_snake_case)]
75
+ #[no_mangle]
76
+ pub extern "C" fn Init_ruston() {
77
+ match init_ruston_internal() {
78
+ Err(e) => exception::rustly_raise(e.as_ref()),
79
+ Ok(_) => {}
80
+ }
81
+ }
data/src/ruby.rs ADDED
@@ -0,0 +1,78 @@
1
+ use crate::json;
2
+
3
+ use rb::RubyValue;
4
+ use rb_sys as rb;
5
+
6
+ mod v {
7
+ use rb_sys::*;
8
+
9
+ #[repr(C)]
10
+ pub struct WrappedRubyValue {
11
+ value: u32,
12
+ padding: u32,
13
+ }
14
+
15
+ impl From<WrappedRubyValue> for RubyValue {
16
+ fn from(from: WrappedRubyValue) -> Self {
17
+ let v = unsafe { std::mem::transmute::<WrappedRubyValue, RubyValue>(from) };
18
+ v
19
+ }
20
+ }
21
+
22
+ #[allow(non_upper_case_globals)]
23
+ pub const True: WrappedRubyValue = WrappedRubyValue {
24
+ value: ruby_special_consts::RUBY_Qtrue as u32,
25
+ padding: 0,
26
+ };
27
+
28
+ #[allow(non_upper_case_globals)]
29
+ pub const False: WrappedRubyValue = WrappedRubyValue {
30
+ value: ruby_special_consts::RUBY_Qfalse as u32,
31
+ padding: 0,
32
+ };
33
+
34
+ #[allow(non_upper_case_globals)]
35
+ pub const Nil: WrappedRubyValue = WrappedRubyValue {
36
+ value: ruby_special_consts::RUBY_Qnil as u32,
37
+ padding: 0,
38
+ };
39
+ }
40
+
41
+ pub fn parse_into_ruby(json: String) -> Result<rb::RubyValue, Box<dyn std::error::Error>> {
42
+ unsafe { rb::ruby_init() };
43
+
44
+ let value = json::parse(json);
45
+ let ruby = walk(&value);
46
+ Ok(ruby)
47
+ }
48
+
49
+ fn walk(value: &json::Value) -> rb::RubyValue {
50
+ use json::Value::*;
51
+ match value {
52
+ Null => v::Nil.into(),
53
+ True => v::True.into(),
54
+ False => v::False.into(),
55
+ Int(i) => unsafe { rb::rb_int2big(*i as isize) },
56
+ Str(s) => unsafe {
57
+ let s = format!("{}\0", s);
58
+ rb::rb_utf8_str_new_cstr(s.as_ptr() as *const i8)
59
+ },
60
+ Array(v) => unsafe {
61
+ let ary = rb::rb_ary_new_capa(v.len() as i64);
62
+ for e in v.iter() {
63
+ let en = walk(e);
64
+ rb::rb_ary_push(ary, en);
65
+ }
66
+ ary
67
+ },
68
+ Object(_, ha) => unsafe {
69
+ let hash = rb::rb_hash_new();
70
+ for (k, v) in ha.iter() {
71
+ let rk = walk(k);
72
+ let rv = walk(v);
73
+ rb::rb_hash_aset(hash, rk, rv);
74
+ }
75
+ hash
76
+ },
77
+ }
78
+ }
metadata ADDED
@@ -0,0 +1,65 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ruston
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Uchio Kondo
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2022-06-21 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: Sample Rust-made gem to parse simple JSON...
14
+ email:
15
+ - udzura@udzura.jp
16
+ executables: []
17
+ extensions:
18
+ - Cargo.toml
19
+ extra_rdoc_files: []
20
+ files:
21
+ - ".gitignore"
22
+ - ".ruby-version"
23
+ - Cargo.lock
24
+ - Cargo.toml
25
+ - Gemfile
26
+ - Gemfile.lock
27
+ - LICENSE.txt
28
+ - README.md
29
+ - Rakefile
30
+ - bin/console
31
+ - bin/setup
32
+ - examples/lex.rs
33
+ - examples/parser.rs
34
+ - examples/rb/parsejson.rb
35
+ - examples/ruby_run.rs
36
+ - lib/ruston.rb
37
+ - lib/ruston/version.rb
38
+ - ruston.gemspec
39
+ - src/json.rs
40
+ - src/lib.rs
41
+ - src/ruby.rs
42
+ homepage: https://github.com/udzura/ruston
43
+ licenses:
44
+ - MIT
45
+ metadata: {}
46
+ post_install_message:
47
+ rdoc_options: []
48
+ require_paths:
49
+ - lib
50
+ required_ruby_version: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ required_rubygems_version: !ruby/object:Gem::Requirement
56
+ requirements:
57
+ - - ">="
58
+ - !ruby/object:Gem::Version
59
+ version: '0'
60
+ requirements: []
61
+ rubygems_version: 3.4.0.dev
62
+ signing_key:
63
+ specification_version: 4
64
+ summary: Sample Rust-made gem to parse simple JSON...
65
+ test_files: []