pub struct ComponentRule {
pub path: PathBuf,
pub index: u32,
pub options: String,
pub bytes: ComponentBytes,
pub source_map: Option<ComponentBytes>,
/* private fields */
}Expand description
Where a component-backed rule’s code is, and what it is configured with.
One value rather than two fields, because the two cannot be independently true. A rule
backed by a component is always configured — with null when the config named it with no
options, which is the shape crates/lanekeep-wasm/wit/world.wit declares so that a guest
has one code path rather than two — and a rule that is not backed by a component has no
configure to reach. Splitting them would make “a component with nothing to configure it
with” and “options belonging to no component” representable, and both are states nothing
downstream knows what to do with.
Fields§
§path: PathBufWhere the bytes came from: a path confined to the rules root, or lanekeep/<name> for
a built-in embedded in the binary.
Kept for diagnostics and for the order ComponentBytes are folded into
ruleset_hash in. Nothing reads the file again — see ComponentRule::bytes.
A built-in’s is a specifier rather than a path, and cannot collide with one. A
confined path is absolute, because RuleRoot::confine canonicalizes; lanekeep/no-unwrap
is relative. So a project that happens to have lanekeep/no-unwrap.wasm inside its rules
root sorts and dedups separately, as two different rules should.
index: u32Which of the component’s rules this is: an index into what its rules export lists.
A component hosts a list, so naming one is a position and not merely a file. Every
export but rules takes this index, so it is what tells configure, metadata,
check and reduce which rule they are being asked about. A component hosting one
rule is 0, which is what every reference resolved to before a component could host
more than one.
It is folded into ruleset_hash beside the component’s identity rather than being
carried only for execution: two rules of one component share every byte of code, so the
index is the whole of what distinguishes the programs they run. Without it, “rule 0 and
rule 1 of this component” and “rule 0 of this component, twice” are one cache key.
options: StringWhat configure is called with, as JSON — "null" for a rule named with no options.
A string rather than a serde_json::Value because that is what crosses the boundary:
a component cannot close over a host-supplied value the way a JavaScript factory does,
so its options arrive as data. Serializing once here also fixes the bytes, which
matters because they are what every worker’s configure is handed.
bytes: ComponentBytesThe component itself, read exactly once.
The rule that was described has to be the rule that runs. The bytes used to be read
three times in a run — once to ask the component what it is, once to hash it, once to
execute it — and a file that changed between those reads would give metadata from one,
a cache key from a second and handlers from a third, with nothing to notice. That is
the same property the TypeScript path already has for free: hash_ruleset folds what
RuleLoader actually consumed, not a second read of the same paths.
So they are read once, here, and carried: metadata is read from them, ruleset_hash
folds them, and lanekeep-engine loads the component from them rather than from the
path beside them.
Behind an std::sync::Arc, because a RuleSpec is cloned per rule when the engine
prepares and a per-rule copy of a megabyte is a cost with nothing to buy it.
source_map: Option<ComponentBytes>The component’s sidecar source map, or None for one that ships without one.
Carried beside the bytes for the same reason they are carried at all: the component that was described has to be the component that runs, and the map is only correct for the bundle it was generated from. Reading it a second time later, from a path, would let a file that changed in between explain the positions of a program it does not describe.
Not a ruleset_hash input, and that is a decision rather than an omission. A map
changes exactly one thing: where a thrown rule error is reported. It cannot move a
violation — a violation’s position comes from the parse tree by way of a node handle — and
every failure it touches cancels the run, so no cache entry is ever written by a run whose
output it affected. Two runs differing only in their maps produce byte-identical output for
every file that completes.
Implementations§
Source§impl ComponentRule
impl ComponentRule
Sourcepub const fn counted_in_ruleset_hash(&self) -> bool
pub const fn counted_in_ruleset_hash(&self) -> bool
Whether these bytes are folded into the ruleset_hash of the Config they arrived
with — see the field.
Sourcepub fn uncounted(
path: PathBuf,
index: u32,
options: String,
bytes: impl Into<ComponentBytes>,
) -> Self
pub fn uncounted( path: PathBuf, index: u32, options: String, bytes: impl Into<ComponentBytes>, ) -> Self
Build a ComponentRule outside lanekeep_config::load.
Whatever this produces is not folded into any Config’s ruleset_hash, because
nothing here computes one — that happens exactly once, inside load, over whichever
rules were in Config.rules at the moment it returned. This is for an embedder, or a
test, that attaches a component to a RuleSpec afterward: lanekeep-engine’s own
component tests are exactly that, which is why Engine::caching refuses the cache for
a run carrying one of these.
Trait Implementations§
Source§impl Clone for ComponentRule
impl Clone for ComponentRule
Source§fn clone(&self) -> ComponentRule
fn clone(&self) -> ComponentRule
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreSource§impl Debug for ComponentRule
impl Debug for ComponentRule
impl Eq for ComponentRule
Source§impl PartialEq for ComponentRule
impl PartialEq for ComponentRule
impl StructuralPartialEq for ComponentRule
Auto Trait Implementations§
impl Freeze for ComponentRule
impl RefUnwindSafe for ComponentRule
impl Send for ComponentRule
impl Sync for ComponentRule
impl Unpin for ComponentRule
impl UnsafeUnpin for ComponentRule
impl UnwindSafe for ComponentRule
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
key and return true if they are equal.Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more