use std::collections::hash_map::DefaultHasher;
use std::convert::TryFrom;
use std::hash::{Hash, Hasher};
use byteorder::{BigEndian};
use rand::Rng;
use log::error;
use serde::{Serialize, Deserialize, de::DeserializeOwned};
use crate::serialization::cdr_serializer::to_bytes;
use crate::serialization::error::Error;
pub trait Keyed {
type K;
fn get_key(&self) -> Self::K;
fn get_hash(&self) -> u64
where
Self::K: Key,
{
let mut hasher = DefaultHasher::new();
self.get_key().hash(&mut hasher);
hasher.finish()
}
}
#[derive(Eq,PartialEq,Ord,PartialOrd,Debug, Clone, Copy)]
pub struct KeyHash([u8;16]);
impl KeyHash {
pub fn zero() -> KeyHash {
KeyHash([0;16])
}
pub fn to_vec(self) -> Vec<u8> {
Vec::from(self.0)
}
pub fn into_cdr_bytes( &self ) -> Result<Vec<u8>, Error> {
Ok( self.to_vec() )
}
pub fn from_cdr_bytes(bytes: Vec<u8>) -> Result<KeyHash, Error> {
let a =
<[u8;16]>::try_from( bytes )
.map_err( |_e| Error::Eof )?;
Ok(KeyHash(a))
}
}
pub trait Key:
Eq + PartialEq + PartialOrd + Ord + Hash + Clone + Serialize + DeserializeOwned
{
fn may_exceed_128_bits() -> bool {
false
}
fn into_hash_key(&self) -> KeyHash {
let mut cdr_bytes = to_bytes::<Self, BigEndian>(&self)
.unwrap_or_else(|e| {
error!("Hashing key {:?} failed!", e);
vec![0;16]
});
KeyHash(
if Self::may_exceed_128_bits() || cdr_bytes.len() > 16 {
*md5::compute(&cdr_bytes)
} else {
cdr_bytes.resize(16, 0x00); <[u8;16]>::try_from(cdr_bytes).unwrap() }
)
}
}
impl Key for () {
fn into_hash_key(&self) -> KeyHash {
KeyHash::zero()
}
}
impl<D: Keyed> Keyed for &D {
type K = D::K;
fn get_key(&self) -> Self::K {
(*self).get_key()
}
}
impl Key for bool {}
impl Key for char {}
impl Key for i8 {}
impl Key for i16 {}
impl Key for i32 {}
impl Key for i64 {}
impl Key for i128 {}
impl Key for isize {}
impl Key for u8 {}
impl Key for u16 {}
impl Key for u32 {}
impl Key for u64 {}
impl Key for u128 {}
impl Key for usize {}
impl Key for String {}
#[derive(Debug, Eq, PartialEq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
pub struct BuiltInTopicKey {
value: [i32; 3],
}
impl BuiltInTopicKey {
pub fn get_random_key() -> BuiltInTopicKey {
let mut rng = rand::thread_rng();
BuiltInTopicKey {
value: [rng.gen(), rng.gen(), rng.gen()],
}
}
pub fn default() -> BuiltInTopicKey {
BuiltInTopicKey { value: [0, 0, 0] }
}
}