use std::hash::Hasher;
use std::ops::{Add, AddAssign};
use xxhash_rust::xxh3::Xxh3;

pub struct UID(Xxh3);

impl Default for UID {
    fn default() -> Self {
        UID(Xxh3::new())
    }
}

impl UID {
    pub fn new() -> Self {
        Self::default()
    }
}

impl Into<u64> for UID {
    fn into(self) -> u64 {
        self.0.finish()
    }
}

impl<B: AsRef<[u8]>> Add<B> for UID {
    type Output = UID;

    fn add(mut self, rhs: B) -> Self::Output {
        self.0.update(rhs.as_ref());
        self
    }
}

impl<B: AsRef<[u8]>> AddAssign<B> for UID {
    fn add_assign(&mut self, rhs: B) {
        self.0.update(rhs.as_ref());
    }
}

#[test]
pub fn test_uid() {
    assert_ne!(
        Into::<u64>::into(UID::new() + "config" + "config.kdl"),
        Into::<u64>::into(UID::new() + "env" + "CONFIG_ARG")
    )
}