use core::convert::TryInto;

#[derive(PartialEq, Eq, Clone, Debug)]
pub(crate) struct Splitu16(u16);

impl From<u16> for Splitu16 {
    fn from(f: u16) -> Self {
        let mut result = Splitu16::new();
        result.set_u16(f);
        result
    }
}

impl Splitu16 {
    pub(crate) const fn new() -> Splitu16 {
        Splitu16(0)
    }

    pub(crate) const fn as_u16(&self) -> u16 {
        self.0
    }

    pub(crate) fn set_u16(&mut self, f: u16) -> &mut Splitu16 {
        self.0 = f;
        self
    }

    pub(crate) fn high_u8(&self) -> u8 {
        (self.0 >> 8).try_into().unwrap()
    }

    pub(crate) fn set_high_u8(&mut self, f: u8) {
        self.0 |= u16::from(f) << 8
    }

    pub(crate) fn low_u8(&self) -> u8 {
        (self.0 & 0x0F).try_into().unwrap()
    }

    pub(crate) fn set_low_u8(&mut self, f: u8) {
        self.0 |= u16::from(f)
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn splitu16() {
        let expected = Splitu16(0b1111111100000000);
        let mut real = Splitu16::new();


        real.set_high_u8(0xFF);

        assert_eq!(expected, real);

        let expected = Splitu16(0b0000000011111111);
        let mut real = Splitu16::new();

        real.set_low_u8(0xFF);

        assert_eq!(expected, real);
        
    }
}