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
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
//! A crate for creating and using types with an __immutable__ identifier field.
//!
//! Author --- daniel.bechaz@gmail.com  
//! Last Moddified --- 2018/02/13
//!
//! The main type provided by this crate is [`WithIdent`](./struct.WithIdent.html).

#![feature(const_fn)]

use std::ops::{Deref, DerefMut};
use std::borrow::{Borrow, BorrowMut};
use std::convert::{AsRef, AsMut, From, Into};

mod derive_ident;
mod ident_collections;

pub use self::derive_ident::*;
pub use self::ident_collections::*;

/// `WithIdent` wraps any value of type `T` and a unique identifier of type `I`.
///
/// The fields of a `WithIdent` instance cannot be accessed but the `T` value can be
/// accessed via a `Box` _like_ interface.
///
/// It can be useful to think of `WithIdent` as a tuple of `(I, T)`, so `From` and `Into`
/// have been implemented for just that conversion.
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
pub struct WithIdent<T, I = usize> {
    /// The unique `identifier` of a `WithIdent` instance.
    identifier: I,
    /// The inner `value` of a `WithIdent` instance.
    value: T,
}

impl<T, I,> WithIdent<T, I,> {
    /// Constructs a new `WithIdent` value from parts.
    ///
    /// # Params
    ///
    /// identifier --- The unique `identifier` for `value`.  
    /// value --- The inner `value` of the `WithIdent` instance.
    #[inline]
    pub const fn new(identifier: I, value: T) -> Self {
        Self { identifier, value }
    }
    /// Returns an immutable reference to the `identifier` of this `WithIdent`.
    #[inline]
    pub const fn ident(&self) -> &I {
        &self.identifier
    }
    /// Consumes the `WithIdent` returning the wrapped `T` value.
    ///
    /// Note: this is an associated function, which means that you have to call it as
    /// `WithIdent::into_value(wi)` instead of `wi.into_value()`. This is so that there is no
    /// conflict with a method on the inner type.
    ///
    /// # Examples
    ///
    /// ```rust
    /// # extern crate ident;
    /// # use ident::*;
    /// # fn main() {
    /// let wi = WithIdent::new(0, 5);
    /// assert_eq!(5, WithIdent::into_value(wi));
    /// # }
    /// ```
    #[inline]
    pub fn into_value(wi: Self) -> T { wi.value }
    /// Consumes the `WithIdent` returning a new instance wrapping the result of the mapping.
    ///
    /// Note: this is an associated function, which means that you have to call it as
    /// `WithIdent::map(wi, f)` instead of `wi.map(f)`. This is so that there is no conflict
    /// with a method on the inner type.
    ///
    /// Note: the returned `WithIdent` will still have the same `identifier` as the consumed instance.
    ///
    /// # Examples
    ///
    /// ```rust
    /// # extern crate ident;
    /// # use ident::*;
    /// # fn main() {
    /// let wi = WithIdent::new(0, 5);
    /// assert_eq!(10, *WithIdent::map(wi, |x| 2 * x));
    /// # }
    /// ```
    #[inline]
    pub fn map<F, U>(wi: Self, f: F) -> WithIdent<U, I,>
        where F: FnOnce(T) -> U {
        WithIdent::new(wi.identifier, f(wi.value))
    }
    /// Consumes the `WithIdent` returning a new instance with an updated `identifier`.
    ///
    /// Note: this is an associated function, which means that you have to call it as
    /// `WithIdent::map_ident(wi, f)` instead of `wi.map_ident(f)`. This is so that there is no conflict
    /// with a method on the inner type.
    ///
    /// Note: the returned `WithIdent` will still have the same inner value as the consumed instance.
    ///
    /// # Examples
    ///
    /// ```rust
    /// # extern crate ident;
    /// # use ident::*;
    /// # fn main() {
    /// let wi = WithIdent::new(0, 5);
    /// assert_eq!(1, *WithIdent::map_ident(wi, |x| x + 1).ident());
    /// # }
    /// ```
    #[inline]
    pub fn map_ident<F, U>(wi: Self, f: F) -> WithIdent<T, U>
        where F: FnOnce(I) -> U, {
        WithIdent::new(f(wi.identifier), wi.value)
    }
}

