Struct someday::Writer

source ·
pub struct Writer<T: Clone> { /* private fields */ }
Expand description

The single Writer of some data T.

The Writer:

  1. Stores your Patch’s with add()
  2. Actually applies them to T by commit()’ing
  3. Can push() so that Reader’s can see the changes

The Writer can also generate infinite Reader’s with Writer::reader().

§Invariants

Some invariants that the Writer upholds, that you can rely on:

InvariantDescription
No “rebasing”Writer::timestamp() will always be greater than or equal to the Reader::head()’s timestamp.
PartialEqIf the Writer::timestamp() is the same as the Reader::head()’s timestamp, the data T is the same as well (as long as Patch’s are deterministic). This can serve as a very cheap way to compare data (just compare the timestamps).
1 WriterThere can only ever be 1 Writer at any given moment (at least, without shared mutual exclusion like Arc + Mutex).
PoisonIf a Writer panics mid-push(), the data can only be poisoned on the Writer side - i.e. Reader’s will be completely fine if the Writer panics, other Writer’s (e.g Arc<Mutex<Writer<T>>>) may panic as well on any function that accesses T.

§Usage

This example covers the typical usage of a Writer:

  • Creating some Reader’s
  • Adding some Patch’s
  • Viewing the staged Patch’s, modifying them
  • Committing those changes
  • Pushing those changes to the Reader’s
use someday::{*,info::*};

// Create a Reader/Writer pair that can "apply"
// the `PatchString` patch to `String`'s.
let (r, w) = someday::new("".into());

// To clarify the types of these things:
// This is the Reader.
// It can clone itself an infinite
// amount of time very cheaply.
let r: Reader<String> = r;
for _ in 0..10_000 {
    let another_reader = r.clone(); // akin to Arc::clone()
}

// This is the single Writer, it cannot clone itself.
let mut w: Writer<String> = w;

// Both Reader and Writer are at timestamp 0 and see no changes.
assert_eq!(w.timestamp(), 0);
assert_eq!(r.head().timestamp, 0);
assert_eq!(w.data(), "");
assert_eq!(r.head().data, "");

// The Writer can add many `Patch`'s
w.add(Patch::Ptr(|w, _| w.push_str("abc")));
w.add(Patch::Ptr(|w, _| w.push_str("def")));
w.add(Patch::Ptr(|w, _| w.push_str("ghi")));
w.add(Patch::Ptr(|w, _| w.push_str("jkl")));

// But `add()`'ing does not actually modify the
// local (Writer) or remote (Readers) data, it
// just "stages" them.
assert_eq!(w.timestamp(), 0);
assert_eq!(r.head().timestamp, 0);
assert_eq!(w.data(), "");
assert_eq!(r.head().data, "");

// We can see our "staged" patches here.
let staged = w.staged();
assert_eq!(staged.len(), 4);

// Let's actually remove a patch.
staged.remove(3); // w.push_str("jkl")

// Okay, now let's commit locally.
let commit_info: CommitInfo = w.commit();
// We applied 3 patches in total.
assert_eq!(commit_info.patches, 3);
// And added 1 commit (timestamp).
assert_eq!(w.timestamp(), 1);

// We haven't pushed yet, so the Readers
// are still un-aware of our local changes.
assert_eq!(w.timestamp(), 1);
assert_eq!(r.head().timestamp, 0);
assert_eq!(w.data(), "abcdefghi");
assert_eq!(r.head().data, "");

// Now we push.
let push_info: PushInfo = w.push();
// We pushed 1 commit in total.
assert_eq!(push_info.commits, 1);
// Our staged functions are now gone.
assert_eq!(w.staged().len(), 0);

// The Readers are now in sync.
assert_eq!(w.timestamp(), 1);
assert_eq!(r.head().timestamp, 1);
assert_eq!(w.data(), "abcdefghi");
assert_eq!(r.head().data, "abcdefghi");

Implementations§

source§

impl<T: Clone> Writer<T>

source

pub fn add(&mut self, patch: Patch<T>)

Add a Patch to apply to the data T

This does not execute the Patch immediately, it will only store it for later usage.

Commit-like operations are when these functions are applied to your data, e.g. Writer::commit().

let (r, mut w) = someday::new::<usize>(0);

// Add a patch.
w.add(Patch::Ptr(|w, _| *w += 1));

// It hasn't been applied yet.
assert_eq!(w.staged().len(), 1);

// Now it has.
w.commit();
assert_eq!(w.staged().len(), 0);
source

pub fn commit(&mut self) -> CommitInfo

Apply all the Patch’s that were add()’ed

The new Commit created from this will become the Writer’s new Writer::head().

You can commit() multiple times and it will only affect the Writer’s local data.

You can choose when to publish those changes to the Reader’s with Writer::push().

The CommitInfo object returned is just a container for some metadata about the commit() operation.

let (r, mut w) = someday::new::<usize>(0);

// Timestamp is 0.
assert_eq!(w.timestamp(), 0);

// Add and commit a patch.
w.add(Patch::Ptr(|w, _| *w += 123));
w.commit();

assert_eq!(w.timestamp(), 1);
assert_eq!(w.head().data, 123);
§Timestamp

This will increment the Writer’s local Timestamp by 1, but only if there were Patch’s to actually apply. In other words, if you did not call add() before this, commit() will do nothing.

let (r, mut w) = someday::new::<usize>(0);

// Timestamp is 0.
assert_eq!(w.timestamp(), 0);

// We didn't `add()` anything, but commit anyway.
let commit_info = w.commit();
assert_eq!(commit_info.patches, 0);
assert_eq!(commit_info.timestamp_diff, 0);

// There was nothing to commit,
// so our timestamp did not change.
assert_eq!(w.timestamp(), 0);
assert_eq!(w.head().data, 0);
source

pub fn add_commit<P, Output>(&mut self, patch: P) -> (CommitInfo, Output)
where P: FnMut(&mut T, &T) -> Output + Send + 'static,

add() and commit()

This function combines add() and commit() together. Since these actions are done together, a return value is allowed to be specified.

This function will apply your Writer::staged() patches first, then your input patch, then commit() them.

§Example

If you’d like to receive a large chunk of data from your T instead of throwing it away:

// Very expensive data.
let vec = (0..100_000).map(|i| format!("{i}")).collect();

