parsanol 1.3.49 → 1.3.51
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 +4 -4
- data/Cargo.lock +14 -7
- data/Cargo.toml +1 -1
- data/Rakefile +19 -0
- data/ext/parsanol_cdylib/Cargo.toml +15 -0
- data/ext/parsanol_cdylib/src/lib.rs +12 -0
- data/ext/parsanol_native/Cargo.toml +1 -1
- data/lib/parsanol/native/ffi.rb +11 -5
- data/lib/parsanol/native/transformer.rb +125 -55
- data/lib/parsanol/version.rb +1 -1
- data/parsanol.gemspec +11 -1
- metadata +3 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: ee4e171a9217d66e90cc5c3cd51fb9af8d901ec7de75182e68e90caf3bbefb57
|
|
4
|
+
data.tar.gz: bb5e4f0391b98f79e86614f7a53158bdbe8cc12feb39a43ff94bcb553706bb75
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: c1cda8632038653dc853bece92e4f804c267fe43f8146cda3fc8481ad031c8087293f965274e12a173da881ad34ec370db71906ede1a1f89ebe52058e08440ba
|
|
7
|
+
data.tar.gz: f2f5c8f67bbd0c6d444593f41551c32f165d99725e17c37ee6475dfd858a4f6887f7185657f4c0c44b3a232a4b66795742a18ddd134b0afd757b0c7b6b0e181f
|
data/Cargo.lock
CHANGED
|
@@ -139,9 +139,9 @@ checksum = "e4eba85ea1d0a966a983acd07deee566e67395d2d96b6fb39e62b5a833f1eb0b"
|
|
|
139
139
|
|
|
140
140
|
[[package]]
|
|
141
141
|
name = "hashbrown"
|
|
142
|
-
version = "0.
|
|
142
|
+
version = "0.17.1"
|
|
143
143
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
144
|
-
checksum = "
|
|
144
|
+
checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a"
|
|
145
145
|
dependencies = [
|
|
146
146
|
"allocator-api2",
|
|
147
147
|
"equivalent",
|
|
@@ -252,9 +252,9 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50"
|
|
|
252
252
|
|
|
253
253
|
[[package]]
|
|
254
254
|
name = "parsanol"
|
|
255
|
-
version = "0.8.
|
|
255
|
+
version = "0.8.8"
|
|
256
256
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
257
|
-
checksum = "
|
|
257
|
+
checksum = "5709d5bc971fa4e28fccf401709ab1d275d180e447e3ab82fde7ebef2ecc787b"
|
|
258
258
|
dependencies = [
|
|
259
259
|
"ahash",
|
|
260
260
|
"getrandom 0.3.4",
|
|
@@ -269,13 +269,20 @@ dependencies = [
|
|
|
269
269
|
|
|
270
270
|
[[package]]
|
|
271
271
|
name = "parsanol-derive"
|
|
272
|
-
version = "0.8.
|
|
272
|
+
version = "0.8.8"
|
|
273
273
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
274
|
-
checksum = "
|
|
274
|
+
checksum = "93258404b7032b85dffd9a60e3fb1ed003a268282b4f3385f1ab1aba98db34e5"
|
|
275
275
|
dependencies = [
|
|
276
276
|
"proc-macro2",
|
|
277
277
|
"quote",
|
|
278
|
-
"syn
|
|
278
|
+
"syn 3.0.6",
|
|
279
|
+
]
|
|
280
|
+
|
|
281
|
+
[[package]]
|
|
282
|
+
name = "parsanol_cdylib"
|
|
283
|
+
version = "1.3.50"
|
|
284
|
+
dependencies = [
|
|
285
|
+
"parsanol",
|
|
279
286
|
]
|
|
280
287
|
|
|
281
288
|
[[package]]
|
data/Cargo.toml
CHANGED
data/Rakefile
CHANGED
|
@@ -64,6 +64,25 @@ namespace :gem do
|
|
|
64
64
|
sh "rake gem:platform:any gem"
|
|
65
65
|
end
|
|
66
66
|
|
|
67
|
+
# Vendor the pure-portable cdylib into PLATFORM gems (TODO.perf/9):
|
|
68
|
+
# the ruby (source) gem stays binary-free; each cross-gem carries its
|
|
69
|
+
# own triple's libparsanol next to the extension for the ffi tier
|
|
70
|
+
# (MRI resilience fallback, TruffleRuby native).
|
|
71
|
+
desc "Build ext/parsanol_cdylib for the active cross target and vendor it"
|
|
72
|
+
task "vendor_cdylib" do
|
|
73
|
+
triplet = ENV["CARGO_BUILD_TARGET"] || ENV.fetch("RUST_TARGET", nil)
|
|
74
|
+
args = ["cargo", "build", "--release", "-p", "parsanol_cdylib"]
|
|
75
|
+
args += ["--target", triplet] if triplet
|
|
76
|
+
sh(*args)
|
|
77
|
+
dir = triplet ? "target/#{triplet}/release" : "target/release"
|
|
78
|
+
name = %w[libparsanol.so libparsanol.dylib parsanol.dll]
|
|
79
|
+
.map { |n| File.join(dir, n) }
|
|
80
|
+
.find { |f| File.file?(f) }
|
|
81
|
+
raise "cdylib not found under #{dir}" unless name
|
|
82
|
+
|
|
83
|
+
cp name, "lib/parsanol/native/"
|
|
84
|
+
end
|
|
85
|
+
|
|
67
86
|
desc "Define the gem task to build on any platform (compile on install)"
|
|
68
87
|
task "platform:any" do
|
|
69
88
|
spec = Gem::Specification.load("parsanol.gemspec").dup
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
[package]
|
|
2
|
+
name = "parsanol_cdylib"
|
|
3
|
+
version = "1.3.51"
|
|
4
|
+
edition = "2021"
|
|
5
|
+
description = "Vendored cdylib for parsanol platform gems: the pure-portable C ABI (no magnus) for the ffi tier"
|
|
6
|
+
license = "MIT"
|
|
7
|
+
publish = false
|
|
8
|
+
|
|
9
|
+
[lib]
|
|
10
|
+
name = "parsanol"
|
|
11
|
+
crate-type = ["cdylib"]
|
|
12
|
+
doc = false
|
|
13
|
+
|
|
14
|
+
[dependencies]
|
|
15
|
+
parsanol = { version = "0.8.8" }
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
//! Vendored cdylib twin of parsanol-rs's `parsanol-ffi` crate, living in
|
|
2
|
+
//! the gem's ext workspace so the cross-gem build matrix can compile it
|
|
3
|
+
//! per platform triple. Mirrors parsanol-ffi: linking the rlib publishes
|
|
4
|
+
//! the `#[no_mangle] parsanol_c_*` exports; no wrappers.
|
|
5
|
+
|
|
6
|
+
// Force the dependency into the link even under aggressive stripping.
|
|
7
|
+
// Keep in sync with parsanol-rs parsanol-ffi/src/lib.rs.
|
|
8
|
+
#[allow(unused_imports)]
|
|
9
|
+
use parsanol::ffi::c::{
|
|
10
|
+
parsanol_c_last_error, parsanol_c_parse, parsanol_c_parse_len, parsanol_c_register,
|
|
11
|
+
parsanol_c_release,
|
|
12
|
+
};
|
|
@@ -28,7 +28,7 @@ rb-sys = { version = "0.9.124", features = ["global-allocator"] }
|
|
|
28
28
|
magnus = { version = "0.9" }
|
|
29
29
|
|
|
30
30
|
# parsanol parser library (from git for latest features)
|
|
31
|
-
parsanol = { version = "0.8.
|
|
31
|
+
parsanol = { version = "0.8.8", features = ["ruby"] }
|
|
32
32
|
|
|
33
33
|
# Logging
|
|
34
34
|
log = "0.4"
|
data/lib/parsanol/native/ffi.rb
CHANGED
|
@@ -97,8 +97,13 @@ module Parsanol
|
|
|
97
97
|
ffi_lib path
|
|
98
98
|
attach_function :c_register, :parsanol_c_register,
|
|
99
99
|
%i[string], :uint64
|
|
100
|
-
|
|
101
|
-
|
|
100
|
+
# Explicit-length entry point: interior NULs stay intact. The
|
|
101
|
+
# input crosses as a raw buffer (:string rejects NUL bytes by
|
|
102
|
+
# design); a cdylib without the symbol is stale relative to
|
|
103
|
+
# this binding and fails availability loudly (pure-Ruby
|
|
104
|
+
# fallback) instead of silently truncating at NULs.
|
|
105
|
+
attach_function :c_parse_len, :parsanol_c_parse_len,
|
|
106
|
+
%i[uint64 buffer_in size_t pointer size_t], :long_long
|
|
102
107
|
attach_function :c_last_error, :parsanol_c_last_error,
|
|
103
108
|
[], :string
|
|
104
109
|
attach_function :c_release, :parsanol_c_release,
|
|
@@ -114,9 +119,10 @@ module Parsanol
|
|
|
114
119
|
|
|
115
120
|
# Two-call buffer protocol: cap=0 asks for the needed size, then
|
|
116
121
|
# the batch lands in a persistent buffer that only grows —
|
|
117
|
-
# steady-state parses allocate nothing.
|
|
122
|
+
# steady-state parses allocate nothing. The explicit-length call
|
|
123
|
+
# keeps interior NULs intact.
|
|
118
124
|
def parse_into(handle, input)
|
|
119
|
-
needed = @binding.
|
|
125
|
+
needed = @binding.c_parse_len(handle, input, input.bytesize, nil, 0)
|
|
120
126
|
return needed unless needed.negative?
|
|
121
127
|
|
|
122
128
|
cap = -needed
|
|
@@ -124,7 +130,7 @@ module Parsanol
|
|
|
124
130
|
@buffer&.free
|
|
125
131
|
@buffer = FFI::MemoryPointer.new(:uint64, cap * 2)
|
|
126
132
|
end
|
|
127
|
-
@binding.
|
|
133
|
+
@binding.c_parse_len(handle, input, input.bytesize, @buffer, cap)
|
|
128
134
|
end
|
|
129
135
|
end
|
|
130
136
|
end
|
|
@@ -18,8 +18,6 @@ module Parsanol
|
|
|
18
18
|
#
|
|
19
19
|
class AstTransformer
|
|
20
20
|
# Frozen string constants for tag comparisons (avoid allocations)
|
|
21
|
-
SEQUENCE_TAG = ":sequence"
|
|
22
|
-
REPETITION_TAG = ":repetition"
|
|
23
21
|
EMPTY_STRING = ""
|
|
24
22
|
EMPTY_ARRAY = [].freeze
|
|
25
23
|
EMPTY_HASH = {}.freeze
|
|
@@ -28,11 +26,12 @@ module Parsanol
|
|
|
28
26
|
# This is a class variable to share across all transformations
|
|
29
27
|
@@symbol_cache = {}
|
|
30
28
|
|
|
31
|
-
#
|
|
29
|
+
# Envelope tags. Both tiers (extension objects and the flat-u64
|
|
30
|
+
# batch wire) deliver Symbols — the encoder writes ':'-prefixed
|
|
31
|
+
# strings as TAG_SYMBOL — so there is exactly one tag form.
|
|
32
32
|
SEQUENCE_SYM = :sequence
|
|
33
33
|
REPETITION_SYM = :repetition
|
|
34
34
|
MAYBE_SYM = :maybe
|
|
35
|
-
MAYBE_TAG = ":maybe"
|
|
36
35
|
|
|
37
36
|
# `named` mirrors CanFlatten#flatten's named flag: inside a Named
|
|
38
37
|
# result (.as), an absent maybe flattens to nil; unnamed it flattens
|
|
@@ -67,7 +66,8 @@ module Parsanol
|
|
|
67
66
|
# Check if this is a tagged array from native parser
|
|
68
67
|
# Native parser produces Symbol tags: [:sequence, item1, item2, ...]
|
|
69
68
|
first = arr.first
|
|
70
|
-
|
|
69
|
+
case first
|
|
70
|
+
when SEQUENCE_SYM
|
|
71
71
|
# Optimized: transform items starting from index 1
|
|
72
72
|
# Avoid creating arr[1..] slice
|
|
73
73
|
len = arr.length
|
|
@@ -80,7 +80,7 @@ module Parsanol
|
|
|
80
80
|
i += 1
|
|
81
81
|
end
|
|
82
82
|
flatten_sequence(items)
|
|
83
|
-
|
|
83
|
+
when REPETITION_SYM
|
|
84
84
|
# Optimized: transform items starting from index 1
|
|
85
85
|
len = arr.length
|
|
86
86
|
# Empty repetition: named → [], unnamed → "" (CanFlatten#flatten_repetition)
|
|
@@ -93,7 +93,7 @@ module Parsanol
|
|
|
93
93
|
i += 1
|
|
94
94
|
end
|
|
95
95
|
flatten_repetition(items, named: named)
|
|
96
|
-
|
|
96
|
+
when MAYBE_SYM
|
|
97
97
|
# Maybe flattens to nil-or-value (named) or ""-or-value (unnamed),
|
|
98
98
|
# never to an array
|
|
99
99
|
len = arr.length
|
|
@@ -103,7 +103,7 @@ module Parsanol
|
|
|
103
103
|
flattened = transform(arr[1])
|
|
104
104
|
named ? flattened : (flattened || EMPTY_STRING)
|
|
105
105
|
end
|
|
106
|
-
|
|
106
|
+
when Symbol
|
|
107
107
|
# Other tagged arrays - pass through
|
|
108
108
|
arr.map { |item| transform(item) }
|
|
109
109
|
else
|
|
@@ -123,59 +123,92 @@ module Parsanol
|
|
|
123
123
|
transform_multi_key_hash(hash)
|
|
124
124
|
end
|
|
125
125
|
|
|
126
|
-
# Optimized handling for single-key hashes (the common case)
|
|
126
|
+
# Optimized handling for single-key hashes (the common case).
|
|
127
|
+
# The shape scans below are fused into as few passes as possible:
|
|
128
|
+
# each predicate was previously its own `all?` walk with a lambda
|
|
129
|
+
# dispatch, and `item.keys.length` allocated a keys array per
|
|
130
|
+
# element (Hash#length is O(1)).
|
|
127
131
|
def self.transform_single_key_hash(hash)
|
|
128
|
-
# Extract the single key-value pair without
|
|
129
|
-
key
|
|
132
|
+
# Extract the single key-value pair without iterating (the hash
|
|
133
|
+
# is guaranteed single-key by the caller).
|
|
134
|
+
key, = hash.first
|
|
130
135
|
value = hash[key]
|
|
131
136
|
sym_key = cached_symbol(key)
|
|
132
137
|
|
|
133
138
|
# Transform the value
|
|
134
139
|
transformed = transform(value, named: true)
|
|
135
140
|
|
|
136
|
-
#
|
|
137
|
-
#
|
|
138
|
-
# ":repetition" Strings — accept both.
|
|
141
|
+
# Tagged repetition from the native parser (Symbol tag; both
|
|
142
|
+
# tiers deliver the same form).
|
|
139
143
|
is_tagged_repetition = value.is_a?(Array) && !value.empty? &&
|
|
140
|
-
|
|
144
|
+
value.first.equal?(REPETITION_SYM)
|
|
141
145
|
|
|
142
146
|
# Check RAW value for repetition pattern BEFORE transformation
|
|
143
|
-
#
|
|
144
|
-
# e.g
|
|
145
|
-
is_raw_array_repetition =
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
147
|
+
# (bare repeated sibling captures, #36): array items that all
|
|
148
|
+
# carry the parent key, e.g. [{x: 1}, {x: 2}].
|
|
149
|
+
is_raw_array_repetition = false
|
|
150
|
+
if value.is_a?(Array) && !value.empty? && !is_tagged_repetition
|
|
151
|
+
is_raw_array_repetition = raw_items_all_named?(value, key)
|
|
152
|
+
end
|
|
149
153
|
|
|
150
154
|
# Empty array from native parser is a repetition result (not a sequence)
|
|
151
155
|
# Sequences produce arrays of arrays like [[], []], not empty arrays
|
|
152
156
|
is_empty_repetition = value.is_a?(Array) && value.empty?
|
|
153
157
|
|
|
154
|
-
#
|
|
155
|
-
#
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
158
|
+
# Single fused pass over the transformed array: detect the
|
|
159
|
+
# single-character join shape AND the untagged repetition shape
|
|
160
|
+
# in one walk (an element cannot be both a Hash and a
|
|
161
|
+
# single-character stringlike, so the predicates share a loop).
|
|
162
|
+
joined = nil
|
|
163
|
+
is_transformed_repetition = false
|
|
164
|
+
if transformed.is_a?(Array) && !transformed.empty?
|
|
165
|
+
all_named = true
|
|
166
|
+
all_single_char = true
|
|
167
|
+
content = nil
|
|
168
|
+
first_slice = nil
|
|
169
|
+
transformed.each do |item|
|
|
170
|
+
if item.is_a?(Hash)
|
|
171
|
+
all_single_char = false
|
|
172
|
+
unless item.length == 1 && item.key?(sym_key)
|
|
173
|
+
all_named = false
|
|
174
|
+
break
|
|
175
|
+
end
|
|
176
|
+
elsif item.is_a?(::Parsanol::Slice) || item.is_a?(String)
|
|
177
|
+
all_named = false
|
|
178
|
+
all_single_char = false unless item.length == 1
|
|
179
|
+
break if !all_single_char && !all_named
|
|
180
|
+
else
|
|
181
|
+
all_named = false
|
|
182
|
+
all_single_char = false
|
|
183
|
+
break
|
|
159
184
|
end
|
|
160
|
-
|
|
161
|
-
first_slice = transformed.find { |i| i.is_a?(::Parsanol::Slice) }
|
|
162
|
-
content = transformed.map { |i| slice_content(i) }.join
|
|
163
|
-
transformed = if first_slice
|
|
164
|
-
::Parsanol::Slice.new(first_slice.offset, content,
|
|
165
|
-
first_slice.input)
|
|
166
|
-
else
|
|
167
|
-
content
|
|
168
|
-
end
|
|
169
|
-
end
|
|
185
|
+
end
|
|
170
186
|
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
187
|
+
if all_single_char
|
|
188
|
+
# Join preserving position from the first Slice
|
|
189
|
+
content = +""
|
|
190
|
+
transformed.each do |item|
|
|
191
|
+
if item.is_a?(::Parsanol::Slice)
|
|
192
|
+
first_slice ||= item
|
|
193
|
+
content << item.content
|
|
194
|
+
else
|
|
195
|
+
content << item.to_s
|
|
196
|
+
end
|
|
197
|
+
end
|
|
198
|
+
joined = if first_slice
|
|
199
|
+
::Parsanol::Slice.new(first_slice.offset,
|
|
200
|
+
content, first_slice.input)
|
|
201
|
+
else
|
|
202
|
+
content
|
|
203
|
+
end
|
|
204
|
+
elsif all_named
|
|
205
|
+
is_transformed_repetition = true
|
|
176
206
|
end
|
|
207
|
+
end
|
|
177
208
|
|
|
178
|
-
|
|
209
|
+
transformed = joined if joined
|
|
210
|
+
is_repetition = is_tagged_repetition || is_raw_array_repetition ||
|
|
211
|
+
is_transformed_repetition || is_empty_repetition
|
|
179
212
|
|
|
180
213
|
# Handle based on type
|
|
181
214
|
if is_repetition
|
|
@@ -190,6 +223,14 @@ module Parsanol
|
|
|
190
223
|
end
|
|
191
224
|
end
|
|
192
225
|
|
|
226
|
+
# Alloc-free raw repetition scan: Hash#length instead of
|
|
227
|
+
# item.keys.length (which allocated per element).
|
|
228
|
+
def self.raw_items_all_named?(value, key)
|
|
229
|
+
value.all? do |item|
|
|
230
|
+
item.is_a?(Hash) && item.length == 1 && item.key?(key)
|
|
231
|
+
end
|
|
232
|
+
end
|
|
233
|
+
|
|
193
234
|
# Get content from Slice or string
|
|
194
235
|
def self.slice_content(value)
|
|
195
236
|
value.is_a?(::Parsanol::Slice) ? value.content : value.to_s
|
|
@@ -255,7 +296,7 @@ module Parsanol
|
|
|
255
296
|
sym_key = cached_symbol(key)
|
|
256
297
|
|
|
257
298
|
is_repetition = value.is_a?(Array) && !value.empty? &&
|
|
258
|
-
value.first.
|
|
299
|
+
value.first.equal?(REPETITION_SYM)
|
|
259
300
|
|
|
260
301
|
transformed = transform(value, named: true)
|
|
261
302
|
|
|
@@ -313,12 +354,26 @@ module Parsanol
|
|
|
313
354
|
return list.reduce { |acc, hash| acc.merge(hash) }
|
|
314
355
|
end
|
|
315
356
|
|
|
316
|
-
# Hot path: all stringlike (String/Slice).
|
|
317
|
-
#
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
357
|
+
# Hot path: all stringlike (String/Slice). One fused pass detects
|
|
358
|
+
# the shape and joins contents in place (no per-item lambda
|
|
359
|
+
# dispatch, no intermediate map array).
|
|
360
|
+
content = +""
|
|
361
|
+
first_slice = nil
|
|
362
|
+
all_stringlike = list.all? do |x|
|
|
363
|
+
if x.is_a?(::Parsanol::Slice)
|
|
364
|
+
first_slice ||= x
|
|
365
|
+
content << x.content
|
|
366
|
+
true
|
|
367
|
+
elsif x.is_a?(String)
|
|
368
|
+
content << x
|
|
369
|
+
true
|
|
370
|
+
else
|
|
371
|
+
false
|
|
372
|
+
end
|
|
373
|
+
end
|
|
374
|
+
if all_stringlike
|
|
375
|
+
return first_slice ? ::Parsanol::Slice.new(first_slice.offset, content,
|
|
376
|
+
first_slice.input) : content
|
|
322
377
|
end
|
|
323
378
|
|
|
324
379
|
# Cold path: parslet's exact fold (Hash/Slice/String/Array
|
|
@@ -372,14 +427,29 @@ module Parsanol
|
|
|
372
427
|
|
|
373
428
|
return EMPTY_ARRAY if named && items.empty?
|
|
374
429
|
|
|
375
|
-
# Hot path: all-stringlike repetition →
|
|
430
|
+
# Hot path: all-stringlike repetition → fused single-pass concat.
|
|
376
431
|
# Cold path: parslet's exact fold.
|
|
377
|
-
if items.
|
|
378
|
-
return EMPTY_STRING
|
|
432
|
+
if items.empty?
|
|
433
|
+
return EMPTY_STRING
|
|
434
|
+
end
|
|
379
435
|
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
436
|
+
content = +""
|
|
437
|
+
first_slice = nil
|
|
438
|
+
all_stringlike = items.all? do |x|
|
|
439
|
+
if x.is_a?(::Parsanol::Slice)
|
|
440
|
+
first_slice ||= x
|
|
441
|
+
content << x.content
|
|
442
|
+
true
|
|
443
|
+
elsif x.is_a?(String)
|
|
444
|
+
content << x
|
|
445
|
+
true
|
|
446
|
+
else
|
|
447
|
+
false
|
|
448
|
+
end
|
|
449
|
+
end
|
|
450
|
+
if all_stringlike
|
|
451
|
+
return first_slice ? ::Parsanol::Slice.new(first_slice.offset, content,
|
|
452
|
+
first_slice.input) : content
|
|
383
453
|
end
|
|
384
454
|
|
|
385
455
|
foldl(items.compact) { |acc, item| acc + item }
|
data/lib/parsanol/version.rb
CHANGED
data/parsanol.gemspec
CHANGED
|
@@ -39,7 +39,17 @@ Gem::Specification.new do |spec|
|
|
|
39
39
|
Cargo.lock
|
|
40
40
|
]
|
|
41
41
|
spec.files.reject! { |f| File.directory?(f) }
|
|
42
|
-
|
|
42
|
+
# Cargo build trees are never gem content (a dirty local
|
|
43
|
+
# ext/parsanol_native/target once inflated a build to 218 MB).
|
|
44
|
+
spec.files.reject! { |f| f.include?("/target/") || f.start_with?("target/") }
|
|
45
|
+
# Binaries are never tracked in git, and the ruby (source) gem stays
|
|
46
|
+
# slim: the pure-portable cdylib is vendored ONLY into platform gems
|
|
47
|
+
# by the cross-gem build (rake gem:vendor_cdylib), never by a plain
|
|
48
|
+
# `gem build`.
|
|
49
|
+
spec.files.reject! do |f|
|
|
50
|
+
f =~ /\.(dll|so|dylib|lib|bundle)\Z/ &&
|
|
51
|
+
!(ENV["PARSANOL_VENDOR_CDYLIB"] == "1" && f.start_with?("lib/parsanol/native/"))
|
|
52
|
+
end
|
|
43
53
|
spec.require_paths = ["lib"]
|
|
44
54
|
|
|
45
55
|
spec.required_ruby_version = ">= 3.2.0"
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: parsanol
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.3.
|
|
4
|
+
version: 1.3.51
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Ribose Inc.
|
|
@@ -40,6 +40,8 @@ files:
|
|
|
40
40
|
- LICENSE
|
|
41
41
|
- README.adoc
|
|
42
42
|
- Rakefile
|
|
43
|
+
- ext/parsanol_cdylib/Cargo.toml
|
|
44
|
+
- ext/parsanol_cdylib/src/lib.rs
|
|
43
45
|
- ext/parsanol_native/Cargo.toml
|
|
44
46
|
- ext/parsanol_native/extconf.rb
|
|
45
47
|
- ext/parsanol_native/src/lib.rs
|