yeptris 0.6.0.1-aarch64-linux → 0.6.1.2-aarch64-linux

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 35b995a0549cefe2283f5fa216a25ad3916fcdad14f3fcd0e82dce4ea4e28d9a
4
- data.tar.gz: fdf0bd113bb0d6fdf2baa5cb666bdb3853414dacb700dfefce2b303adb6fe311
3
+ metadata.gz: 66b2f9041d103ed43571c0c954eaf50c2b17bf1caa6e1ec6df597dea7ffa0caa
4
+ data.tar.gz: b1e7a04b72e712e2627d804015f95563b8f76896e959e310ab26e77382ca3b18
5
5
  SHA512:
6
- metadata.gz: e351d18a024db7421267347d3cbfde3fbe5909204440a75574859939ef850f14b32f32c57d0fef441f7dfd5f900dd3958198f7c15d6f55a89c6a714d343635df
7
- data.tar.gz: 900b366334570cbfe0239f7f7f284d74ba74dc57f1215eba35a6fda17fb541b3d081fd0cc13a29ec3e926eeb50d96a9d8ec61bc7a95367737890834f1520260d
6
+ metadata.gz: cf83a3760805a881ee6e119aa8acd314e12a5d0fb7e7fe6c1bbc0c20e80a30515402c1ffc43aef2dd1da1ee87668198fcb6770bd71453eb7c2fb9df2eac35a6d
7
+ data.tar.gz: 90bb5e3646864b04542ca5c65ac5b08562f0e22141f50e6a43c98fdba47199f9eb2deb7878c9cd12ea2602cf77069a5a7bb295c0c695dc7d2ff4f3c54e71ff00
@@ -116,8 +116,14 @@ module Yeptris
116
116
  text =
117
117
  if obj.is_a?(::Date) || obj.is_a?(::Time)
118
118
  obj.iso8601 # canonical timestamp form, not to_s
119
+ elsif obj.nil?
120
+ "" # libyaml's null rendering rides bare (issue #290)
121
+ elsif obj.is_a?(::Float)
122
+ ::Yeptris::YAML::BulkBuilder.float_text(obj)
123
+ elsif obj.is_a?(::Time)
124
+ ::Yeptris::YAML::BulkBuilder.time_text(obj)
119
125
  else
120
- obj.nil? ? "null" : obj.to_s
126
+ obj.to_s
121
127
  end
122
128
  n =
123
129
  if obj.is_a?(::String)
@@ -200,7 +206,8 @@ module Yeptris
200
206
  end
201
207
  m = @tree.new_mapping
202
208
  m.set_anchor(name) if name
203
- m.set_tag("!ruby/object:#{obj.class.name}")
209
+ custom = ::Yeptris::Psych.dump_tags[obj.class]
210
+ m.set_tag(custom || "!ruby/object:#{obj.class.name}")
204
211
  m.map_add("__init__", init)
205
212
  remember(obj, m)
206
213
  m
@@ -327,7 +334,13 @@ module Yeptris
327
334
  klass = resolve_class(Regexp.last_match(1).to_s)
328
335
  revive_object(klass, node)
329
336
  else
330
- hash_into({}, node)
337
+ # Psych.load_tags first (the class registry, #95 bug 4);
338
+ # anything else stays the plain mapping
339
+ if (klass = ::Yeptris::Psych.load_tags[tag])
340
+ revive_tagged(klass, node)
341
+ else
342
+ hash_into({}, node)
343
+ end
331
344
  end
332
345
  end
333
346
 
@@ -339,6 +352,23 @@ module Yeptris
339
352
  h
340
353
  end
341
354
 
355
+ # A load_tags-registered class revives from the mapping's own
356
+ # top-level pairs (Psych's coder semantics — no __init__
357
+ # wrapper, which is OUR encoder's internal convention)
358
+ def revive_tagged(klass, node)
359
+ raise ::Yeptris::DumpError,
360
+ "#{klass} is not Yeptris::Psych::Encodable: implement init_with(coder)" unless klass <= ::Yeptris::Psych::Encodable
361
+
362
+ obj = klass.allocate
363
+ anchors[node.anchor] = obj if node.anchor
364
+ coder = ::Yeptris::Psych::CoderShim.new
365
+ node.children.each_slice(2) do |k, v|
366
+ coder[k.to_ruby.to_s] = visit(v)
367
+ end
368
+ obj.init_with(coder)
369
+ obj
370
+ end
371
+
342
372
  def revive_object(klass, node)
