use crate::lib_enum;
use crate::result::{Error, Result};
use super::{ExtCsd, ExtCsdIndex, ModeConfig};
mod ffu;
pub use ffu::*;
#[repr(u8)]
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum ModeOperationCodes {
Normal(u8),
Ffu(FfuOperationCodes),
Vendor(u8),
}
impl ModeOperationCodes {
pub const fn new() -> Self {
Self::Normal(0)
}
pub const fn mode_config(&self) -> ModeConfig {
match self {
Self::Normal(_) => ModeConfig::Normal,
Self::Ffu(_) => ModeConfig::Ffu,
Self::Vendor(_) => ModeConfig::Vendor,
}
}
pub const fn try_from_mode_config(mode: ModeConfig, code: u8) -> Result<Self> {
match mode {
ModeConfig::Normal => Ok(ModeOperationCodes::Normal(code)),
ModeConfig::Ffu => match FfuOperationCodes::from_raw(code) {
Ok(c) => Ok(ModeOperationCodes::Ffu(c)),
Err(err) => Err(err),
},
ModeConfig::Vendor => Ok(ModeOperationCodes::Vendor(code)),
}
}
pub const fn into_inner(self) -> u8 {
match self {
Self::Normal(code) => code,
Self::Ffu(ffu) => ffu.into_raw(),
Self::Vendor(code) => code,
}
}
}
impl Default for ModeOperationCodes {
fn default() -> Self {
Self::new()
}
}
impl ExtCsd {
pub const fn mode_operation_codes(&self) -> Result<ModeOperationCodes> {
let code = self.0[ExtCsdIndex::ModeOperationCodes.into_inner()];
match self.mode_config() {
Ok(mode) => ModeOperationCodes::try_from_mode_config(mode, code),
Err(err) => Err(err),
}
}
pub fn set_mode_operation_codes(&mut self, val: ModeOperationCodes) {
self.set_mode_config(val.mode_config());
self.0[ExtCsdIndex::ModeOperationCodes.into_inner()] = val.into_inner();
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_mode_operation_codes() {
let mut ext_csd = ExtCsd::new();
assert_eq!(
ext_csd.mode_operation_codes(),
Ok(ModeOperationCodes::new())
);
[ModeConfig::Normal, ModeConfig::Ffu, ModeConfig::Vendor]
.into_iter()
.for_each(|mode| {
(0..=u8::MAX).for_each(|code| {
match ModeOperationCodes::try_from_mode_config(mode, code) {
Ok(c) => {
ext_csd.set_mode_operation_codes(c);
assert_eq!(ext_csd.mode_config(), Ok(c.mode_config()));
assert_eq!(ext_csd.mode_operation_codes(), Ok(c));
}
Err(err) => {
assert_eq!(mode, ModeConfig::Ffu);
assert_eq!(Err(err), FfuOperationCodes::from_raw(code));
}
}
});
});
}
}