From c6d7ca79d03c8752aacc2f0895e85136877a224c Mon Sep 17 00:00:00 2001 From: Djeeberjr Date: Fri, 8 Aug 2025 13:03:47 +0200 Subject: [PATCH] implemented more functionality for embedded_io --- src/embedded_io/device.rs | 49 ++++++++++++------ src/embedded_io/head.rs | 105 +++++++++++++++++++++++--------------- 2 files changed, 97 insertions(+), 57 deletions(-) diff --git a/src/embedded_io/device.rs b/src/embedded_io/device.rs index 51e7c0d..4f2e8f2 100644 --- a/src/embedded_io/device.rs +++ b/src/embedded_io/device.rs @@ -6,12 +6,12 @@ use crate::{ embedded_io::{error::MB85RCErrorType, head::Head}, }; -pub struct EmbedIODev { +pub struct EmbedIODev { dev: crate::MB85RC, - head: Head, + head: Head, } -impl EmbedIODev { +impl EmbedIODev { pub fn new(mb85rc: MB85RC) -> Self { Self { dev: mb85rc, @@ -20,42 +20,59 @@ impl EmbedIODev { } } -impl ErrorType for EmbedIODev { +impl ErrorType for EmbedIODev { type Error = MB85RCErrorType; } -impl Read for EmbedIODev { +impl Read for EmbedIODev { fn read(&mut self, buf: &mut [u8]) -> Result { - self.dev - .sequential_read(&self.head.memory_address().unwrap(), buf) - .map_err(MB85RCErrorType::I2c) - .map(|_| { - self.head.advance(buf.len()); - buf.len() - }) + match self.head.memory_address() { + Some(addr) => self + .dev + .sequential_read(&addr, buf) + .map_err(MB85RCErrorType::I2c) + .map(|_| { + self.head.advance(buf.len()); + buf.len() + }), + None => Err(MB85RCErrorType::InvalidPosition), + } } } -impl Write for EmbedIODev { +impl Write for EmbedIODev { fn write(&mut self, buf: &[u8]) -> Result { // From trait doc: Implementations must not return Ok(0) unless buf is empty. if buf.is_empty() { return Ok(0); } + // match self.head.memory_address() { + // Some(addr) => self + // .dev + // .write_page(&addr, buf) + // .map_err(MB85RCErrorType::I2c) + // .map(|_| { + // self.head.advance(buf.len()); + // buf.len() + // }), + // None => Err(MB85RCErrorType::InvalidPosition), + // } + todo!() } fn flush(&mut self) -> Result<(), Self::Error> { - todo!() + // We can't really flush here. + Ok(()) } } -impl Seek for EmbedIODev { +impl Seek for EmbedIODev { fn seek(&mut self, pos: embedded_io::SeekFrom) -> Result { self.head .seek(pos) - .map_err(|_| MB85RCErrorType::InvalidPosition)?; + .ok_or(MB85RCErrorType::InvalidPosition)?; Ok(self.head.into()) } } diff --git a/src/embedded_io/head.rs b/src/embedded_io/head.rs index f8fae2a..561da7e 100644 --- a/src/embedded_io/head.rs +++ b/src/embedded_io/head.rs @@ -1,28 +1,34 @@ use embedded_io::SeekFrom; /// moveable Read/Write head +/// Capped at `N` +/// Does not allow overflow #[derive(Clone, Copy, Default)] -pub struct Head(u64); +pub struct Head(u64); -impl Head { +impl Head { pub fn new() -> Self { Self(0) } - pub fn seek(&mut self, pos: SeekFrom) -> Result { + pub fn seek(&mut self, pos: SeekFrom) -> Option { match pos { - SeekFrom::Start(offset) => { - self.0 = offset; - Ok(self.0) - } + SeekFrom::Start(offset) => match self.0.checked_add(offset).filter(|&sum| sum <= N) { + Some(new_pos) => { + self.0 = new_pos; + Some(new_pos) + } + None => None, + }, SeekFrom::End(offset) => { + // Do not allow seek over the end if offset > 0 { - return Err(()); + return None; } - self.0 = u64::MAX - offset.unsigned_abs(); + self.0 = N - offset.unsigned_abs(); - Ok(self.0) + Some(self.0) } SeekFrom::Current(offset) => { let new_pos = if offset > 0 { @@ -33,21 +39,31 @@ impl Head { match new_pos { Some(pos) => { - self.0 = pos; - Ok(self.0) + if pos > N { + None + } else { + self.0 = pos; + Some(self.0) + } } - None => Err(()), + None => None, } } } } /// Move the head forward when reading files. - /// Expected to not overflow. If it does it is capped at `u64::MAX`. + /// Expected to not overflow. If it does it is capped at `N`. pub fn advance(&mut self, bytes: usize) { - match u64::try_from(bytes) { - Ok(offset) => self.0 += offset, - Err(_) => self.0 = u64::MAX, + match self.0.checked_add(bytes as u64) { + Some(sum) => { + if sum > N { + self.0 = N + } else { + self.0 = sum; + } + } + None => self.0 = N, } } @@ -65,8 +81,8 @@ impl Head { } } -impl From for u64 { - fn from(head: Head) -> Self { +impl From> for u64 { + fn from(head: Head) -> Self { head.0 } } @@ -77,87 +93,94 @@ mod tests { #[test] fn create() { - let head = Head::new(); + let head: Head<65_535> = Head::new(); let inner: u64 = head.into(); assert_eq!(inner, 0u64); } #[test] fn seek_start() { - let mut head = Head::new(); + let mut head: Head<65_535> = Head::new(); let res = head.seek(SeekFrom::Start(1337)); let inner: u64 = head.into(); assert_eq!(inner, 1337u64); - assert_eq!(res, Ok(inner)); + assert_eq!(res, Some(inner)); } #[test] fn seek_current_forward() { - let mut head = Head::new(); + let mut head: Head<65_535> = Head::new(); let _ = head.seek(SeekFrom::Start(1337)); let res = head.seek(SeekFrom::Current(3)); let inner: u64 = head.into(); assert_eq!(inner, 1340u64); - assert_eq!(res, Ok(inner)); + assert_eq!(res, Some(inner)); } #[test] fn seek_current_back() { - let mut head = Head::new(); + let mut head: Head<65_535> = Head::new(); let _ = head.seek(SeekFrom::Start(1337)); let res = head.seek(SeekFrom::Current(-337)); let inner: u64 = head.into(); assert_eq!(inner, 1000u64); - assert_eq!(res, Ok(inner)); + assert_eq!(res, Some(inner)); } #[test] fn seek_current_zero() { - let mut head = Head::new(); + let mut head: Head<65_535> = Head::new(); let _ = head.seek(SeekFrom::Start(1337)); let res = head.seek(SeekFrom::Current(0)); let inner: u64 = head.into(); assert_eq!(inner, 1337u64); - assert_eq!(res, Ok(inner)); + assert_eq!(res, Some(inner)); } #[test] fn seek_end() { - let mut head = Head::new(); + let mut head: Head<65_535> = Head::new(); let res = head.seek(SeekFrom::End(-10)); let inner: u64 = head.into(); - assert_eq!(inner, u64::MAX - 10); - assert_eq!(res, Ok(inner)); + assert_eq!(inner, 65_535 - 10); + assert_eq!(res, Some(inner)); + } + + #[test] + fn seek_end_overflow() { + let mut head: Head<65_535> = Head::new(); + let res = head.seek(SeekFrom::End(10)); + assert!(res.is_none()); } #[test] fn seek_invalid_overflow() { - let mut head = Head::new(); - let _ = head.seek(SeekFrom::Start(u64::MAX - 5)); + let mut head: Head<65_535> = Head::new(); + let _ = head.seek(SeekFrom::Start(65_535 - 5)); let res = head.seek(SeekFrom::Current(10)); - assert!(res.is_err()); + assert!(res.is_none()); } #[test] fn seek_invalid_underflow() { - let mut head = Head::new(); + let mut head: Head<65_535> = Head::new(); let res = head.seek(SeekFrom::Current(-1)); - assert!(res.is_err()); + assert!(res.is_none()); } #[test] fn convert_zero() { - let head = Head::new(); + let head: Head<65_535> = Head::new(); let addr = head.memory_address(); assert_eq!(addr, Some([0, 0])); @@ -165,7 +188,7 @@ mod tests { #[test] fn convert_1_byte() { - let mut head = Head::new(); + let mut head: Head<65_535> = Head::new(); let _ = head.seek(SeekFrom::Start(50)); let addr = head.memory_address(); @@ -175,7 +198,7 @@ mod tests { #[test] fn convert_2_bytes() { - let mut head = Head::new(); + let mut head: Head<65_535> = Head::new(); let _ = head.seek(SeekFrom::Start(260)); let addr = head.memory_address(); @@ -185,8 +208,8 @@ mod tests { #[test] fn convert_invalid() { - let mut head = Head::new(); - let _ = head.seek(SeekFrom::Start(u16::MAX as u64 + 1)); + let mut head: Head<4_294_967_295> = Head::new(); // Needs to be more then u16::MAX + let _ = head.seek(SeekFrom::Start(65_536)); // One more then u16::MAX let addr = head.memory_address(); assert!(addr.is_none());