yeptris 0.4.0.1-aarch64-linux → 0.5.1.1-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: b0564531041910fb120994e2f4cac8c9f3ddf0b176bf5ae9ca3289cb58f6ac87
4
- data.tar.gz: 4b6da94d1b0706fdfdd597bc173ca9556e26482a517b391670ef2bb1471f17df
3
+ metadata.gz: c4a44a9db7ff23a982534d2f3f18bc5e829c3e824acd80c774f5b0c73674ffc3
4
+ data.tar.gz: '00944fc916a5ddb777810ddcb57113038778443d2b975cb2689b4d92bbb64e13'
5
5
  SHA512:
6
- metadata.gz: 47c6f2bfe6920039b2e2e0a69f84688cac61bd11e61df76d1f9ec39ccfad227ff5a831b0b7bdbc644829c8dd364bd4b112b7b54183758dee182f66f325371350
7
- data.tar.gz: 1e7e5b9bbe7b38b3db23b7c16bf03f3981178f6e52f2db99e091a5560c21c2a98a50823b9598bbeb4d93bb14302c34a3f1e5e2fe97eb0de5c3b8c6ac873cc36f
6
+ metadata.gz: faa61207b3f1c19a78e5fe61cab47acef7d59c160298520f963ccbfb426187fd3a6b7a2cb7312d4fc5af51f8724e06491a3e76d78f1140b44b99dc0733a4a7e0
7
+ data.tar.gz: da1187d0c569cb4193a8b0edd5b33356dcdec32b4772f77669a1513824412a17f6a95f40fcca49470ea74ab89ee8cf2c5b5f904b3619a49905872ad83e57c65c
@@ -137,15 +137,16 @@ class Yeptris::Document
137
137
  Yeptris::FFI.yeptris_document_build(@c_ptr, entries, count, blob, blob_len)
138
138
  end
139
139
 
140
- def serialize(canonical: false, best_width: 0)
140
+ def serialize(canonical: false, best_width: 0, explicit_doc_start: false)
141
141
  ensure_alive!
142
142
  len = ::FFI::MemoryPointer.new(:uint64)
143
143
  ptr =
144
- if canonical || best_width.positive?
144
+ if canonical || best_width.positive? || explicit_doc_start
145
145
  opts = Yeptris::FFI::EmitOptions.new
146
146
  opts[:size] = Yeptris::FFI::EmitOptions.size
147
147
  opts[:canonical] = canonical ? 1 : 0
148
148
  opts[:best_width] = best_width
149
+ opts[:explicit_doc_start] = explicit_doc_start ? 1 : 0
149
150
  Yeptris::FFI.yeptris_serialize_ex(@c_ptr, opts, len)
150
151
  else
151
152
  Yeptris::FFI.yeptris_serialize(@c_ptr, len)
data/lib/yeptris/ffi.rb CHANGED
@@ -47,7 +47,8 @@ module Yeptris
47
47
  class EmitOptions < ::FFI::Struct
48
48
  layout :size, :uint32,
49
49
  :canonical, :int,
50
- :best_width, :int
50
+ :best_width, :int,
51
+ :explicit_doc_start, :int
51
52
  end
52
53
 
53
54
  attach_function :yeptris_version, [], :string
@@ -28,13 +28,13 @@ module Yeptris
28
28
  end
29
29
 
30
30
  def finish
31
- @tree.serialize
31
+ @tree.serialize(explicit_doc_start: true)
32
32
  end
33
33
 
34
34
  def visit(obj)
35
35
  case obj
36
36
  when nil, true, false, ::Integer, ::Float, ::String then scalar(obj)
37
- when ::Symbol then scalar(":#{obj}")
37
+ when ::Symbol then @tree.new_scalar(":#{obj}", :plain) # psych emits symbols bare, never through visit_String's quoting rules
38
38
  when ::Date, ::Time then scalar(obj) # timestamp text, never ivars
39
39
  when ::Hash then visit_hash(obj)
40
40
  when ::Array then visit_array(obj)
data/lib/yeptris/psych.rb CHANGED
@@ -138,7 +138,7 @@ module Yeptris
138
138
  out =
139
139
  case obj
140
140
  when nil, true, false, ::String, ::Integer, ::Float, ::Symbol, ::Date, ::Time
141
- Yeptris::YAML.dump(obj)
141
+ Yeptris::YAML.dump(obj, header: true)
142
142
  else
143
143
  Visitors::YAMLTree.new.push(obj).finish
144
144
  end
@@ -366,3 +366,12 @@ end
366
366
  # yeptris/psych/drop_in — process-exclusive by nature, since the
367
367
  # stdlib cannot be prevented from re-opening whatever ::Psych points
368
368
  # at once IT loads.
