Class: Moxml::StructPlan

Inherits:
Object
  • Object
show all
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

Instance Method Summary collapse

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

#compileObject

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.



44
45
46
47
48
49
50
51
52
53
54
# File 'lib/moxml/struct_plan.rb', line 44

def compile
  @elements.each_with_object({}) do |(name, el), spec|
    members = el.klass.members
    spec[name] = [
      el.klass,
      el.attrs.each_with_object({}) { |(a, slot), h| h[a] = members.index(slot) || slot },
      members.index(el.text) || el.text,
      members.index(el.children) || el.children,
    ]
  end
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.



34
35
36
37
# File 'lib/moxml/struct_plan.rb', line 34

def element(name, klass, attrs: {}, text: nil, children: nil)
  @elements[name] = Element.new(klass, attrs, text, children)
  self
end

#materialize(node) ⇒ Object



60
61
62
63
64
65
66
# File 'lib/moxml/struct_plan.rb', line 60

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



56
57
58
# File 'lib/moxml/struct_plan.rb', line 56

def parse(xml, context)
  materialize(context.parse(xml))
end