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
//! 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: Eq> {
    
    /// 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.get_identifier(), &5);
    /// assert_eq!(*wi, 5);
    /// # }
    /// ```
    fn derive_ident(value: &Self) -> I;
}

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

/// 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)););
}