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>
impl<T> RoData<T>
sourcepub fn new(data: T) -> Self
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,
impl<T> RoData<T>where
T: ?Sized,
sourcepub fn new_unsized<SizedT: 'static>(data: Arc<RwLock<T>>) -> Self
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.
sourcepub fn read(&self) -> RwLockReadGuard<'_, T>
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));
});sourcepub fn inspect<U>(&self, f: impl FnOnce(&T) -> U) -> U
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();sourcepub fn try_read(&self) -> Option<RwLockReadGuard<'_, T>>
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)));sourcepub fn try_inspect<U>(&self, f: impl FnOnce(&T) -> U) -> Option<U>
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)));sourcepub fn has_changed(&self) -> bool
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());sourcepub fn ptr_eq<U>(&self, other: &impl Data<U>) -> boolwhere
U: ?Sized,
pub fn ptr_eq<U>(&self, other: &impl Data<U>) -> boolwhere
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));sourcepub fn inspect_as<U: 'static, R>(&self, f: impl FnOnce(&U) -> R) -> Option<R>
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
));pub fn data_is<U>(&self) -> boolwhere
U: 'static,
sourcepub fn try_downcast<U>(&self) -> Option<RoData<U>>where
U: 'static,
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,
impl<U> RoData<dyn ActiveWidget<U>>where
U: Ui,
pub fn to_passive(self) -> RoData<dyn PassiveWidget<U>>
Trait Implementations§
impl<T: ?Sized + Send> Send for RoData<T>
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> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
source§default unsafe fn clone_to_uninit(&self, dst: *mut T)
default unsafe fn clone_to_uninit(&self, dst: *mut T)
clone_to_uninit)