impl<T, I: Eq,> WithIdent<T, I,> {
    /// Compares the `identifiers` of two `WithIdent` instances for equality.
    #[inline]
    pub fn same_ident<U>(a: &WithIdent<T, I,>, b: &WithIdent<U, I,>) -> bool {
        a.ident() == b.ident()
    }
}

impl<T, I: Clone> WithIdent<T, I,> {
    /// Returns a new `WithIdent` instance wrapping a reference to the original value.
    ///
    /// Note: this is an associated function, which means that you have to call it as
    /// `WithIdent::as_ref(&wi)` instead of `wi.as_ref()`. This is so that there is no conflict
    /// with a method on the inner type.
    ///
    /// # Examples
    ///
    /// ```rust
    /// # extern crate ident;
    /// # use ident::*;
    /// # fn main() {
    /// let wi = WithIdent::new(0, 5);
    /// assert_eq!(&5, *WithIdent::as_ref(&wi));
    /// # }
    /// ```
    #[inline]
    pub fn as_ref(wi: &Self) -> WithIdent<&T, I,> {
        WithIdent::new(wi.identifier.clone(), &wi.value)
    }
    /// Returns a new `WithIdent` instance wrapping a mutable reference to the original value.
    ///
    /// Note: this is an associated function, which means that you have to call it as
    /// `WithIdent::as_mut(&mut wi)` instead of `wi.as_mut()`. This is so that there is
    /// no conflict with a method on the inner type.
    ///
    /// # Examples
    ///
    /// ```rust
    /// # extern crate ident;
    /// # use ident::*;
    /// # fn main() {
    /// let mut wi = WithIdent::new(0, 5);
    /// assert_eq!(5, **WithIdent::as_mut(&mut wi));
    /// # }
    /// ```
    #[inline]
    pub fn as_mut(wi: &mut Self) -> WithIdent<&mut T, I,> {
        WithIdent::new(wi.identifier.clone(), &mut wi.value)
    }
}

impl<T: Eq, I,> WithIdent<T, I,> {
    /// Compares the `values` of two `WithIdent` instances for equality.
    #[inline]
    pub fn same_value<U>(a: &WithIdent<T, I,>, b: &WithIdent<T, U>) -> bool {
        a.value == b.value
    }
}

impl<T, I,> From<(I, T)> for WithIdent<T, I,> {
    #[inline]
    fn from((id, value): (I, T)) -> Self { Self::new(id, value) }
}

impl<T, I,> Into<(I, T)> for WithIdent<T, I,> {
    #[inline]
    fn into(self) -> (I, T) { (self.identifier, self.value) }
}

impl<T, I,> Deref for WithIdent<T, I,> {
    type Target = T;
    
    #[inline]
    fn deref(&self) -> &Self::Target { &self.value }
}

impl<T, I,> DerefMut for WithIdent<T, I,> {

    #[inline]
    fn deref_mut(&mut self) -> &mut Self::Target { &mut self.value }
}

impl<T, I,> Borrow<T> for WithIdent<T, I,> {
    #[inline]
    fn borrow(&self) -> &T { self.deref() }
}

impl<T, I,> BorrowMut<T> for WithIdent<T, I,> {
    #[inline]
    fn borrow_mut(&mut self) -> &mut T { self.deref_mut() }
}

impl<T, I,> AsRef<T> for WithIdent<T, I,> {
    #[inline]
    fn as_ref(&self) -> &T { self.borrow() }
}

impl<T, I,> AsMut<T> for WithIdent<T, I,> {
    #[inline]
    fn as_mut(&mut self) -> &mut T { self.borrow_mut() }
}