1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
//! Rust implementation of a monad which provides ownership of an object.

#![no_std]
#![warn(missing_docs)]

extern crate alloc;

use alloc::{rc, sync};
use core::marker::PhantomData;

/// A monad which conditionally provides access to a `T` value.
///
/// This is included alongside [`Owner`] and [`OwnerMut`] for completeness, but
/// this trait is isomorphic to `FnOnce() -> T`.
pub trait OwnerOnce<T> {
    /// Consumes the monad, applying the given function to the contained value,
    /// if it exists.
    fn with<U>(self, f: impl FnOnce(T) -> U) -> Option<U>;
}

/// A monad which conditionally provides immutable access to a `T` value.
pub trait Owner<T: ?Sized> {
    /// Applies the given function to the contained value, if it exists.
    fn with<'a, U>(&'a self, f: impl FnOnce(&T) -> U) -> Option<U>
    where
        T: 'a;
}

/// A monad which conditionally provides mutable access to a `T` value.
pub trait OwnerMut<T: ?Sized> {
    /// Applies the given function to the contained value, if it exists.
    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()?))
    }
}

/// An implementation of the [`OwnerOnce`], [`Owner`] and [`OwnerMut`] traits
/// which simply contains a single (pure) value; see [`pure()`].
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))
    }
}

/// Creates an instance of ownership monads which provides access to the given
/// value.
pub fn pure<T>(t: T) -> PureOwner<T> {
    PureOwner(t)
}

/// An implementation of the [`OwnerOnce`], [`Owner`] and [`OwnerMut`] traits
/// which contains a mapping from one owner to another; see [`bind()`].
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))?
    }
}

/// Creates an instance of ownership monads which maps from the given owner to
/// another using the given function.
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,
    }
}