Struct duat_core::data::RoData

source ·
pub struct RoData<T>
where T: ?Sized + 'static,
{ /* private fields */ }
Expand description

A read-only reference to information.

A data type that can read, but not write, the inner data. If you wish to get a read write struct, see RwData. This struct is usually what you will get as a readable handle from structs containing RwData. For example, when opening a new file, we use a hook, called the constructor_hook, to do certain actions to that file, like opening surroundig Widgets. This hook can provide an RoData<FileWidget<U>>, which is then queryed by the widget for information about the file. This also prevents the modification of data by third parties which shouldn`t be able to do so.

Can only be created by cloning the Arc<RwLock<T>> from a RwData<T>, or through cloning.

Implementations§

source§

impl<T> RoData<T>

source

pub fn new(data: T) -> Self

Returns a new instance of a RoData<T>, assuming that it is sized.

This has to be sized because of some Rust limitations, as you cant really pass an unsized argument to a function (for now). If you're looking to store unsized types (dyn Trait, [Type], etc) on a [RwData], see [RwData::new_unsized`].

source§

impl<T> RoData<T>
where T: ?Sized,

source

pub fn new_unsized<SizedT: 'static>(data: Arc<RwLock<T>>) -> Self

Returns a new instance of RoData<T>, assuming that it is unsized.

This method is only required if you’re dealing with types that may not be Sized (dyn Trait, [Type], etc). If the type in question is sized, use RwData::new instead.

source

pub fn read(&self) -> RwLockReadGuard<'_, T>

Blocking reference to the information.

Also makes it so that has_changed returns false.

§Examples

Since this is a blocking read, the thread will hault while the data is being written to:

let read_write_data = RwData::new("☹️");
let read_only_data = RoData::from(&read_write_data);
let instant = Instant::now();
thread::scope(|scope| {
    scope.spawn(|| {
        let mut read_write = read_write_data.write();
        // Supposedly long computations.
        thread::sleep(Duration::from_millis(100));
        *read_write = "☺️";
    });

    // Just making sure that the read happens slighly after the write.
    thread::sleep(Duration::from_millis(1));

    let read_only = read_only_data.read();
    let time_elapsed = Instant::now().duration_since(instant);
    assert!(time_elapsed >= Duration::from_millis(100));
    assert!(*read_only == "☺️");
});

Note that other reads will NOT block reading in this way, only writes:

let read_write_data = RwData::new("☹️");
let read_only_data = RoData::from(&read_write_data);
let instant = Instant::now();
thread::scope(|scope| {
    scope.spawn(|| {
        let read_only = read_write_data.read();
        // The thread hangs, but reading is still possible.
        thread::sleep(Duration::from_millis(100));
    });

    // Just making sure that this read happens slighly after the last one.
    thread::sleep(Duration::from_millis(1));

    let read_only = read_only_data.read();
    let time_elapsed = Instant::now().duration_since(instant);
    assert!(time_elapsed < Duration::from_millis(100));
});
source

pub fn inspect<U>(&self, f: impl FnOnce(&T) -> U) -> U

Blocking inspection of the inner data.

Also makes it so that has_changed returns false.

§Examples

This method is useful if you want to scope the reading, or need to drop the reference quickly, so it can be written to.

You can do this:

let count = RwData::new(31);
let count_reader = RoData::from(&count);

// The read write counterpart to `inspect`.
count.mutate(|count| {
    *count += 5;
    add_to_count(count)
});

count_reader.inspect(|count| { /* reading operations */ });

*count.write() = new_count();

Instead of this:

let count = RwData::new(31);
let count_reader = RoData::from(&count);

// The read write counterpart to `inspect`.
let mut count_write = count.write();
*count_write += 5;
add_to_count(&mut *count_write);
drop(count_write);

let count_read = count_reader.read();
// reading operations
drop(count_read);

*count.write() = new_count();

Or this:

let count = RwData::new(31);
let count_reader = RoData::from(&count);

// The read write counterpart to `inspect`.
{
    let mut count = count.write();
    *count += 5;
    add_to_count(&mut count)
}

{
    let count = count.read();
    // reading operations
}

*count.write() = new_count();
source

pub fn try_read(&self) -> Option<RwLockReadGuard<'_, T>>

Non blocking reference to the information.

If successful, also makes it so that has_changed returns false.

§Examples

Unlike read, can fail to return a reference to the underlying data:

let new_data = RwData::new("hello 👋");

let mut blocking_write = new_data.write();
*blocking_write = "bye 👋";

let try_read = new_data.try_read();
assert!(matches!(try_read, Err(TryLockError::WouldBlock)));
source