let (_, mut w) = someday::new::<Vec<String>>(vec);
assert_eq!(w.timestamp(), 0);
assert_eq!(w.timestamp_remote(), 0);

// Add some patches normally.
// These will be applied in `add_commit()` below.
for i in 100_000..200_000 {
    w.add(Patch::boxed(move |w: &mut Vec<String>, _| {
        w.push(format!("{i}"));
    }));
}

let (commit_info, r) = w.add_commit(|w, _| {
    // Swap our value, and get back the strings.
    // This implicitly becomes our <Output> (Vec<String>).
    std::mem::take(w)
});

// We got our 200,000 `String`'s back
// instead of dropping them!
let r: Vec<String> = r;
assert_eq!(r.len(), 200_000);
assert_eq!(commit_info.patches, 100_001); // 100_000 normal patches + 1 `add_commit()`
assert_eq!(commit_info.timestamp_diff, 1);

// We got back our original strings.
for (i, string) in r.into_iter().enumerate() {
    assert_eq!(format!("{i}"), string);
}

// And the `Patch` got applied to the `Writer`'s data,
// but hasn't been `push()`'ed yet.
assert!(w.data().is_empty());
assert_eq!(w.timestamp(), 1);
assert_eq!(w.timestamp_remote(), 0);
§Generics

The generic inputs are:

  • Patch
  • Output

Patch is the same as Writer::add() however, it has a -> Output value associated with it, this is defined by you, using the Output generic.

§Timestamp

This function will always increment the Writer’s local Timestamp by 1.

source

pub fn add_commit_push<Patch, Output>( &mut self, patch: Patch ) -> (PushInfo, Output, Option<Output>)
where Patch: FnMut(&mut T, &T) -> Output,

add(), commit(), and push()

This function combines add(), commit(), push() together. Since these actions are done together, return values are allowed to be specified where they wouldn’t otherwise be.

The input Patch no longer has to be Send + 'static either.

This allows you to specify any arbitrary return value from your Patch’s, even return values from your T itself.

For example, if you’d like to receive a large chunk of data from your T instead of throwing it away:

// Very expensive data.
let vec = (0..100_000).map(|i| format!("{i}")).collect();

let (_, mut w) = someday::new::<Vec<String>>(vec);
assert_eq!(w.timestamp(), 0);
assert_eq!(w.timestamp_remote(), 0);

let (info, r1, r2) = w.add_commit_push(|w, _| {
    // Swap our value, and get back the strings.
    // This implicitly becomes our <Output> (Vec<String>).
    std::mem::take(w)
});

// We got our 100,000 `String`'s back
// instead of dropping them!
let r1: Vec<String> = r1;
// If `Writer` reclaimed data and applied our
// `Patch` to it, it also got returned!
let r2: Option<Vec<String>> = r2;
// And, some push info.
let info: PushInfo = info;

// We got back our original strings.
for (i, string) in r1.into_iter().enumerate() {
    assert_eq!(format!("{i}"), string);
}

// If the `Writer` reclaimed data,
// then `r2` will _always_ be a `Some`.
if info.reclaimed {
    // This also contains 100,000 strings.
    assert!(r2.is_some());
}

// And the `Patch` got applied to the `Writer`'s data.
assert!(w.data().is_empty());
assert_eq!(w.timestamp(), 1);
assert_eq!(w.timestamp_remote(), 1);
§Generics

The generic inputs are:

  • Patch
  • Output

Patch is the same as Writer::add() however, it has a -> Output value associated with it, this is defined by you, using the Output generic.

§Returned Tuple

The returned tuple is contains the regular PushInfo along with a Output and Option<Output>.

The Output is the data returned by operating on the Writer’s side of the data.

The Option<Output> is Some if the Writer reclaimed the Reader’s side of the data, and re-applied your Patch - it returns it instead of dropping it. This means that if PushInfo’s reclaimed is true, this Option<Output> will always be Some.

§Timestamp

This function will always increment the Writer’s local Timestamp by 1.

source

pub fn add_commit_push_wait<Patch, Output>( &mut self, duration: Duration, patch: Patch ) -> (PushInfo, Output, Option<Output>)
where Patch: FnMut(&mut T, &T) -> Output,

This is the same as Self::add_commit_push() with Self::push_wait() semantics.

See push_wait()’s documentation for more info.

let (r, mut w) = someday::new::<String>("".into());

let commit = r.head();
spawn(move || {
    // This `Reader` is holding onto the old data.
    let moved = commit;
    // But will let go after 1 millisecond.
    sleep(Duration::from_millis(1));
});

// Wait 250 milliseconds before resorting to cloning data.
let (push_info, _, _) = w.add_commit_push_wait(
    Duration::from_millis(250),
    |w, _| w.push_str("abc"),
);
// We pushed 1 commit.
assert_eq!(push_info.commits, 1);
// And we successfully reclaimed the old data cheaply.
assert_eq!(push_info.reclaimed, true);
source

pub fn add_commit_push_do<Patch, Output, F, R>( &mut self, f: F, patch: Patch ) -> (PushInfo, Output, Option<Output>, R)
where Patch: FnMut(&mut T, &T) -> Output, F: FnOnce() -> R,

This is the same as Self::add_commit_push() with Self::push_do() semantics.

See push_do()’s documentation for more info.

let (r, mut w) = someday::new::<String>("".into());

let head = r.head();
spawn(move || {
    // This `Reader` is holding onto the old data.
    let moved = head;
    // But will let go after 100 milliseconds.
    sleep(Duration::from_millis(100));
});

// Some work to be done.
let mut hashmap = HashMap::<usize, String>::new();
let mut vec     = vec![];

// The actual `Patch` on our data.
let patch = |w: &mut String, _: &_| w.push_str("abc");

// The closure to do arbitrary things while pushing.
let closure = || {
    // While we're waiting, let's get some work done.
    // Add a bunch of data to this HashMap.
    (0..1_000).for_each(|i| {
        hashmap.insert(i, format!("{i}"));
    });
    // Add some data to the vector.
    (0..1_000).for_each(|_| {
        vec.push(format!("aaaaaaaaaaaaaaaa"));
    }); // <- `add_commit_push_do()` returns `()`
};      // although we could return anything
        // and it would be binded to `return_value`

// Pass in a closure, so that we can do
// arbitrary things in the meanwhile...!
let (push_info, _, _, return_value) = w.add_commit_push_do(closure, patch);

