trion/asm/memory/map/
mod.rs

1use core::fmt;
2use std::error::Error;
3use std::iter::FusedIterator;
4use std::slice::Iter as SliceIter;
5
6use crate::asm::memory::MemoryRange;
7
8#[cfg(test)]
9mod test;
10
11#[derive(Clone, Debug)]
12struct MemorySegment
13{
14	range: MemoryRange,
15	data: Vec<u8>,
16}
17
18#[derive(Clone, Copy, Debug, Eq, PartialEq)]
19pub enum Search
20{
21	Exact, Below, Above,
22}
23
24#[derive(Clone, Debug)]
25pub struct MemoryMap
26{
27	parts: Vec<MemorySegment>,
28}
29
30impl MemoryMap
31{
32	pub fn new() -> Self
33	{
34		Self{parts: Vec::new()}
35	}
36	
37	pub fn len(&self) -> usize
38	{
39		self.parts.len()
40	}
41	
42	fn locate(&self, addr: u32, search: Search) -> Option<usize>
43	{
44		if self.parts.is_empty() {return None;}
45		let mut first = 0;
46		let mut last = self.parts.len() - 1;
47		loop
48		{
49			let mid = first + (last - first) / 2;
50			let range = self.parts[mid].range;
51			if addr < range.first
52			{
53				if mid == first
54				{
55					return match search
56					{
57						Search::Exact => None,
58						Search::Below => if first > 0 {Some(first - 1)} else {None},
59						Search::Above => Some(first),
60					};
61				}
62				debug_assert!(mid > first);
63				last = mid - 1;
64			}
65			else if addr > range.last
66			{
67				if mid == last
68				{
69					return match search
70					{
71						Search::Exact => None,
72						Search::Below => Some(last),
73						Search::Above => if last < self.parts.len() - 1 {Some(last + 1)} else {None},
74					};
75				}
76				debug_assert!(mid < last);
77				first = mid + 1;
78			}
79			else {return Some(mid);}
80		}
81	}
82	
83	pub fn find(&self, addr: u32, search: Search) -> Option<MemoryRange>
84	{
85		self.locate(addr, search).map(|i| self.parts[i].range)
86	}
87	
88	pub fn get(&self, addr: u32, search: Search) -> Option<(MemoryRange, &[u8])>
89	{
90		self.locate(addr, search).map(|i| &self.parts[i]).map(|p| (p.range, &p.data[(addr - p.range.first) as usize..]))
91	}
92	
93	pub fn get_mut(&mut self, addr: u32, search: Search) -> Option<(MemoryRange, &mut [u8])>
94	{
95		self.locate(addr, search).map(|i| &mut self.parts[i]).map(|p| (p.range, &mut p.data[(addr - p.range.first) as usize..]))
96	}
97	
98	pub fn put(&mut self, addr: u32, data: &[u8]) -> Result<usize, PutError>
99	{
100		if !data.is_empty()
101		{
102			let have_last = usize::try_from(u32::MAX - addr).unwrap_or(usize::MAX);
103			if data.len() - 1 > have_last
104			{
105				return Err(PutError::Overflow{need: data.len(), have: have_last.saturating_add(1)})
106			}
107			let addr_last = addr + (data.len() - 1) as u32;
108			
109			// compute the index of the final segment (and the first one involved in a merge)
110			let idx_first = match self.locate(addr.saturating_sub(1), Search::Above)
111			{
112				None => self.parts.len(),
113				Some(idx) => idx,
114			};
115			// compute the last index involved in a merge (`None` if no merging)
116			let idx_last = match self.locate(addr_last.saturating_add(1), Search::Below)
117			{
118				None => None,
119				Some(idx) =>
120				{
121					if self.parts[idx].range.last >= addr.saturating_sub(1) {Some(idx)} else {None}
122				},
123			};
124			
125			match idx_last
126			{
127				None =>
128				{
129					self.parts.insert(idx_first, MemorySegment{range: MemoryRange{first: addr, last: addr_last}, data: data.to_owned()});
130					Ok(data.len())
131				},
132				Some(idx_last) =>
133				{
134					let first = &mut self.parts[idx_first];
135					let mut added = data.len();
136					if addr <= first.range.first
137					{
138						if addr_last >= first.range.last
139						{
140							// completely replaces existing data
141							added -= first.data.len();
142							first.data.clear();
143							first.data.extend_from_slice(data);
144						}
145						else
146						{
147							// prepend and overwrite
148							let num_remove = data.len() - usize::try_from(first.range.first - addr).unwrap();
149							first.data.splice(..num_remove, data.iter().copied());
150							added -= num_remove;
151						}
152					}
153					else
154					{
155						let offset = usize::try_from(addr - first.range.first).unwrap();
156						if addr_last > first.range.last
157						{
158							// overwrite and append
159							let num_overwrite = first.data.len() - offset;
160							first.data.truncate(offset);
161							first.data.extend_from_slice(data);
162							added -= num_overwrite;
163						}
164						else
165						{
166							// interior overwrite only
167							first.data[offset..offset + data.len()].copy_from_slice(data);
168							added = 0;
169						}
170					}
171					
172					if idx_last > idx_first
173					{
174						// `idx_first + 1..idx_last` are always overwritten completely
175						for idx in idx_first + 1..idx_last
176						{
177							added -= self.parts[idx].data.len();
178						}
179						// crazy shenanigans to copy from one segment to another
180						let (first, last) = {
181							let split = self.parts.split_at_mut(idx_last);
182							(&mut split.0[idx_first], &split.1[0])
183						};
184						if addr_last < last.range.last
185						{
186							// only partial replaces the final segment, copy what remains
187							let end_off = usize::try_from(last.range.last - addr_last).unwrap();
188							let overwritten = last.data.len() - end_off;
189							first.data.extend_from_slice(&last.data[last.data.len() - end_off..]);
190							first.range.last = last.range.last;
191							added -= overwritten;
192						}
193						else
194						{
195							// nothing of the final segment remains
196							added -= last.data.len();
197							first.range.last = addr_last;
198						}
199						first.range.first = first.range.first.min(addr);
200						self.parts.drain(idx_first + 1..=idx_last);
201					}
202					else
203					{
204						first.range.first = first.range.first.min(addr);
205						first.range.last = first.range.last.max(addr_last);
206					}
207					Ok(added)
208				},
209			}
210		}
211		else {Ok(0)}
212	}
213	
214	pub fn count(&self) -> (u32, usize)
215	{
216		let mut addrs = 0;
217		for seg in self.parts.iter()
218		{
219			// off by one but cannot overflow (we compensate afterwards)
220			addrs += seg.range.last - seg.range.first;
221		}
222		// `self.parts.len() <= 1 << (u32::BITS - 1)` otherwise segments would get merged
223		addrs = addrs.saturating_add(self.parts.len() as u32);
224		(addrs, self.parts.len())
225	}
226	
227	pub fn iter<'s>(&'s self) -> Iter<'s>
228	{
229		Iter(self.parts.iter())
230	}
231	
232	pub fn count_range(&self, range: MemoryRange) -> (u32, usize)
233	{
234		let first = match self.locate(range.first, Search::Above)
235		{
236			None => self.parts.len(),
237			Some(idx) => idx,
238		};
239		let mut addrs = 0;
240		let mut cnt = 0;
241		for seg in self.parts[first..].iter().filter(|seg| seg.range.first <= range.last)
242		{
243			debug_assert!(seg.range.last >= range.first);
244			let min_addr = seg.range.first.max(range.first);
245			let max_addr = seg.range.last.min(range.last);
246			// off by one, see `Self::count`
247			addrs += max_addr - min_addr;
248			cnt += 1;
249		}
250		// safe for the same reason as in `Self::count`
251		addrs = addrs.saturating_add(cnt as u32);
252		(addrs, cnt)
253	}
254	
255	pub fn iter_range<'s>(&'s self, range: MemoryRange) -> RangeIter<'s>
256	{
257		let first = match self.locate(range.first, Search::Above)
258		{
259			None => self.parts.len(),
260			Some(idx) => idx,
261		};
262		RangeIter{base: self, next: first, range}
263	}
264	
265	pub fn remove(&mut self, addr: u32) -> Option<(MemoryRange, Vec<u8>)>
266	{
267		match self.locate(addr, Search::Exact)
268		{
269			None => None,
270			Some(idx) =>
271			{
272				let seg = self.parts.remove(idx);
273				Some((seg.range, seg.data))
274			},
275		}
276	}
277	
278	pub fn remove_range(&mut self, range: MemoryRange)
279	{
280		match self.locate(range.first, Search::Above)
281		{
282			Some(first_idx) if range.last >= self.parts[first_idx].range.first =>
283			{
284				let first = &mut self.parts[first_idx];
285				if range.first > first.range.first && range.last < first.range.last
286				{
287					// only one segment is affected, but we have to split it into 2
288					// both casts are fine as the values are smaller than `first.data.len()`
289					let start_off = (range.first - first.range.first) as usize;
290					let end_off = (first.range.last - range.last) as usize;
291					
292					let end_range = MemoryRange{first: range.last + 1, last: first.range.last};
293					let end_data = first.data[first.data.len() - end_off..].to_owned();
294					first.range.last = range.first - 1;
295					first.data.truncate(start_off);
296					self.parts.insert(first_idx + 1, MemorySegment{range: end_range, data: end_data});
297				}
298				else
299				{
300					let remove_first = if range.first <= first.range.first
301					{
302						if range.last < first.range.last
303						{
304							// cut from the beginning
305							first.data.drain(..(range.last + 1 - first.range.first) as usize);
306							first.range.first = range.last + 1;
307							false
308						}
309						else {true}
310					}
311					else
312					{
313						// no overflow because `range.first <= first.range.last` (from locate)
314						first.data.truncate((range.first - first.range.first) as usize);
315						first.range.last = range.first - 1;
316						false // never drop because `range.first > first.range.first`
317					};
318					
319					// we know that something exists not after `range.last` but above may have truncated it
320					match self.locate(range.last, Search::Below)
321					{
322						// only possible if above code cut this segment from the begining, in which case this is always false
323						None => assert!(!remove_first),
324						Some(last_idx) =>
325						{
326							if last_idx > first_idx
327							{
328								let last = &mut self.parts[last_idx];
329								// we know `range.first < last.range.last` because `range.first <= first.range.last` (from locate)
330								let remove_last = if range.last < last.range.last
331								{
332									// cut from the beginning
333									last.data.drain(..(range.last + 1 - last.range.first) as usize);
334									last.range.first = range.last + 1;
335									false
336								}
337								else {true};
338								self.parts.drain(first_idx + (!remove_first) as usize..last_idx + remove_last as usize);
339							}
340							else
341							{
342								if remove_first {self.parts.remove(first_idx);}
343							}
344						},
345					}
346				}
347			},
348			_ => return,
349		}
350	}
351	
352	pub fn clear(&mut self)
353	{
354		self.parts.clear();
355	}
356}
357
358#[derive(Clone, Debug, Eq, PartialEq)]
359pub enum PutError
360{
361	Overflow{need: usize, have: usize},
362}
363
364impl fmt::Display for PutError
365{
366	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
367	{
368		match self
369		{
370			Self::Overflow{need, have} => write!(f, "segment overflow (expected {need} but got {have})"),
371		}
372	}
373}
374
375impl Error for PutError {}
376
377#[derive(Clone, Debug)]
378pub struct Iter<'l>(SliceIter<'l, MemorySegment>);
379
380impl<'l> Iterator for Iter<'l>
381{
382	type Item = (MemoryRange, &'l [u8]);
383	
384	fn next(&mut self) -> Option<Self::Item>
385	{
386		self.0.next().map(|e| (e.range, e.data.as_ref()))
387	}
388}
389
390impl<'l> FusedIterator for Iter<'l> where SliceIter<'l, MemorySegment>: FusedIterator {}
391
392#[derive(Clone, Debug)]
393pub struct RangeIter<'l>
394{
395	base: &'l MemoryMap,
396	next: usize,
397	range: MemoryRange,
398}
399
400impl<'l> RangeIter<'l>
401{
402	pub fn range(&self) -> MemoryRange
403	{
404		self.range
405	}
406}
407
408impl<'l> Iterator for RangeIter<'l>
409{
410	type Item = (MemoryRange, &'l [u8]);
411	
412	fn next(&mut self) -> Option<Self::Item>
413	{
414		match self.base.parts.get(self.next)
415		{
416			None => None,
417			Some(seg) =>
418			{
419				if seg.range.first <= self.range.last
420				{
421					self.next += 1;
422					let (start_off, first_addr) = if self.range.first <= seg.range.first {(0, seg.range.first)}
423					else {((self.range.first - seg.range.first) as usize, self.range.first)};
424					let (end_off, last_addr) = if self.range.last >= seg.range.last {(0, seg.range.last)}
425					else {((seg.range.last - self.range.last) as usize, self.range.last)};
426					Some((MemoryRange{first: first_addr, last: last_addr}, &seg.data[start_off..seg.data.len() - end_off]))
427				}
428				else
429				{
430					self.next = self.base.parts.len();
431					None
432				}
433			},
434		}
435	}
436}
437
438impl<'l> FusedIterator for RangeIter<'l> {}