use super::bad_block::{BadBlockStrategy, BadBlockTable};
use super::types::{Address, Progress};
use crate::error::Result;
pub struct ReadRequest {
pub address: Address,
pub length: u32,
pub use_ecc: bool,
pub ignore_ecc_errors: bool,
pub oob_mode: OobMode,
pub bad_block_strategy: BadBlockStrategy,
pub bbt: Option<BadBlockTable>,
pub retry_count: u32,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum OobMode {
None,
Included,
Only,
}
pub struct WriteRequest<'a> {
pub address: Address,
pub data: &'a [u8],
pub use_ecc: bool,
pub verify: bool,
pub ignore_ecc_errors: bool,
pub oob_mode: OobMode,
pub bad_block_strategy: BadBlockStrategy,
pub bbt: Option<BadBlockTable>,
pub retry_count: u32,
}
pub struct EraseRequest {
pub address: Address,
pub length: u32,
pub bad_block_strategy: BadBlockStrategy,
pub bbt: Option<BadBlockTable>,
}
pub trait FlashOperation {
fn read(&mut self, request: ReadRequest, on_progress: &dyn Fn(Progress)) -> Result<Vec<u8>>;
fn write(&mut self, request: WriteRequest, on_progress: &dyn Fn(Progress)) -> Result<()>;
fn erase(&mut self, request: EraseRequest, on_progress: &dyn Fn(Progress)) -> Result<()>;
fn get_status(&mut self) -> Result<Vec<u8>> {
Err(crate::error::Error::NotSupported(
"get_status not implemented".to_string(),
))
}
fn set_status(&mut self, _status: &[u8]) -> Result<()> {
Err(crate::error::Error::NotSupported(
"set_status not implemented".to_string(),
))
}
fn scan_bbt(&mut self, _on_progress: &dyn Fn(Progress)) -> Result<BadBlockTable> {
Err(crate::error::Error::NotSupported(
"BBT scan not implemented".to_string(),
))
}
}
impl FlashOperation for Box<dyn FlashOperation> {
fn read(&mut self, request: ReadRequest, on_progress: &dyn Fn(Progress)) -> Result<Vec<u8>> {
self.as_mut().read(request, on_progress)
}
fn write(&mut self, request: WriteRequest, on_progress: &dyn Fn(Progress)) -> Result<()> {
self.as_mut().write(request, on_progress)
}
fn erase(&mut self, request: EraseRequest, on_progress: &dyn Fn(Progress)) -> Result<()> {
self.as_mut().erase(request, on_progress)
}
fn get_status(&mut self) -> Result<Vec<u8>> {
self.as_mut().get_status()
}
fn set_status(&mut self, status: &[u8]) -> Result<()> {
self.as_mut().set_status(status)
}
fn scan_bbt(&mut self, on_progress: &dyn Fn(Progress)) -> Result<BadBlockTable> {
self.as_mut().scan_bbt(on_progress)
}
}
impl<T: FlashOperation + ?Sized> FlashOperation for &mut T {
fn read(&mut self, request: ReadRequest, on_progress: &dyn Fn(Progress)) -> Result<Vec<u8>> {
(**self).read(request, on_progress)
}
fn write(&mut self, request: WriteRequest, on_progress: &dyn Fn(Progress)) -> Result<()> {
(**self).write(request, on_progress)
}
fn erase(&mut self, request: EraseRequest, on_progress: &dyn Fn(Progress)) -> Result<()> {
(**self).erase(request, on_progress)
}
fn get_status(&mut self) -> Result<Vec<u8>> {
(**self).get_status()
}
fn set_status(&mut self, status: &[u8]) -> Result<()> {
(**self).set_status(status)
}
fn scan_bbt(&mut self, on_progress: &dyn Fn(Progress)) -> Result<BadBlockTable> {
(**self).scan_bbt(on_progress)
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::error::Error;
struct MockFlashOp;
impl FlashOperation for MockFlashOp {
fn read(
&mut self,
_request: ReadRequest,
_on_progress: &dyn Fn(Progress),
) -> Result<Vec<u8>> {
Ok(vec![])
}
fn write(&mut self, _request: WriteRequest, _on_progress: &dyn Fn(Progress)) -> Result<()> {
Ok(())
}
fn erase(&mut self, _request: EraseRequest, _on_progress: &dyn Fn(Progress)) -> Result<()> {
Ok(())
}
}
#[test]
fn test_default_trait_implementations() {
let mut op = MockFlashOp;
match op.get_status() {
Err(Error::NotSupported(msg)) => assert_eq!(msg, "get_status not implemented"),
_ => panic!("Expected NotSupported error"),
}
match op.set_status(&[0]) {
Err(Error::NotSupported(msg)) => assert_eq!(msg, "set_status not implemented"),
_ => panic!("Expected NotSupported error"),
}
let dummy_progress = |_: Progress| {};
match op.scan_bbt(&dummy_progress) {
Err(Error::NotSupported(msg)) => assert_eq!(msg, "BBT scan not implemented"),
_ => panic!("Expected NotSupported error"),
}
}
}