pub struct Selfie<'a, P, R>where
P: 'a,
R: for<'this> RefType<'this>,{ /* private fields */ }
Expand description
A self-referential struct with a shared reference (R
) to an object owned by a pinned pointer (P
).
If you need a self-referential struct with an exclusive (mutable) reference to the data behind P
, see SelfieMut
.
This struct is a simple wrapper containing both the pinned pointer P
and the shared reference to it R
alongside it.
It does not perform any additional kind of boxing or allocation.
A Selfie
is constructed by using the new
constructor, which requires the pinned pointer P
,
and a function to create the reference type R
from a shared reference to the data behind P
.
Because R
references the data behind P
for as long as this struct exists, the data behind P
has to be considered to be borrowed for the lifetime of the Selfie
.
Therefore, you can only access the data behind P
through shared references (&T
) using owned
, or by
using into_owned
, which drops R
and returns P
as it was given to
the constructor.
Note that the referential type R
is not accessible outside of the Selfie
either, and can
only be accessed by temporarily borrowing it through the with_referential
and with_referential_mut
methods, which hide its true lifetime.
This is done because R
actually has a self-referential lifetime, which cannot be named
in Rust’s current lifetime system.
Also because of the non-nameable self-referential lifetime, R
is not the referential type
itself, but a stand-in that implements RefType
(e.g. Ref<T>
instead of &T
).
See the refs
module for some reference type stand-ins this library provides, or see
the RefType
trait documentation for how to implement your own.
§Example
This example stores both an owned String
and a str
slice pointing
into it.
use core::pin::Pin;
use selfie::{refs::Ref, Selfie};
let data: Pin<String> = Pin::new("Hello, world!".to_owned());
let selfie: Selfie<String, Ref<str>> = Selfie::new(data, |s| &s[0..5]);
assert_eq!("Hello", selfie.with_referential(|r| *r));
assert_eq!("Hello, world!", selfie.owned());
Implementations§
source§impl<'a, P, R> Selfie<'a, P, R>
impl<'a, P, R> Selfie<'a, P, R>
sourcepub fn new<F>(owned: Pin<P>, handler: F) -> Self
pub fn new<F>(owned: Pin<P>, handler: F) -> Self
Creates a new Selfie
from a pinned pointer P
, and a closure to create the reference
type R
from a shared reference to the data behind P
.
Note the closure cannot expect to be called with a specific lifetime, as it will handle
the unnameable 'this
lifetime instead.
§Example
use std::pin::Pin;
use selfie::refs::Ref;
use selfie::Selfie;
let data = Pin::new("Hello, world!".to_owned());
let selfie: Selfie<String, Ref<str>> = Selfie::new(data, |s| &s[0..5]);
// The selfie now contains both the String buffer and a subslice to "Hello"
assert_eq!("Hello", selfie.with_referential(|r| *r));
sourcepub fn try_new<E, F>(
owned: Pin<P>,
handler: F
) -> Result<Self, SelfieError<P, E>>
pub fn try_new<E, F>( owned: Pin<P>, handler: F ) -> Result<Self, SelfieError<P, E>>
Creates a new Selfie
from a pinned pointer P
, and a fallible closure to create the
reference type R
from a shared reference to the data behind P
.
Note the closure cannot expect to be called with a specific lifetime, as it will handle
the unnameable 'this
lifetime instead.
§Errors
The closure can return a Result
containing either the referential type, or any error type.
If the closure returns an Err
, it will be returned in a SelfieError
alongside the original
owned pointer type.
§Example
use std::pin::Pin;
use selfie::refs::Ref;
use selfie::{Selfie, SelfieError};
let data = Pin::new("Hello, world!".to_owned());
let selfie: Result<Selfie<String, Ref<str>>, SelfieError<String, ()>>
= Selfie::try_new(data, |s| Ok(&s[0..5]));
assert_eq!("Hello", selfie.unwrap().with_referential(|r| *r));
sourcepub fn owned(&self) -> &P::Target
pub fn owned(&self) -> &P::Target
Returns a shared reference to the owned type by de-referencing P
.
§Example
use core::pin::Pin;
use selfie::{refs::Ref, Selfie};
let data: Pin<Box<u32>> = Box::pin(42);
let selfie: Selfie<Box<u32>, Ref<u32>> = Selfie::new(data, |i| i);
assert_eq!(&42, selfie.owned());
sourcepub fn with_referential<'s, F, T>(&'s self, handler: F) -> T
pub fn with_referential<'s, F, T>(&'s self, handler: F) -> T
Performs an operation borrowing the referential type R
, and returns its result.
§Example
use core::pin::Pin;
use selfie::{refs::Ref, Selfie};
let data: Pin<Box<u32>> = Box::pin(42);
let selfie: Selfie<Box<u32>, Ref<u32>> = Selfie::new(data, |i| i);
assert_eq!(50, selfie.with_referential(|r| *r + 8));
sourcepub fn with_referential_mut<'s, F, T>(&'s mut self, handler: F) -> T
pub fn with_referential_mut<'s, F, T>(&'s mut self, handler: F) -> T
Performs an operation mutably borrowing the referential type R
, and returns its result.
Note that this operation cannot mutably access the data behind P
, it only mutates the
referential type R
itself.
§Example
use core::pin::Pin;
use selfie::{refs::Ref, Selfie};
let data: Pin<String> = Pin::new("Hello, world!".to_owned());
let mut selfie: Selfie<String, Ref<str>> = Selfie::new(data, |s| &s[0..5]);
assert_eq!("Hello", selfie.with_referential(|r| *r));
assert_eq!("Hello, world!", selfie.owned());
selfie.with_referential_mut(|s| *s = &s[0..2]);
assert_eq!("He", selfie.with_referential(|r| *r));
assert_eq!("Hello, world!", selfie.owned());
sourcepub fn into_owned(self) -> Pin<P>
pub fn into_owned(self) -> Pin<P>
Unwraps the Selfie
by dropping the reference type R
, and returning the owned pointer
type P
, as it was passed to the constructor.
§Example
use std::pin::Pin;
use selfie::refs::Ref;
use selfie::Selfie;
let data = Pin::new("Hello, world!".to_owned());
let selfie: Selfie<String, Ref<str>> = Selfie::new(data, |str| &str[0..5]);
let original_data: Pin<String> = selfie.into_owned();
assert_eq!("Hello, world!", original_data.as_ref().get_ref());
sourcepub fn map<R2: for<'this> RefType<'this>, F>(
self,
mapper: F
) -> Selfie<'a, P, R2>
pub fn map<R2: for<'this> RefType<'this>, F>( self, mapper: F ) -> Selfie<'a, P, R2>
Creates a new Selfie
by consuming this Selfie
’s reference type R
and producing another
(R2
), using a given closure.
The owned pointer type P
is left unchanged, and a shared reference to the data behind it
is also provided to the closure for convenience.
This method consumes the Selfie
. If you need to keep it intact, see
map_cloned
.
§Example
use std::pin::Pin;
use selfie::refs::Ref;
use selfie::Selfie;
let data = Pin::new("Hello, world!".to_owned());
let selfie: Selfie<String, Ref<str>> = Selfie::new(data, |str| &str[0..5]);
assert_eq!("Hello", selfie.with_referential(|r| *r));
let selfie = selfie.map::<Ref<str>, _>(|str, _| &str[3..]);
assert_eq!("lo", selfie.with_referential(|r| *r));
let selfie: Selfie<String, Ref<str>> = selfie.map(|_, owned| &owned[7..]);
assert_eq!("world!", selfie.with_referential(|r| *r));
sourcepub fn try_map<R2: for<'this> RefType<'this>, E, F>(
self,
mapper: F
) -> Result<Selfie<'a, P, R2>, SelfieError<P, E>>
pub fn try_map<R2: for<'this> RefType<'this>, E, F>( self, mapper: F ) -> Result<Selfie<'a, P, R2>, SelfieError<P, E>>
Creates a new Selfie
by consuming this Selfie
’s reference type R
and producing another
(R2
), using a given fallible closure.
The owned pointer type P
is left unchanged, and a shared reference to the data behind it
is also provided to the closure for convenience.
This method consumes the Selfie
. If you need to keep it intact, see
try_map_cloned
.
§Errors
The closure can return a Result
containing either the referential type, or any error type.
If the closure returns an Err
, it will be returned in a SelfieError
alongside the original
owned pointer type.
§Example
use std::pin::Pin;
use selfie::refs::Ref;
use selfie::{Selfie, SelfieError};
let data = Pin::new("Hello, world!".to_owned());
let selfie: Selfie<String, Ref<str>> = Selfie::new(data, |str| &str[0..5]);
assert_eq!("Hello", selfie.with_referential(|r| *r));
let selfie = selfie.try_map::<Ref<str>, (), _>(|str, _| Ok(&str[3..])).unwrap();
assert_eq!("lo", selfie.with_referential(|r| *r));
let selfie: Result<Selfie<String, Ref<str>>, SelfieError<String,()>> = selfie.try_map(|_, owned| Ok(&owned[7..]));
assert_eq!("world!", selfie.unwrap().with_referential(|r| *r));
sourcepub fn map_cloned<R2: for<'this> RefType<'this>, F>(
&self,
mapper: F
) -> Selfie<'a, P, R2>
pub fn map_cloned<R2: for<'this> RefType<'this>, F>( &self, mapper: F ) -> Selfie<'a, P, R2>
Creates a new Selfie
by cloning this Selfie
’s reference pointer P
and producing
a new reference (R2
), using a given closure.
The owned pointer type P
needs to be CloneStableDeref
,
as only the pointer itself is going to be cloned, not the data behind it. Both the current
reference R
and the new R2
will refer to the data behind P
.
This method keeps the original Selfie
unchanged, as only its owned pointer is cloned.
§Example
use std::rc::Rc;
use selfie::refs::Ref;
use selfie::Selfie;
let data = Rc::pin("Hello, world!".to_owned());
let selfie: Selfie<Rc<String>, Ref<str>> = Selfie::new(data, |str| &str[0..5]);
selfie.with_referential(|s| assert_eq!("Hello", *s));
let second_selfie = selfie.map_cloned::<Ref<str>, _>(|str, _| &str[3..]);
second_selfie.with_referential(|s| assert_eq!("lo", *s));
selfie.with_referential(|s| assert_eq!("Hello", *s)); // Old one still works
drop(selfie);
second_selfie.with_referential(|s| assert_eq!("lo", *s)); // New one still works
sourcepub fn try_map_cloned<R2: for<'this> RefType<'this>, E, F>(
&self,
mapper: F
) -> Result<Selfie<'a, P, R2>, E>
pub fn try_map_cloned<R2: for<'this> RefType<'this>, E, F>( &self, mapper: F ) -> Result<Selfie<'a, P, R2>, E>
Creates a new Selfie
by cloning this Selfie
’s reference pointer P
and producing
a new reference (R2
), using a given fallible closure.
The owned pointer type P
needs to be CloneStableDeref
,
as only the pointer itself is going to be cloned, not the data behind it. Both the current
reference R
and the new R2
will refer to the data behind P
.
This method keeps the original Selfie
unchanged, as only its owned pointer is cloned.
§Errors
The closure can return a Result
containing either the referential type, or any error type.
If the closure returns an Err
, it will be returned right away.
§Example
use std::rc::Rc;
use selfie::refs::Ref;
use selfie::Selfie;
let data = Rc::pin("Hello, world!".to_owned());
let selfie: Selfie<Rc<String>, Ref<str>> = Selfie::new(data, |str| &str[0..5]);
selfie.with_referential(|s| assert_eq!("Hello", *s));
let second_selfie = selfie.try_map_cloned::<Ref<str>, (), _>(|str, _| Ok(&str[3..])).unwrap();
second_selfie.with_referential(|s| assert_eq!("lo", *s));
selfie.with_referential(|s| assert_eq!("Hello", *s)); // Old one still works
drop(selfie);
second_selfie.with_referential(|s| assert_eq!("lo", *s)); // New one still works