#[repr(u8)]
#[derive(Eq, PartialEq, Clone, Copy, Debug)]
pub enum IllegalMoveKind {
TwoPawns = 1,
IgnoredCheck = 2,
DropPawnMate = 3,
DropStuck = 4,
NormalStuck = 5,
GameFinished = 6,
IncorrectMove = 7,
}
impl IllegalMoveKind {
pub fn from_u8(repr: u8) -> Option<Self> {
if matches!(repr, 1..=7) {
Some(unsafe { Self::from_u8_unchecked(repr) })
} else {
None
}
}
#[export_name = "IllegalMoveKind_from_u8_unchecked"]
pub unsafe extern "C" fn from_u8_unchecked(repr: u8) -> Self {
core::mem::transmute(repr)
}
}
impl_ord_for_fieldless_enum!(IllegalMoveKind);
impl_hash_for_fieldless_enum!(IllegalMoveKind);
#[repr(transparent)]
#[derive(Eq, PartialEq, Clone, Copy, Debug, Default)]
pub struct ResultUnitIllegalMoveKind(u8);
impl From<Option<IllegalMoveKind>> for ResultUnitIllegalMoveKind {
#[inline(always)]
fn from(arg: Option<IllegalMoveKind>) -> Self {
Self(match arg {
Some(result) => result as u8,
None => 0,
})
}
}
impl From<ResultUnitIllegalMoveKind> for Option<IllegalMoveKind> {
#[inline(always)]
fn from(arg: ResultUnitIllegalMoveKind) -> Self {
if arg.0 == 0 {
None
} else {
Some(unsafe { IllegalMoveKind::from_u8_unchecked(arg.0) })
}
}
}
impl From<Result<(), IllegalMoveKind>> for ResultUnitIllegalMoveKind {
#[inline(always)]
fn from(arg: Result<(), IllegalMoveKind>) -> Self {
Self(match arg {
Err(result) => result as u8,
Ok(()) => 0,
})
}
}
impl From<ResultUnitIllegalMoveKind> for Result<(), IllegalMoveKind> {
#[inline(always)]
fn from(arg: ResultUnitIllegalMoveKind) -> Self {
if arg.0 == 0 {
Ok(())
} else {
Err(unsafe { IllegalMoveKind::from_u8_unchecked(arg.0) })
}
}
}
impl_ord_for_single_field!(ResultUnitIllegalMoveKind);
impl_hash_for_single_field!(ResultUnitIllegalMoveKind);
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn illegal_move_kind_is_one_byte() {
assert_eq!(core::mem::size_of::<IllegalMoveKind>(), 1);
}
#[test]
fn option_illegal_move_kind_default_is_compatible() {
assert_eq!(ResultUnitIllegalMoveKind::default(), None.into());
}
#[test]
fn repr_is_correct() {
for repr in 1..=7 {
let value = IllegalMoveKind::from_u8(repr).unwrap();
assert_eq!(value as u8, repr);
}
}
#[test]
fn from_works() {
for repr in 1..=7 {
let value = IllegalMoveKind::from_u8(repr).unwrap();
assert_eq!(
Result::from(ResultUnitIllegalMoveKind::from(Err(value))),
Err(value),
);
assert_eq!(ResultUnitIllegalMoveKind::from(Err(value)).0, repr);
}
}
}