// At this point, the old `Reader`'s have
// probably all dropped their old references
// and we can probably cheaply reclaim our
// old data back.

// And yes, looks like we got it back cheaply:
assert_eq!(push_info.reclaimed, true);

// And we did some work
// while waiting to get it:
assert_eq!(hashmap.len(), 1_000);
assert_eq!(vec.len(), 1_000);
assert_eq!(return_value, ());
source

pub fn add_commit_push_clone<Patch, Output>( &mut self, patch: Patch ) -> (PushInfo, Output, Option<Output>)
where Patch: FnMut(&mut T, &T) -> Output,

This is the same as Self::add_commit_push() with Self::push_clone() semantics.

See push_clone()’s documentation for more info.

let (r, mut w) = someday::new::<String>("".into());
let (push_info, _, _) = w.add_commit_push_clone(|w, _| {
    w.push_str("abc");
});

assert_eq!(push_info.commits, 1);
assert_eq!(push_info.reclaimed, false);
source§

impl<T: Clone> Writer<T>

source

pub fn reader(&self) -> Reader<T>

Cheaply construct a Reader connected to this Writer

This creates a new Reader that can read all the data push()’ed from this Writer.

There is no limit on concurrent Reader’s.

let (r, mut w) = someday::new::<usize>(0);

// Create 100 more readers.
let readers: Vec<Reader<usize>> = vec![w.reader(); 100];
source

pub const fn data(&self) -> &T

View the Writer’s local data

This is the Writer’s local data that may or may not have been push()’ed yet.

commit()’ing will apply the add()’ed Patch’s directly to this data.

If push() is called, this would be the new data that Reader’s would see.

let (r, mut w) = someday::new::<usize>(0);

// No changes yet.
assert_eq!(*w.data(), 0);
assert_eq!(r.head().data,  0);

// Writer commits some changes.
w.add(Patch::Ptr(|w, _| *w += 1));
w.commit();

//  Writer sees local change.
assert_eq!(*w.data(), 1);
// Reader doesn't see change.
assert_eq!(r.head().data, 0);
source

pub fn tx(&mut self) -> Transaction<'_, T>

Mutate the Writer’s local data without going through a Patch.

This function gives you direct access to the underlying local T via a Transaction.

In order to prevent out-of-sync situations, Transaction will unconditionally add a Patch that clones data after it has been drop’ed.

This is cheaper than Patch if you had already planned to clone data anyway.

See Transaction for more details.

source

pub fn data_remote(&self) -> &T

View the latest copy of data Reader’s have access to

let (_, mut w) = someday::new::<usize>(0);

// Writer commits some changes.
w.add(Patch::Ptr(|w, _| *w += 1));
w.commit();

// Writer sees local change.
assert_eq!(*w.data(), 1);
// But they haven't been pushed to the remote side
// (Readers can't see them)
assert_eq!(*w.data_remote(), 0);
source

pub const fn head(&self) -> &Commit<T>

View the Writer’s local “head” Commit

This is the latest, and local Commit from the Writer.

Calling commit() would make that new Commit be the return value for this function.

Reader’s may or may not see this Commit yet.

let (_, mut w) = someday::new::<usize>(500);

// No changes yet.
let commit: &Commit<usize> = w.head();
assert_eq!(commit.timestamp, 0);
assert_eq!(commit.data, 500);

// Writer commits some changes.
w.add(Patch::Ptr(|w, _| *w += 1));
w.commit();

// Head commit is now changed.
let commit: &Commit<usize> = w.head();
assert_eq!(commit.timestamp, 1);
assert_eq!(commit.data, 501);
source

pub fn head_remote(&self) -> &Commit<T>

View the Reader’s latest “head” Commit

This is the latest Commit the Reader’s can see.

Calling push() would update the Reader’s head Commit.

let (_, mut w) = someday::new::<usize>(500);

// No changes yet.
let commit: &Commit<usize> = w.head_remote();
assert_eq!(commit.timestamp, 0);
assert_eq!(commit.data, 500);

// Writer commits & pushes some changes.
w.add(Patch::Ptr(|w, _| *w += 1));
w.commit();
w.push();

// Reader's head commit is now changed.
let commit: &Commit<usize> = w.head_remote();
assert_eq!(commit.timestamp, 1);
assert_eq!(commit.data, 501);
source

pub fn head_remote_ref(&self) -> CommitRef<T>

Cheaply acquire ownership of the Reader’s latest “head” Commit

This is the latest Commit the Reader’s can see.

Calling push() would update the Reader’s head Commit.

This is an shared “owned” Commit (it uses Arc internally).

let (r, mut w) = someday::new::<usize>(0);

// Reader gets a reference.
let reader: CommitRef<usize> = r.head();
// Writer gets a reference.
let writer: CommitRef<usize> = w.head_remote_ref();

// Reader drops their reference.
// Nothing happens, an atomic count is decremented.
drop(reader);

// Writer drops their reference.
// They were the last reference, so they are
// responsible for deallocating the backing data.
drop(writer);
source

pub fn staged(&mut self) -> &mut Vec<Patch<T>>

All the Patch’s that haven’t been commit()’ed yet, aka, “staged” changes

You are allowed to do anything to these Patch’s as they haven’t been committed yet and the Writer does not necessarily need them.

You can use something like .staged().drain(..) to get back all the Patch’s.

All the Patch’s that have been commit()’ed but not yet push()’ed are safely stored internally by the Writer.

let (r, mut w) = someday::new::<String>("".into());

// Add some changes.
w.add(Patch::Ptr(|w, _| w.push_str("abc")));

// We see and mutate the staged changes.
assert_eq!(w.staged().len(), 1);

// Let's actually remove that change.
let removed = w.staged().remove(0);
assert_eq!(w.staged().len(), 0);
source

pub const fn committed_patches(&self) -> &Vec<Patch<T>>

All the Patch’s that have been commit()’ed but not yet push()’ed

You are not allowed to mutate these Patch’s as they haven’t been push()’ed yet and the Writer may need them in the future.

let (r, mut w) = someday::new::<String>("".into());

// Commit some changes.
w.add(Patch::Ptr(|w, _| w.push_str("abc")));
w.commit();

// We can see but not mutate functions.
assert_eq!(w.committed_patches().len(), 1);
source