343
373
  # bare !ruby/object (no class): Psych.dump(Object.new)'s form.
344
374
  # An Object has no declared state — allocation is the whole
data/lib/yeptris/psych.rb CHANGED
@@ -17,6 +17,28 @@ require "set"
17
17
  # document without materializing.
18
18
  module Yeptris
19
19
  module Psych
20
+ # The tag registries (Psych's class-level API, #95 bug 4):
21
+ # load_tags maps a serialized tag to the Class that revives it;
22
+ # dump_tags overrides the emitted tag for a Class. Consulted by
23
+ # the revival visitor (custom tags) and the dumper's tag choice.
24
+ class << self
25
+ def load_tags
26
+ @load_tags ||= {}
27
+ end
28
+
29
+ def load_tags=(tags)
30
+ @load_tags = tags
31
+ end
32
+
33
+ def dump_tags
34
+ @dump_tags ||= {}
35
+ end
36
+
37
+ def dump_tags=(tags)
38
+ @dump_tags = tags
39
+ end
40
+ end
41
+
20
42
  # Children load via autoload declared HERE — the immediate parent
21
43
  # namespace's file (never internal requires).
22
44
  autoload :Handler, "yeptris/psych/handler"
data/lib/yeptris/yaml.rb CHANGED
@@ -101,9 +101,28 @@ module Yeptris
101
101
  STYLE_PLAIN = 1
102
102
  STYLE_SQ = 2
103
103
  STYLE_DQ = 3
104
+ STYLE_LIT = 4
104
105
 
105
106
  module_function
106
107
 
108
+ # Psych's exact timestamp spelling (format_time, #300): space
109
+ # separated, nanosecond width, Z for UTC — iso8601 diverged
110
+ def time_text(t)
111
+ t.utc? ? t.strftime("%Y-%m-%d %H:%M:%S.%9N Z") : t.strftime("%Y-%m-%d %H:%M:%S.%9N %:z")
112
+ end
113
+
114
+ # Psych's float spelling (#290): Infinity/NAN ride the YAML words,
115
+ # not Ruby's to_s (which prints "Infinity"/"NaN" — a STRING on
116
+ # reload)
117
+ def float_text(f)
118
+ return ".nan" if f.respond_to?(:nan?) && f.nan?
119
+ case (inf = f.infinite?)
120
+ when 1 then ".inf"
121
+ when -1 then "-.inf"
122
+ else f.to_s
123
+ end
124
+ end
125
+
107
126
  # container entries are constant bytes — no pack per op
108
127
  MAP_ENTRY = [Yeptris::FFI::BUILD_MAP, 0, 0, 0].pack("CCx2VV").freeze
109
128
  SEQ_ENTRY = [Yeptris::FFI::BUILD_SEQ, 0, 0, 0].pack("CCx2VV").freeze
@@ -141,10 +160,17 @@ module Yeptris
141
160
  # Symbol keys emit as bare ":k" plain — the compat
142
161
  # reader resolves them back to Symbols; string keys
143
162
  # ride the visit_String rules like any other scalar
163
+ # Symbol keys emit as bare ":k" plain — the compat
164
+ # reader resolves them back to Symbols; Integer/Float/
165
+ # bool keys ride plain like their values (Psych emits
166
+ # 1: unquoted — #290 family 5); string keys ride the
167
+ # visit_String rules like any other scalar
144
168
  if k.is_a?(Symbol)
145
169
  scalar(":#{k}", STYLE_PLAIN, emit, blob, off)
170
+ elsif k.is_a?(String)
171
+ place(k, emit, blob, off, seen)
146
172
  else
147
- place(k.to_s, emit, blob, off, seen)
173
+ scalar(k.to_s, STYLE_PLAIN, emit, blob, off)
148
174
  end
149
175
  place(v, emit, blob, off, seen)
150
176
  end
@@ -158,10 +184,12 @@ module Yeptris
158
184
  end
159
185
  when String then scalar(obj, STYLE_BY_NAME[string_style(obj)], emit, blob, off)
160
186
  when Symbol then scalar(":#{obj}", STYLE_PLAIN, emit, blob, off)
