opentitanlib/util/vmem/
mod.rs1use std::iter;
10use std::str::FromStr;
11
12mod parser;
13
14use parser::VmemParser;
15pub use parser::{ParseError, ParseResult};
16
17#[derive(Clone, Debug, Default, PartialEq, Eq)]
21pub struct Vmem {
22 sections: Vec<Section>,
23}
24
25#[derive(Clone, Debug, Default, PartialEq, Eq)]
27pub struct Section {
28 pub addr: u32,
29 pub data: Vec<u32>,
30}
31
32impl FromStr for Vmem {
33 type Err = ParseError;
34
35 fn from_str(s: &str) -> Result<Self, Self::Err> {
37 VmemParser::parse(s)
38 }
39}
40
41impl Vmem {
42 pub fn sections(&self) -> impl Iterator<Item = &Section> {
44 self.sections
46 .iter()
47 .filter(|section| !section.data.is_empty())
48 }
49}
50
51#[derive(Clone, Copy, Debug, PartialEq, Eq)]
53pub struct Data {
54 pub addr: u32,
55 pub value: u32,
56}
57
58impl Vmem {
59 pub fn data_addrs(&self) -> impl Iterator<Item = Data> + '_ {
61 self.sections().flat_map(|section| section.data_addrs())
62 }
63
64 pub fn merge_sections(&mut self) {
66 let mut res: Vec<Section> = Vec::new();
67 for mut sec in std::mem::take(&mut self.sections) {
69 match res.last_mut() {
70 Some(ref mut last) if { last.addr + last.data.len() as u32 * 4 == sec.addr } => {
71 last.data.append(&mut sec.data)
72 }
73 _ => res.push(sec),
74 }
75 }
76 self.sections = res
77 }
78}
79
80impl Section {
81 pub fn data_addrs(&self) -> impl Iterator<Item = Data> + '_ {
83 let addrs = (self.addr..).step_by(4);
84 let values = self.data.iter();
85 iter::zip(addrs, values).map(|(addr, value)| Data {
86 addr,
87 value: *value,
88 })
89 }
90}
91
92#[cfg(test)]
93mod test {
94 use super::*;
95
96 #[test]
97 fn vmem_data() {
98 let vmem = Vmem::from_str("@10 12 23 34 @20 @26 45").unwrap();
99 let expected = [(0x40, 0x12), (0x44, 0x23), (0x48, 0x34), (0x98, 0x45)]
100 .map(|(addr, value)| Data { addr, value });
101
102 let data: Vec<_> = vmem.data_addrs().collect();
103 assert_eq!(data, expected);
104 }
105
106 #[test]
107 fn section_data() {
108 let section = Section {
109 addr: 0x42,
110 data: vec![0x12, 0x23, 0x34, 0x45],
111 };
112 let expected = [(0x42, 0x12), (0x46, 0x23), (0x4a, 0x34), (0x4e, 0x45)]
113 .map(|(addr, value)| Data { addr, value });
114
115 let data: Vec<_> = section.data_addrs().collect();
116 assert_eq!(data, expected);
117 }
118}