sejong 0.1.5

Sejong Buffer is a buffer that can receive ASCII bytes different from keyboard and send out UTF-32 Hangul string. This buffer allows deletion by Jamo.
Documentation
use super::{Byte, InitialConsonant};
use std::convert::{TryFrom, TryInto};

#[derive(Clone, Copy, PartialEq, Debug)]
#[repr(u8)]
pub(crate) enum FinalConsonant {
    None,
    G,  //    KK, //    GS, //    N,  //    NJ, //    NH, //    D,  //    L,  //    LG, //    LM, //    LB, //    LS, //    LT, //    LP, //    LH, //    M,  //    B,  //    BS, //    S,  //    SS, //    NG, //    J,  //    CH, //    K,  //    T,  //    P,  //    H,  //}

impl TryFrom<Byte> for FinalConsonant {
    type Error = Byte;
    fn try_from(b: Byte) -> Result<Self, Self::Error> {
        match b {
            Byte::G => Ok(Self::G),
            Byte::KK => Ok(Self::KK),
            Byte::N => Ok(Self::N),
            Byte::D => Ok(Self::D),
            Byte::R => Ok(Self::L),
            Byte::M => Ok(Self::M),
            Byte::B => Ok(Self::B),
            Byte::S => Ok(Self::S),
            Byte::SS => Ok(Self::SS),
            Byte::NG => Ok(Self::NG),
            Byte::J => Ok(Self::J),
            Byte::CH => Ok(Self::CH),
            Byte::K => Ok(Self::K),
            Byte::T => Ok(Self::T),
            Byte::P => Ok(Self::P),
            Byte::H => Ok(Self::H),
            _ => Err(b),
        }
    }
}

impl TryFrom<(Self, Byte)> for FinalConsonant {
    type Error = (Self, Byte);
    fn try_from(input: (Self, Byte)) -> Result<Self, Self::Error> {
        match input.0 {
            Self::G => match input.1 {
                Byte::S => Ok(Self::GS),
                _ => Err(input),
            },
            Self::N => match input.1 {
                Byte::J => Ok(Self::NJ),
                Byte::H => Ok(Self::NH),
                _ => Err(input),
            },
            Self::L => match input.1 {
                Byte::G => Ok(Self::LG),
                Byte::M => Ok(Self::LM),
                Byte::B => Ok(Self::LB),
                Byte::S => Ok(Self::LS),
                Byte::T => Ok(Self::LT),
                Byte::P => Ok(Self::LP),
                Byte::H => Ok(Self::LH),
                _ => Err(input),
            },
            Self::B => match input.1 {
                Byte::S => Ok(Self::BS),
                _ => Err(input),
            },
            _ => Err(input),
        }
    }
}

impl Default for FinalConsonant {
    fn default() -> Self {
        Self::None
    }
}

impl TryInto<(Self, InitialConsonant)> for FinalConsonant {
    type Error = Self;
    fn try_into(self) -> Result<(Self, InitialConsonant), Self> {
        match self {
            Self::GS => Ok((Self::G, InitialConsonant::S)),
            Self::NJ => Ok((Self::N, InitialConsonant::J)),
            Self::NH => Ok((Self::N, InitialConsonant::H)),
            Self::LG => Ok((Self::L, InitialConsonant::G)),
            Self::LM => Ok((Self::L, InitialConsonant::M)),
            Self::LB => Ok((Self::L, InitialConsonant::B)),
            Self::LS => Ok((Self::L, InitialConsonant::S)),
            Self::LT => Ok((Self::L, InitialConsonant::T)),
            Self::LP => Ok((Self::L, InitialConsonant::P)),
            Self::LH => Ok((Self::L, InitialConsonant::H)),
            Self::BS => Ok((Self::B, InitialConsonant::S)),
            _ => Err(self),
        }
    }
}

impl FinalConsonant {
    pub fn try_remove_second_half(self) -> Option<Self> {
        match self {
            Self::GS => Some(Self::G),
            Self::NJ | Self::NH => Some(Self::N),
            Self::LG | Self::LM | Self::LB | Self::LS | Self::LT | Self::LP | Self::LH => {
                Some(Self::L)
            }
            Self::BS => Some(Self::B),
            _ => None,
        }
    }
}