pub fn head_count(&self) -> NonZeroUsize

How many Reader’s are currently accessing the current Reader head Commit?

Note that this will always at least return 2, as the Writer carries 2 strong references to the backing data T.

let (_, mut w) = someday::new::<String>("".into());

// The Writer, `w` holds 2 strong counts.
assert_eq!(w.head_count().get(), 2);

// Create and leak 8 Reader's.
// Note however, the above Reader's
// do not have strong references to the
// underlying data, so they don't count.
for i in 0..8 {
    let reader = w.reader();
    std::mem::forget(reader);
}
let r = w.reader();
assert_eq!(w.head_count().get(), 2);

// Leak the actual data 8 times.
for i in 0..8 {
    let head: CommitRef<String> = r.head();
    std::mem::forget(head);
}

// Now there are 10 strong references.
// (which will never be reclaimed since
// we just leaked them)
assert_eq!(w.head_count().get(), 10);
source

pub fn reader_count(&self) -> NonZeroUsize

How many Reader’s are there?

Unlike Writer::head_count(), this doesn’t count references to the current data, it counts how many Reader objects are in existence.

Note that this will always at least return 1, as the Writer counts as a Reader.

let (r, mut w) = someday::new::<String>("".into());

// 2 Reader's (the Writer counts as a Reader).
assert_eq!(w.reader_count().get(), 2);

// Create and leak 8 Reader's.
for i in 0..8 {
    let reader = r.clone();
    std::mem::forget(reader);
}

// Now there are 10.
assert_eq!(w.reader_count().get(), 10);
source

pub fn readers_exist(&self) -> bool

Does a Reader object associated with this Writer exist?

As noted in Writer::reader_count, the Writer will always count as a Reader, meaning the strong count will always at least be 1.

If it is 1, that means no Reader object exists, in that case, this function will return false.

let (r, mut w) = someday::new::<String>("".into());

// 1 `Reader` exists.
assert!(w.readers_exist());

// 0 `Reader`'s (excluding the `Writer`) exist.
drop(r);
assert!(!w.readers_exist());
source

pub fn status(&self) -> StatusInfo<'_, T>

Get the current status on the Writer and Reader

This is a bag of various metadata about the current state of the Writer and Reader.

If you only need 1 or a few of the fields in StatusInfo, consider using their individual methods instead.

source§

impl<T: Clone> Writer<T>

source

pub fn push(&mut self) -> PushInfo

Conditionally push Writer’s local committed data to the Reader’s.

This will only push changes if there are new Commit’s (i.e if Writer::synced returns true).

This may be expensive as there are other operations in this function (memory reclaiming, re-applying patches).

This will return how many Commit’s the Writer’s pushed.

Reader’s will atomically be able to access the the new Commit before this function is over.

The Patch’s that were not commit()’ed will not be pushed and will remain in the staged() vector of patches.

The PushInfo object returned is just a container for some metadata about the push() operation.

let (r, mut w) = someday::new::<String>("".into());
w.add(Patch::Ptr(|w, _| w.push_str("abc")));

// This call does nothing since
// we haven't committed anything.
let push_info = w.push();
assert_eq!(push_info.timestamp, 0);
assert_eq!(push_info.commits, 0);
assert_eq!(push_info.reclaimed, false);

// Now there are commits to push.
w.commit();

if w.ahead() {
    let push_info = w.push();
    // We pushed 1 commit.
    assert_eq!(push_info.timestamp, 1);
    assert_eq!(push_info.commits, 1);
    assert_eq!(push_info.reclaimed, true);
} else {
    // this branch cannot happen
    unreachable!();
}
source

pub fn push_wait(&mut self, duration: Duration) -> PushInfo

This function is the same as Writer::push() but it will std::thread::sleep() for at least duration amount of time to wait to reclaim the old Reader’s data.

If duration has passed, the Writer will clone the data as normal and continue on.

This is useful if you know your Reader’s only hold onto old data for a brief moment.

let (r, mut w) = someday::new::<String>("".into());
w.add(Patch::Ptr(|w, _| w.push_str("abc")));
w.commit();

let commit = r.head();
spawn(move || {
    // This `Reader` is holding onto the old data.
    let moved = commit;
    // But will let go after 1 millisecond.
    sleep(Duration::from_millis(1));
});

// Wait 250 milliseconds before resorting to cloning data.
let commit_info = w.push_wait(Duration::from_millis(250));
// We pushed 1 commit.
assert_eq!(commit_info.commits, 1);
// And we successfully reclaimed the old data cheaply.
assert_eq!(commit_info.reclaimed, true);
source

pub fn push_do<F, R>(&mut self, f: F) -> (PushInfo, R)
where F: FnOnce() -> R,

This function is the same as Writer::push() but it will execute the function F in the meanwhile before attempting to reclaim the old Reader data.

The generic R is the return value of the function. Leaving it blank and having a non-returning function will be enough inference that the return value is ().

Basically: “run the function F while we’re waiting”

This is useful to get some work done before waiting on the Reader’s to drop old copies of data.

let (r, mut w) = someday::new::<String>("".into());

let head = r.head();
spawn(move || {
    // This `Reader` is holding onto the old data.
    let moved = head;
    // But will let go after 100 milliseconds.
    sleep(Duration::from_millis(100));
});

// Some work to be done.
let mut hashmap = HashMap::<usize, String>::new();
let mut vec     = vec![];

// Commit.
// Now the `Writer` is ahead by 1 commit, while
// the `Reader` is hanging onto the old one.
w.add(Patch::Ptr(|w, _| w.push_str("abc")));
w.commit();

// Pass in a closure, so that we can do
// arbitrary things in the meanwhile...!
let (push_info, return_value) = w.push_do(|| {
    // While we're waiting, let's get some work done.
    // Add a bunch of data to this HashMap.
    (0..1_000).for_each(|i| {
        hashmap.insert(i, format!("{i}"));
    });
    // Add some data to the vector.
    (0..1_000).for_each(|_| {
        vec.push(format!("aaaaaaaaaaaaaaaa"));
    }); // <- `push_do()` returns `()`
});     // although we could return anything
        // and it would be binded to `return_value`

// At this point, the old `Reader`'s have
// probably all dropped their old references
// and we can probably cheaply reclaim our
// old data back.

// And yes, looks like we got it back cheaply:
assert_eq!(push_info.reclaimed, true);

