pub struct DeclaredEditPlan(/* private fields */);Expand description
An EditPlan decoded without materializing any extension member.
Decoding an envelope through EditPlan retains every undeclared member as
an owned JSON value at all three levels. That is required to round-trip a
plan, and it is the dominant cost of decoding a large multi-file plan. A
consumer that only validates or applies a plan never reads those values and
should not pay for them.
This wrapper recovers identical declared data and reports declared-member
errors identically, but skips undeclared members structurally instead of
building a key and a value tree for each one. The EditPlan it yields has
empty extensions at every level.
§It is not an input-rejection gate
The two decodes do not accept the same documents. Capturing decode
materializes each undeclared member into a value, so a member the value
model cannot represent — a number outside the representable range, a lone
surrogate escape, nesting past the driver’s depth limit — fails the whole
decode. This wrapper consumes that member without inspecting it and
succeeds. The divergence is confined to content this path never looks at,
and tests/declared_divergence.rs pins it.
Use it as a terminal consumer of declared data. Do not use it as the gate
that rejects malformed input: PlanLimits does not
bound extension payloads either, so a caller that must constrain undeclared
content has to decode through EditPlan and enforce its own budget.
§Extensions are dropped, not hidden
The recovered plan is not round-trippable: re-serializing it emits only
declared members. Decode through EditPlan whenever the extension members
must survive. Validation is unaffected either way — a reserved member name
can never reach an extension map through the wire, because a JSON member
spelled like a declared field always binds to that field.
§Examples
use weavatrix_edit::DeclaredEditPlan;
let json = r#"{
"schemaVersion": "weavatrix.edit-plan.v1",
"operation": "rename_symbol",
"createdAt": "2026-08-01T12:00:00Z",
"files": [{
"path": "src/user.ts",
"sha256": "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
"language": "typescript",
"edits": [{
"startLine": 10, "startChar": 8, "endLine": 10, "endChar": 15,
"before": "getUser", "after": "getCustomer", "provenance": "EXACT_LSP"
}]
}]
}"#;
let declared: DeclaredEditPlan = blazingly_json::from_str(json)?;
let plan = declared.into_plan();
assert!(plan.validate().is_ok());
assert!(plan.extensions.is_empty());
assert!(plan.files[0].extensions.is_empty());Implementations§
Trait Implementations§
Source§impl AsRef<EditPlan> for DeclaredEditPlan
impl AsRef<EditPlan> for DeclaredEditPlan
Source§impl Clone for DeclaredEditPlan
impl Clone for DeclaredEditPlan
Source§fn clone(&self) -> DeclaredEditPlan
fn clone(&self) -> DeclaredEditPlan
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read more