#![no_std]
#![warn(missing_docs)]
extern crate alloc;
use alloc::{rc, sync};
use core::marker::PhantomData;
pub trait OwnerOnce<T> {
fn with<U>(self, f: impl FnOnce(T) -> U) -> Option<U>;
}
pub trait Owner<T: ?Sized> {
fn with<'a, U>(&'a self, f: impl FnOnce(&T) -> U) -> Option<U>
where
T: 'a;
}
pub trait OwnerMut<T: ?Sized> {
fn with<'a, U>(&'a mut self, f: impl FnOnce(&mut T) -> U) -> Option<U>
where
T: 'a;
}
impl<T: ?Sized, O: ?Sized + Owner<T>> Owner<T> for &O {
fn with<'a, U>(&'a self, f: impl FnOnce(&T) -> U) -> Option<U>
where
T: 'a,
{
(*self).with(f)
}
}
impl<T: ?Sized, O: ?Sized + OwnerMut<T>> OwnerMut<T> for &mut O {
fn with<'a, U>(&'a mut self, f: impl FnOnce(&mut T) -> U) -> Option<U>
where
T: 'a,
{
(*self).with(f)
}
}
impl<T: ?Sized> Owner<T> for rc::Weak<T> {
fn with<'a, U>(&'a self, f: impl FnOnce(&T) -> U) -> Option<U>
where
T: 'a,
{
Some(f(&*self.upgrade()?))
}
}
impl<T: ?Sized> Owner<T> for sync::Weak<T> {
fn with<'a, U>(&'a self, f: impl FnOnce(&T) -> U) -> Option<U>
where
T: 'a,
{
Some(f(&*self.upgrade()?))
}
}
pub struct PureOwner<T>(T);
impl<T> OwnerOnce<T> for PureOwner<T> {
fn with<U>(self, f: impl FnOnce(T) -> U) -> Option<U> {
Some(f(self.0))
}
}
impl<T> Owner<T> for PureOwner<T> {
fn with<'a, U>(&'a self, f: impl FnOnce(&T) -> U) -> Option<U>
where
T: 'a,
{
Some(f(&self.0))
}
}
impl<T> OwnerMut<T> for PureOwner<T> {
fn with<'a, U>(&'a mut self, f: impl FnOnce(&mut T) -> U) -> Option<U>
where
T: 'a,
{
Some(f(&mut self.0))
}
}
pub fn pure<T>(t: T) -> PureOwner<T> {
PureOwner(t)
}
pub struct BindOwner<T, U, OT, OU, F> {
owner: OT,
func: F,
_phantom: PhantomData<(T, U, OU)>,
}
impl<T, U, OT: OwnerOnce<T>, OU: OwnerOnce<U>, F: FnOnce(T) -> OU> OwnerOnce<U>
for BindOwner<T, U, OT, OU, F>
{
fn with<V>(self, f: impl FnOnce(U) -> V) -> Option<V> {
let func = self.func;
self.owner.with(move |t| func(t).with(f))?
}
}
impl<T, U, OT: Owner<T>, OU: Owner<U>, F: Fn(&T) -> OU> Owner<U> for BindOwner<&T, U, OT, OU, F> {
fn with<'a, V>(&'a self, f: impl FnOnce(&U) -> V) -> Option<V>
where
U: 'a,
{
self.owner.with(|t| (&self.func)(t).with(f))?
}
}
impl<T, U, OT: OwnerMut<T>, OU: OwnerMut<U>, F: FnMut(&mut T) -> OU> OwnerMut<U>
for BindOwner<&mut T, U, OT, OU, F>
{
fn with<'a, V>(&'a mut self, f: impl FnOnce(&mut U) -> V) -> Option<V>
where
U: 'a,
{
let func = &mut self.func;
self.owner.with(|t| func(t).with(f))?
}
}
pub fn bind<T, U, OT, OU, F>(o: OT, f: F) -> BindOwner<T, U, OT, OU, F> {
BindOwner {
owner: o,
func: f,
_phantom: PhantomData,
}
}