// And we did some work
// while waiting to get it:
assert_eq!(hashmap.len(), 1_000);
assert_eq!(vec.len(), 1_000);
assert_eq!(return_value, ());
source

pub fn push_clone(&mut self) -> PushInfo

This function is the same as Writer::push() but it will always clone the data and not attempt to reclaim any old data.

This is useful if you know reclaiming old data and re-applying your commits would take longer and/or be more expensive than cloning the data itself.

Or if you know your Reader’s will be holding onto the data for a long time, and reclaiming data will be unlikely.

let (r, mut w) = someday::new::<String>("".into());
w.add(Patch::Ptr(|w, _| w.push_str("abc")));
w.commit();

let commit = r.head();
spawn(move || {
    // This `Reader` will hold onto the old data forever.
    let moved = commit;
    loop { std::thread::park(); }
});

// Always clone data, don't wait.
let push_info = w.push_clone();
// We pushed 1 commit.
assert_eq!(push_info.commits, 1);
assert_eq!(push_info.reclaimed, false);
source§

impl<T: Clone> Writer<T>

source

pub fn pull(&mut self) -> Option<PullInfo<T>>

Conditionally overwrite the Writer’s local Commit with the current Reader Commit

If the Writer and Reader are Writer::synced(), this will return None.

If the Writer is ahead of the Reader, this will:

  • Discard all Patch’s that have been already commit()’ed
  • Keep staged Patch’s that haven’t been commit()
  • Return Some(PullInfo)

The PullInfo object returned is just a container for some metadata about the pull() operation.

§Timestamp

If this pull is successful (the Writer and Reader aren’t in sync), this will reset your Writer’s Timestamp to whatever your Reader’s was.

§⚠️ Warning

This overwrites your Writer’s data!

Like a git pull --force!

let (r, mut w) = someday::new::<String>("".into());

// Commit local changes.
w.add(Patch::Ptr(|w, _| w.push_str("hello")));
w.commit();
assert_eq!(w.head().data, "hello");

// Reader's sees nothing
assert_eq!(r.head().data, "");

// Pull from the Reader.
let pull_status: PullInfo<String> = w.pull().unwrap();
assert_eq!(pull_status.old_writer_commit.data, "hello");

// We're back to square 1.
assert_eq!(w.head().data, "");

// If we try to pull again, nothing will happen
// since we are already synced with `Reader`s.
assert!(w.pull().is_none());
source

pub fn overwrite(&mut self, data: T) -> Commit<T>

Overwrite the Writer’s local data with data.

The Writer’s old local data is returned.

All Patch’s that have been already commit()’ed are discarded (Writer::committed_patches()).

Staged Patch’s that haven’t been commit() still kept around (Writer::staged()).

A Patch that overwrites the data applied with commit() would be equivalent to this convenience function, although, this function will be slightly cheaper as it avoids cloning an extra time.

let (r, mut w) = someday::new::<String>("".into());

// Push changes.
w.add(Patch::Ptr(|w, _| w.push_str("hello")));
w.commit(); // <- commit 1
w.push();

assert_eq!(w.timestamp(), 1);

// Reader's sees them.
assert_eq!(r.head().data, "hello");
assert_eq!(r.head().timestamp, 1);

// Commit some changes.
w.add(Patch::Ptr(|w, _| *w = "hello".into()));
w.commit(); // <- commit 2
w.add(Patch::Ptr(|w, _| *w = "hello".into()));
w.commit(); // <- commit 3
w.add(Patch::Ptr(|w, _| *w = "hello".into()));
w.commit(); // <- commit 4
assert_eq!(w.committed_patches().len(), 3);

// Overwrite the Writer with arbitrary data.
let old_data = w.overwrite(String::from("world")); // <- commit 5
assert_eq!(old_data.data, "hello");
assert_eq!(w.data(), "world");
// Committed functions were deleted, but 1 patch is leftover.
// This is an automatically inserted patch that makes the
// reclaimed `Reader`'s `.clone()` the new data.
assert_eq!(w.committed_patches().len(), 1);

// `Reader`'s still don't see changes.
assert_eq!(r.head().data, "hello");

// Push that change.
w.push();

// Now `Reader`s see change.
assert_eq!(r.head().data, "world");

// 5 commits total.
assert_eq!(w.timestamp(), 5);
assert_eq!(r.head().timestamp, 5);
§Timestamp

This increments the Writer’s local Timestamp by 1.

source§

impl<T: Clone> Writer<T>

source

pub fn fork(&self) -> Self

Fork off from the current Reader::head commit and create a Writer.

This new Writer:

  • will contain no Patch’s
  • is disconnected, meaning it has absolutely no relation to self or any other previous Reader’s.
  • has the latest Writer::head as the base for Writer and Reader’s
let (r, mut w) = someday::new(String::new());

// Connected `Reader` <-> `Writer`.
assert!(r.connected_writer(&w));

// Add local changes, but don't push.
w.add_commit(|s, _| {
    s.push_str("hello");
});
assert_eq!(w.data(), "hello");
assert_eq!(w.timestamp(), 1);
assert_eq!(r.head().data, "");
assert_eq!(r.head().timestamp, 0);

// Fork off into another `Writer`.
let mut w2 = w.fork();
let r2 = w2.reader();

// It inherits the data of the previous `Writer`.
assert_eq!(w.data(), "hello");
assert_eq!(w.timestamp(), 1);
assert_eq!(w.head().data, "hello");
assert_eq!(w.head().timestamp, 1);

// And has no relation to the previous `Writer/Reader`'s.
assert!(!r.connected(&r2));
assert!(!r.connected_writer(&w2));

w2.add_commit(|s, _| {
    s.push_str(" world!");
});

assert_eq!(w2.data(), "hello world!");
assert_eq!(w2.timestamp(), 2);
assert_eq!(w.data(), "hello");
assert_eq!(w.timestamp(), 1);
assert_eq!(r.head().data, "");
assert_eq!(r.head().timestamp, 0);
source§

impl<T: Clone> Writer<T>

source

pub fn diff(&self) -> bool
where T: PartialEq<T>,

If the Writer’s local Commit is different than the Reader’s

Compares the Commit that the Reader’s can currently access with the Writer’s current local Commit.

This returns true if either the:

§Purpose

