Skip to main content

ApplyObserver

Trait ApplyObserver 

Source
pub trait ApplyObserver {
    // Provided methods
    fn on_chunk_applied(&mut self, ev: ChunkEvent) -> ControlFlow<(), ()> { ... }
    fn should_cancel(&mut self) -> bool { ... }
}
Expand description

Hook trait for observing apply-time progress and signalling cancellation.

All methods have no-op defaults so implementors override only what they need.

§Threading

An observer is borrowed mutably by the apply driver for the lifetime of the apply_to call. There is no internal synchronisation: implementors that need to forward events to another thread should do so via channels they own.

§Example

use std::ops::ControlFlow;
use zipatch_rs::{ApplyContext, ApplyObserver, ChunkEvent, ZiPatchReader};

struct Progress {
    total: u64,
    applied: u64,
}

impl ApplyObserver for Progress {
    fn on_chunk_applied(&mut self, ev: ChunkEvent) -> ControlFlow<(), ()> {
        self.applied = ev.bytes_read;
        println!("progress: {}/{}", self.applied, self.total);
        ControlFlow::Continue(())
    }
}

let mut ctx = ApplyContext::new("/opt/ffxiv/game")
    .with_observer(Progress { total: 12_345_678, applied: 0 });
ZiPatchReader::from_path("patch.patch")
    .unwrap()
    .apply_to(&mut ctx)
    .unwrap();

Provided Methods§

Source

fn on_chunk_applied(&mut self, ev: ChunkEvent) -> ControlFlow<(), ()>

Called after each top-level chunk has been applied successfully.

Returning ControlFlow::Break aborts the apply loop immediately; the apply call returns ZiPatchError::Cancelled.

Not invoked when the chunk’s apply itself fails — the error propagates from apply_to without firing this method. The event is therefore a “chunk succeeded” signal, not a “chunk attempted” one.

The default implementation does nothing and continues.

Source

fn should_cancel(&mut self) -> bool

Polled inside long-running chunks to check for user cancellation.

Implementors should make this method cheap — it is called once per block inside the SqpkFile AddFile loop and on every iteration of any future fine-grained loop the apply layer adds. A simple atomic-bool load is the recommended implementation.

Polled before each block within long-running chunks (currently only SQPK F AddFile). Once a block’s I/O has started, it completes — cancellation takes effect at the next block boundary, not mid-write. This means the last block of any chunk always finishes once started.

Returning true causes the current apply operation to abort at the next checkpoint with ZiPatchError::Cancelled.

The default implementation always returns false.

Implementors§

Source§

impl ApplyObserver for NoopObserver

Source§

impl<F> ApplyObserver for F
where F: FnMut(ChunkEvent) -> ControlFlow<(), ()>,

Blanket impl: any FnMut(ChunkEvent) -> ControlFlow<(), ()> closure is an ApplyObserver that only forwards per-chunk events.

Cancellation falls back to the trait default (always false). For cancellation support, implement ApplyObserver directly on a struct that owns whatever cancellation handle you use (e.g. an AtomicBool).

§Example

use std::ops::ControlFlow;
use zipatch_rs::{ApplyContext, ChunkEvent, ZiPatchReader};

let mut ctx = ApplyContext::new("/opt/ffxiv/game")
    .with_observer(|ev: ChunkEvent| {
        println!("applied chunk {} ({} bytes total)", ev.index, ev.bytes_read);
        ControlFlow::Continue(())
    });
ZiPatchReader::from_path("patch.patch")
    .unwrap()
    .apply_to(&mut ctx)
    .unwrap();