yeptris 0.6.1.2 → 0.6.2.1
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/lib/yeptris/ffi.rb +3 -0
- data/lib/yeptris/node.rb +11 -0
- data/lib/yeptris/psych/visitors.rb +45 -7
- data/lib/yeptris/psych.rb +55 -1
- data/lib/yeptris/yaml.rb +19 -3
- data/lib/yeptris.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 965e8f62705fce2b6b3566e5f64e4719c504cb08ae995a9a58de071c13543481
|
|
4
|
+
data.tar.gz: 4f06fa6f1ecddc993a58c54ae4f3e6fb160bc39d3629ff8c2293d9de59fda11f
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 6126e07fdbf24026edc357d5748d659e2c4a7fa534cdf4dbdfa2ccadabc00fa41548917f563fedbe09ea56324a7fb28d28417559136b2648a2c9631c72d07a87
|
|
7
|
+
data.tar.gz: 5222f3d5c13e87a0b119d5505077f6288e53711319d901a30de3f33ba5232e9ffc56bf6d4560ee6332dbcb129b8c6eb818a24b4211abdd7b1848bd66e2a0b4f3
|
data/lib/yeptris/ffi.rb
CHANGED
|
@@ -89,6 +89,8 @@ module Yeptris
|
|
|
89
89
|
%i[yeptris_document pointer size_t int], :yeptris_node
|
|
90
90
|
attach_function :yeptris_node_map_add,
|
|
91
91
|
%i[yeptris_node pointer size_t yeptris_node], :int
|
|
92
|
+
attach_function :yeptris_node_map_add_node,
|
|
93
|
+
%i[yeptris_node yeptris_node yeptris_node], :int
|
|
92
94
|
attach_function :yeptris_node_map_set,
|
|
93
95
|
%i[yeptris_node pointer size_t yeptris_node], :int
|
|
94
96
|
attach_function :yeptris_node_map_del, %i[yeptris_node pointer size_t], :int
|
|
@@ -176,6 +178,7 @@ module Yeptris
|
|
|
176
178
|
BUILD_SEQ = 2
|
|
177
179
|
BUILD_MAP = 3
|
|
178
180
|
BUILD_END = 4
|
|
181
|
+
BUILD_TAG = 5
|
|
179
182
|
|
|
180
183
|
# the ABI-pinned shape; the bulk builder packs these bytes
|
|
181
184
|
# directly (12 per entry)
|
data/lib/yeptris/node.rb
CHANGED
|
@@ -201,6 +201,17 @@ class Yeptris::Node
|
|
|
201
201
|
self
|
|
202
202
|
end
|
|
203
203
|
|
|
204
|
+
# A pre-built key NODE ( Psych parity: nil keys ride the explicit
|
|
205
|
+
# `!` tag on an empty single-quoted scalar, which the byte-key form
|
|
206
|
+
# cannot carry)
|
|
207
|
+
def map_add_node(key_node, node)
|
|
208
|
+
rc = alive do
|
|
209
|
+
Yeptris::FFI.yeptris_node_map_add_node(@c_ptr, key_node.c_ptr, node.c_ptr)
|
|
210
|
+
end
|
|
211
|
+
Yeptris::FFI.check_status(rc, "yeptris_node_map_add_node")
|
|
212
|
+
self
|
|
213
|
+
end
|
|
214
|
+
|
|
204
215
|
def map_set(key, node)
|
|
205
216
|
key = key.to_s
|
|
206
217
|
rc = alive { Yeptris::FFI.yeptris_node_map_set(@c_ptr, key, key.bytesize, node.c_ptr) }
|
|
@@ -12,6 +12,12 @@ module Yeptris
|
|
|
12
12
|
# objects, aliases for repeats, the Encodable protocol, and the
|
|
13
13
|
# !ruby/... tags Psych's own emitter produces.
|
|
14
14
|
class YAMLTree
|
|
15
|
+
# stdlib's factory (relaton's db cache calls it): the options
|
|
16
|
+
# ride our visitor defaults
|
|
17
|
+
def self.create(options = {}, emitter = nil)
|
|
18
|
+
new
|
|
19
|
+
end
|
|
20
|
+
|
|
15
21
|
def initialize
|
|
16
22
|
@tree = ::Yeptris::Document.create
|
|
17
23
|
@names = {} # object_id -> anchor name
|
|
@@ -142,7 +148,17 @@ module Yeptris
|
|
|
142
148
|
m = @tree.new_mapping
|
|
143
149
|
remember(hash, m)
|
|
144
150
|
m.set_anchor(name) if name
|
|
145
|
-
hash.each
|
|
151
|
+
hash.each do |k, v|
|
|
152
|
+
if k.nil?
|
|
153
|
+
# Psych's nil-key form: `! ''` — the explicit tag on an
|
|
154
|
+
# empty single-quoted key (#300 family 2)
|
|
155
|
+
key_node = @tree.new_scalar("", :single_quoted)
|
|
156
|
+
key_node.set_tag("!")
|
|
157
|
+
m.map_add_node(key_node, visit(v))
|
|
158
|
+
else
|
|
159
|
+
m.map_add(key_text(k), visit(v))
|
|
160
|
+
end
|
|
161
|
+
end
|
|
146
162
|
m
|
|
147
163
|
end
|
|
148
164
|
|
|
@@ -245,15 +261,37 @@ module Yeptris
|
|
|
245
261
|
new.visit(node)
|
|
246
262
|
end
|
|
247
263
|
|
|
264
|
+
# stdlib ToRuby#accept's domain post-pass: normalize the tag
|
|
265
|
+
# (strip leading !//, ensure tag: unless x-private) and run the
|
|
266
|
+
# registered block over the revived result (#95 thread)
|
|
267
|
+
def apply_domain_type(result, node)
|
|
268
|
+
return result if node.tag.nil? || node.tag.empty?
|
|
269
|
+
|
|
270
|
+
key = node.tag.sub(/\A[!\/]*/, "").sub(/(,\d+)\//, '\1:')
|
|
271
|
+
key = "tag:#{key}" unless key.match?(/\A(?:tag:|x-private)/)
|
|
272
|
+
entry = ::Yeptris::Psych.domain_types[key]
|
|
273
|
+
return result unless entry
|
|
274
|
+
|
|
275
|
+
_value, block = entry
|
|
276
|
+
block.call(key, result)
|
|
277
|
+
end
|
|
278
|
+
|
|
248
279
|
def visit(node)
|
|
249
280
|
@root ||= node
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
281
|
+
result =
|
|
282
|
+
case node
|
|
283
|
+
when ::Yeptris::Psych::Nodes::Alias then visit_alias(node)
|
|
284
|
+
when ::Yeptris::Psych::Nodes::Scalar then visit_scalar(node)
|
|
285
|
+
when ::Yeptris::Psych::Nodes::Sequence then visit_sequence(node)
|
|
286
|
+
when ::Yeptris::Psych::Nodes::Mapping then visit_mapping(node)
|
|
287
|
+
else node&.to_ruby
|
|
288
|
+
end
|
|
289
|
+
# the domain-types post-pass (stdlib ToRuby#accept's tail):
|
|
290
|
+
# registered blocks transform the revived result per node
|
|
291
|
+
if node && !::Yeptris::Psych.domain_types.empty?
|
|
292
|
+
result = apply_domain_type(result, node)
|
|
256
293
|
end
|
|
294
|
+
result
|
|
257
295
|
end
|
|
258
296
|
|
|
259
297
|
private
|
data/lib/yeptris/psych.rb
CHANGED
|
@@ -37,6 +37,38 @@ module Yeptris
|
|
|
37
37
|
def dump_tags=(tags)
|
|
38
38
|
@dump_tags = tags
|
|
39
39
|
end
|
|
40
|
+
|
|
41
|
+
# The third registry (stdlib psych carries all three; the rebind
|
|
42
|
+
# broke relaton/lutaml callers that wrote it — the 26x
|
|
43
|
+
# undefined-method report). Keys are normalized tag strings
|
|
44
|
+
# ("tag:DOMAIN:TYPE"), values are [key, block] post-processors.
|
|
45
|
+
def domain_types
|
|
46
|
+
@domain_types ||= {}
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def domain_types=(types)
|
|
50
|
+
@domain_types = types
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def add_domain_type(domain, type_tag, &block)
|
|
54
|
+
key = ["tag", domain, type_tag].join(":")
|
|
55
|
+
domain_types[key] = [key, block]
|
|
56
|
+
domain_types["tag:#{type_tag}"] = [key, block]
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def add_builtin_type(type_tag, &block)
|
|
60
|
+
key = ["tag", "yaml.org,2002", type_tag].join(":")
|
|
61
|
+
domain_types[key] = [key, block]
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def remove_type(type_tag)
|
|
65
|
+
domain_types.delete type_tag
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def add_tag(tag, klass)
|
|
69
|
+
load_tags[tag] = klass.name
|
|
70
|
+
dump_tags[klass] = tag
|
|
71
|
+
end
|
|
40
72
|
end
|
|
41
73
|
|
|
42
74
|
# Children load via autoload declared HERE — the immediate parent
|
|
@@ -152,7 +184,15 @@ module Yeptris
|
|
|
152
184
|
|
|
153
185
|
# Arbitrary object graphs through the YAMLTree visitor
|
|
154
186
|
# (anchors, !ruby/ tags); plain data rides the fast builder.
|
|
155
|
-
def dump(obj, io = nil)
|
|
187
|
+
def dump(obj, io = nil, options = {})
|
|
188
|
+
# stdlib's Object#to_yaml calls Psych.dump(self, options) —
|
|
189
|
+
# the options hash lands in the io slot positionally; treat a
|
|
190
|
+
# Hash there as options (the options themselves ride the
|
|
191
|
+
# visitor's defaults, #95 thread)
|
|
192
|
+
if io.is_a?(::Hash)
|
|
193
|
+
options = io
|
|
194
|
+
io = nil
|
|
195
|
+
end
|
|
156
196
|
# scalars take the fast builder; EVERYTHING else (including
|
|
157
197
|
# plain containers — they may nest custom objects) goes
|
|
158
198
|
# through the visitor, which builds the same DOM for plain
|
|
@@ -388,6 +428,20 @@ end
|
|
|
388
428
|
# yeptris/psych/drop_in — process-exclusive by nature, since the
|
|
389
429
|
# stdlib cannot be prevented from re-opening whatever ::Psych points
|
|
390
430
|
# at once IT loads.
|
|
431
|
+
# The core extension (stdlib psych/core_ext parity): Object#to_yaml
|
|
432
|
+
# and Object.yaml_tag exist whether the consumer came through stdlib
|
|
433
|
+
# psych first or pure drop-in. Both definitions are compatible —
|
|
434
|
+
# whoever loads last wins, and both call the rebound Psych.dump.
|
|
435
|
+
class Object
|
|
436
|
+
def self.yaml_tag(url)
|
|
437
|
+
::Yeptris::Psych.add_tag(url, self)
|
|
438
|
+
end
|
|
439
|
+
|
|
440
|
+
def to_yaml(options = {})
|
|
441
|
+
::Yeptris::Psych.dump(self, options)
|
|
442
|
+
end
|
|
443
|
+
end
|
|
444
|
+
|
|
391
445
|
# 0.4-contract migration signal (issue #95): this require used to
|
|
392
446
|
# rebind ::Psych. It does not anymore, and re-binding it here would
|
|
393
447
|
# regress #69 (any stdlib psych loaded afterwards would explode with
|
data/lib/yeptris/yaml.rb
CHANGED
|
@@ -102,6 +102,7 @@ module Yeptris
|
|
|
102
102
|
STYLE_SQ = 2
|
|
103
103
|
STYLE_DQ = 3
|
|
104
104
|
STYLE_LIT = 4
|
|
105
|
+
BUILD_TAG = Yeptris::FFI::BUILD_TAG
|
|
105
106
|
|
|
106
107
|
module_function
|
|
107
108
|
|
|
@@ -164,8 +165,15 @@ module Yeptris
|
|
|
164
165
|
# reader resolves them back to Symbols; Integer/Float/
|
|
165
166
|
# bool keys ride plain like their values (Psych emits
|
|
166
167
|
# 1: unquoted — #290 family 5); string keys ride the
|
|
167
|
-
# visit_String rules like any other scalar
|
|
168
|
-
|
|
168
|
+
# visit_String rules like any other scalar; NIL keys
|
|
169
|
+
# ride Psych's explicit-`!` empty-scalar form
|
|
170
|
+
# (#300 family 2)
|
|
171
|
+
if k.nil?
|
|
172
|
+
scalar("", STYLE_SQ, emit, blob, off)
|
|
173
|
+
emit.call(BUILD_TAG, 0, off[0], 1)
|
|
174
|
+
blob << "!"
|
|
175
|
+
off[0] += 1
|
|
176
|
+
elsif k.is_a?(Symbol)
|
|
169
177
|
scalar(":#{k}", STYLE_PLAIN, emit, blob, off)
|
|
170
178
|
elsif k.is_a?(String)
|
|
171
179
|
place(k, emit, blob, off, seen)
|
|
@@ -316,7 +324,15 @@ module Yeptris
|
|
|
316
324
|
def build_map(doc, h, seen)
|
|
317
325
|
cycle_guard(h, seen) do
|
|
318
326
|
m = doc.new_mapping
|
|
319
|
-
h.each
|
|
327
|
+
h.each do |k, v|
|
|
328
|
+
if k.nil?
|
|
329
|
+
key_node = doc.new_scalar("", :single_quoted)
|
|
330
|
+
key_node.set_tag("!")
|
|
331
|
+
m.map_add_node(key_node, build(doc, v, seen))
|
|
332
|
+
else
|
|
333
|
+
m.map_add(key_text(k), build(doc, v, seen))
|
|
334
|
+
end
|
|
335
|
+
end
|
|
320
336
|
m
|
|
321
337
|
end
|
|
322
338
|
end
|
data/lib/yeptris.rb
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
module Yeptris
|
|
4
4
|
# The gem's version lives in the parent namespace's file — the last
|
|
5
5
|
# internal require (yeptris/version) retired with it.
|
|
6
|
-
VERSION = "0.6.1
|
|
6
|
+
VERSION = "0.6.2.1".freeze
|
|
7
7
|
# The error hierarchy lives in THIS file (the parent namespace's
|
|
8
8
|
# own file): nested constants do not trigger a parent-constant
|
|
9
9
|
# autoload, and the law forbids internal requires — defining the
|