369
+ # 0.4-contract migration signal (issue #95): this require used to
370
+ # rebind ::Psych. It does not anymore, and re-binding it here would
371
+ # regress #69 (any stdlib psych loaded afterwards would explode with
372
+ # a superclass mismatch), so the old path warns instead of acting.
373
+ if defined?(::Psych) && !::Psych.equal?(Yeptris::Psych)
374
+ warn "yeptris: \"yeptris/psych\" defines the namespace only — it no " \
375
+ "longer rebinds ::Psych. Require \"yeptris/psych/drop_in\" for the " \
376
+ "drop-in rebind, or call Yeptris::Psych explicitly."
377
+ end
data/lib/yeptris/yaml.rb CHANGED
@@ -1,5 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # Self-sufficient (issue #95): the neutral surface is a valid entry
4
+ # point on its own — lutaml-model requires exactly this file.
5
+ require "yeptris"
6
+
3
7
  module Yeptris
4
8
  # The neutral Ruby surface (the Psych-compat namespace arrives with
5
9
  # the recorder-driven Visitors in phase B; this is the yeptris-native
@@ -76,8 +80,8 @@ module Yeptris
76
80
  # (TODO.impl/11 phase 3). Strings are emitted plain only when the
77
81
  # resolver round-trips them as strings — everything else takes a
78
82
  # quoted style, so dump(load(x)) == x for the scalar types.
79
- def dump(obj, canonical: false)
80
- BulkBuilder.dump(obj, canonical: canonical)
83
+ def dump(obj, canonical: false, header: false)
84
+ BulkBuilder.dump(obj, canonical: canonical, header: header)
81
85
  end
82
86
 
83
87
 
@@ -95,6 +99,7 @@ module Yeptris
95
99
  MAP = Yeptris::FFI::BUILD_MAP
96
100
  STOP = Yeptris::FFI::BUILD_END
97
101
  STYLE_PLAIN = 1
102
+ STYLE_SQ = 2
98
103
  STYLE_DQ = 3
99
104
 
100
105
  module_function
@@ -107,7 +112,7 @@ module Yeptris
107
112
  Yeptris::FFI::BUILD_SEQ => SEQ_ENTRY,
108
113
  Yeptris::FFI::BUILD_END => END_ENTRY }.freeze
109
114
 
110
- def dump(obj, canonical: false)
115
+ def dump(obj, canonical: false, header: false)
111
116
  parts = []
112
117
  blob = String.new(encoding: Encoding::BINARY)
113
118
  off = [0]
@@ -122,7 +127,7 @@ module Yeptris
122
127
  bblob = ::FFI::MemoryPointer.from_string(blob)
123
128
  rc = doc.build_entries(buf, parts.length, bblob, blob.bytesize)
124
129
  raise DumpError, "document_build failed: #{rc}" unless rc == FFI::OK
125
- doc.serialize(canonical: canonical)
130
+ doc.serialize(canonical: canonical, explicit_doc_start: header)
126
131
  ensure
127
132
  doc&.free
128
133
  end
@@ -133,7 +138,14 @@ module Yeptris
133
138
  cycle_guard(obj, seen) do
134
139
  emit.call(MAP, 0, 0, 0)
135
140
  obj.each do |k, v|
136
- place(key_text(k), emit, blob, off, seen)
141
+ # Symbol keys emit as bare ":k" plain — the compat
142
+ # reader resolves them back to Symbols; string keys
143
+ # ride the visit_String rules like any other scalar
144
+ if k.is_a?(Symbol)
145
+ scalar(":#{k}", STYLE_PLAIN, emit, blob, off)
146
+ else
147
+ place(k.to_s, emit, blob, off, seen)
148
+ end
137
149
  place(v, emit, blob, off, seen)
138
150
  end
139
151
  emit.call(STOP, 0, 0, 0)
@@ -144,12 +156,12 @@ module Yeptris
144
156
  obj.each { |e| place(e, emit, blob, off, seen) }
145
157
  emit.call(STOP, 0, 0, 0)
146
158
  end
147
- when String then scalar(obj, plain_string?(obj), emit, blob, off)
148
- when Symbol then scalar(":#{obj}", true, emit, blob, off)
149
- when Integer, Float then scalar(obj.to_s, true, emit, blob, off)
150
- when true, false then scalar(obj.to_s, true, emit, blob, off)
151
- when nil then scalar("null", true, emit, blob, off)
152
- when Date, Time then scalar(obj.iso8601, true, emit, blob, off)
159
+ when String then scalar(obj, STYLE_BY_NAME[string_style(obj)], emit, blob, off)
160
+ when Symbol then scalar(":#{obj}", STYLE_PLAIN, emit, blob, off)
161
+ when Integer, Float then scalar(obj.to_s, STYLE_PLAIN, emit, blob, off)
162
+ 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)
153
165
  else
154
166
  raise DumpError,
155
167
  "cannot dump #{obj.class}: unsupported object " \
@@ -157,12 +169,12 @@ module Yeptris
157
169
  end
158
170
  end
159
171
 
160
- def scalar(text, plain, emit, blob, off)
172
+ def scalar(text, style, emit, blob, off)
161
173
  # a BINARY blob absorbs any String bytewise (String#<< on
162
174
  # ASCII-8BIT is compatible with every encoding) — the old
163
175
  # text.b made a throwaway copy of every scalar before the
164
176
  # blob's own copy
