1use std::ops::{Index, IndexMut};
2
3#[derive(Debug, Clone)]
4pub struct VirtualMemory<T> {
5 memory_size: usize,
6 segment_mask: usize,
7 segment_shift: u32,
8 default: T,
9 data: Vec<Vec<T>>,
10}
11
12impl<T: Copy + Default> Index<usize> for VirtualMemory<T> {
13 type Output = T;
14 fn index(&self, index: usize) -> &Self::Output {
15 let segment_index = index >> self.segment_shift;
16 let segment_offset = index & self.segment_mask;
17 if self.data[segment_index].is_empty() {
18 return &self.default;
19 }
20 Index::index(&self.data[segment_index], segment_offset)
21 }
22}
23
24impl<T: Copy + Default> IndexMut<usize> for VirtualMemory<T> {
25 fn index_mut(&mut self, index: usize) -> &mut Self::Output {
26 let segment_index = index >> self.segment_shift;
27 let segment_offset = index & self.segment_mask;
28 if self.data[segment_index].is_empty() {
29 self.data[segment_index] = vec![T::default(); self.segment_mask + 1];
30 }
31 IndexMut::index_mut(&mut self.data[segment_index], segment_offset)
32 }
33}
34
35impl<T: Copy + Default> VirtualMemory<T> {
36 pub fn new(memory_size: usize, segment_size: usize) -> Self {
37 assert!(
38 memory_size % segment_size == 0,
39 "memory size must be multiple of segment size"
40 );
41 assert!(
42 segment_size.is_power_of_two(),
43 "segment size must be a power of two"
44 );
45 let segment_mask = segment_size - 1;
46 let segment_shift = segment_size.trailing_zeros();
47 let segments = memory_size / segment_size;
48 Self {
49 memory_size,
50 segment_mask,
51 segment_shift,
52 default: T::default(),
53 data: vec![[].to_vec(); segments],
54 }
55 }
56
57 pub fn iter(&self) -> impl Iterator<Item = &T> {
64 self.data.iter().filter(|x| !x.is_empty()).flatten()
65 }
66
67 pub fn size(&self) -> usize {
68 self.memory_size
69 }
70}
71
72#[cfg(test)]
73mod tests {
74 use super::*;
75
76 #[test]
77 fn load_default() {
78 let m = VirtualMemory::<i32>::new(32, 16);
79 assert_eq!(m[0], 0);
80 assert_eq!(m[15], 0);
81 assert_eq!(m[16], 0);
82 assert_eq!(m[31], 0);
83 }
84
85 #[test]
86 #[should_panic]
87 fn load_out_of_bounds() {
88 let m = VirtualMemory::<i32>::new(32, 16);
89 let _this_will_panic = m[32];
90 }
91
92 #[test]
93 fn store_value() {
94 let mut m = VirtualMemory::<i32>::new(32, 16);
95 assert_eq!(m[0], 0);
96 assert_eq!(m[1], 0);
97 m[0] = 7;
98 assert_eq!(m[0], 7);
99 assert_eq!(m[1], 0);
100 }
101
102 #[test]
103 #[should_panic]
104 fn store_out_of_bounds() {
105 let mut m = VirtualMemory::<i32>::new(32, 16);
106 m[32] = 7; }
108
109 #[test]
110 fn iter_values() {
111 let mut m = VirtualMemory::<i32>::new(8, 2);
112 m[0] = 23; m[3] = 42; assert_eq!(m.iter().copied().collect::<Vec<i32>>(), vec![23, 0, 0, 42]);
115 }
116}