pub struct Yoke<Y: for<'a> Yokeable<'a>, C> { /* private fields */ }
Expand description
A Cow-like borrowed object “yoked” to its backing data.
This allows things like zero copy deserialized data to carry around shared references to their backing buffer, by “erasing” their static lifetime and turning it into a dynamically managed one.
Y
(the Yokeable
) is the object containing the references,
and will typically be of the form Foo<'static>
. The 'static
is
not the actual lifetime of the data, rather it is a convenient way to mark the
erased lifetime and make it dynamic.
C
is the “cart”, which Y
may contain references to. After the yoke is constructed,
the cart serves little purpose except to guarantee that Y
’s references remain valid
for as long as the yoke remains in memory (by calling the destructor at the appropriate moment).
The primary constructor for Yoke
is Yoke::attach_to_cart()
. Several variants of that
constructor are provided to serve numerous types of call sites and Yoke
signatures.
The key behind this type is Yoke::get()
, where calling .get()
on a type like
Yoke<Cow<'static, str>, _>
will get you a short-lived &'a Cow<'a, str>
, restricted to the
lifetime of the borrow used during .get()
. This is entirely safe since the Cow
borrows from
the cart type C
, which cannot be interfered with as long as the Yoke
is borrowed by .get ()
. .get()
protects access by essentially reifying the erased lifetime to a safe local one
when necessary.
Furthermore, there are various .project()
methods that allow turning a Yoke
into another Yoke
containing a different type that may contain elements of the original yoked
value. See the Yoke::project()
docs for more details.
In general, C
is a concrete type, but it is also possible for it to be a trait object;
for more information, see IsCovariant
.
Example
For example, we can use this to store zero-copy deserialized data in a cache:
fn load_object(filename: &str) -> Yoke<Cow<'static, str>, Rc<[u8]>> {
let rc: Rc<[u8]> = load_from_cache(filename);
Yoke::<Cow<'static, str>, Rc<[u8]>>::attach_to_cart_badly(rc, |data: &[u8]| {
// essentially forcing a #[serde(borrow)]
Cow::Borrowed(bincode::deserialize(data).unwrap())
})
}
let yoke = load_object("filename.bincode");
assert_eq!(&**yoke.get(), "hello");
assert!(matches!(yoke.get(), &Cow::Borrowed(_)));
Implementations
sourceimpl<Y: for<'a> Yokeable<'a>, C: StableDeref> Yoke<Y, C>
impl<Y: for<'a> Yokeable<'a>, C: StableDeref> Yoke<Y, C>
sourcepub fn attach_to_cart<F>(cart: C, f: F) -> Self where
F: for<'de> FnOnce(&'de <C as Deref>::Target) -> <Y as Yokeable<'de>>::Output,
pub fn attach_to_cart<F>(cart: C, f: F) -> Self where
F: for<'de> FnOnce(&'de <C as Deref>::Target) -> <Y as Yokeable<'de>>::Output,
Construct a Yoke
by yokeing an object to a cart in a closure.
See also Yoke::try_attach_to_cart()
to return a Result
from the closure.
Call sites for this function may not compile; if this happens, use
Yoke::attach_to_cart_badly()
instead.
Examples
The following code does not currently compile. See #1061.
fn load_object(filename: &str) -> Yoke<Cow<'static, str>, Rc<[u8]>> {
let rc: Rc<[u8]> = load_from_cache(filename);
Yoke::<Cow<'static, str>, Rc<[u8]>>::attach_to_cart(rc, |data: &[u8]| {
// essentially forcing a #[serde(borrow)]
Cow::Borrowed(bincode::deserialize(data).unwrap())
})
}
let yoke: Yoke<Cow<str>, _> = load_object("filename.bincode");
assert_eq!(&**yoke.get(), "hello");
assert!(matches!(yoke.get(), &Cow::Borrowed(_)));
sourcepub fn try_attach_to_cart<E, F>(cart: C, f: F) -> Result<Self, E> where
F: for<'de> FnOnce(&'de <C as Deref>::Target) -> Result<<Y as Yokeable<'de>>::Output, E>,
pub fn try_attach_to_cart<E, F>(cart: C, f: F) -> Result<Self, E> where
F: for<'de> FnOnce(&'de <C as Deref>::Target) -> Result<<Y as Yokeable<'de>>::Output, E>,
Construct a Yoke
by yokeing an object to a cart. If an error occurs in the
deserializer function, the error is passed up to the caller.
Call sites for this function may not compile; if this happens, use
Yoke::try_attach_to_cart_badly()
instead.
See #1061.
sourcepub fn attach_to_cart_badly(
cart: C,
f: for<'de> fn(_: &'de <C as Deref>::Target) -> <Y as Yokeable<'de>>::Output
) -> Self
pub fn attach_to_cart_badly(
cart: C,
f: for<'de> fn(_: &'de <C as Deref>::Target) -> <Y as Yokeable<'de>>::Output
) -> Self
Construct a Yoke
by yokeing an object to a cart in a closure.
For a version of this function that takes a FnOnce
instead of a raw function pointer,
see Yoke::attach_to_cart()
.
Example
For example, we can use this to store zero-copy deserialized data in a cache:
fn load_object(filename: &str) -> Yoke<Cow<'static, str>, Rc<[u8]>> {
let rc: Rc<[u8]> = load_from_cache(filename);
Yoke::<Cow<'static, str>, Rc<[u8]>>::attach_to_cart_badly(rc, |data: &[u8]| {
// essentially forcing a #[serde(borrow)]
Cow::Borrowed(bincode::deserialize(data).unwrap())
})
}
let yoke: Yoke<Cow<str>, _> = load_object("filename.bincode");
assert_eq!(&**yoke.get(), "hello");
assert!(matches!(yoke.get(), &Cow::Borrowed(_)));
sourcepub fn try_attach_to_cart_badly<E>(
cart: C,
f: for<'de> fn(_: &'de <C as Deref>::Target) -> Result<<Y as Yokeable<'de>>::Output, E>
) -> Result<Self, E>
pub fn try_attach_to_cart_badly<E>(
cart: C,
f: for<'de> fn(_: &'de <C as Deref>::Target) -> Result<<Y as Yokeable<'de>>::Output, E>
) -> Result<Self, E>
Construct a Yoke
by yokeing an object to a cart. If an error occurs in the
deserializer function, the error is passed up to the caller.
For a version of this function that takes a FnOnce
instead of a raw function pointer,
see Yoke::try_attach_to_cart()
.
Examples
let rc = Rc::new([0xb, 0xa, 0xd]);
let yoke_result: Result<Yoke<Cow<str>, Rc<[u8]>>, _> =
Yoke::try_attach_to_cart_badly(rc, |data: &[u8]| {
bincode::deserialize(data)
});
assert!(matches!(yoke_result, Err(_)));
sourceimpl<Y: for<'a> Yokeable<'a>, C> Yoke<Y, C>
impl<Y: for<'a> Yokeable<'a>, C> Yoke<Y, C>
sourcepub fn get<'a>(&'a self) -> &'a <Y as Yokeable<'a>>::Output
pub fn get<'a>(&'a self) -> &'a <Y as Yokeable<'a>>::Output
Obtain a valid reference to the yokeable data
This essentially transforms the lifetime of the internal yokeable data to
be valid.
For example, if you’re working with a Yoke<Cow<'static, T>, C>
, this
will return an &'a Cow<'a, T>
Example
// load_object() defined in the example at the top of this page
let yoke: Yoke<Cow<str>, _> = load_object("filename.bincode");
assert_eq!(yoke.get(), "hello");
sourcepub fn backing_cart(&self) -> &C
pub fn backing_cart(&self) -> &C
Get a reference to the backing cart.
This can be useful when building caches, etc. However, if you plan to store the cart
separately from the yoke, read the note of caution below in Yoke::into_backing_cart
.
sourcepub fn into_backing_cart(self) -> C
pub fn into_backing_cart(self) -> C
Get the backing cart by value, dropping the yokeable object.
Caution: Calling this method could cause information saved in the yokeable object but not the cart to be lost. Use this method only if the yokeable object cannot contain its own information.
Example
Good example: the yokeable object is only a reference, so no information can be lost.
use yoke::Yoke;
let local_data = "foo".to_string();
let yoke = Yoke::<
&'static str,
Box<String>
>::attach_to_zero_copy_cart(Box::new(local_data));
assert_eq!(*yoke.get(), "foo");
// Get back the cart
let cart = yoke.into_backing_cart();
assert_eq!(&*cart, "foo");
Bad example: information specified in .with_mut()
is lost.
use yoke::Yoke;
use std::borrow::Cow;
let local_data = "foo".to_string();
let mut yoke = Yoke::<
Cow<'static, str>,
Box<String>
>::attach_to_zero_copy_cart(Box::new(local_data));
assert_eq!(yoke.get(), "foo");
// Override data in the cart
yoke.with_mut(|cow| {
let mut_str = cow.to_mut();
mut_str.clear();
mut_str.push_str("bar");
});
assert_eq!(yoke.get(), "bar");
// Get back the cart
let cart = yoke.into_backing_cart();
assert_eq!(&*cart, "foo"); // WHOOPS!
sourcepub unsafe fn replace_cart<C2>(self, f: impl FnOnce(C) -> C2) -> Yoke<Y, C2>
pub unsafe fn replace_cart<C2>(self, f: impl FnOnce(C) -> C2) -> Yoke<Y, C2>
Unsafe function for replacing the cart with another
This can be used for type-erasing the cart, for example.
Safety
f()
must not panic- References from the yokeable
Y
should still be valid for the lifetime of the returned cart typeC
.
Typically, this means implementing f
as something which wraps the inner cart type C
.
Yoke
only really cares about destructors for its carts so it’s fine to erase other
information about the cart, as long as the backing data will still be destroyed at the
same time.
sourcepub fn with_mut<'a, F>(&'a mut self, f: F) where
F: 'static + for<'b> FnOnce(&'b mut <Y as Yokeable<'a>>::Output),
pub fn with_mut<'a, F>(&'a mut self, f: F) where
F: 'static + for<'b> FnOnce(&'b mut <Y as Yokeable<'a>>::Output),
Mutate the stored Yokeable
data.
See Yokeable::transform_mut()
for why this operation is safe.
Example
This can be used to partially mutate the stored data, provided no new borrowed data is introduced.
// also implements Yokeable
struct Bar<'a> {
numbers: Cow<'a, [u8]>,
string: Cow<'a, str>,
owned: Vec<u8>,
}
// `load_object()` deserializes an object from a file
let mut bar: Yoke<Bar, _> = load_object("filename.bincode");
assert_eq!(bar.get().string, "hello");
assert!(matches!(bar.get().string, Cow::Borrowed(_)));
assert_eq!(&*bar.get().numbers, &[0x68, 0x65, 0x6c, 0x6c, 0x6f]);
assert!(matches!(bar.get().numbers, Cow::Borrowed(_)));
assert_eq!(&*bar.get().owned, &[]);
bar.with_mut(|bar| {
bar.string.to_mut().push_str(" world");
bar.owned.extend_from_slice(&[1, 4, 1, 5, 9]);
});
assert_eq!(bar.get().string, "hello world");
assert!(matches!(bar.get().string, Cow::Owned(_)));
assert_eq!(&*bar.get().owned, &[1, 4, 1, 5, 9]);
// Unchanged and still Cow::Borrowed
assert_eq!(&*bar.get().numbers, &[0x68, 0x65, 0x6c, 0x6c, 0x6f]);
assert!(matches!(bar.get().numbers, Cow::Borrowed(_)));
sourcepub fn wrap_cart_in_option(self) -> Yoke<Y, Option<C>>
pub fn wrap_cart_in_option(self) -> Yoke<Y, Option<C>>
Helper function allowing one to wrap the cart type C
in an Option<T>
.
sourceimpl<Y: for<'a> Yokeable<'a>> Yoke<Y, ()>
impl<Y: for<'a> Yokeable<'a>> Yoke<Y, ()>
sourcepub fn new_always_owned(yokeable: Y) -> Self
pub fn new_always_owned(yokeable: Y) -> Self
Construct a new Yoke
from static data. There will be no
references to cart
here since Yokeable
s are 'static
,
this is good for e.g. constructing fully owned
Yoke
s with no internal borrowing.
This is similar to Yoke::new_owned()
but it does not allow you to
mix the Yoke
with borrowed data. This is primarily useful
for using Yoke
in generic scenarios.
Example
let owned: Cow<str> = "hello".to_owned().into();
// this yoke can be intermingled with actually-borrowed Yokes
let yoke: Yoke<Cow<str>, ()> = Yoke::new_always_owned(owned);
assert_eq!(yoke.get(), "hello");
sourcepub fn into_yokeable(self) -> Y
pub fn into_yokeable(self) -> Y
Obtain the yokeable out of a Yoke<Y, ()>
For most Yoke
types this would be unsafe but it’s
fine for Yoke<Y, ()>
since there are no actual internal
references
sourceimpl<Y: for<'a> Yokeable<'a>, C: StableDeref> Yoke<Y, Option<C>>
impl<Y: for<'a> Yokeable<'a>, C: StableDeref> Yoke<Y, Option<C>>
sourcepub fn new_owned(yokeable: Y) -> Self
pub fn new_owned(yokeable: Y) -> Self
Construct a new Yoke
from static data. There will be no
references to cart
here since Yokeable
s are 'static
,
this is good for e.g. constructing fully owned
Yoke
s with no internal borrowing.
This can be paired with [Yoke:: wrap_cart_in_option()
] to mix owned
and borrowed data.
If you do not wish to pair this with borrowed data, Yoke::new_always_owned()
can
be used to get a Yoke
API on always-owned data.
Example
let owned: Cow<str> = "hello".to_owned().into();
// this yoke can be intermingled with actually-borrowed Yokes
let yoke: Yoke<Cow<str>, Option<Rc<[u8]>>> = Yoke::new_owned(owned);
assert_eq!(yoke.get(), "hello");
sourcepub fn try_into_yokeable(self) -> Result<Y, Self>
pub fn try_into_yokeable(self) -> Result<Y, Self>
Obtain the yokeable out of a Yoke<Y, Option<C>>
if possible.
If the cart is None
, this returns Some
, but if the cart is Some
,
this returns self
as an error.
sourceimpl<Y: for<'a> Yokeable<'a>, C> Yoke<Y, C>
impl<Y: for<'a> Yokeable<'a>, C> Yoke<Y, C>
sourcepub fn project<P>(
self,
f: for<'a> fn(_: <Y as Yokeable<'a>>::Output, _: PhantomData<&'a ()>) -> <P as Yokeable<'a>>::Output
) -> Yoke<P, C> where
P: for<'a> Yokeable<'a>,
pub fn project<P>(
self,
f: for<'a> fn(_: <Y as Yokeable<'a>>::Output, _: PhantomData<&'a ()>) -> <P as Yokeable<'a>>::Output
) -> Yoke<P, C> where
P: for<'a> Yokeable<'a>,
Allows one to “project” a yoke to perform a transformation on the data, potentially looking at a subfield, and producing a new yoke. This will move cart, and the provided transformation is only allowed to use data known to be borrowed from the cart.
This takes an additional PhantomData<&()>
parameter as a workaround to the issue
described in #86702. This parameter
should just be ignored in the function.
To capture data and pass it to the closure, use Yoke::project_with_capture()
.
See #1061.
This can be used, for example, to transform data from one format to another:
fn slice(y: Yoke<&'static str, Rc<[u8]>>) -> Yoke<&'static [u8], Rc<[u8]>> {
y.project(move |yk, _| yk.as_bytes())
}
This can also be used to create a yoke for a subfield
// also safely implements Yokeable<'a>
struct Bar<'a> {
string_1: &'a str,
string_2: &'a str,
}
fn project_string_1(bar: Yoke<Bar<'static>, Rc<[u8]>>) -> Yoke<&'static str, Rc<[u8]>> {
bar.project(|bar, _| bar.string_1)
}
sourcepub fn project_cloned<'this, P>(
&'this self,
f: for<'a> fn(_: &'this <Y as Yokeable<'a>>::Output, _: PhantomData<&'a ()>) -> <P as Yokeable<'a>>::Output
) -> Yoke<P, C> where
P: for<'a> Yokeable<'a>,
C: CloneableCart,
pub fn project_cloned<'this, P>(
&'this self,
f: for<'a> fn(_: &'this <Y as Yokeable<'a>>::Output, _: PhantomData<&'a ()>) -> <P as Yokeable<'a>>::Output
) -> Yoke<P, C> where
P: for<'a> Yokeable<'a>,
C: CloneableCart,
This is similar to Yoke::project
, however it does not move
Self
and instead clones the cart (only if the cart is a CloneableCart
)
This is a bit more efficient than cloning the Yoke
and then calling Yoke::project
because then it will not clone fields that are going to be discarded.
sourcepub fn project_with_capture<P, T>(
self,
capture: T,
f: for<'a> fn(_: <Y as Yokeable<'a>>::Output, capture: T, _: PhantomData<&'a ()>) -> <P as Yokeable<'a>>::Output
) -> Yoke<P, C> where
P: for<'a> Yokeable<'a>,
pub fn project_with_capture<P, T>(
self,
capture: T,
f: for<'a> fn(_: <Y as Yokeable<'a>>::Output, capture: T, _: PhantomData<&'a ()>) -> <P as Yokeable<'a>>::Output
) -> Yoke<P, C> where
P: for<'a> Yokeable<'a>,
This is similar to Yoke::project
, but it works around it not being able to
use FnOnce
by using an explicit capture input.
See #1061.
See the docs of Yoke::project
for how this works.
sourcepub fn project_cloned_with_capture<'this, P, T>(
&'this self,
capture: T,
f: for<'a> fn(_: &'this <Y as Yokeable<'a>>::Output, capture: T, _: PhantomData<&'a ()>) -> <P as Yokeable<'a>>::Output
) -> Yoke<P, C> where
P: for<'a> Yokeable<'a>,
C: CloneableCart,
pub fn project_cloned_with_capture<'this, P, T>(
&'this self,
capture: T,
f: for<'a> fn(_: &'this <Y as Yokeable<'a>>::Output, capture: T, _: PhantomData<&'a ()>) -> <P as Yokeable<'a>>::Output
) -> Yoke<P, C> where
P: for<'a> Yokeable<'a>,
C: CloneableCart,
This is similar to Yoke::project_cloned
, however it works around it not being able to
use FnOnce
by using an explicit capture input.
See #1061.
See the docs of Yoke::project_cloned
for how this works.
sourcepub fn try_project_with_capture<P, T, E>(
self,
capture: T,
f: for<'a> fn(_: <Y as Yokeable<'a>>::Output, capture: T, _: PhantomData<&'a ()>) -> Result<<P as Yokeable<'a>>::Output, E>
) -> Result<Yoke<P, C>, E> where
P: for<'a> Yokeable<'a>,
pub fn try_project_with_capture<P, T, E>(
self,
capture: T,
f: for<'a> fn(_: <Y as Yokeable<'a>>::Output, capture: T, _: PhantomData<&'a ()>) -> Result<<P as Yokeable<'a>>::Output, E>
) -> Result<Yoke<P, C>, E> where
P: for<'a> Yokeable<'a>,
A version of Yoke::project
that takes a capture and bubbles up an error
from the callback function.
sourcepub fn try_project_cloned_with_capture<'this, P, T, E>(
&'this self,
capture: T,
f: for<'a> fn(_: &'this <Y as Yokeable<'a>>::Output, capture: T, _: PhantomData<&'a ()>) -> Result<<P as Yokeable<'a>>::Output, E>
) -> Result<Yoke<P, C>, E> where
P: for<'a> Yokeable<'a>,
C: CloneableCart,
pub fn try_project_cloned_with_capture<'this, P, T, E>(
&'this self,
capture: T,
f: for<'a> fn(_: &'this <Y as Yokeable<'a>>::Output, capture: T, _: PhantomData<&'a ()>) -> Result<<P as Yokeable<'a>>::Output, E>
) -> Result<Yoke<P, C>, E> where
P: for<'a> Yokeable<'a>,
C: CloneableCart,
A version of Yoke::project_cloned
that takes a capture and bubbles up an error
from the callback function.
sourceimpl<Y: for<'a> Yokeable<'a>, C: 'static + Sized> Yoke<Y, Rc<C>>
impl<Y: for<'a> Yokeable<'a>, C: 'static + Sized> Yoke<Y, Rc<C>>
sourcepub fn erase_rc_cart(self) -> Yoke<Y, ErasedRcCart>
pub fn erase_rc_cart(self) -> Yoke<Y, ErasedRcCart>
Allows type-erasing the cart in a Yoke<Y, Rc<C>>
.
The yoke only carries around a cart type C
for its destructor,
since it needs to be able to guarantee that its internal references
are valid for the lifetime of the Yoke. As such, the actual type of the
Cart is not very useful unless you wish to extract data out of it
via Yoke::backing_cart()
. Erasing the cart allows for one to mix
Yoke
s obtained from different sources.
In case the cart type C
is not already an Rc<T>
, you can use
Yoke::wrap_cart_in_rc()
to wrap it.
Example
use yoke::Yoke;
use yoke::erased::ErasedRcCart;
use std::rc::Rc;
let buffer1: Rc<String> = Rc::new(" foo bar baz ".into());
let buffer2: Box<String> = Box::new(" baz quux ".into());
let yoke1 = Yoke::<&'static str, _>::attach_to_cart_badly(buffer1, |rc| rc.trim());
let yoke2 = Yoke::<&'static str, _>::attach_to_cart_badly(buffer2, |b| b.trim());
let erased1: Yoke<_, ErasedRcCart> = yoke1.erase_rc_cart();
// Wrap the Box in an Rc to make it compatible
let erased2: Yoke<_, ErasedRcCart> = yoke2.wrap_cart_in_rc().erase_rc_cart();
// Now erased1 and erased2 have the same type!
Available with the "alloc"
feature enabled.
sourceimpl<Y: for<'a> Yokeable<'a>, C: 'static + Sized> Yoke<Y, Box<C>>
impl<Y: for<'a> Yokeable<'a>, C: 'static + Sized> Yoke<Y, Box<C>>
sourcepub fn erase_box_cart(self) -> Yoke<Y, ErasedBoxCart>
pub fn erase_box_cart(self) -> Yoke<Y, ErasedBoxCart>
Allows type-erasing the cart in a Yoke<Y, Box<C>>
.
The yoke only carries around a cart type C
for its destructor,
since it needs to be able to guarantee that its internal references
are valid for the lifetime of the Yoke. As such, the actual type of the
Cart is not very useful unless you wish to extract data out of it
via Yoke::backing_cart()
. Erasing the cart allows for one to mix
Yoke
s obtained from different sources.
In case the cart type C
is not already Box<T>
, you can use
Yoke::wrap_cart_in_box()
to wrap it.
Example
use yoke::Yoke;
use yoke::erased::ErasedBoxCart;
use std::rc::Rc;
let buffer1: Rc<String> = Rc::new(" foo bar baz ".into());
let buffer2: Box<String> = Box::new(" baz quux ".into());
let yoke1 = Yoke::<&'static str, _>::attach_to_cart_badly(buffer1, |rc| rc.trim());
let yoke2 = Yoke::<&'static str, _>::attach_to_cart_badly(buffer2, |b| b.trim());
// Wrap the Rc in an Box to make it compatible
let erased1: Yoke<_, ErasedBoxCart> = yoke1.wrap_cart_in_box().erase_box_cart();
let erased2: Yoke<_, ErasedBoxCart> = yoke2.erase_box_cart();
// Now erased1 and erased2 have the same type!
Available with the "alloc"
feature enabled.
sourceimpl<Y: for<'a> Yokeable<'a>, C> Yoke<Y, C>
impl<Y: for<'a> Yokeable<'a>, C> Yoke<Y, C>
sourcepub fn wrap_cart_in_box(self) -> Yoke<Y, Box<C>>
pub fn wrap_cart_in_box(self) -> Yoke<Y, Box<C>>
Helper function allowing one to wrap the cart type C
in a Box<T>
.
Can be paired with Yoke::erase_box_cart()
Available with the "alloc"
feature enabled.
sourcepub fn wrap_cart_in_rc(self) -> Yoke<Y, Rc<C>>
pub fn wrap_cart_in_rc(self) -> Yoke<Y, Rc<C>>
Helper function allowing one to wrap the cart type C
in an Rc<T>
.
Can be paired with Yoke::erase_rc_cart()
, or generally used
to make the Yoke
cloneable.
Available with the "alloc"
feature enabled.
sourceimpl<Y: for<'a> Yokeable<'a>, C> Yoke<Y, C>
impl<Y: for<'a> Yokeable<'a>, C> Yoke<Y, C>
sourcepub fn wrap_cart_in_either_a<B>(self) -> Yoke<Y, EitherCart<C, B>>
pub fn wrap_cart_in_either_a<B>(self) -> Yoke<Y, EitherCart<C, B>>
Helper function allowing one to wrap the cart type C
in an EitherCart
.
This function wraps the cart into the A
variant. To wrap it into the
B
variant, use Self::wrap_cart_in_either_b()
.
For an example, see EitherCart
.
sourcepub fn wrap_cart_in_either_b<A>(self) -> Yoke<Y, EitherCart<A, C>>
pub fn wrap_cart_in_either_b<A>(self) -> Yoke<Y, EitherCart<A, C>>
Helper function allowing one to wrap the cart type C
in an EitherCart
.
This function wraps the cart into the B
variant. To wrap it into the
A
variant, use Self::wrap_cart_in_either_a()
.
For an example, see EitherCart
.
sourceimpl<Y, C> Yoke<Y, C> where
Y: for<'a> Yokeable<'a>,
for<'a> YokeTraitHack<<Y as Yokeable<'a>>::Output>: ZeroFrom<'a, <C as Deref>::Target>,
C: StableDeref + Deref,
impl<Y, C> Yoke<Y, C> where
Y: for<'a> Yokeable<'a>,
for<'a> YokeTraitHack<<Y as Yokeable<'a>>::Output>: ZeroFrom<'a, <C as Deref>::Target>,
C: StableDeref + Deref,
sourcepub fn attach_to_zero_copy_cart(cart: C) -> Self
pub fn attach_to_zero_copy_cart(cart: C) -> Self
Construct a Yoke
<Y, C>
from a cart implementing StableDeref
by zero-copy cloning
the cart to Y
and then yokeing that object to the cart.
The type Y
must implement ZeroFrom
<C::Target>
. This trait is auto-implemented
on many common types and can be custom implemented or derived in order to make it easier
to construct a Yoke
.
Example
Attach to a cart:
use yoke::Yoke;
use std::borrow::Cow;
let yoke = Yoke::<
Cow<'static, str>,
String
>::attach_to_zero_copy_cart("demo".to_string());
assert_eq!("demo", yoke.get());
Trait Implementations
sourceimpl<Y: for<'a> Yokeable<'a>, C: CloneableCart> Clone for Yoke<Y, C> where
for<'a> YokeTraitHack<<Y as Yokeable<'a>>::Output>: Clone,
impl<Y: for<'a> Yokeable<'a>, C: CloneableCart> Clone for Yoke<Y, C> where
for<'a> YokeTraitHack<<Y as Yokeable<'a>>::Output>: Clone,
Clone requires that the cart type C
derefs to the same address after it is cloned. This works for
Rc, Arc, and &’a T.
For other cart types, clone .backing_cart()
and re-use .attach_to_cart()
; however, doing
so may lose mutations performed via .with_mut()
.
Cloning a Yoke
is often a cheap operation requiring no heap allocations, in much the same
way that cloning an Rc
is a cheap operation. However, if the yokeable
contains owned data
(e.g., from .with_mut()
), that data will need to be cloned.
sourceimpl<Y, C> Serialize for Yoke<Y, C> where
Y: for<'a> Yokeable<'a>,
for<'a> &'a <Y as Yokeable<'a>>::Output: Serialize,
impl<Y, C> Serialize for Yoke<Y, C> where
Y: for<'a> Yokeable<'a>,
for<'a> &'a <Y as Yokeable<'a>>::Output: Serialize,
impl<'b, Y: for<'a> Yokeable<'a>, C: IsCovariant<'b>> IsCovariant<'b> for Yoke<Y, C>
Auto Trait Implementations
impl<Y, C> RefUnwindSafe for Yoke<Y, C> where
C: RefUnwindSafe,
Y: RefUnwindSafe,
impl<Y, C> Send for Yoke<Y, C> where
C: Send,
Y: Send,
impl<Y, C> Sync for Yoke<Y, C> where
C: Sync,
Y: Sync,
impl<Y, C> Unpin for Yoke<Y, C> where
C: Unpin,
Y: Unpin,
impl<Y, C> UnwindSafe for Yoke<Y, C> where
C: UnwindSafe,
Y: 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