lutaml-model 0.8.66 → 0.8.68
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/lutaml/key_value/mapping_rule.rb +7 -0
- data/lib/lutaml/key_value/transform.rb +9 -5
- data/lib/lutaml/model/attribute.rb +33 -11
- data/lib/lutaml/model/version.rb +1 -1
- data/lib/lutaml/xml/plan_hydrator.rb +23 -10
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: '08259545535ddbd9c57aad9adfcb1fa66ebf9179fe00cbfa6be408285d1cdca5'
|
|
4
|
+
data.tar.gz: 84c75404c371bb433b18d9cc87fab24b252b15fe8c2555544fc7b12478ff37c6
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 2b730dcc7e7f555270929f4a42eb9b7a2f7e2d26a4a73fb1c75cbaa6415d2d54c0c5674ba2fad1bdba1cda106c3f625f19eed4db5d58d59334c79311c5dc46ad
|
|
7
|
+
data.tar.gz: 4a8fa22b33898a088d8ba3e9a2b00c8bed316f73a0d0e2dcca776aa290f484bf9519952c7e2076161779faaff4aa5d16fb3be52b10e963366369bf663d75d6f4
|
|
@@ -83,6 +83,13 @@ module Lutaml
|
|
|
83
83
|
def root_mapping?
|
|
84
84
|
name == "root_mapping"
|
|
85
85
|
end
|
|
86
|
+
|
|
87
|
+
# The writer symbol for this rule's target, interned once per
|
|
88
|
+
# rule: the interpolation allocated a String and interned it per
|
|
89
|
+
# row per document in the transform's hot loop.
|
|
90
|
+
def kv_setter
|
|
91
|
+
@kv_setter ||= :"#{to}="
|
|
92
|
+
end
|
|
86
93
|
end
|
|
87
94
|
end
|
|
88
95
|
end
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
module Lutaml
|
|
2
2
|
module KeyValue
|
|
3
|
+
MISSING = Object.new.freeze
|
|
3
4
|
class Transform < Lutaml::Model::Transform
|
|
4
5
|
def data_to_model(data, format, options = {})
|
|
5
6
|
# Use child's own default register if it has one
|
|
@@ -208,14 +209,17 @@ module Lutaml
|
|
|
208
209
|
children = []
|
|
209
210
|
absent = []
|
|
210
211
|
rows.each do |rule, attr, kind, type, child_rows|
|
|
211
|
-
|
|
212
|
+
# One hash pass per row: fetch with a sentinel distinguishes
|
|
213
|
+
# absent keys from present-nil values (both read as nil), so
|
|
214
|
+
# the separate string_or_symbol_key? probe goes away.
|
|
215
|
+
v = Lutaml::Model::Utils.fetch_str_or_sym(doc, rule.name, MISSING)
|
|
216
|
+
if v.equal?(MISSING)
|
|
212
217
|
absent << rule
|
|
213
218
|
next
|
|
214
219
|
end
|
|
215
|
-
v = Lutaml::Model::Utils.fetch_str_or_sym(doc, rule.name)
|
|
216
220
|
|
|
217
221
|
if kind == :scalar
|
|
218
|
-
setters << [
|
|
222
|
+
setters << [rule.kv_setter, v]
|
|
219
223
|
next
|
|
220
224
|
end
|
|
221
225
|
|
|
@@ -239,7 +243,7 @@ module Lutaml
|
|
|
239
243
|
|
|
240
244
|
built << child
|
|
241
245
|
end
|
|
242
|
-
setters << [
|
|
246
|
+
setters << [rule.kv_setter, built]
|
|
243
247
|
children.concat(built)
|
|
244
248
|
else
|
|
245
249
|
return nil unless v.is_a?(::Hash)
|
|
@@ -249,7 +253,7 @@ module Lutaml
|
|
|
249
253
|
options)
|
|
250
254
|
return nil if child.nil?
|
|
251
255
|
|
|
252
|
-
setters << [
|
|
256
|
+
setters << [rule.kv_setter, child]
|
|
253
257
|
children << child
|
|
254
258
|
end
|
|
255
259
|
end
|
|
@@ -316,6 +316,16 @@ module Lutaml
|
|
|
316
316
|
@unresolved_type || @type
|
|
317
317
|
end
|
|
318
318
|
|
|
319
|
+
def reference_type?
|
|
320
|
+
(@reference_type ||= unresolved_type == Lutaml::Model::Type::Reference)
|
|
321
|
+
end
|
|
322
|
+
|
|
323
|
+
def value_map_boolean?
|
|
324
|
+
(@value_map_boolean ||=
|
|
325
|
+
type == Lutaml::Model::Type::Boolean ||
|
|
326
|
+
unresolved_type == Lutaml::Model::Type::Boolean)
|
|
327
|
+
end
|
|
328
|
+
|
|
319
329
|
def polymorphic?
|
|
320
330
|
@options[:polymorphic_class]
|
|
321
331
|
end
|
|
@@ -438,8 +448,7 @@ module Lutaml
|
|
|
438
448
|
|
|
439
449
|
option = value_map[key]
|
|
440
450
|
if (option.is_a?(TrueClass) || option.is_a?(FalseClass)) &&
|
|
441
|
-
|
|
442
|
-
unresolved_type == Lutaml::Model::Type::Boolean)
|
|
451
|
+
value_map_boolean?
|
|
443
452
|
return option
|
|
444
453
|
end
|
|
445
454
|
|
|
@@ -507,7 +516,8 @@ module Lutaml
|
|
|
507
516
|
return resolved_type.new(value) if value.is_a?(::Hash) && !hash_type?
|
|
508
517
|
|
|
509
518
|
# Special handling for Reference types - pass the metadata
|
|
510
|
-
|
|
519
|
+
# (the comparison is attribute-constant; memoize the verdict)
|
|
520
|
+
if reference_type?
|
|
511
521
|
return resolved_type.cast_with_metadata(value,
|
|
512
522
|
@options[:ref_model_class], @options[:ref_key_attribute])
|
|
513
523
|
end
|
|
@@ -566,10 +576,15 @@ instance_object = nil)
|
|
|
566
576
|
end
|
|
567
577
|
|
|
568
578
|
def default_value(register, instance_object = nil)
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
579
|
+
# The kind is fixed at definition; the common case (no default
|
|
580
|
+
# at all) paid three option checks per absent attribute per
|
|
581
|
+
# instantiation before the memo.
|
|
582
|
+
case (@default_kind ||= _default_kind)
|
|
583
|
+
when :none
|
|
584
|
+
Lutaml::Model::UninitializedClass.instance
|
|
585
|
+
when :static
|
|
586
|
+
options[:default]
|
|
587
|
+
when :proc
|
|
573
588
|
if instance_object
|
|
574
589
|
::Lutaml::Model::Attribute.evaluating_default do
|
|
575
590
|
instance_object.instance_exec(&options[:default])
|
|
@@ -577,13 +592,20 @@ instance_object = nil)
|
|
|
577
592
|
else
|
|
578
593
|
options[:default].call
|
|
579
594
|
end
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
Lutaml::Model::UninitializedClass.instance
|
|
595
|
+
else # :delegate
|
|
596
|
+
type(register).attributes(register)[to].default(register,
|
|
597
|
+
instance_object)
|
|
584
598
|
end
|
|
585
599
|
end
|
|
586
600
|
|
|
601
|
+
def _default_kind
|
|
602
|
+
return :delegate if delegate
|
|
603
|
+
return :proc if options[:default].is_a?(Proc)
|
|
604
|
+
return :static if options.key?(:default)
|
|
605
|
+
|
|
606
|
+
:none
|
|
607
|
+
end
|
|
608
|
+
|
|
587
609
|
# Marks the dynamic extent in which a default proc runs against a
|
|
588
610
|
# model instance, so Serialize#method_missing can fall back to the
|
|
589
611
|
# model class for methods the instance does not define (0.7.x
|
data/lib/lutaml/model/version.rb
CHANGED
|
@@ -66,14 +66,14 @@ module Lutaml
|
|
|
66
66
|
def attributes_kwargs(plan, value, node = nil)
|
|
67
67
|
kwargs = {}
|
|
68
68
|
sole_claimants = sole_claimant_names(plan)
|
|
69
|
-
plan
|
|
70
|
-
v = value.attribute(
|
|
71
|
-
if v.nil? && node && sole_claimants.include?(
|
|
69
|
+
plan_attr_rows(plan).each do |rule, attr, name|
|
|
70
|
+
v = value.attribute(name)
|
|
71
|
+
if v.nil? && node && sole_claimants.include?(name)
|
|
72
72
|
# #754/#790 parity: a sole-claimant attribute rule binds
|
|
73
73
|
# any qualification (the interpretive matcher's lenient
|
|
74
74
|
# recovery). The walk captures exact (URI, local) matches
|
|
75
75
|
# only, so the qualified spelling is read off the node.
|
|
76
|
-
v = lenient_node_attribute(node,
|
|
76
|
+
v = lenient_node_attribute(node, name)
|
|
77
77
|
end
|
|
78
78
|
next if v.nil?
|
|
79
79
|
|
|
@@ -86,6 +86,15 @@ module Lutaml
|
|
|
86
86
|
kwargs
|
|
87
87
|
end
|
|
88
88
|
|
|
89
|
+
# Wire-name strings are plan-frozen; materializing them per
|
|
90
|
+
# hydration allocated two or three strings per attribute row
|
|
91
|
+
# per instance.
|
|
92
|
+
def plan_attr_rows(plan)
|
|
93
|
+
plan[:attr_row_names] ||= plan[:attr_rows].map do |rule, attr|
|
|
94
|
+
[rule, attr, rule.name.to_s]
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
|
|
89
98
|
# Returns [kwargs, hydrated_child_instances, delegate_values]
|
|
90
99
|
# — child instances come back so the caller can decorate
|
|
91
100
|
# parent/root links once the parent exists; delegate values
|
|
@@ -364,10 +373,11 @@ module Lutaml
|
|
|
364
373
|
# names eligible for #754/#790 lenient binding (multi-claimant
|
|
365
374
|
# names stay exact; per #841 leniency is sole-claimant-only).
|
|
366
375
|
def sole_claimant_names(plan)
|
|
367
|
-
plan
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
.
|
|
376
|
+
# Frozen with the plan: recomputing the tally per hydration
|
|
377
|
+
# showed in the #876-era profile as Enumerable#find/tally churn.
|
|
378
|
+
plan[:sole_claimants] ||= plan[:attr_rows]
|
|
379
|
+
.map { |rule, _attr| rule.name.to_s }.tally
|
|
380
|
+
.select { |_n, c| c == 1 }.keys
|
|
371
381
|
end
|
|
372
382
|
|
|
373
383
|
# Local-name attribute lookup on the source node, qualified
|
|
@@ -391,9 +401,12 @@ module Lutaml
|
|
|
391
401
|
want_tags = !row_tags.nil?
|
|
392
402
|
value.count.times do |i|
|
|
393
403
|
child = value.at(i)
|
|
394
|
-
|
|
404
|
+
# One FFI crossing per child: the name was read twice here
|
|
405
|
+
# (nil check + bucket key), doubling the hottest accessor.
|
|
406
|
+
name = child.name
|
|
407
|
+
next if name.nil? # content runs, read separately
|
|
395
408
|
|
|
396
|
-
(grouped[
|
|
409
|
+
(grouped[name] ||= []) << child
|
|
397
410
|
if want_tags && child.type_tag != 0
|
|
398
411
|
(tagged[child.type_tag] ||= []) << child
|
|
399
412
|
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: lutaml-model
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.8.
|
|
4
|
+
version: 0.8.68
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Ribose Inc.
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-09-
|
|
11
|
+
date: 2026-09-27 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: base64
|