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
//! This type defines Wrap / Unwrap utilities. Unwrap is like `Deref` but does not implement
//! `impl<'a, T> Unwrap for &'a T` in order to make it less error prone. `Wrap` is like `pure` in
//! applicative functors – if lifts a value to the specific type.

use crate::std_reexports::*;

// ===============
// === Wrapper ===
// ===============

/// Trait for any type which wraps other type. See docs of `Wrapper` to learn more.
pub trait HasContent {
    type Content : ?Sized;
}

/// Accessor for the wrapped value.
pub type Content<T> = <T as HasContent>::Content;

/// Trait which enables `Sized` super-bound on the `Content` type.
pub trait HasSizedContent = HasContent where Content<Self> : Sized;

/// Trait for objects which wrap values. Please note that this implements safe wrappers, so the
/// object - value relation must be bijective.
pub trait Wrapper = Wrap + ContentRef;

/// Wrapping utility for values.
pub trait Wrap : HasSizedContent {
    /// Wraps the value and returns the wrapped type.
    fn wrap(t:Self::Content) -> Self;
}

/// Unwrapping utility for wrapped types.
///
/// Please note that this trait is very similar to the Deref trait. However, there is a very
/// important difference. Unlike `Deref`, there is no `impl<'a, T> Unwrap for &'a T` defined. The
/// existence of such impl is very error prone when writing complex impls. The `Deref` docs warn
/// about it explicitly: "[...] Because of this, Deref should only be implemented for smart pointers
/// to avoid confusion.". As an example, consider the following code which contains infinite loop:
///
/// ```compile_fail
/// pub trait HasId {
///     fn id(&self) -> usize;
/// }
///
/// // Notice the lack of bound `<T as Deref>::Target : HasId`
/// impl<T:Deref> HasId for T {
///     fn id(&self) -> usize {
///         self.deref().id()
///     }
/// }
/// ```
///
/// And the correct version:
///
/// ```compile_fail
/// pub trait HasId {
///     fn id(&self) -> usize;
/// }
///
/// // Notice the lack of bound `<T as Deref>::Target : HasId`
/// impl<T:Deref> HasId for T where <T as Deref>::Target : HasId {
///     fn id(&self) -> usize {
///         self.deref().id()
///     }
/// }
/// ```
///
/// Both versions compile fine, but the former loops for ever.
pub trait ContentRef : HasContent {
    /// Unwraps this type to get the inner value.
    fn content(&self) -> &Self::Content;
}

/// Runs a function on the reference to the content.
pub trait WithContent : HasSizedContent {
    /// Runs a function on the reference to the content.
    fn with_content<F,T>(&self,f:F) -> T where F : FnOnce(&Content<Self>) -> T;
}

/// Unwraps the content by consuming this value.
pub trait Unwrap : HasSizedContent {
    /// Unwraps the content by consuming this value.
    fn unwrap(self) -> Self::Content;
}


// === Utils ===

/// Wraps the value and returns the wrapped type.
pub fn wrap<T:Wrap>(t:T::Content) -> T {
    T::wrap(t)
}

/// Provides reference to the content of this value.
pub fn content<T:ContentRef>(t:&T) -> &T::Content {
    T::content(t)
}

/// Unwrap the content by consuming this value.
pub fn unwrap<T:Unwrap>(t:T) -> T::Content {
    T::unwrap(t)
}


// === Default Impls ===

impl<T:ContentRef + HasSizedContent> WithContent for T {
    fn with_content<F,S>(&self,f:F) -> S
        where F : FnOnce(&Content<Self>) -> S {
        f(self.content())
    }
}

// TODO: This should be implemented with the marker trait overlapping rules magic.
// impl<T:Deref> Unwrap for T
// where <T as Deref>::Target: Unwrap {
//     default fn unwrap(&self) -> &Self::Content {
//         self.deref().unwrap()
//     }
// }


// === Impls ===

impl<T:?Sized> HasContent for Rc<T> { type Content = T; }
impl<T>        Wrap       for Rc<T> { fn wrap(t:T) -> Self { Rc::new(t) } }
impl<T:?Sized> ContentRef for Rc<T> { fn content(&self) -> &Self::Content { self.deref() }}

impl HasContent for String { type Content = char; }
impl Wrap       for String { fn wrap(t:char) -> Self { t.to_string() } }

impl<T> HasContent for Vec<T> { type Content = T; }
impl<T> Wrap       for Vec<T> { fn wrap(t:T) -> Self { vec![t] } }