Struct icu_provider::prelude::DataPayload
source · [−]pub struct DataPayload<M> where
M: DataMarker, { /* private fields */ }
Expand description
A container for data payloads returned from a data provider.
DataPayload
is built on top of the yoke
framework, which allows for cheap, zero-copy
operations on data via the use of self-references.
The type of the data stored in DataPayload
is determined by the DataMarker
type parameter.
Accessing the data
To get a reference to the data inside DataPayload
, use DataPayload::get()
. If you need
to store the data for later use, you need to store the DataPayload
itself, since get
only
returns a reference with an ephemeral lifetime.
Mutating the data
To modify the data stored in a DataPayload
, use DataPayload::with_mut()
.
Transforming the data to a different type
To transform a DataPayload
to a different type backed by the same data store (cart), use
DataPayload::map_project()
or one of its sister methods.
Cargo feature: sync
By default, the payload uses non-concurrent reference counting internally, and hence is neither
Sync
nor Send
; if these traits are required, the sync
Cargo feature can be enabled.
Examples
Basic usage, using the HelloWorldV1Marker
marker:
use icu_provider::hello_world::*;
use icu_provider::prelude::*;
use std::borrow::Cow;
let payload = DataPayload::<HelloWorldV1Marker>::from_owned(HelloWorldV1 {
message: Cow::Borrowed("Demo"),
});
assert_eq!("Demo", payload.get().message);
Implementations
sourceimpl<M> DataPayload<M> where
M: DataMarker + 'static,
M::Yokeable: MaybeSendSync,
impl<M> DataPayload<M> where
M: DataMarker + 'static,
M::Yokeable: MaybeSendSync,
sourcepub fn wrap_into_any_payload(self) -> AnyPayload
pub fn wrap_into_any_payload(self) -> AnyPayload
Moves this DataPayload to the heap (requiring an allocation) and returns it as an
erased AnyPayload
.
Examples
use icu_provider::hello_world::*;
use icu_provider::prelude::*;
use std::borrow::Cow;
use std::rc::Rc;
let payload: DataPayload<HelloWorldV1Marker> =
DataPayload::from_owned(HelloWorldV1 {
message: Cow::Borrowed("Custom Hello World"),
});
let any_payload = payload.wrap_into_any_payload();
let payload: DataPayload<HelloWorldV1Marker> =
any_payload.downcast().expect("TypeId matches");
assert_eq!("Custom Hello World", payload.get().message);
sourceimpl DataPayload<AnyMarker>
impl DataPayload<AnyMarker>
sourcepub fn downcast<M>(self) -> Result<DataPayload<M>, DataError> where
M: DataMarker + 'static,
for<'a> YokeTraitHack<<M::Yokeable as Yokeable<'a>>::Output>: Clone,
M::Yokeable: ZeroFrom<'static, M::Yokeable>,
M::Yokeable: MaybeSendSync,
pub fn downcast<M>(self) -> Result<DataPayload<M>, DataError> where
M: DataMarker + 'static,
for<'a> YokeTraitHack<<M::Yokeable as Yokeable<'a>>::Output>: Clone,
M::Yokeable: ZeroFrom<'static, M::Yokeable>,
M::Yokeable: MaybeSendSync,
Transforms a type-erased DataPayload<AnyMarker>
into a concrete DataPayload<M>
.
sourceimpl DataPayload<BufferMarker>
impl DataPayload<BufferMarker>
sourcepub fn attempt_zero_copy_heap_size<M>(self) -> HeapStats where
M: DataMarker,
for<'a> &'a <M::Yokeable as Yokeable<'a>>::Output: Serialize,
for<'de> YokeTraitHack<<M::Yokeable as Yokeable<'de>>::Output>: Deserialize<'de>,
pub fn attempt_zero_copy_heap_size<M>(self) -> HeapStats where
M: DataMarker,
for<'a> &'a <M::Yokeable as Yokeable<'a>>::Output: Serialize,
for<'de> YokeTraitHack<<M::Yokeable as Yokeable<'de>>::Output>: Deserialize<'de>,
Given a buffer known to be in postcard-0.7 format, attempt to zero-copy deserialize it and record the amount of heap allocations that occurred.
Ideally, this number should be zero.
[dhat
]’s profiler must be initialized before using this.
Panics
Panics if the buffer is not in postcard-0.7 format.
sourceimpl DataPayload<ExportMarker>
impl DataPayload<ExportMarker>
sourcepub fn serialize<S>(&self, serializer: S) -> Result<(), DataError> where
S: Serializer,
S::Ok: 'static,
pub fn serialize<S>(&self, serializer: S) -> Result<(), DataError> where
S: Serializer,
S::Ok: 'static,
Serializes this DataPayload
into a serializer using Serde.
Examples
use icu_provider::datagen::*;
use icu_provider::dynutil::UpcastDataPayload;
use icu_provider::hello_world::HelloWorldV1Marker;
use icu_provider::prelude::*;
// Create an example DataPayload
let payload: DataPayload<HelloWorldV1Marker> = Default::default();
let export: DataPayload<ExportMarker> = UpcastDataPayload::upcast(payload);
// Serialize the payload to a JSON string
let mut buffer: Vec<u8> = vec![];
export
.serialize(&mut serde_json::Serializer::new(&mut buffer))
.expect("Serialization should succeed");
assert_eq!("{\"message\":\"(und) Hello World\"}".as_bytes(), buffer);
sourcepub fn tokenize(&self, env: &CrateEnv) -> TokenStream
pub fn tokenize(&self, env: &CrateEnv) -> TokenStream
Serializes this DataPayload
’s value into a TokenStream
using its Bake
implementations.
Examples
use icu_provider::datagen::*;
use icu_provider::dynutil::UpcastDataPayload;
use icu_provider::hello_world::HelloWorldV1Marker;
use icu_provider::prelude::*;
// Create an example DataPayload
let payload: DataPayload<HelloWorldV1Marker> = Default::default();
let export: DataPayload<ExportMarker> = UpcastDataPayload::upcast(payload);
let env = databake::CrateEnv::default();
let tokens = export.tokenize(&env);
assert_eq!(
quote! {
::icu_provider::hello_world::HelloWorldV1 {
message: alloc::borrow::Cow::Borrowed("(und) Hello World"),
}
}
.to_string(),
tokens.to_string()
);
assert_eq!(
env.into_iter().collect::<BTreeSet<_>>(),
["icu_provider", "alloc"]
.into_iter()
.collect::<BTreeSet<_>>()
);
sourceimpl DataPayload<HelloWorldV1Marker>
impl DataPayload<HelloWorldV1Marker>
sourcepub fn from_static_str(s: &'static str) -> DataPayload<HelloWorldV1Marker>
pub fn from_static_str(s: &'static str) -> DataPayload<HelloWorldV1Marker>
Make a DataPayload
<
HelloWorldV1Marker
>
from a static string slice.
sourceimpl<M> DataPayload<M> where
M: DataMarker,
impl<M> DataPayload<M> where
M: DataMarker,
sourcepub fn from_owned(data: M::Yokeable) -> Self
pub fn from_owned(data: M::Yokeable) -> Self
Convert a fully owned ('static
) data struct into a DataPayload.
This constructor creates 'static
payloads.
Examples
use icu_provider::hello_world::*;
use icu_provider::prelude::*;
use std::borrow::Cow;
let local_struct = HelloWorldV1 {
message: Cow::Owned("example".to_owned()),
};
let payload =
DataPayload::<HelloWorldV1Marker>::from_owned(local_struct.clone());
assert_eq!(payload.get(), &local_struct);
sourcepub fn try_unwrap_owned(self) -> Result<M::Yokeable, DataError>
pub fn try_unwrap_owned(self) -> Result<M::Yokeable, DataError>
Convert a DataPayload that was created via DataPayload::from_owned()
back into the
concrete type used to construct it.
sourcepub fn with_mut<'a, F>(&'a mut self, f: F) where
F: 'static + for<'b> FnOnce(&'b mut <M::Yokeable as Yokeable<'a>>::Output),
pub fn with_mut<'a, F>(&'a mut self, f: F) where
F: 'static + for<'b> FnOnce(&'b mut <M::Yokeable as Yokeable<'a>>::Output),
Mutate the data contained in this DataPayload.
For safety, all mutation operations must take place within a helper function that cannot borrow data from the surrounding context.
Examples
Basic usage:
use icu_provider::hello_world::HelloWorldV1Marker;
use icu_provider::prelude::*;
let mut payload =
DataPayload::<HelloWorldV1Marker>::from_static_str("Hello");
payload.with_mut(|s| s.message.to_mut().push_str(" World"));
assert_eq!("Hello World", payload.get().message);
To transfer data from the context into the data struct, use the move
keyword:
use icu_provider::hello_world::HelloWorldV1Marker;
use icu_provider::prelude::*;
let mut payload =
DataPayload::<HelloWorldV1Marker>::from_static_str("Hello");
let suffix = " World";
payload.with_mut(move |s| s.message.to_mut().push_str(suffix));
assert_eq!("Hello World", payload.get().message);
sourcepub fn get<'a>(&'a self) -> &'a <M::Yokeable as Yokeable<'a>>::Output
pub fn get<'a>(&'a self) -> &'a <M::Yokeable as Yokeable<'a>>::Output
Borrows the underlying data.
This function should be used like Deref
would normally be used. For more information on
why DataPayload cannot implement Deref
, see the yoke
crate.
Examples
use icu_provider::hello_world::HelloWorldV1Marker;
use icu_provider::prelude::*;
let payload = DataPayload::<HelloWorldV1Marker>::from_static_str("Demo");
assert_eq!("Demo", payload.get().message);
sourcepub fn map_project<M2, F>(self, f: F) -> DataPayload<M2> where
M2: DataMarker,
F: for<'a> FnOnce(<M::Yokeable as Yokeable<'a>>::Output, PhantomData<&'a ()>) -> <M2::Yokeable as Yokeable<'a>>::Output,
pub fn map_project<M2, F>(self, f: F) -> DataPayload<M2> where
M2: DataMarker,
F: for<'a> FnOnce(<M::Yokeable as Yokeable<'a>>::Output, PhantomData<&'a ()>) -> <M2::Yokeable as Yokeable<'a>>::Output,
Maps DataPayload<M>
to DataPayload<M2>
by projecting it with Yoke::map_project
.
This is accomplished by a function that takes M
’s data type and returns M2
’s data
type. The function takes a second argument which should be ignored. For more details,
see Yoke::map_project()
.
The standard DataPayload::map_project()
function moves self
and cannot capture any
data from its context. Use one of the sister methods if you need these capabilities:
DataPayload::map_project_cloned()
if you don’t have ownership ofself
DataPayload::try_map_project()
to bubble up an errorDataPayload::try_map_project_cloned()
to do both of the above
Examples
Map from HelloWorldV1
to a Cow<str>
containing just the message:
use icu_provider::hello_world::*;
use icu_provider::prelude::*;
use std::borrow::Cow;
// A custom marker type is required when using `map_project`. The Yokeable should be the
// target type, and the Cart should correspond to the type being transformed.
struct HelloWorldV1MessageMarker;
impl DataMarker for HelloWorldV1MessageMarker {
type Yokeable = Cow<'static, str>;
}
let p1: DataPayload<HelloWorldV1Marker> = DataPayload::from_owned(HelloWorldV1 {
message: Cow::Borrowed("Hello World"),
});
assert_eq!("Hello World", p1.get().message);
let p2: DataPayload<HelloWorldV1MessageMarker> = p1.map_project(|obj, _| obj.message);
// Note: at this point, p1 has been moved.
assert_eq!("Hello World", p2.get());
sourcepub fn map_project_cloned<'this, M2, F>(&'this self, f: F) -> DataPayload<M2> where
M2: DataMarker,
F: for<'a> FnOnce(&'this <M::Yokeable as Yokeable<'a>>::Output, PhantomData<&'a ()>) -> <M2::Yokeable as Yokeable<'a>>::Output,
pub fn map_project_cloned<'this, M2, F>(&'this self, f: F) -> DataPayload<M2> where
M2: DataMarker,
F: for<'a> FnOnce(&'this <M::Yokeable as Yokeable<'a>>::Output, PhantomData<&'a ()>) -> <M2::Yokeable as Yokeable<'a>>::Output,
Version of DataPayload::map_project()
that borrows self
instead of moving self
.
Examples
Same example as above, but this time, do not move out of p1
:
// Same imports and definitions as above
let p1: DataPayload<HelloWorldV1Marker> =
DataPayload::from_owned(HelloWorldV1 {
message: Cow::Borrowed("Hello World"),
});
assert_eq!("Hello World", p1.get().message);
let p2: DataPayload<HelloWorldV1MessageMarker> =
p1.map_project_cloned(|obj, _| obj.message.clone());
// Note: p1 is still valid.
assert_eq!(p1.get().message, *p2.get());
sourcepub fn try_map_project<M2, F, E>(self, f: F) -> Result<DataPayload<M2>, E> where
M2: DataMarker,
F: for<'a> FnOnce(<M::Yokeable as Yokeable<'a>>::Output, PhantomData<&'a ()>) -> Result<<M2::Yokeable as Yokeable<'a>>::Output, E>,
pub fn try_map_project<M2, F, E>(self, f: F) -> Result<DataPayload<M2>, E> where
M2: DataMarker,
F: for<'a> FnOnce(<M::Yokeable as Yokeable<'a>>::Output, PhantomData<&'a ()>) -> Result<<M2::Yokeable as Yokeable<'a>>::Output, E>,
Version of DataPayload::map_project()
that bubbles up an error from f
.
Examples
Same example as above, but bubble up an error:
// Same imports and definitions as above
let p1: DataPayload<HelloWorldV1Marker> =
DataPayload::from_owned(HelloWorldV1 {
message: Cow::Borrowed("Hello World"),
});
assert_eq!("Hello World", p1.get().message);
let string_to_append = "Extra";
let p2: DataPayload<HelloWorldV1MessageMarker> =
p1.try_map_project(|mut obj, _| {
if obj.message.is_empty() {
return Err("Example error");
}
obj.message.to_mut().push_str(string_to_append);
Ok(obj.message)
})?;
assert_eq!("Hello WorldExtra", p2.get());
sourcepub fn try_map_project_cloned<'this, M2, F, E>(
&'this self,
f: F
) -> Result<DataPayload<M2>, E> where
M2: DataMarker,
F: for<'a> FnOnce(&'this <M::Yokeable as Yokeable<'a>>::Output, PhantomData<&'a ()>) -> Result<<M2::Yokeable as Yokeable<'a>>::Output, E>,
pub fn try_map_project_cloned<'this, M2, F, E>(
&'this self,
f: F
) -> Result<DataPayload<M2>, E> where
M2: DataMarker,
F: for<'a> FnOnce(&'this <M::Yokeable as Yokeable<'a>>::Output, PhantomData<&'a ()>) -> Result<<M2::Yokeable as Yokeable<'a>>::Output, E>,
Version of DataPayload::map_project_cloned()
that bubbles up an error from f
.
Examples
Same example as above, but bubble up an error:
// Same imports and definitions as above
let p1: DataPayload<HelloWorldV1Marker> =
DataPayload::from_owned(HelloWorldV1 {
message: Cow::Borrowed("Hello World"),
});
assert_eq!("Hello World", p1.get().message);
let string_to_append = "Extra";
let p2: DataPayload<HelloWorldV1MessageMarker> = p1
.try_map_project_cloned(|obj, _| {
if obj.message.is_empty() {
return Err("Example error");
}
let mut message = obj.message.clone();
message.to_mut().push_str(string_to_append);
Ok(message)
})?;
// Note: p1 is still valid, but the values no longer equal.
assert_ne!(p1.get().message, *p2.get());
assert_eq!("Hello WorldExtra", p2.get());
sourcepub fn cast<M2>(self) -> DataPayload<M2> where
M2: DataMarker<Yokeable = M::Yokeable>,
pub fn cast<M2>(self) -> DataPayload<M2> where
M2: DataMarker<Yokeable = M::Yokeable>,
Convert between two DataMarker
types that are compatible with each other.
This happens if they both have the same DataMarker::Yokeable
type.
Can be used to erase the key of a data payload in cases where multiple keys correspond to the same data struct.
Examples
use icu_locid::locale;
use icu_provider::hello_world::*;
use icu_provider::prelude::*;
struct CustomHelloWorldV1Marker;
impl DataMarker for CustomHelloWorldV1Marker {
type Yokeable = HelloWorldV1<'static>;
}
let hello_world: DataPayload<HelloWorldV1Marker> = todo!();
let custom: DataPayload<CustomHelloWorldV1Marker> = hello_world.cast();
sourceimpl DataPayload<BufferMarker>
impl DataPayload<BufferMarker>
sourcepub fn from_owned_buffer(buffer: Box<[u8]>) -> Self
pub fn from_owned_buffer(buffer: Box<[u8]>) -> Self
Converts an owned byte buffer into a DataPayload<BufferMarker>
.
sourcepub fn from_yoked_buffer(yoke: Yoke<&'static [u8], Option<Cart>>) -> Self
pub fn from_yoked_buffer(yoke: Yoke<&'static [u8], Option<Cart>>) -> Self
Converts a yoked byte buffer into a DataPayload<BufferMarker>
.
sourcepub fn from_static_buffer(buffer: &'static [u8]) -> Self
pub fn from_static_buffer(buffer: &'static [u8]) -> Self
Converts a static byte buffer into a DataPayload<BufferMarker>
.
sourceimpl DataPayload<BufferMarker>
impl DataPayload<BufferMarker>
sourcepub fn into_deserialized<M>(
self,
buffer_format: BufferFormat
) -> Result<DataPayload<M>, DataError> where
M: DataMarker,
for<'de> YokeTraitHack<<M::Yokeable as Yokeable<'de>>::Output>: Deserialize<'de>,
pub fn into_deserialized<M>(
self,
buffer_format: BufferFormat
) -> Result<DataPayload<M>, DataError> where
M: DataMarker,
for<'de> YokeTraitHack<<M::Yokeable as Yokeable<'de>>::Output>: Deserialize<'de>,
Deserialize a DataPayload
<
BufferMarker
>
into a DataPayload
of a
specific concrete type.
This function takes the buffer format as an argument. When a buffer payload is returned
from a data provider, the buffer format is stored in the DataResponseMetadata
.
Examples
Requires the deserialize_json
Cargo feature:
use icu_provider::buf::BufferFormat;
use icu_provider::hello_world::*;
use icu_provider::prelude::*;
let buffer: &[u8] = b"{\"message\":\"Hallo Welt\"}";
let buffer_payload = DataPayload::from_owned(buffer);
let payload: DataPayload<HelloWorldV1Marker> = buffer_payload
.into_deserialized(BufferFormat::Json)
.expect("Deserialization successful");
assert_eq!(payload.get().message, "Hallo Welt");
Trait Implementations
sourceimpl<M> Clone for DataPayload<M> where
M: DataMarker,
for<'a> YokeTraitHack<<M::Yokeable as Yokeable<'a>>::Output>: Clone,
impl<M> Clone for DataPayload<M> where
M: DataMarker,
for<'a> YokeTraitHack<<M::Yokeable as Yokeable<'a>>::Output>: Clone,
sourceimpl<M> Debug for DataPayload<M> where
M: DataMarker,
for<'a> &'a <M::Yokeable as Yokeable<'a>>::Output: Debug,
impl<M> Debug for DataPayload<M> where
M: DataMarker,
for<'a> &'a <M::Yokeable as Yokeable<'a>>::Output: Debug,
sourceimpl<M> Default for DataPayload<M> where
M: DataMarker,
M::Yokeable: Default,
impl<M> Default for DataPayload<M> where
M: DataMarker,
M::Yokeable: Default,
sourceimpl<M> PartialEq<DataPayload<M>> for DataPayload<M> where
M: DataMarker,
for<'a> YokeTraitHack<<M::Yokeable as Yokeable<'a>>::Output>: PartialEq,
impl<M> PartialEq<DataPayload<M>> for DataPayload<M> where
M: DataMarker,
for<'a> YokeTraitHack<<M::Yokeable as Yokeable<'a>>::Output>: PartialEq,
sourceimpl<M> TryFrom<DataResponse<M>> for DataPayload<M> where
M: DataMarker,
impl<M> TryFrom<DataResponse<M>> for DataPayload<M> where
M: DataMarker,
impl<M> Eq for DataPayload<M> where
M: DataMarker,
for<'a> YokeTraitHack<<M::Yokeable as Yokeable<'a>>::Output>: Eq,
Auto Trait Implementations
impl<M> RefUnwindSafe for DataPayload<M> where
<M as DataMarker>::Yokeable: RefUnwindSafe,
impl<M> Send for DataPayload<M> where
<M as DataMarker>::Yokeable: Send,
impl<M> Sync for DataPayload<M> where
<M as DataMarker>::Yokeable: Sync,
impl<M> Unpin for DataPayload<M> where
<M as DataMarker>::Yokeable: Unpin,
impl<M> UnwindSafe for DataPayload<M> where
<M as DataMarker>::Yokeable: UnwindSafe,
Blanket Implementations
sourceimpl<T> BorrowMut<T> for T where
T: ?Sized,
impl<T> BorrowMut<T> for T where
T: ?Sized,
const: unstable · sourcefn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more
sourceimpl<T> ToOwned for T where
T: Clone,
impl<T> ToOwned for T where
T: Clone,
type Owned = T
type Owned = T
The resulting type after obtaining ownership.
sourcefn clone_into(&self, target: &mut T)
fn clone_into(&self, target: &mut T)
toowned_clone_into
)Uses borrowed data to replace owned data, usually by cloning. Read more