Skip to main content

Store

Struct Store 

Source
pub struct Store<D, X = ()> { /* private fields */ }
Expand description

Owns a document D and its undo history.

  • Reads are free: Store::doc borrows the current snapshot, Store::snapshot clones the Arc for a job or another thread.
  • Edits are copy-on-write: the closure gets a fresh copy (Arc::make_mut while the history still holds the old state), so its cost is D::clone. Make D cheap to clone by keeping large parts in Arcs (chunks, tracks, pages); an edit then copies only the chunk it touches.
  • Every change gets a new Revision; undo and redo restore the revision of the state they bring back, so caches keyed by revision stay valid and Store::is_dirty is exact.
  • X is extra state recorded with each step and restored by undo/redo (selection, caret). It can be changed freely with Store::extra_mut without making a step.

Implementations§

Source§

impl<D: Clone, X: Clone + Default> Store<D, X>

Source

pub fn new(doc: D) -> Store<D, X>

A store holding doc, considered saved (not dirty).

Source§

impl<D: Clone, X: Clone> Store<D, X>

Source

pub fn with_extra(doc: D, extra: X) -> Store<D, X>

A store holding doc with extra state extra, considered saved.

Source

pub fn doc(&self) -> &Arc<D> ⓘ

The current document.

Source

pub fn snapshot(&self) -> Arc<D> ⓘ

The current document, to keep or send to another thread (an Arc clone).

Source

pub fn revision(&self) -> Revision

Source

pub fn extra(&self) -> &X

Source

pub fn extra_mut(&mut self) -> &mut X

Change the extra state without making an undo step.

Source

pub fn history(&self) -> &History<D, X>

Source

pub fn history_mut(&mut self) -> &mut History<D, X>

The history, to change its limits or squash steps.

Source

pub fn edit<R>(&mut self, label: &str, f: impl FnOnce(&mut D) -> R) -> R

Apply an undoable edit called label.

Source

pub fn try_edit<R, E>( &mut self, label: &str, f: impl FnOnce(&mut D) -> Result<R, E>, ) -> Result<R, E>

Apply an edit that may fail; on error (or a panic in f) nothing changes.

Source

pub fn edit_merged<R>( &mut self, label: &str, merge_key: &str, f: impl FnOnce(&mut D) -> R, ) -> R

Store::edit that folds into the previous step when that step has the same label and was made with the same merge_key with nothing in between (one undo step per drag).

Source

pub fn try_edit_with<R, E>( &mut self, label: &str, merge_key: Option<&str>, f: impl FnOnce(&mut D, &mut X) -> Result<R, E>, ) -> Result<R, E>

The general edit: optional merge key, access to the extra state, may fail. On error (or a panic in f) the document, the extra state, the revision and the history are unchanged.

Source

pub fn commit(&mut self, label: &str, merge_key: Option<&str>, doc: Arc<D>)

Make doc, built elsewhere (a command’s working copy, a job’s result), the new state as one undo step label, without copying it. merge_key as in Store::edit_merged. Committing the current snapshot itself (Arc::ptr_eq) changes nothing.

Source

pub fn transaction<T, E>( &mut self, label: &str, f: impl FnOnce(&mut Store<D, X>) -> Result<T, E>, ) -> Result<T, E>

Run f, which may make any number of edits, as one undo step called label.

On Ok the edits fold into one step (none when they changed nothing); the steps before the transaction are untouched and the redo line is dropped only if something changed. On Err, or a panic in f, the document, extra state, revision, history (redo line and merge key included) and saved state are put back as they were. See Transaction.

Source

pub fn begin_transaction(&mut self, label: &str) -> Transaction<'_, D, X>

Start a Transaction called label: edit through it, then Transaction::commit; dropping it without committing (an early return, a panic) rolls everything back.

Source

pub fn transaction_on<H, T, E>( host: &mut H, store: impl Fn(&mut H) -> &mut Store<D, X>, label: &str, f: impl FnOnce(&mut H) -> Result<T, E>, ) -> Result<T, E>

Store::transaction for a host that owns the store: f gets the whole host (to run commands that take &mut H), store finds the store in it. Same semantics: one step on Ok, everything put back on Err or a panic in f (the panic then continues), nesting as a savepoint, nothing recorded when nothing changed.

struct Host { store: Store<Vec<i32>>, runs: u32 }
let mut host = Host { store: Store::new(Vec::new()), runs: 0 };
let r: Result<(), ()> = Store::transaction_on(&mut host, |h| &mut h.store, "Two", |h| {
    h.runs += 1;
    h.store.edit("a", |d| d.push(1));
    h.store.edit("b", |d| d.push(2));
    Ok(())
});
assert_eq!(r, Ok(()));
assert_eq!(host.store.history().undo_labels().collect::<Vec<_>>(), ["Two"]);
Source

pub fn undo(&mut self) -> Option<String>

Undo the last step; returns its label.

Source

pub fn redo(&mut self) -> Option<String>

Redo the next undone step; returns its label.

Source

pub fn redo_branch(&mut self, index: usize) -> Option<String>

Redo into branch index of History::branches (it must grow from the current state).

Source

pub fn can_undo(&self) -> bool

Source

pub fn can_redo(&self) -> bool

Source

pub fn replace(&mut self, doc: D, extra: X)

Replace the whole document (New, Open, Revert): clears the history, counts as saved.

Source

pub fn is_dirty(&self) -> bool

The document differs from the last saved (or loaded) state.

Source

pub fn mark_saved(&mut self)

The current state was saved.

Source

pub fn mark_saved_at(&mut self, revision: Revision)

Record that the state with revision was saved (a background save of an older snapshot).

Source

pub fn saved_revision(&self) -> Revision

Source

pub fn subscribe_snapshots(&mut self) -> Arc<SnapshotCell<D>> ⓘ

A cell other threads read the latest snapshot from without locking; the store publishes every change to it. The same cell is returned on every call.

Trait Implementations§

Source§

impl<D: Debug, X: Debug> Debug for Store<D, X>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

§

impl<D, X = ()> !RefUnwindSafe for Store<D, X>

§

impl<D, X = ()> !UnwindSafe for Store<D, X>

§

impl<D, X> Forget for Store<D, X>

§

impl<D, X> Freeze for Store<D, X>
where Arc<D>: Freeze, X: Freeze, History<D, X>: Freeze, Option<Arc<SnapshotCell<D>>>: Freeze,

§

impl<D, X> Move for Store<D, X>

§

impl<D, X> Send for Store<D, X>
where Arc<D>: Send, X: Send, History<D, X>: Send, Option<Arc<SnapshotCell<D>>>: Send,

§

impl<D, X> Sync for Store<D, X>
where Arc<D>: Sync, X: Sync, History<D, X>: Sync, Option<Arc<SnapshotCell<D>>>: Sync,

§

impl<D, X> Unpin for Store<D, X>
where Arc<D>: Unpin, X: Unpin, History<D, X>: Unpin, Option<Arc<SnapshotCell<D>>>: Unpin,

§

impl<D, X> UnsafeUnpin for Store<D, X>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.