161
- when Integer, Float then scalar(obj.to_s, STYLE_PLAIN, emit, blob, off)
187
+ when Integer then scalar(obj.to_s, STYLE_PLAIN, emit, blob, off)
188
+ when Float then scalar(float_text(obj), STYLE_PLAIN, emit, blob, off)
162
189
  when true, false then scalar(obj.to_s, STYLE_PLAIN, emit, blob, off)
163
- when nil then scalar("null", STYLE_PLAIN, emit, blob, off)
164
- when Date, Time then scalar(obj.iso8601, STYLE_PLAIN, emit, blob, off)
190
+ when nil then scalar("", STYLE_PLAIN, emit, blob, off)
191
+ when Time then scalar(time_text(obj), STYLE_PLAIN, emit, blob, off)
192
+ when Date then scalar(obj.iso8601, STYLE_PLAIN, emit, blob, off)
165
193
  else
166
194
  raise DumpError,
167
195
  "cannot dump #{obj.class}: unsupported object " \
@@ -235,9 +263,14 @@ module Yeptris
235
263
  # otherwise → plain
236
264
  # psych's literal/folded/binary forms and its !!str tag for
237
265
  # "<<" are follow-ups; those strings double-quote today.
238
- STYLE_BY_NAME = { plain: STYLE_PLAIN, single: STYLE_SQ, double: STYLE_DQ }.freeze
266
+ STYLE_BY_NAME = { plain: STYLE_PLAIN, single: STYLE_SQ, double: STYLE_DQ,
267
+ literal: STYLE_LIT }.freeze
239
268
 
240
269
  def string_style(s)
270
+ # psych's visit_String: any interior newline rides a literal
271
+ # block (the C writer's libyaml indicator rules render it) —
272
+ # first, exactly as psych orders it (#290 family 4)
273
+ return :literal if s.match?(/\n(?!\z)/)
241
274
  return :double if s == "y" || s == "Y" || s == "n" || s == "N"
242
275
  return :double if !s.empty? && !s.include?('"') && s.match?(/\A[^[:word:]]/)
243
276
  return :single if s.match?(/\A0[0-7]*[89]/)
@@ -267,10 +300,12 @@ module Yeptris
267
300
  when Array then build_seq(doc, obj, seen)
268
301
  when String then build_string(doc, obj)
269
302
  when Symbol then new_scalar(doc, ":#{obj}")
270
- when Integer, Float then new_scalar(doc, obj.to_s)
303
+ when Integer then new_scalar(doc, obj.to_s)
304
+ when Float then new_scalar(doc, BulkBuilder.float_text(obj))
271
305
  when true, false then new_scalar(doc, obj.to_s)
272
- when nil then new_scalar(doc, "null")
273
- when Date, Time then new_scalar(doc, obj.iso8601)
306
+ when nil then new_scalar(doc, "")
307
+ when Time then new_scalar(doc, BulkBuilder.time_text(obj))
308
+ when Date then new_scalar(doc, obj.iso8601)
274
309
  else
275
310
  raise DumpError,
276
311
  "cannot dump #{obj.class}: unsupported object " \
@@ -301,6 +336,7 @@ module Yeptris
301
336
  case BulkBuilder.string_style(s)
302
337
  when :single then new_scalar(doc, s, :force_str_sq)
303
338
  when :double then new_scalar(doc, s, :force_str)
339
+ when :literal then new_scalar(doc, s, :force_lit)
304
340
  else new_scalar(doc, s)
305
341
  end
306
342
  end
@@ -313,7 +349,8 @@ module Yeptris
313
349
  def new_scalar(doc, text, mode = nil)
314
350
  doc.new_scalar(text.to_s,
315
351
  mode == :force_str ? :double_quoted :
316
- mode == :force_str_sq ? :single_quoted : :plain)
352
+ mode == :force_str_sq ? :single_quoted :
353
+ mode == :force_lit ? :literal : :plain)
317
354
  end
318
355
 
319
356
  def cycle_guard(obj, seen)
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.0.1".freeze
6
+ VERSION = "0.6.1.2".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
data/libyeptris.so CHANGED
Binary file
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: yeptris
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.0.1
4
+ version: 0.6.1.2
5
5
  platform: aarch64-linux
6
6
  authors:
7
7
  - Ribose Inc.
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2026-09-16 00:00:00.000000000 Z
11
+ date: 2026-09-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ffi