use std::marker::PhantomData;
use std::str;
use digest::Digest;
use kv::Value;
pub trait Hash: Digest {
fn hex(self) -> String;
}
pub struct Token<T: Hash>(String, PhantomData<T>);
impl<T: Hash> Clone for Token<T> {
fn clone(&self) -> Self {
Token(self.0.clone(), PhantomData)
}
}
impl<'a, T: Hash> kv::Value<'a> for Token<T> {
fn from_raw(data: &[u8]) -> Token<T> {
Token::from(data)
}
}
impl<T: Hash> Token<T> {
pub fn generate<'a, V: Value<'a>>(val: &V) -> Token<T> {
let mut hasher = T::new();
hasher.input(val.as_ref());
let hash = hasher.hex();
Token::new(hash)
}
pub fn new(s: String) -> Token<T> {
Token(s, PhantomData)
}
pub fn as_string(&self) -> &String {
&self.0
}
}
impl<T: Hash> AsRef<[u8]> for Token<T> {
fn as_ref(&self) -> &[u8] {
self.0.as_ref()
}
}
impl<'a, T: Hash> From<&'a [u8]> for Token<T> {
fn from(x: &'a [u8]) -> Token<T> {
let s = unsafe { str::from_utf8_unchecked(x) };
Token::new(String::from(s))
}
}