use crate::serialize::{hex_range, hex_u_int};
use core::ops::Range;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct NvmRegion {
pub name: Option<String>,
#[serde(serialize_with = "hex_range")]
pub range: Range<u64>,
#[serde(default)]
pub is_boot_memory: bool,
pub cores: Vec<String>,
}
impl NvmRegion {
pub fn nvm_info(&self) -> NvmInfo {
NvmInfo {
rom_start: self.range.start,
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct RamRegion {
pub name: Option<String>,
#[serde(serialize_with = "hex_range")]
pub range: Range<u64>,
#[serde(default)]
pub is_boot_memory: bool,
pub cores: Vec<String>,
}
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct GenericRegion {
pub name: Option<String>,
#[serde(serialize_with = "hex_range")]
pub range: Range<u64>,
pub cores: Vec<String>,
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub struct SectorInfo {
pub base_address: u64,
pub size: u64,
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct SectorDescription {
#[serde(serialize_with = "hex_u_int")]
pub size: u64,
#[serde(serialize_with = "hex_u_int")]
pub address: u64,
}
#[derive(Debug, Copy, Clone)]
pub struct PageInfo {
pub base_address: u64,
pub size: u32,
}
#[derive(Debug, Copy, Clone)]
pub struct NvmInfo {
pub rom_start: u64,
}
pub trait MemoryRange {
fn contains_range(&self, range: &Range<u64>) -> bool;
fn intersects_range(&self, range: &Range<u64>) -> bool;
fn align_to_32_bits(&mut self);
}
impl MemoryRange for Range<u64> {
fn contains_range(&self, range: &Range<u64>) -> bool {
if range.end == 0 {
false
} else {
self.contains(&range.start) && self.contains(&(range.end - 1))
}
}
fn intersects_range(&self, range: &Range<u64>) -> bool {
if range.end == 0 {
false
} else {
self.contains(&range.start) && !self.contains(&(range.end - 1))
|| !self.contains(&range.start) && self.contains(&(range.end - 1))
|| self.contains_range(range)
|| range.contains_range(self)
}
}
fn align_to_32_bits(&mut self) {
if self.start % 4 != 0 {
self.start -= self.start % 4;
}
if self.end % 4 != 0 {
if let Some(new_end) = self.end.checked_add(4 - self.end % 4) {
self.end = new_end;
}
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum MemoryRegion {
Ram(RamRegion),
Generic(GenericRegion),
#[serde(alias = "Flash")] Nvm(NvmRegion),
}
impl MemoryRegion {
pub fn cores(&self) -> &[String] {
match self {
MemoryRegion::Ram(region) => ®ion.cores,
MemoryRegion::Generic(region) => ®ion.cores,
MemoryRegion::Nvm(region) => ®ion.cores,
}
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn contains_range1() {
let range1 = 0..1;
let range2 = 0..1;
assert!(range1.contains_range(&range2));
}
#[test]
fn contains_range2() {
let range1 = 0..1;
let range2 = 0..2;
assert!(!range1.contains_range(&range2));
}
#[test]
fn contains_range3() {
let range1 = 0..4;
let range2 = 0..1;
assert!(range1.contains_range(&range2));
}
#[test]
fn contains_range4() {
let range1 = 4..8;
let range2 = 3..9;
assert!(!range1.contains_range(&range2));
}
#[test]
fn contains_range5() {
let range1 = 4..8;
let range2 = 0..1;
assert!(!range1.contains_range(&range2));
}
#[test]
fn contains_range6() {
let range1 = 4..8;
let range2 = 6..8;
assert!(range1.contains_range(&range2));
}
#[test]
fn intersects_range1() {
let range1 = 0..1;
let range2 = 0..1;
assert!(range1.intersects_range(&range2));
}
#[test]
fn intersects_range2() {
let range1 = 0..1;
let range2 = 0..2;
assert!(range1.intersects_range(&range2));
}
#[test]
fn intersects_range3() {
let range1 = 0..4;
let range2 = 0..1;
assert!(range1.intersects_range(&range2));
}
#[test]
fn intersects_range4() {
let range1 = 4..8;
let range2 = 3..9;
assert!(range1.intersects_range(&range2));
}
#[test]
fn intersects_range5() {
let range1 = 4..8;
let range2 = 0..1;
assert!(!range1.intersects_range(&range2));
}
#[test]
fn intersects_range6() {
let range1 = 4..8;
let range2 = 6..8;
assert!(range1.intersects_range(&range2));
}
#[test]
fn intersects_range7() {
let range1 = 4..8;
let range2 = 3..4;
assert!(!range1.intersects_range(&range2));
}
#[test]
fn intersects_range8() {
let range1 = 8..9;
let range2 = 6..8;
assert!(!range1.intersects_range(&range2));
}
#[test]
fn intersects_range9() {
let range1 = 2..4;
let range2 = 6..8;
assert!(!range1.intersects_range(&range2));
}
#[test]
fn test_align_to_32_bits_case1() {
let mut range = Range { start: 0, end: 8 };
range.align_to_32_bits();
assert_eq!(range.start, 0);
assert_eq!(range.end, 8);
}
#[test]
fn test_align_to_32_bits_case2() {
let mut range = Range { start: 3, end: 12 };
range.align_to_32_bits();
assert_eq!(range.start, 0);
assert_eq!(range.end, 12);
}
#[test]
fn test_align_to_32_bits_case3() {
let mut range = Range { start: 16, end: 23 };
range.align_to_32_bits();
assert_eq!(range.start, 16);
assert_eq!(range.end, 24);
}
#[test]
fn test_align_to_32_bits_case4() {
let mut range = Range { start: 5, end: 13 };
range.align_to_32_bits();
assert_eq!(range.start, 4);
assert_eq!(range.end, 16);
}
}