In correct scenarios, the Writer’s and Reader’s Timestamp’s should be all that is needed to indicate if the data is different or not.

However, if your Patch functions are non-determistic, the data may get out of sync.

Thus, this function is mostly meant to be used for debugging purposes.

// Create a non-deterministic `Writer/Reader`
// out-of-sync issue.
static STATE: Mutex<usize> = Mutex::new(1);
let (_, mut w) = someday::new::<usize>(0);
w.add(Patch::boxed(move |w, _| {
    let mut state = STATE.lock().unwrap();
    *state *= 10; // 1*10 the first time, 10*10 the second time...
    *w = *state;
}));
w.commit();
w.push();

// Same timestamps...
assert_eq!(w.timestamp(), w.reader().head().timestamp);

// ⚠️ Out of sync data!
assert_eq!(*w.data(), 100);
assert_eq!(w.reader().head().data, 10);

// But, this function tells us the truth.
assert_eq!(w.diff(), true);
source

pub fn ahead(&self) -> bool

If the Writer’s local Timestamp is greater than the Reader’s Timestamp

Compares the timestamp of the Reader’s currently available data with the Writer’s current local timestamp.

This returns true if the Writer’s timestamp is greater than Reader’s timestamp (which means Writer is ahead of the Reader’s)

Note that this does not check the data itself, only the Timestamp.

let (r, mut w) = someday::new::<String>("".into());

// Commit 10 times but don't push.
for i in 0..10 {
    w.add(Patch::Ptr(|w, _| w.push_str("abc")));
    w.commit();
}

// Writer at timestamp 10.
assert_eq!(w.timestamp(), 10);

// Reader at timestamp 0.
assert_eq!(r.head().timestamp, 0);

// Writer is ahead of the Reader's.
assert!(w.ahead());
source

pub const fn ahead_of(&self, commit: &Commit<T>) -> bool

If the Writer’s local Timestamp is greater than an arbitrary Commit’s Timestamp

This takes any type of Commit, so either CommitRef or Commit can be used as input.

let (_, mut w) = someday::new::<String>("".into());

// Commit 10 times.
for i in 0..10 {
    w.add(Patch::Ptr(|w, _| w.push_str("abc")));
    w.commit();
}
// At timestamp 10.
assert_eq!(w.timestamp(), 10);

// Create fake `Commit`
let fake_commit = Commit {
    timestamp: 1,
    data: String::new(),
};

// Writer is ahead of that commit.
assert!(w.ahead_of(&fake_commit));
source

pub const fn behind(&self, commit: &Commit<T>) -> bool

If the Writer’s local Timestamp is less than an arbitrary Commit’s Timestamp

This takes any type of Commit, so either CommitRef or Commit can be used as input.

let (_, mut w) = someday::new::<String>("".into());

// At timestamp 0.
assert_eq!(w.timestamp(), 0);

// Create fake `Commit`
let fake_commit = Commit {
    timestamp: 1000,
    data: String::new(),
};

// Writer is behind that commit.
assert!(w.behind(&fake_commit));
source

pub const fn timestamp(&self) -> Timestamp

Get the current Timestamp of the Writer’s local Commit

This returns the number indicating the Writer’s data’s version.

This number starts at 0, increments by 1 every time a Writer::commit() -like operation is called, and it will never be less than the Reader’s Timestamp.

let (r, mut w) = someday::new::<String>("".into());

// At timestamp 0.
assert_eq!(w.timestamp(), 0);

// Commit some changes.
w.add(Patch::Ptr(|w, _| w.push_str("abc")));
w.commit();

// At timestamp 1.
assert_eq!(w.timestamp(), 1);
// We haven't pushed, so Reader's
// are still at timestamp 0.
assert_eq!(r.head().timestamp, 0);
source

pub fn timestamp_remote(&self) -> Timestamp

Get the current Timestamp of the Reader’s “head” Commit

This returns the number indicating the Reader’s data’s version.

This will never be greater than the Writer’s timestamp.

let (r, mut w) = someday::new::<String>("".into());

// At timestamp 0.
assert_eq!(w.timestamp(), 0);

// Commit some changes.
w.add(Patch::Ptr(|w, _| w.push_str("abc")));
w.commit();

// Writer is at timestamp 1.
assert_eq!(w.timestamp(), 1);
// We haven't pushed, so Reader's
// are still at timestamp 0.
assert_eq!(r.head().timestamp, 0);

// Push changes
w.push();

// Readers are now up-to-date.
assert_eq!(r.head().timestamp, 1);
source

pub fn timestamp_diff(&self) -> usize

Get the difference between the Writer’s and Reader’s Timestamp

This returns the number indicating how many commits the Writer is ahead on compared to the Reader’s.

In other words, it is: writer_timestamp - reader_timestamp

let (r, mut w) = someday::new::<String>("".into());

// At timestamp 0.
assert_eq!(w.timestamp(), 0);

// Push 1 change.
w.add(Patch::Ptr(|w, _| w.push_str("abc")));
w.commit();
w.push();

// Commit 5 changes locally.
for i in 0..5 {
    w.add(Patch::Ptr(|w, _| w.push_str("abc")));
    w.commit();
}

// Writer is at timestamp 5.
assert_eq!(w.timestamp(), 6);
// Reader's are still at timestamp 1.
assert_eq!(r.head().timestamp, 1);

// The difference is 5.
assert_eq!(w.timestamp_diff(), 5);
source

pub fn synced(&self) -> bool

Is the Writer’s and Reader’s Timestamp the same?

This returns true if the Writer and Reader’s timestamp are the same, indicating they have same data and are in-sync.

let (r, mut w) = someday::new::<String>("".into());

// At timestamp 0.
assert_eq!(w.timestamp(), 0);

// Push 1 change.
w.add(Patch::Ptr(|w, _| w.push_str("abc")));
w.commit();
w.push();

// Commit 5 changes locally.
for i in 0..5 {
    w.add(Patch::Ptr(|w, _| w.push_str("abc")));
    w.commit();
}

// Writer is at timestamp 5.
assert_eq!(w.timestamp(), 6);
// Reader's are still at timestamp 1.
assert_eq!(r.head().timestamp, 1);

// They aren't in sync.
assert_eq!(w.synced(), false);
// Now they are.
w.push();
assert_eq!(w.synced(), true);
source§

impl<T: Clone> Writer<T>

source

pub fn new(data: T) -> Self