pub fn try_inspect<U>(&self, f: impl FnOnce(&T) -> U) -> Option<U>

Non blocking inspection of the inner data.

If successful, also makes it so that has_changed returns false.

§Examples

Unlike inspect, can fail to return a reference to the underlying data:

let new_data = RwData::new("hello 👋");

let try_inspect = new_data.mutate(|blocking_mutate| {
    *blocking_mutate = "bye 👋";

    new_data.try_inspect(|try_inspect| *try_inspect == "bye 👋")
});

assert!(matches!(try_inspect, Err(TryLockError::WouldBlock)));
source

pub fn has_changed(&self) -> bool

Wether or not it has changed since it was last read.

A “change” is defined as any time the methods write, mutate, try_write, or try_mutate, are called on an RwData. Once has_changed is called, the data will be considered unchanged since the last has_changed call, for that specific instance of a [ReadableData].

When first creating a [ReadableData] type, has_changed will return false;

§Examples
use duat_core::data::{ReadableData, RoData, RwData};
let new_data = RwData::new("Initial text");
assert!(!new_data.has_changed());

let first_reader = RoData::from(&new_data);

*new_data.write() = "Final text";

let second_reader = RoData::from(&new_data);

assert!(first_reader.has_changed());
assert!(!second_reader.has_changed());
source

pub fn ptr_eq<U>(&self, other: &impl Data<U>) -> bool
where U: ?Sized,

Returns true if both [ReadableData<T>]s point to the same data.

§Examples
let data_1 = RwData::new(false);
let data_1_clone = data_1.clone();

let data_2 = RwData::new(true);

assert!(data_1.ptr_eq(&data_1_clone));
assert!(!data_1.ptr_eq(&data_2));
source

pub fn inspect_as<U: 'static, R>(&self, f: impl FnOnce(&U) -> R) -> Option<R>

Blocking inspection of the inner data.

§Examples

You may want this method if you’re storing a list of RwData<dyn Trait>, and want to know, at runtime, what type each element is:

let list: [RwData<dyn Any>; 3] = [
    RwData::new_unsized(Arc::new(RwLock::new(DownCastableString(
        String::from("I can show you the world"),
    )))),
    RwData::new_unsized(Arc::new(RwLock::new(DownCastableString(
        String::from("Shining, shimmering, splendid"),
    )))),
    RwData::new_unsized(Arc::new(RwLock::new(DownCastableChar('🧞')))),
];

assert!(matches!(
    list[2].inspect_as::<DownCastableChar, char>(|char| char.0),
    Some('🧞')
));
assert!(matches!(
    list[1].inspect_as::<DownCastableChar, char>(|char| char.0),
    None
));
source

pub fn data_is<U>(&self) -> bool
where U: 'static,

source

pub fn try_downcast<U>(&self) -> Option<RoData<U>>
where U: 'static,

Tries to downcast to a concrete type.

source§

impl<U> RoData<dyn ActiveWidget<U>>
where U: Ui,

source

pub fn to_passive(self) -> RoData<dyn PassiveWidget<U>>

Trait Implementations§

source§

impl<T> Clone for RoData<T>
where T: ?Sized,

source§

fn clone(&self) -> Self

Returns a copy of the value. Read more
1.0.0 · source§

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

Performs copy-assignment from source. Read more
source§

impl<T: ?Sized> Data<T> for RoData<T>

source§

fn to_ro(&self) -> RoData<T>

source§

fn has_changed(&self) -> bool

source§

impl<T> Debug for RoData<T>
where T: ?Sized + Debug,

source§

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

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

impl<T> Default for RoData<T>
where T: Default,

source§

fn default() -> Self

Returns the “default value” for a type. Read more
source§

impl<D> From<&RoData<D>> for BuilderPart<String>
where D: Display,

source§

fn from(value: &RoData<D>) -> Self

Converts to this type from the input type.
source§

impl<T> From<&RwData<T>> for RoData<T>
where T: ?Sized,

source§

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

Converts to this type from the input type.
source§

impl<T: ?Sized + Send> Send for RoData<T>

source§

impl<T: ?Sized + Sync> Sync for RoData<T>

Auto Trait Implementations§

§

impl<T> !Freeze for RoData<T>

§

impl<T> !RefUnwindSafe for RoData<T>

§

impl<T> Unpin for RoData<T>
where T: ?Sized,

§

impl<T> !UnwindSafe for RoData<T>

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> CloneToUninit for T
where T: Clone,

source§

default unsafe fn clone_to_uninit(&self, dst: *mut T)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dst. 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> 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.