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
//! Author --- daniel.bechaz@gmail.com  
//! Last Moddified --- 2018/03/13

use super::*;

/// Derives an `identifier` from a value.
///
/// `DeriveIdent` is a "quality of life" trait when using [`WithIdent`](./struct.WithIdent.html).
///
/// Any type `T` which implements this trait can easily be converted into a
/// `WithIdent<T, I,>` instance using `From` and `Into`.
pub trait DeriveIdent<I,> {
    
    /// Returns an `Identifier` value derived from the passed `value`.
    ///
    /// Note: this is an associated function, which means that you have to call it as
    /// `DeriveIdent::derive_ident(value)` instead of `value.derive_ident()`. This is so
    /// that there is no conflict with a method on the inner type.
    ///
    /// # Examples
    ///
    /// ```rust
    /// # extern crate ident;
    /// # use ident::*;
    /// # fn main() {
    /// assert_eq!(5, DeriveIdent::derive_ident(&5)); //Integer types return themselves by default.
    ///
    /// let wi = WithIdent::from(5);
    /// assert_eq!(wi.ident(), &5);
    /// assert_eq!(*wi, 5);
    /// # }
    /// ```
    fn derive_ident(value: &Self) -> I;
}

impl<T: DeriveIdent<I,>, I,> From<T> for WithIdent<T, I,> {
    fn from(from: T) -> Self {
        Self::new(DeriveIdent::derive_ident(&from), from)
    }
}

impl<T: DeriveIdent<I,> + Default, I,> Default for WithIdent<T, I,> {
    fn default() -> Self { T::default().into() }
}

impl<T: DeriveIdent<I,>, I,> WithIdent<T, I,> {
    /// Consumes the `WithIdent` and returns a new instance with an updated `identifier`
    /// derived from the inner value.
    ///
    /// Note: this is an associated function, which means that you have to call it as
    /// `WithIdent::update_ident(wi)` instead of `wi.update_ident()`. 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::from(5);
    /// assert_eq!(5, *wi.ident());
    ///
    /// *wi = 10;
    /// wi = WithIdent::update_ident(wi);
    /// assert_eq!(10, *wi.ident());
    /// # }
    /// ```
    #[inline]
    pub fn update_ident(mut wi: Self) -> Self {
        wi.identifier = DeriveIdent::derive_ident(&wi.value); wi
    }
}

/// In some cases, such as `integer` types, a value is its own unique `identifier`.
///
/// This macro implements [`DeriveIdent`](./trait.DeriveIdent.html) for the passed type to
/// simply return itself. (NOTE: the type must derive `Clone`)
#[macro_export]
macro_rules! impl_identity {
    ($type:ty) => {
        impl DeriveIdent<$type> for $type {
            fn derive_ident(value: &Self) -> $type {
                value.clone()
            }
        }
    };
    ($type:tt $($t:tt)*) => {
        impl_identity!($type);
        impl_identity!($($t)*);
    };
}

impl_identity! { usize isize u8 i8 u16 i16 u32 i32 u64 i64 }

/// A hash is often a useful and convenient `identifier` value.
///
/// This macro implements [`DeriveIdent<u64>`](./trait.DeriveIdent.html) for the passed
/// type using the passed [`Hasher`](https://doc.rust-lang.org/std/hash/trait.Hasher.html).
/// (NOTE: the type must derive [`Hash`](https://doc.rust-lang.org/std/hash/trait.Hash.html))
///
/// # Examples
///
/// ```rust
/// #[macro_use]
/// extern crate ident;
///
/// use std::collections::hash_map::DefaultHasher;
/// use ident::*;
///
/// #[derive(Hash)]
/// struct MyType(pub usize);
///
/// //Implements DeriveIdent<u64> for MyType using DefaultHasher to calculate the hash.
/// impl_hash_identity!(MyType, DefaultHasher);
///
/// fn main() {
///     let x = MyType(5);
///     println!("{}", DeriveIdent::<u64>::derive_ident(&x));
/// }
/// ```
#[macro_export]
macro_rules! impl_hash_identity {
    (($type:tt, $hasher:tt)) => {
        impl DeriveIdent<u64> for $type {
            fn derive_ident(value: &Self) -> u64 {
                use std::hash::{Hash, Hasher};
                
                let mut hasher = $hasher::default();
                value.hash(&mut hasher);
                hasher.finish()
            }
        }
    };
    (($type:tt, $hasher:tt) $($t:tt)*) => {
        impl_hash_identity!(($type, $hasher));
        impl_hash_identity!($($t)*);
    };
    ($type:tt, $hasher:tt) => (impl_hash_identity!(($type, $hasher)););
}