Same as crate::free::new but without creating a Reader.

let (r, w) = someday::new("hello");
let w2 = Writer::new("hello");

assert_eq!(w.data(), w2.data());
assert_eq!(w.timestamp(), w2.timestamp());
source

pub fn restore(&mut self) -> Drain<'_, Patch<T>>

Restore all the staged changes.

This removes all the Patch’s that haven’t yet been commit()’ed.

Calling Writer::staged().drain(..) would be equivalent.

Dropping the std::vec::Drain will drop the Patch’s.

let (r, mut w) = someday::new::<String>("".into());

// Add some changes, but don't commit.
w.add(Patch::Ptr(|w, _| w.push_str("abc")));
assert_eq!(w.staged().len(), 1);

// Restore changes.
let drain = w.restore();
assert_eq!(drain.count(), 1);
source

pub fn shrink_to_fit(&mut self)

Shrinks the capacity of the Patch Vec’s as much as possible

This calls Vec::shrink_to_fit() on the 2 internal Vec’s in Writer holding:

  1. The currently staged Patch’s
  2. The already committed Patch’s
let (_, mut w) = someday::new::<String>("".into());

// Capacity is 16.
assert_eq!(w.committed_patches().capacity(), 16);
assert_eq!(w.staged().capacity(),            16);

// Commit 32 `Patch`'s
for i in 0..32 {
    w.add(Patch::Ptr(|w, _| *w = "".into()));
    w.commit();
}
// Stage 16 `Patch`'s
for i in 0..16 {
    w.add(Patch::Ptr(|w, _| *w = "".into()));
}

// Commit capacity is now 32.
assert_eq!(w.committed_patches().capacity(), 32);
// This didn't change, we already had
// enough space to store them.
assert_eq!(w.staged().capacity(), 16);

// Commit, push, shrink.
w.commit();
w.push();
w.shrink_to_fit();

// They're now empty and taking 0 space.
assert_eq!(w.committed_patches().capacity(), 0);
assert_eq!(w.staged().capacity(), 0);
source

pub fn reserve_exact(&mut self, additional: usize)

Reserve capacity in the Patch Vec’s

This calls Vec::reserve_exact() on the 2 internal Vec’s in Writer holding:

  1. The currently staged Patch’s
  2. The already committed Patch’s
let (_, mut w) = someday::new::<String>("".into());

// Capacity is 16.
assert_eq!(w.committed_patches().capacity(), 16);
assert_eq!(w.staged().capacity(),            16);

// Reserve space for 48 more patches.
w.reserve_exact(48);
assert!(w.committed_patches().capacity() >= 48);
assert!(w.staged().capacity()            >= 48);
§Panics

Panics if the new capacity exceeds isize::MAX bytes.

source

pub fn connected(&self, reader: &Reader<T>) -> bool

Is this Writer associated with this Reader?

This returns true if both self and other are Reader’s from the same Writer.

This means both Reader’s receive the same Commit upon calling Reader::head.

let (r, w) = someday::new(());

// All `Reader`'s read from the same `Writer`.
let r2 = w.reader();
let r3 = r2.clone();
assert!(w.connected(&r));
assert!(w.connected(&r2));
assert!(w.connected(&r3));

// This one is completely separate.
let (r4, _) = someday::new(());
assert!(!r.connected(&r4));
source

pub fn disconnect(&mut self)

Disconnect from the Reader’s associated with this Writer.

This completely severs the link between the Reader’s associated with this Writer.

Any older Reader’s will no longer receive Commit’s from this Writer, and Reader::writer_dropped will start to return true. From the perspective of the older Reader’s, calling this function is the same as this Writer being dropped.

Any future Reader’s created after this function are completely separate from the past Reader’s.

let (r, mut w) = someday::new("");

// Connected `Reader` <-> `Writer`.
assert!(w.connected(&r));

// Now, disconnected.
w.disconnect();
assert!(!w.connected(&r));

// The older `Reader` won't see pushes anymore.
w.add_commit_push(|w, _| *w = "hello");
assert_eq!(*w.data(), "hello");
assert_eq!(r.head().data, "");

// But, newer `Reader`'s will.
let r2 = w.reader();
assert_eq!(r2.head().data, "hello");
source

pub fn into_inner(self) -> WriterInfo<T>

Consume this Writer and return the inner components.

let (r, mut w) = someday::new::<String>("".into());

// Commit some changes.
w.add(Patch::Ptr(|w, _| w.push_str("a")));
w.commit();

// Add but don't commit.
w.add(Patch::Ptr(|w, _| w.push_str("b")));

let WriterInfo {
    writer,
    reader,
    staged,
    committed_patches,
} = w.into_inner();

assert_eq!(writer.data, "a");
assert_eq!(reader.data, ""); // We never `push()`'ed, so Readers saw nothing.
assert_eq!(staged.len(), 1);
assert_eq!(committed_patches.len(), 1);

Trait Implementations§

source§

impl<T: Clone> AsRef<T> for Writer<T>

source§

fn as_ref(&self) -> &T

Converts this type into a shared reference of the (usually inferred) input type.
source§

impl<T: Clone> Borrow<T> for Writer<T>

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorshDeserialize for Writer<T>

source§

fn deserialize_reader<R: Read>(reader: &mut R) -> Result<Self>

This will deserialize a Commit directly into a Writer.

let (r, mut w) = someday::new(String::from("hello"));
w.add_commit(|w, _| {
    w.push_str(" world!");
});
assert_eq!(w.timestamp(), 1);
assert_eq!(w.data(), "hello world!");
assert_eq!(r.head().timestamp, 0);
assert_eq!(r.head().data, "hello");

// Decode into a `Commit`.
let encoded = borsh::to_vec(&w).unwrap();
let decoded: Commit<String> = borsh::from_slice(&encoded).unwrap();
assert_eq!(decoded, Commit { timestamp: 1, data: String::from("hello world!") });

// Decode directly into a `Writer<T>`.
let writer: Writer<String> = borsh::from_slice(&encoded).unwrap();
assert_eq!(writer.timestamp(), 1);
assert_eq!(writer.data(), "hello world!");
source§

fn deserialize(buf: &mut &[u8]) -> Result<Self, Error>

Deserializes this instance from a given slice of bytes. Updates the buffer to point at the remaining bytes.
source§

