Class: Moxml::StructPlan
- Inherits:
-
Object
- Object
- Moxml::StructPlan
- Defined in:
- lib/moxml/struct_plan.rb
Overview
Struct-compiled materialization — the fully compiled grammar: declare the document shape once as STRUCTS; adapters with a C executor (leptris 1.9.201.1+, the varargs-mint fix) mint the typed with zero Ruby frames per element; everything else falls back to an equivalent Moxml::Plan over the row stream (spec-pinned equal).
plan = Moxml::StructPlan.new do
element "record", Record, attrs: { "id" => :id, "kind" => :kind },
children: :fields
element "field", Field, attrs: { "name" => :name, "unit" => :unit },
text: :value
end
records = plan.parse(xml, ctx) # Array of Record
Slot symbols must be the Struct's member names. Semantics equal Moxml::Plan: unmatched elements are barriers — their matched descendants surface at top level.
Defined Under Namespace
Classes: Element
Constant Summary collapse
- TYPE_TAGS =
The compiled spec the C executor consumes: => [klass, attrs, text slot, children slot]. Slots resolve to member INDICES once — the C executor's Integer key path then writes by index, skipping the per-write member name scan.
{ integer: 1, float: 2, boolean: 3 }.freeze
Instance Method Summary collapse
- #compile ⇒ Object
-
#compile_slot(slot, members, typed) ⇒ Object
Resolve a slot to the executor's wire form: the member index (or the raw symbol for unknown slots), wrapped as [slot, tag] when a type is declared and the binding's executor is typed.
-
#element(name, klass, attrs: {}, text: nil, children: nil) ⇒ Object
Registers a struct element.
-
#initialize(&block) ⇒ StructPlan
constructor
A new instance of StructPlan.
- #materialize(node) ⇒ Object
- #parse(xml, context) ⇒ Object
Constructor Details
#initialize(&block) ⇒ StructPlan
Returns a new instance of StructPlan.
25 26 27 28 |
# File 'lib/moxml/struct_plan.rb', line 25 def initialize(&block) @elements = {} instance_eval(&block) if block end |
Instance Method Details
#compile ⇒ Object
53 54 55 56 57 58 59 60 61 62 63 64 65 66 |
# File 'lib/moxml/struct_plan.rb', line 53 def compile typed = Moxml::Adapter::Leptris::NATIVE_PLAN_TYPED @elements.each_with_object({}) do |(name, el), spec| members = el.klass.members spec[name] = [ el.klass, el.attrs.each_with_object({}) do |(a, slot), h| h[a] = compile_slot(slot, members, typed) end, compile_slot(el.text, members, typed), members.index(el.children) || el.children, ] end end |
#compile_slot(slot, members, typed) ⇒ Object
Resolve a slot to the executor's wire form: the member index (or the raw symbol for unknown slots), wrapped as [slot, tag] when a type is declared and the binding's executor is typed. Without the face, types degrade to strings.
73 74 75 76 77 78 79 80 81 82 |
# File 'lib/moxml/struct_plan.rb', line 73 def compile_slot(slot, members, typed) if slot.is_a?(Array) inner, type = slot tag = TYPE_TAGS[type] || 0 resolved = members.index(inner) || inner return typed && tag != 0 ? [resolved, tag] : resolved end members.index(slot) || slot end |
#element(name, klass, attrs: {}, text: nil, children: nil) ⇒ Object
Registers a struct element. attrs maps attribute names to
member slots; text and children name the member slots
receiving the first text child and the matched children array.
Returns self so registrations chain.
Typed scalars (binding with the typed executor — probe Moxml::Adapter::Leptris::NATIVE_PLAN_TYPED): slot values may be [slot, type] pairs — type one of :integer, :float, :boolean (attrs and text). The executor casts in C with no Ruby String materialized; unparseable input degrades to the raw String (lenient). :boolean accepts t/1/y/Y as true.
41 42 43 44 |
# File 'lib/moxml/struct_plan.rb', line 41 def element(name, klass, attrs: {}, text: nil, children: nil) @elements[name] = Element.new(klass, attrs, text, children) self end |
#materialize(node) ⇒ Object
88 89 90 91 92 93 94 |
# File 'lib/moxml/struct_plan.rb', line 88 def materialize(node) adapter = node.context.config.adapter roots = adapter.plan_structs(node.native, compile) return roots if roots plan.materialize(node) end |
#parse(xml, context) ⇒ Object
84 85 86 |
# File 'lib/moxml/struct_plan.rb', line 84 def parse(xml, context) materialize(context.parse(xml)) end |