use crate::Reader;
#[cfg(not(feature = "std"))]
use alloc::{format, string::String, vec, vec::Vec};
#[derive(Debug)]
pub struct MemoryReader {
regions: Vec<MemoryRegion>,
}
#[derive(Debug)]
struct MemoryRegion {
kind: RegionKind,
base_address: u32,
data: Vec<u8>,
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum RegionKind {
Flash,
Ram,
}
impl MemoryReader {
pub fn new(data: Vec<u8>, base_address: u32) -> Self {
Self {
regions: vec![MemoryRegion {
kind: RegionKind::Flash,
data,
base_address,
}],
}
}
pub fn new_of_kind(kind: RegionKind, data: Vec<u8>, base_address: u32) -> Self {
Self {
regions: vec![MemoryRegion {
kind,
data,
base_address,
}],
}
}
pub fn add_region(&mut self, kind: RegionKind, data: Vec<u8>, base_address: u32) {
self.regions.push(MemoryRegion {
kind,
base_address,
data,
});
}
}
impl Reader for MemoryReader {
type Error = String;
async fn read(&mut self, addr: u32, buf: &mut [u8]) -> Result<(), Self::Error> {
let end_addr = addr
.checked_add(buf.len() as u32)
.ok_or_else(|| format!("Address overflow at 0x{:08X}", addr))?;
let region = self
.regions
.iter()
.find(|r| {
let region_end = r.base_address.saturating_add(r.data.len() as u32);
addr >= r.base_address && end_addr <= region_end
})
.ok_or_else(|| format!("No region covers 0x{:08X}..0x{:08X}", addr, end_addr))?;
let offset = (addr - region.base_address) as usize;
buf.copy_from_slice(®ion.data[offset..offset + buf.len()]);
Ok(())
}
fn update_base_address(&mut self, new_base: u32) {
if let Some(r) = self
.regions
.iter_mut()
.find(|r| r.kind == RegionKind::Flash)
{
r.base_address = new_base;
}
}
}