#[non_exhaustive]pub struct Plan {
pub schema_version: SchemaVersion,
pub platform: Platform,
pub patches: Vec<PatchRef>,
pub targets: Vec<Target>,
pub fs_ops: Vec<FilesystemOp>,
}Expand description
Complete write plan for a chain of one or more source patches.
§Schema versioning
Under the serde feature, every Plan carries a schema_version: u32
that records the in-memory layout this build emits. The current value is
exposed as Plan::CURRENT_SCHEMA_VERSION and is currently 1.
Compatibility policy: the schema version is bumped any time a new
required field is added to Plan or any of the types it transitively
contains. Additive optional fields (defaulted via #[serde(default)])
do not bump the version. On deserialize, a Plan whose persisted
schema_version does not equal Plan::CURRENT_SCHEMA_VERSION is
rejected with crate::IndexError::SchemaVersionMismatch — older
readers refuse to silently drop fields they cannot represent, rather than
risk an apply against a partial plan. Callers persisting plans across
crate-version boundaries should be prepared to rebuild the plan from the
patch chain on mismatch.
#[non_exhaustive]: the top-level plan owns the schema-version
contract; new persisted fields land here under that contract.
Fields (Non-exhaustive)§
This struct is marked as non-exhaustive
Struct { .. } syntax; cannot be matched against without a wildcard ..; and struct update syntax will not work.schema_version: SchemaVersionSchema-format version of this persisted plan. See the
type-level docs for the compatibility policy. New plans
constructed via Plan::new / PlanBuilder
always carry Plan::CURRENT_SCHEMA_VERSION.
platform: PlatformTarget platform pinned by the chain’s most recent SqpkTargetInfo
chunk. Defaults to Platform::Win32 when no TargetInfo is seen.
patches: Vec<PatchRef>Source patches in chain order. PartSource::Patch::patch_idx indexes
into this vector; the applier asks the caller’s crate::index::PatchSource
for bytes by (patch_idx, offset).
targets: Vec<Target>Per-target write timelines, reflecting the chain’s end state — regions
killed by a mid-chain RemoveAll, DeleteFile, or AddFile@0 are
dropped at build time, not at apply time.
fs_ops: Vec<FilesystemOp>Filesystem operations to run before any region writes, in chain order.
Destructive ops (DeleteFile, DeleteDir, RemoveAllInExpansion) are
preserved so that the applier still removes any pre-chain artefacts
that the plan’s region set does not re-create.
Implementations§
Source§impl Plan
impl Plan
Sourcepub const CURRENT_SCHEMA_VERSION: SchemaVersion
pub const CURRENT_SCHEMA_VERSION: SchemaVersion
Current on-disk schema version for Plan under the serde feature.
See the type-level docs for the compatibility policy.
Sourcepub fn check_schema_version(&self) -> Result<()>
pub fn check_schema_version(&self) -> Result<()>
Validate that self.schema_version matches
Self::CURRENT_SCHEMA_VERSION. Intended to be called by consumers
immediately after deserializing a Plan from persistent storage,
before handing it to the applier or verifier.
§Errors
Returns crate::IndexError::SchemaVersionMismatch when the
persisted version does not equal Self::CURRENT_SCHEMA_VERSION.
Sourcepub fn new(
platform: Platform,
patches: Vec<PatchRef>,
targets: Vec<Target>,
fs_ops: Vec<FilesystemOp>,
) -> Self
pub fn new( platform: Platform, patches: Vec<PatchRef>, targets: Vec<Target>, fs_ops: Vec<FilesystemOp>, ) -> Self
Construct a Plan from its component parts.
Exists so callers outside this crate can still build synthetic plans
after the struct picked up #[non_exhaustive] for SemVer hygiene —
in-crate code may continue to use the struct literal form directly.
The constructed plan always carries
Plan::CURRENT_SCHEMA_VERSION.
Sourcepub fn with_crc32<S: PatchSource>(self, source: &mut S) -> Result<Self>
pub fn with_crc32<S: PatchSource>(self, source: &mut S) -> Result<Self>
Consume this plan, walk every region, and return a new plan in which
every applicable region’s PartExpected has been replaced with
PartExpected::Crc32 of the region’s effective output bytes.
Consumes self and returns the populated plan so the mutation is
honest at the type level — there’s no in-place “compute” call that
silently rewrites an outwardly-immutable-looking data type. Pairs with
the PlanBuilder::finish() -> Plan
owned-builder style.
PartSource::Patchregions read the source bytes viasourceand, forPatchSourceKind::Deflatedsources, decompress them in full before slicing the[decoded_skip..decoded_skip + region.length]window and CRC32-ing the slice. A single sharedflate2::Decompressis reused across every Deflated region.PartSource::Zerosregions use the canonical all-zero payload, cached per-length so plans with many same-sized Zeros regions hitcrc32fast::hashonce per unique length.PartSource::EmptyBlockregions use the canonical empty-block payload the apply layer’s internalwrite_empty_blockhelper produces (a 20-byteSqPackempty-block header followed byunits * 128 - 20zero bytes), cached per-units.PartSource::Unavailableregions are left with their existingPartExpected(typicallyPartExpected::SizeOnly). A singletracing::warn!summary fires per call with the total count of skipped regions — per-region tracing happens attrace!.
Once populated, crate::index::PlanVerifier uses
PartExpected::Crc32 to detect single-byte damage inside Patch
regions, which the v1 size-only policy missed.
§Errors
Surfaces any crate::IndexError produced by source.read or by
DEFLATE decompression of a Patch region’s bytes. On error the
original plan is dropped; callers that need to retry must hold an
independent copy.
§Atomicity
All-or-nothing: on Ok, every applicable region in the returned plan
carries a fresh PartExpected::Crc32; on Err, no partially-mutated
plan is observable — the input was consumed and the staging buffer is
dropped without being flushed.
Sourcepub fn crc32(&self) -> u32
pub fn crc32(&self) -> u32
Stable CRC32 identity over this plan’s structural content.
Used by IndexedCheckpoint::plan_crc32 and
crate::index::IndexApplier::resume_execute to detect a checkpoint
that was persisted against a different plan revision than the one a
resume call is given. The CRC is computed from a fixed,
deterministically-ordered byte feed of every field that affects which
bytes the applier writes — schema version, platform, patch chain,
every target’s path and region timeline (including PartSource /
PartExpected discriminants and payload), and the fs_ops list. The
encoding does not match any serde format on purpose: we hash
directly so the result stays stable regardless of which serializer the
consumer picks for on-disk persistence.
Not cryptographic — collision space is 32 bits and the function is trivial to forge. Stale-detection only; never use this as an authentication or integrity check.
0 is a legitimate output value. CRC32 is uniform over u32 and a
real plan can hash to zero; consumers must represent the
“no checkpoint yet” state via Option<IndexedCheckpoint> rather
than a sentinel plan_crc32: 0. See
IndexedCheckpoint::plan_crc32 for the matching field doc.
Trait Implementations§
Source§impl<'de> Deserialize<'de> for Plan
impl<'de> Deserialize<'de> for Plan
Source§fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
impl Eq for Plan
impl StructuralPartialEq for Plan
Auto Trait Implementations§
impl Freeze for Plan
impl RefUnwindSafe for Plan
impl Send for Plan
impl Sync for Plan
impl Unpin for Plan
impl UnsafeUnpin for Plan
impl UnwindSafe for Plan
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<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
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