selya/
domain.rs

1#[derive(Debug)]
2pub struct Memory {
3    size: u16,
4    memory: Vec<u16>,
5    position: usize,
6    position_as_u16: u16,
7}
8
9#[derive(Debug)]
10pub enum MemoryError {
11    Overflow,
12    OutOfRange,
13}
14
15#[derive(Debug)]
16pub enum ShiftDirection {
17    Right,
18    Left,
19}
20
21impl Memory {
22    pub fn new(size: u16) -> Self {
23        Memory {
24            size,
25            memory: vec![0; size.into()],
26            position: 0,
27            position_as_u16: 0,
28        }
29    }
30
31    fn update_position(&mut self, new_value: u16) -> u16 {
32        self.position_as_u16 = new_value;
33        self.position = new_value.into();
34
35        new_value
36    }
37
38    pub fn write(&mut self, value: u16) -> u16 {
39        self.memory[self.position] = value;
40
41        value
42    }
43
44    pub fn add(&mut self, value: u16) -> Result<u16, MemoryError> {
45        let current = self.memory[self.position];
46
47        if let Some(result) = current.checked_add(value) {
48            self.memory[self.position] = result;
49            return Ok(result);
50        }
51
52        Err(MemoryError::Overflow)
53    }
54
55    pub fn add_modulo(&mut self, value: u16) -> u16 {
56        self.memory[self.position] ^= value;
57
58        value
59    }
60
61    fn shift(&mut self, value: u16, direction: ShiftDirection) -> Result<u16, MemoryError> {
62        match direction {
63            ShiftDirection::Left => match self.position_as_u16.checked_sub(value) {
64                Some(value) => Ok(self.update_position(value)),
65                None => Err(MemoryError::OutOfRange),
66            },
67            ShiftDirection::Right => match self.position_as_u16.checked_add(value) {
68                Some(value) => Ok(self.update_position(value)),
69                None => Err(MemoryError::OutOfRange),
70            },
71        }
72    }
73
74    pub fn shift_right(&mut self) -> Result<u16, MemoryError> {
75        self.shift(1, ShiftDirection::Right)
76    }
77
78    pub fn shift_left(&mut self) -> Result<u16, MemoryError> {
79        self.shift(1, ShiftDirection::Left)
80    }
81
82    fn rotate(&mut self, value: usize, direction: ShiftDirection) {
83        let guard: usize = self.size.into();
84
85        match direction {
86            ShiftDirection::Right => self.memory.rotate_right(value % guard),
87            ShiftDirection::Left => self.memory.rotate_left(value % guard),
88        }
89    }
90
91    pub fn shift_word_left(&mut self) {
92        self.rotate(1, ShiftDirection::Left)
93    }
94
95    pub fn shift_word_right(&mut self) {
96        self.rotate(1, ShiftDirection::Right)
97    }
98
99    #[allow(dead_code)]
100    pub fn get_size(&self) -> u16 {
101        self.size
102    }
103
104    pub fn memory_view(&self) -> Vec<u16> {
105        self.memory.clone()
106    }
107}
108
109impl IntoIterator for Memory {
110    type IntoIter = std::vec::IntoIter<u16>;
111    type Item = u16;
112
113    fn into_iter(self) -> Self::IntoIter {
114        self.memory.into_iter()
115    }
116}