Skip to main content

EditSession

Struct EditSession 

Source
pub struct EditSession<T, C> { /* private fields */ }
Expand description

A single-use edit. It never writes to a document or records history itself.

This type intentionally does not implement Clone. finish consumes it, so the same session cannot accidentally emit two commits. A failed finish also consumes the draft; call check first if invalid input should remain editable in the UI.

Implementations§

Source§

impl<T: Clone, C> EditSession<T, C>

Source

pub fn new(original: T, context: C) -> Self

Begin from a value already validated by the application.

Cloning original must produce an independently editable snapshot. Shared mutable pointers such as Rc<RefCell<_>> can let edits change the original or live document and defeat cancellation/conflict checks. Use owned fields or immutable shared data. The context must also remain a stable snapshot until the session ends.

Examples found in repository?
examples/retry_command.rs (line 78)
75    fn open(host: &Host) -> Self {
76        Self {
77            text: host.value.clone(),
78            draft: Some(EditSession::new(host.value.clone(), host.context)),
79        }
80    }
Source

pub fn reset(&mut self)

Restore the original preview and clear invalid input, keeping the draft open.

The original value and context are retained: this does not rebase a stale draft or change the live document. The host must refresh its displayed preview itself.

Source§

impl<T, C> EditSession<T, C>

Source

pub fn original(&self) -> &T

The validated value captured when editing began.

Examples found in repository?
examples/retry_command.rs (line 99)
92    fn confirm(&mut self, host: &mut Host) -> Result<Outcome, ConfirmError> {
93        // This whole method runs on the host's serialized edit path, without an await
94        // or a callback that can change the target between check and command dispatch.
95        let draft = self.draft.as_ref().ok_or(ConfirmError::Closed)?;
96        draft
97            .check(&host.value, &host.context)
98            .map_err(ConfirmError::Draft)?;
99        let outcome = if draft.preview() == draft.original() {
100            Outcome::Unchanged // Do not dispatch a command or clear Redo for a no-op.
101        } else {
102            // Borrow the proposal: finish() would consume it before this fallible call.
103            host.apply(draft.preview())?;
104            Outcome::Applied
105        };
106        self.cancel(); // Close only after a successful command or a checked no-op.
107        Ok(outcome)
108    }
Source

pub fn preview(&self) -> &T

Last valid preview, even when a later incomplete/invalid input is present.

Examples found in repository?
examples/retry_command.rs (line 99)
92    fn confirm(&mut self, host: &mut Host) -> Result<Outcome, ConfirmError> {
93        // This whole method runs on the host's serialized edit path, without an await
94        // or a callback that can change the target between check and command dispatch.
95        let draft = self.draft.as_ref().ok_or(ConfirmError::Closed)?;
96        draft
97            .check(&host.value, &host.context)
98            .map_err(ConfirmError::Draft)?;
99        let outcome = if draft.preview() == draft.original() {
100            Outcome::Unchanged // Do not dispatch a command or clear Redo for a no-op.
101        } else {
102            // Borrow the proposal: finish() would consume it before this fallible call.
103            host.apply(draft.preview())?;
104            Outcome::Applied
105        };
106        self.cancel(); // Close only after a successful command or a checked no-op.
107        Ok(outcome)
108    }
Source

pub fn context(&self) -> &C

The host context captured when editing began; never changed by this session.

Source

pub fn is_valid(&self) -> bool

Whether the latest proposal was accepted. This does not check live host state.

Source

pub fn propose<E>(&mut self, proposal: Result<T, E>) -> Result<(), E>

Accept a host-validated proposal. Errors invalidate commit without replacing the last valid preview. Units, mixed values, finite checks and bounds belong to the host.

Examples found in repository?
examples/retry_command.rs (lines 85-89)
82    fn set_text(&mut self, text: &str) -> Result<(), &'static str> {
83        let draft = self.draft.as_mut().ok_or("dialog is closed")?;
84        self.text = text.to_owned();
85        draft.propose(if text.trim().is_empty() {
86            Err("enter a title")
87        } else {
88            Ok(self.text.clone())
89        })
90    }
Source

pub fn cancel(self)

Discard the local draft. No rollback commands or history entries are generated.

Examples found in repository?
examples/retry_command.rs (line 112)
110    fn cancel(&mut self) {
111        if let Some(draft) = self.draft.take() {
112            draft.cancel();
113        }
114    }
Source§

impl<T: PartialEq, C: PartialEq> EditSession<T, C>

Source

pub fn check_live(&self, live: &T, context: &C) -> Result<(), FinishError>

Check whether the draft still belongs to the current host state, independently of invalid input. Useful when deciding whether an open editor must be dismissed.

This never returns InvalidProposal and does not authorize a commit. Use check or finish immediately before applying on the host’s serialized command path. Context conflicts take precedence over value conflicts. No lock is acquired.

Source

pub fn check(&self, live: &T, context: &C) -> Result<(), FinishError>

Check live host state and proposal validity immediately before applying on the host’s serialized command path. Live conflicts take precedence over invalid input. This comparison is not a lock and is not a distributed transaction.

Examples found in repository?
examples/retry_command.rs (line 97)
92    fn confirm(&mut self, host: &mut Host) -> Result<Outcome, ConfirmError> {
93        // This whole method runs on the host's serialized edit path, without an await
94        // or a callback that can change the target between check and command dispatch.
95        let draft = self.draft.as_ref().ok_or(ConfirmError::Closed)?;
96        draft
97            .check(&host.value, &host.context)
98            .map_err(ConfirmError::Draft)?;
99        let outcome = if draft.preview() == draft.original() {
100            Outcome::Unchanged // Do not dispatch a command or clear Redo for a no-op.
101        } else {
102            // Borrow the proposal: finish() would consume it before this fallible call.
103            host.apply(draft.preview())?;
104            Outcome::Applied
105        };
106        self.cancel(); // Close only after a successful command or a checked no-op.
107        Ok(outcome)
108    }
Source

pub fn finish( self, live: &T, context: &C, ) -> Result<Option<Change<T>>, FinishError>

Emit at most one change; a no-op emits none, preserving the host’s redo stack. The host still validates and applies the command and handles execution failure.

Trait Implementations§

Source§

impl<T: Debug, C: Debug> Debug for EditSession<T, C>

Source§

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

Formats the value using the given formatter. Read more

Auto Trait Implementations§

§

impl<T, C> Freeze for EditSession<T, C>
where T: Freeze, C: Freeze,

§

impl<T, C> RefUnwindSafe for EditSession<T, C>

§

impl<T, C> Send for EditSession<T, C>
where T: Send, C: Send,

§

impl<T, C> Sync for EditSession<T, C>
where T: Sync, C: Sync,

§

impl<T, C> Unpin for EditSession<T, C>
where T: Unpin, C: Unpin,

§

impl<T, C> UnsafeUnpin for EditSession<T, C>
where T: UnsafeUnpin, C: UnsafeUnpin,

§

impl<T, C> UnwindSafe for EditSession<T, C>
where T: UnwindSafe, C: UnwindSafe,

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.