165
- emit.call(SCALAR, plain ? STYLE_PLAIN : STYLE_DQ, off[0], text.bytesize)
177
+ emit.call(SCALAR, style, off[0], text.bytesize)
166
178
  blob << text
167
179
  off[0] += text.bytesize
168
180
  end
@@ -200,15 +212,40 @@ module Yeptris
200
212
  return false if s.include?(": ") || s.end_with?(":") || s.include?(" #")
201
213
  return false if RESHAPES_SET[s]
202
214
  # compat's float grammar REQUIRES the dot ("1e3" re-reads as a
203
- # String and may dump plain); ints/sexagesimals still reshape
215
+ # String and may dump plain); ints/sexagesimals still reshape.
216
+ # psych's FLOAT has no trailing [.:] group — "1.2.3" is a
217
+ # String and dumps plain (pinned by spec/yaml_spec.rb)
204
218
  return false if s.match?(/\A[-+]?(0|[1-9][0-9_]*)(:[0-5]?[0-9])+\z/)
205
219
  return false if s.match?(/\A[-+]?(0|[1-9][0-9_]*)\z/)
206
- return false if s.match?(/\A[-+]?[0-9][0-9_]*\.[0-9_]*([eE][-+]?[0-9]+)?([.:][0-9_:.]*)?\z/)
220
+ return false if s.match?(/\A[-+]?[0-9][0-9_]*\.[0-9_]*([eE][-+]?[0-9]+)?\z/)
221
+ return false if s.match?(/\A[-+]?[0-9][0-9_]*(:[0-5]?[0-9])+\.[0-9_]*\z/)
207
222
  return false if s.match?(/\A[-+]?(0x[0-9a-fA-F_]+|0b[01_]+|0o?[0-7_]+)\z/)
208
223
  return false if s.match?(/\A[-+]?\.(inf|Inf|INF)\z|\A\.(nan|NaN|NAN)\z/)
209
224
  !s.match?(/\A\d{4}-\d\d?-\d\d?([Tt ]|$)/)
210
225
  end
211
226
 
227
+ # Psych parity (psych yaml_tree#visit_String) — the quoting
228
+ # decision for a String, in psych's own order:
229
+ # y/Y/n/N (the 1.1 bool words psych double-quotes) → double
230
+ # a leading non-word character, no " anywhere → double
231
+ # a 1.1 bad-octal shape (0[0-7]*[89]) → single
232
+ # re-loads as something other than String (plain_string?
233
+ # rejects the 1.1 number/bool/null/timestamp shapes) → single
234
+ # needs escapes (control bytes, multiline) → double
235
+ # otherwise → plain
236
+ # psych's literal/folded/binary forms and its !!str tag for
237
+ # "<<" are follow-ups; those strings double-quote today.
238
+ STYLE_BY_NAME = { plain: STYLE_PLAIN, single: STYLE_SQ, double: STYLE_DQ }.freeze
239
+
240
+ def string_style(s)
241
+ return :double if s == "y" || s == "Y" || s == "n" || s == "N"
242
+ return :double if !s.empty? && !s.include?('"') && s.match?(/\A[^[:word:]]/)
243
+ return :single if s.match?(/\A0[0-7]*[89]/)
244
+ return :plain if plain_string?(s)
245
+ return :double if s.each_byte.any? { |b| b < 0x20 || b == 0x7f }
246
+ :single
247
+ end
248
+
212
249
  def cycle_guard(obj, seen)
213
250
  id = obj.object_id
214
251
  raise DumpError, "cycle detected: cannot dump recursive #{obj.class}" if seen[id]
@@ -257,12 +294,15 @@ module Yeptris
257
294
  end
258
295
  end
259
296
 
260
- # A plain scalar that re-resolves to STR stays plain (nice
261
- # round-trips); anything ambiguous is double-quoted so the
262
- # reparse yields String again.
297
+ # One quoting table (BulkBuilder.string_style psych's
298
+ # visit_String matrix) serves both builders; this side carries
299
+ # the style onto the per-node DOM.
263
300
  def build_string(doc, s)
264
- n = new_scalar(doc, s)
265
- n.tag_id == :str ? n : new_scalar(doc, s, :force_str)
301
+ case BulkBuilder.string_style(s)
302
+ when :single then new_scalar(doc, s, :force_str_sq)
303
+ when :double then new_scalar(doc, s, :force_str)
304
+ else new_scalar(doc, s)
305
+ end
266
306
  end
267
307
 
268
308
  def key_text(k)
@@ -272,7 +312,8 @@ module Yeptris
272
312
 
273
313
  def new_scalar(doc, text, mode = nil)
274
314
  doc.new_scalar(text.to_s,
275
- mode == :force_str ? :double_quoted : :plain)
315
+ mode == :force_str ? :double_quoted :
316
+ mode == :force_str_sq ? :single_quoted : :plain)
276
317
  end
277
318
 
278
319
  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.4.0.1".freeze
6
+ VERSION = "0.5.1.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
data/libyeptris.so CHANGED
Binary file
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: yeptris
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0.1
4
+ version: 0.5.1.1
5
5
  platform: aarch64-linux
6
6
  authors:
7
7
  - Ribose Inc.