fn try_from_slice(v: &[u8]) -> Result<Self, Error>

Deserialize this instance from a slice of bytes.
source§

fn try_from_reader<R>(reader: &mut R) -> Result<Self, Error>
where R: Read,

source§

impl<T> BorshSerialize for Writer<T>
where T: Clone + BorshSerialize,

source§

fn serialize<W: Write>(&self, writer: &mut W) -> Result<()>

This will serialize the latest Commit of the Writer.

source§

impl<T: Clone> Clone for Writer<T>

source§

fn clone(&self) -> Self

This is the exact same as Writer::fork.

Note that this means cloning a Writer completely disconnects it from previous Reader’s.

This does not create 2 Writer’s to the same data, as that is not allowed.

let (r, mut w) = someday::new(String::new());

// The clone has no relation to the previous `Writer/Reader`'s.
let clone: Writer<String> = w.clone();
assert!(!clone.connected(&r));

// Wrapping `Writer` in a shared mutual exclusion primitive
// allows it to be cheaply cloned, without `fork()`-like behavior.
let shared = Arc::new(Mutex::new(clone));
let reader = shared.lock().unwrap().reader();
assert!(shared.lock().unwrap().connected(&reader));
assert!(!shared.lock().unwrap().connected(&r));
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl<T> Debug for Writer<T>
where T: Clone + Debug,

source§

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

Formats the value using the given formatter. Read more
source§

impl<T> Decode for Writer<T>
where T: Clone + Decode,

source§

fn decode<D: Decoder>(decoder: &mut D) -> Result<Self, DecodeError>

This will deserialize a Commit directly into a Writer.

let (r, mut w) = someday::new(String::from("hello"));
w.add_commit(|w, _| {
    w.push_str(" world!");
});
assert_eq!(w.timestamp(), 1);
assert_eq!(w.data(), "hello world!");
assert_eq!(r.head().timestamp, 0);
assert_eq!(r.head().data, "hello");

let config = bincode::config::standard();

// Decode into a `Commit`.
let encoded = bincode::encode_to_vec(&w, config).unwrap();
let decoded: Commit<String> = bincode::decode_from_slice(&encoded, config).unwrap().0;
assert_eq!(decoded, Commit { timestamp: 1, data: String::from("hello world!") });

// Decode directly into a `Writer<T>`.
let writer: Writer<String> = bincode::decode_from_slice(&encoded, config).unwrap().0;
assert_eq!(writer.timestamp(), 1);
assert_eq!(writer.data(), "hello world!");
source§

impl<T> Default for Writer<T>
where T: Clone + Default,

source§

fn default() -> Self

Only generates the Writer.

This initializes your data T with Default::default().

let (_, w1) = someday::new::<usize>(Default::default());
let w2      = Writer::<usize>::default();

assert_eq!(*w1.data(), 0);
assert_eq!(*w2.data(), 0);
source§

impl<T: Clone> Deref for Writer<T>

§

type Target = T

The resulting type after dereferencing.
source§

fn deref(&self) -> &Self::Target

Dereferences the value.
source§

impl<'de, T> Deserialize<'de> for Writer<T>
where T: Clone + Deserialize<'de>,

source§

fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where D: Deserializer<'de>,

This will deserialize a Commit directly into a Writer.

let (r, mut w) = someday::new(String::from("hello"));
w.add_commit(|w, _| {
    w.push_str(" world!");
});
assert_eq!(w.timestamp(), 1);
assert_eq!(w.data(), "hello world!");
assert_eq!(r.head().timestamp, 0);
assert_eq!(r.head().data, "hello");

let json = serde_json::to_string(&w).unwrap();
assert_eq!(json, "{\"timestamp\":1,\"data\":\"hello world!\"}");

let writer: Writer<String> = serde_json::from_str(&json).unwrap();
assert_eq!(writer.timestamp(), 1);
assert_eq!(writer.data(), "hello world!");
source§

impl<T> Encode for Writer<T>
where T: Clone + Encode,

source§

fn encode<E: Encoder>(&self, encoder: &mut E) -> Result<(), EncodeError>

This will serialize the latest Commit of the Writer.

source§

impl<T: Clone> From<&Writer<T>> for Reader<T>

source§

fn from(value: &Writer<T>) -> Self

Converts to this type from the input type.
source§

impl<T: Clone> From<Arc<Commit<T>>> for Writer<T>

source§

fn from(commit: CommitRef<T>) -> Self

Same as crate::free::from_commit but without creating a Reader.

source§

impl<T: Clone> From<Commit<T>> for Writer<T>

source§

fn from(commit: Commit<T>) -> Self

Same as crate::free::from_commit but without creating a Reader.

source§

impl<T: Clone> From<T> for Writer<T>

source§

fn from(data: T) -> Self

Same as crate::free::new but without creating a Reader.

source§

impl<T> Serialize for Writer<T>
where T: Clone + Serialize,

source§

fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer,

This will serialize the latest Commit of the Writer.

source§

impl<T: Clone> TryFrom<Reader<T>> for Writer<T>

source§

fn try_from(reader: Reader<T>) -> Result<Self, Self::Error>

§

type Error = Reader<T>

The type returned in the event of a conversion error.

Auto Trait Implementations§

§

impl<T> !RefUnwindSafe for Writer<T>

§

impl<T> Send for Writer<T>
where T: Sync + Send,

§

impl<T> !Sync for Writer<T>

§

impl<T> Unpin for Writer<T>
where T: Unpin,

§

impl<T> !UnwindSafe for Writer<T>

Blanket Implementations§

source§

impl<T, A, P> Access<T> for P
where A: Access<T> + ?Sized, P: Deref<Target = A>,

§

type Guard = <A as Access<T>>::Guard

A guard object containing the value and keeping it alive. Read more
source§

fn load(&self) -> <P as Access<T>>::Guard

The loading method. Read more
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, A> DynAccess<T> for A
where A: Access<T>, <A as Access<T>>::Guard: 'static,

source§

fn load(&self) -> DynGuard<T>

The equivalent of Access::load.
source§

impl<T> From<!> for T

source§

fn from(t: !) -> T

Converts to this type from the input type.
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> ToOwned for T
where T: Clone,

§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

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

§

type Error = Infallible

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

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

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

§

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.
source§

impl<T> DeserializeOwned for T
where T: for<'de> Deserialize<'de>,