pub struct ModelAdapter<A: AstAdapter> { /* private fields */ }Expand description
A base arbor enriched with a model’s derived structure.
Implementations§
Source§impl<A: AstAdapter> ModelAdapter<A>
impl<A: AstAdapter> ModelAdapter<A>
pub fn new(base: A, model: Model) -> Self
Sourcepub fn check(&self) -> Result<(), String>
pub fn check(&self) -> Result<(), String>
Everything a model can get wrong that only the source can tell: call after construction, before the first query.
Sourcepub fn check_trees(&self) -> Result<(), String>
pub fn check_trees(&self) -> Result<(), String>
Refuse a tree whose path names no node.
Sourcepub fn check_ref_targets(&self) -> Result<(), String>
pub fn check_ref_targets(&self) -> Result<(), String>
Refuse a ref whose target names nothing: neither a
container a node statement declares nor a root-level node
of the source (a table, a mount, a top-level key). A typo in
the target would otherwise resolve nothing, silently. The
derived containers are not materialized for the check: their
names are in the declarations.
Sourcepub fn check_declared_traits(&self) -> Result<(), String>
pub fn check_declared_traits(&self) -> Result<(), String>
Refuse a declared trait that redefines one the arbor already
has: a trait the adapter puts on any node, or the trait a
node constructor gives a derived container’s members. The
check walks the base arbor once per declaration; call it
after construction, before the first query.
pub fn base(&self) -> &A
Trait Implementations§
Source§impl<A: AstAdapter> AstAdapter for ModelAdapter<A>
impl<A: AstAdapter> AstAdapter for ModelAdapter<A>
Source§fn child_host(&self, node: NodeId) -> NodeId
fn child_host(&self, node: NodeId) -> NodeId
A base node’s transparent links stay transparent; the model’s own nodes host their own children.
Source§fn can_refer_to(&self, source: NodeId, target: NodeId) -> Option<bool>
fn can_refer_to(&self, source: NodeId, target: NodeId) -> Option<bool>
A ref declared over the source whose target is the
container the target node stands in (a derived container, or
a container of the source it sits under); else the base’s
own declarations.
Source§fn reference_properties(&self, source: NodeId, target: NodeId) -> Vec<String>
fn reference_properties(&self, source: NodeId, target: NodeId) -> Vec<String>
The fields of the refs declared over the source into the
target’s container; else the base’s own declarations.
Source§fn reverse_label(&self, target: NodeId) -> Option<String>
fn reverse_label(&self, target: NodeId) -> Option<String>
A base node’s label is the base’s to give; a derived node needs none (the model’s refs resolve without labels).
Source§fn tree_identities(&self) -> Vec<(String, NodeId)>
fn tree_identities(&self) -> Vec<(String, NodeId)>
The declared trees first (a declaration names the same node as the mount’s own target would, and wins), then the base’s own identities.
Source§fn resolve_needs_label(&self, node: NodeId, property: &str) -> bool
fn resolve_needs_label(&self, node: NodeId, property: &str) -> bool
A property the model declares a ref for resolves by that
declaration; any other asks the base.
Source§fn aliased_metadata(&self, node: NodeId) -> &'static [&'static str]
fn aliased_metadata(&self, node: NodeId) -> &'static [&'static str]
Model nodes add their own annotations (n-rows); base nodes
keep the mounted adapter’s, aliases included. A model node’s
id means nothing to the base, so it is never passed down
(a mount would read a mount index out of it).
Source§fn provenance(&self, node: NodeId) -> Provenance
fn provenance(&self, node: NodeId) -> Provenance
Data provenance. An aliased node is its base node under a
role, so it answers that node’s provenance. An elevated node
is a new value the model made: it answers a derivation source
only (model:/container), never the components of any row it
was computed from — the same no-leak discipline property
applies to elevated values.
Source§fn answers_to(&self, node: NodeId, name: &str) -> bool
fn answers_to(&self, node: NodeId, name: &str) -> bool
A written name reaches a node under its canonical name or
any alias the model declares for names.
Source§fn has_trait(&self, node: NodeId, name: &str) -> bool
fn has_trait(&self, node: NodeId, name: &str) -> bool
A written trait reaches a node under a canonical trait or any
alias <...> the model declares.
Source§fn document_by_ref(&self, id: &str) -> Option<NodeId>
fn document_by_ref(&self, id: &str) -> Option<NodeId>
The document the base holds under a URL — base ids pass straight through this layer.
Source§fn reverse_resolve(
&self,
node: NodeId,
property: Option<&str>,
hint: Option<&str>,
) -> Option<Vec<NodeId>>
fn reverse_resolve( &self, node: NodeId, property: Option<&str>, hint: Option<&str>, ) -> Option<Vec<NodeId>>
The base’s reverse index answers only when the model adds no reference fabric of its own; otherwise the walk sees both.
Source§fn descendants_named(
&self,
node: NodeId,
name: &str,
) -> Option<Vec<(NodeId, usize)>>
fn descendants_named( &self, node: NodeId, name: &str, ) -> Option<Vec<(NodeId, usize)>>
The base’s name index answers below any base node but the root (the model’s containers hang there) and only when no name alias could widen the match.
Source§fn link_property(
&self,
source: NodeId,
label: &str,
target: NodeId,
name: &str,
) -> Option<Value>
fn link_property( &self, source: NodeId, label: &str, target: NodeId, name: &str, ) -> Option<Value>
An edge’s own properties are the base’s: a model adds links (refs, relations) that carry none, and a node standing for a base one reads through to it.
Source§fn unit_scale(&self, expr: &str) -> Option<(f64, String)>
fn unit_scale(&self, expr: &str) -> Option<(f64, String)>
The imported libraries first (units LIBRARY;), then the
source’s own.
Source§fn children(&self, node: NodeId) -> Vec<NodeId>
fn children(&self, node: NodeId) -> Vec<NodeId>
node, in document order. Read moreSource§fn non_tree_nodes(&self) -> Vec<NodeId>
fn non_tree_nodes(&self) -> Vec<NodeId>
*// reaches them after the tree, in this
order; :::is-non-tree is true on them. The default is
none: every shipped adapter puts every node in the tree.Source§fn walks_for_references(&self) -> bool
fn walks_for_references(&self) -> bool
ref) answers through reverse_resolve
and needs no walk.Source§fn resolves_references(&self) -> bool
fn resolves_references(&self) -> bool
Source§fn property_names(&self, node: NodeId) -> Vec<String>
fn property_names(&self, node: NodeId) -> Vec<String>
<--(SCOPE::*). By default its off-tree
properties, its reference property, and its children’s names
(a row’s columns, an object’s keys are properties under the
same names); an adapter whose properties are not children
(an element’s attributes) lists them.Source§fn index_lookup(
&self,
scope: &str,
property: &str,
value: &Value,
) -> Option<Vec<NodeId>>
fn index_lookup( &self, scope: &str, property: &str, value: &Value, ) -> Option<Vec<NodeId>>
index SCOPE::prop; — the nodes of the declared scope whose
property holds value, from an index the model keeps; None
when no declaration covers the pair (the walk answers). An
index changes cost, never the answer: the caller still tests
each node it names.Source§fn index_referrers(
&self,
scope: &str,
property: &str,
label: Option<&str>,
target: NodeId,
) -> Option<Vec<NodeId>>
fn index_referrers( &self, scope: &str, property: &str, label: Option<&str>, target: NodeId, ) -> Option<Vec<NodeId>>
property resolves (under the
relation label, when given) to target, from the same index;
None when no declaration covers the pair.Source§fn properties(&self, node: NodeId) -> Vec<(String, Value)>
fn properties(&self, node: NodeId) -> Vec<(String, Value)>
| json, | xml,
| kaiv) merge them with the children, a child winning a
shared name. The default is none: for a reading whose values
are all nodes, the children already say everything.Source§fn children_named(&self, node: NodeId, name: &str) -> Vec<NodeId>
fn children_named(&self, node: NodeId, name: &str) -> Vec<NodeId>
node whose edge name is exactly name —
the engine’s fast path for name-matcher child hops. The
default filters children; an adapter
whose containers cannot be enumerated (permission-scoped or
unbounded remote trees) overrides this with a direct,
name-addressed lookup. Must be observationally identical to
the default wherever enumeration works. The adapter owns the
name test: it may deliberately alias — resolve a name to a
node whose edge name differs (git revision syntax landing on
a hash-named commit) — and the engine will not re-filter.
Container-scoped resolution like that stays child-axis only;
per-node spelling aliases belong in
answers_to, which this default
consults.Source§fn name(&self, node: NodeId) -> Option<String>
fn name(&self, node: NodeId) -> Option<String>
node — the label of its incoming tree edge. Read moreSource§fn traits(&self, node: NodeId) -> Vec<String>
fn traits(&self, node: NodeId) -> Vec<String>
node — its adapter-defined classifications,
used by <trait> navigation filters (e.g. a filesystem
adapter’s <dir>, <code>, <image>).Source§fn property(&self, node: NodeId, name: &str) -> Option<Value>
fn property(&self, node: NodeId, name: &str) -> Option<Value>
node — ::prop. None if absent.Source§fn default_value(&self, node: NodeId) -> Option<Value>
fn default_value(&self, node: NodeId) -> Option<Value>
node — bare ::, adapter-specific
(a filesystem adapter returns file content).Source§fn metadata(&self, node: NodeId, key: &str) -> Option<Value>
fn metadata(&self, node: NodeId, key: &str) -> Option<Value>
::::key (a filesystem adapter’s
size, modified, permissions, …). None if absent.Source§fn provenance_list(&self, node: NodeId) -> ProvenanceList
fn provenance_list(&self, node: NodeId) -> ProvenanceList
node as a list — every source the
substrate records for the datum, and how many it elides.
The default is the singular answer as a one-entry list; an
adapter whose substrate records several (kaiv’s ?a;b;+N)
overrides it, and a wrapper layers each entry.Source§fn resolve(
&self,
node: NodeId,
property: &str,
hint: Option<&str>,
) -> Option<NodeId>
fn resolve( &self, node: NodeId, property: &str, hint: Option<&str>, ) -> Option<NodeId>
::property-->hint maps node’s
property (a value that references another node) to its target,
with an optional adapter-specific hint (a relation type such as
an html rel, or a target container such as a table). A JSON
adapter resolves a $ref JSON Pointer; None if unresolvable.Source§fn external_ref(
&self,
node: NodeId,
property: &str,
hint: Option<&str>,
) -> Option<ExternalRef>
fn external_ref( &self, node: NodeId, property: &str, hint: Option<&str>, ) -> Option<ExternalRef>
node’s property holds, if any: the
identity of a document outside this arbor and, where the
reference says so, the location within it — both as the
adapter reads them out of its own reference syntax (for html,
the anchor’s absolute URL and its fragment). The engine does
not look inside either string: it asks for the document among
the mounts (the host’s registration, then
document_by_ref), and hands the
location to resolve_fragment on
the document it found. Consulted by ::property--> when
in-document resolution misses; an unmounted document lands
among the run’s unresolved external references for the
host’s acquisition loop. The engine itself never fetches.Source§fn resolve_fragment(&self, node: NodeId, fragment: &str) -> Option<NodeId>
fn resolve_fragment(&self, node: NodeId, fragment: &str) -> Option<NodeId>
fragment names inside the document node
belongs to — html’s id lookup. The landing rung of a
fragment-carrying external reference, once its document is
mounted.Source§fn ref_property(&self, node: NodeId) -> Option<String>
fn ref_property(&self, node: NodeId) -> Option<String>
node’s own reference, for the bare
arrow (//a-->): an html anchor’s href, an iframe’s
src. None for a node that references nothing.Source§fn ref_label(&self, node: NodeId, property: &str) -> Option<String>
fn ref_label(&self, node: NodeId, property: &str) -> Option<String>
node via
property carries — html’s rel attribute. None falls
back to the property name as the edge label.Source§fn links(&self, node: NodeId) -> Vec<(String, NodeId)>
fn links(&self, node: NodeId) -> Vec<(String, NodeId)>
node, as (label, target) pairs,
for -> navigation (a filesystem adapter’s symlinks).Source§fn backlinks(&self, node: NodeId) -> Vec<(String, NodeId)>
fn backlinks(&self, node: NodeId) -> Vec<(String, NodeId)>
node, as (label, source) pairs, for
<- navigation. May be expensive (an adapter that does not
precompute edges must search for referrers).Source§fn descendants_where(
&self,
node: NodeId,
name: &str,
property: &str,
value: &Value,
) -> Option<Vec<(NodeId, usize)>>
fn descendants_where( &self, node: NodeId, name: &str, property: &str, value: &Value, ) -> Option<Vec<(NodeId, usize)>>
node named name whose property
property equals value, each with its depth, in document
order — the fast path behind //name[::property = "value"]
for an adapter that indexes a property (the corpus reading’s
positional index answers //token[::lower = "tom"] from it).
None keeps the engine’s walk and its comparison; Some
must be exactly what the walk would find under the standard
equality, so an adapter answers only the values it can
compare as the engine does (text against text).Source§fn select_plan(&self, scope: &[&str], plan: &StepPlan<'_>) -> Option<Vec<bool>>
fn select_plan(&self, scope: &[&str], plan: &StepPlan<'_>) -> Option<Vec<bool>>
select: which of the
plan’s conjuncts the adapter would apply, decided from its
catalog alone (a column’s existence and type, an index’s
presence), with no node in hand. scope is the literal path
from the root to the step’s base (["invoices"] for
/invoices/*[...]), empty at the root. None when the
adapter cannot say — the static plan then counts every
conjunct as the engine’s.Source§fn estimate(&self, scope: &[&str], plan: &StepPlan<'_>) -> Option<Estimate>
fn estimate(&self, scope: &[&str], plan: &StepPlan<'_>) -> Option<Estimate>
scope as for
select_plan): a warehouse’s dry run,
a table’s statistics, a file’s size, an arena’s count.
None where the adapter has no estimator — the plan then
reads “unknown” for the step.Source§fn select(&self, from: NodeId, plan: &StepPlan<'_>) -> Option<Selection>
fn select(&self, from: NodeId, plan: &StepPlan<'_>) -> Option<Selection>
from
under plan, answered from an index — None keeps the
engine’s walk (the default folds children_named,
descendants_named and descendants_where:
select_by_hooks). Some must be exactly what the walk
would find for the conjuncts it marks applied, under the
engine’s standard equality; the engine tests the remaining
conjuncts and every other predicate on the nodes returned. A
child plan’s answer is never re-filtered by name (the adapter
owns the name test, as children_named does); a descendant
plan’s nodes still pass the nameless tests.Source§fn has_node(&self, node: NodeId) -> bool
fn has_node(&self, node: NodeId) -> bool
node is an id this adapter minted — the guard
behind the node-id anchor ((!N)), which may name an id
from an earlier run (ids are minted deterministically: the
same source, the same ids). The default probes the id
through parent and name and treats a panic as absence,
so an adapter that indexes by id needs no override; one that
can answer cheaply should.Source§fn prefetch_links(&self, nodes: &[NodeId], dir: LinkDir)
fn prefetch_links(&self, nodes: &[NodeId], dir: LinkDir)
dir
crosslinks from every node in nodes. An adapter backed by
a store may fetch them in one statement; semantics are
unchanged either way.Source§fn quantifier_bound(&self) -> usize
fn quantifier_bound(&self) -> usize
+, *, {m,}) expand, and the ceiling of any
explicit {m,n} (the effective upper bound is min(n, N_max)).
An adapter whose natural structures run deep may raise it; a
run may override it (Run::quantifier_bound, the CLI’s
--quantifier-bound). The shell gate and the invocation
instant are the run’s alone (Run::allow_shell, Run::now).Source§fn count(&self, _from: NodeId, _plan: &StepPlan<'_>) -> Option<usize>
fn count(&self, _from: NodeId, _plan: &StepPlan<'_>) -> Option<usize>
from under plan,
without materializing them — @| count right after the step
asks before walking. None walks; Some must be exactly the
walk’s count for the conjuncts the plan carries (every one of
them, or none: a count cannot be partially applied). SQL:
SELECT COUNT(*); a document index: the bucket’s length.Source§fn prefetch_properties(&self, _nodes: &[NodeId], _names: &[&str])
fn prefetch_properties(&self, _nodes: &[NodeId], _names: &[&str])
prefetch_links: the
engine is about to read the properties names of every node
in nodes (the next command projects them). A remote adapter
fetches the columns for the frontier in one round trip;
semantics are unchanged either way.