bf_playground/
lib.rs

1use std::io::{Write, Read};
2
3#[allow(dead_code)]
4pub struct BFPlayground {
5    array: [u8; 30000],
6    pointer: usize,
7}
8
9#[allow(dead_code)]
10impl BFPlayground {
11    pub fn new() -> Self {
12        BFPlayground {
13            array: [0; 30000],
14            pointer: 0,
15        }
16    }
17
18    pub fn get_pointer_position(&self) -> usize {
19        self.pointer
20    }
21
22    pub fn set_pointer_position(&mut self, position: usize) {
23        self.pointer = position;
24    }
25
26    pub fn increment_pointer_position(&mut self) {
27        if self.pointer == 29999 {
28            self.pointer = 0;
29        } else {
30            self.pointer += 1;
31        }
32    }
33
34    pub fn decrement_pointer_position(&mut self) {
35        if self.pointer == 0 {
36            self.pointer = 29999;
37        } else {
38            self.pointer -= 1;
39        }
40    }
41
42    pub fn set_value_at(&mut self, position: usize, value: u8) {
43        if position > 29999 {
44            panic!("Index out of bounds");
45        }
46
47        self.array[position] = value;
48    }
49
50    pub fn get_value_at(&mut self, position: usize) -> u8 {
51        if position > 29999 {
52            panic!("Index out of bounds");
53        }
54
55        self.array[position]
56    }
57
58    pub fn get_pointer_value(&self) -> u8 {
59        self.array[self.pointer]
60    }
61
62    pub fn set_pointer_value(&mut self, value: u8) {
63        self.array[self.pointer] = value;
64    }
65
66    pub fn increment_pointer_value(&mut self) {
67        if self.array[self.pointer] == 255 {
68            self.array[self.pointer] = 0;
69        } else {
70            self.array[self.pointer] += 1;
71        }
72    }
73
74    pub fn decrement_pointer_value(&mut self) {
75        if self.array[self.pointer] == 0 {
76            self.array[self.pointer] = 255;
77        } else {
78            self.array[self.pointer] -= 1;
79        }
80    }
81
82    pub fn print_pointer_value(&self, output: &mut impl Write) -> Result<(), std::io::Error> {
83        
84        output.write_all((self.array[self.pointer] as char).to_string().as_bytes())?;
85        Ok(())
86    }
87
88    pub fn read_pointer_value(&mut self, input: &mut impl Read) -> Result<(), std::io::Error> {
89        let mut buffer = [0; 1];
90        input.read_exact(&mut buffer)?;
91        self.set_pointer_value(buffer[0]);
92        Ok(())
93    }
94
95    pub fn execute(&mut self, code: &str, input: &mut impl Read, output: &mut impl Write) {
96        let mut code_pointer: usize = 0;
97
98        while let Some(character) = code.chars().nth(code_pointer) {
99            match character {
100                '>' => self.increment_pointer_position(),
101                '<' => self.decrement_pointer_position(),
102                '+' => self.increment_pointer_value(),
103                '-' => self.decrement_pointer_value(),
104                '.' => self.print_pointer_value(output).unwrap_or(()),
105                ',' => self.read_pointer_value(input).unwrap_or(()),
106                '[' => {
107                    if self.get_pointer_value() == 0 {
108                        let mut bracket_counter = 1;
109                        while bracket_counter != 0 {
110                            code_pointer += 1;
111                            if code.chars().nth(code_pointer).unwrap() == '[' {
112                                bracket_counter += 1;
113                            } else if code.chars().nth(code_pointer).unwrap() == ']' {
114                                bracket_counter -= 1;
115                            }
116                        }
117                    }
118                },
119                ']' => {
120                    if self.get_pointer_value() != 0 {
121                        let mut bracket_counter = 1;
122                        while bracket_counter != 0 {
123                            code_pointer -= 1;
124                            if code.chars().nth(code_pointer).unwrap() == ']' {
125                                bracket_counter += 1;
126                            } else if code.chars().nth(code_pointer).unwrap() == '[' {
127                                bracket_counter -= 1;
128                            }
129                        }
130                    }
131                }
132                _ => {}
133            };
134            code_pointer += 1;
135        }
136    }
137}
138
139#[cfg(test)]
140#[warn(dead_code)]
141mod tests {
142    use super::*;
143
144    #[test]
145    fn should_create_array_full_of_zeros() {
146        let bf_playground = BFPlayground::new();
147        assert_eq!(bf_playground.array, [0; 30000]);
148    }
149
150    #[test]
151    fn should_create_pointer_set_to_zero() {
152        let bf_playground = BFPlayground::new();
153        assert_eq!(bf_playground.pointer, 0);
154    }
155
156    #[test]
157    fn get_pointer_position() {
158        let bf_playground = BFPlayground{
159            array: [0; 30000],
160            pointer: 23123,
161        };
162        assert_eq!(bf_playground.get_pointer_position(), 23123);
163    }
164
165    #[test]
166    fn set_pointer_position() {
167        let mut bf_playground = BFPlayground::new();
168        assert_eq!(bf_playground.get_pointer_position(), 0);
169        bf_playground.set_pointer_position(123);
170        assert_eq!(bf_playground.get_pointer_position(), 123);
171    }
172
173    #[test]
174    fn increment_pointer_position() {
175        let mut bf_playground = BFPlayground::new();
176        assert_eq!(bf_playground.get_pointer_position(), 0);
177        bf_playground.increment_pointer_position();
178        assert_eq!(bf_playground.get_pointer_position(), 1);
179    }
180
181    #[test]
182    fn increment_overflow_pointer_position() {
183        let mut bf_playground = BFPlayground::new();
184        bf_playground.set_pointer_position(29999);
185        assert_eq!(bf_playground.get_pointer_position(), 29999);
186        bf_playground.increment_pointer_position();
187        assert_eq!(bf_playground.get_pointer_position(), 0);
188    }
189
190    #[test]
191    fn decrement_pointer_position() {
192        let mut bf_playground = BFPlayground::new();
193        bf_playground.set_pointer_position(1);
194        assert_eq!(bf_playground.get_pointer_position(), 1);
195        bf_playground.decrement_pointer_position();
196        assert_eq!(bf_playground.get_pointer_position(), 0);
197    }
198    
199    #[test]
200    fn decrement_underflow_pointer_position() {
201        let mut bf_playground = BFPlayground::new();
202        assert_eq!(bf_playground.get_pointer_position(), 0);
203        bf_playground.decrement_pointer_position();
204        assert_eq!(bf_playground.get_pointer_position(), 29999);
205    }
206
207    #[test]
208    fn set_value_at() {
209        let mut bf_playground = BFPlayground::new();
210        assert_eq!(bf_playground.get_value_at(0), 0);
211        bf_playground.set_value_at(0, 12);
212        assert_eq!(bf_playground.get_value_at(0), 12);
213    }
214
215    #[test]
216    #[should_panic]
217    fn set_value_at_out_of_bounds_exacly() {
218        let mut bf_playground = BFPlayground::new();
219        bf_playground.get_value_at(30000);
220    }
221
222    #[test]
223    #[should_panic]
224    fn set_value_at_out_of_bounds_more() {
225        let mut bf_playground = BFPlayground::new();
226        bf_playground.get_value_at(30001);
227    }
228
229    #[test]
230    fn get_value_at() {
231        let mut bf_playground = BFPlayground::new();
232        bf_playground.set_value_at(43, 12);
233        assert_eq!(bf_playground.get_value_at(43), 12);
234    }
235
236    #[test]
237    #[should_panic]
238    fn get_value_at_out_of_bounds_exacly() {
239        let mut bf_playground = BFPlayground::new();
240        bf_playground.get_value_at(30000);
241    }
242
243    #[test]
244    #[should_panic]
245    fn get_value_at_out_of_bounds_more() {
246        let mut bf_playground = BFPlayground::new();
247        bf_playground.get_value_at(30001);
248    }
249
250    #[test]
251    fn get_pointer_value() {
252        let bf_playground = BFPlayground{
253            array: [12; 30000],
254            pointer: 0,
255        };
256        assert_eq!(bf_playground.get_pointer_value(), 12);
257    }
258
259    #[test]
260    fn set_pointer_value() {
261        let mut bf_playground = BFPlayground::new();
262        assert_eq!(bf_playground.get_pointer_value(), 0);
263        bf_playground.set_pointer_value(12);
264        assert_eq!(bf_playground.get_pointer_value(), 12);
265    }
266
267    #[test]
268    fn increment_pointer_value() {
269        let mut bf_playground = BFPlayground::new();
270        assert_eq!(bf_playground.get_pointer_value(), 0);
271        bf_playground.increment_pointer_value();
272        assert_eq!(bf_playground.get_pointer_value(), 1);
273    }
274
275    #[test]
276    fn increment_overflow_pointer_value() {
277        let mut bf_playground = BFPlayground::new();
278        bf_playground.set_pointer_value(255);
279        assert_eq!(bf_playground.get_pointer_value(), 255);
280        bf_playground.increment_pointer_value();
281        assert_eq!(bf_playground.get_pointer_value(), 0);
282    }
283
284    #[test]
285    fn decrement_pointer_value() {
286        let mut bf_playground = BFPlayground::new();
287        bf_playground.set_pointer_value(1);
288        assert_eq!(bf_playground.get_pointer_value(), 1);
289        bf_playground.decrement_pointer_value();
290        assert_eq!(bf_playground.get_pointer_value(), 0);
291    }
292
293    #[test]
294    fn decrement_underflow_pointer_value() {
295        let mut bf_playground = BFPlayground::new();
296        assert_eq!(bf_playground.get_pointer_value(), 0);
297        bf_playground.decrement_pointer_value();
298        assert_eq!(bf_playground.get_pointer_value(), 255);
299    }
300
301    #[test]
302    fn print_pointer_value() {
303        let mut output = Vec::new();
304        let bf_playground = BFPlayground{
305            array: ['a' as u8; 30000],
306            pointer: 0,
307        };
308        bf_playground.print_pointer_value(&mut output).unwrap();
309        assert_eq!(String::from_utf8(output).unwrap(), "a");
310    }
311    
312    #[test]
313    fn read_pointer_value() {
314        let mut input = "a".as_bytes();
315        let mut bf_playground = BFPlayground::new();
316        assert_eq!(bf_playground.get_pointer_value(), 0);
317        bf_playground.read_pointer_value(&mut input).unwrap();
318        assert_eq!(bf_playground.get_pointer_value(), 'a' as u8);
319    }
320
321    #[test]
322    fn execute_increment() {
323        let mut bf_playground = BFPlayground::new();
324        let code = "+";
325        bf_playground.execute(code, &mut "".as_bytes(), &mut Vec::new());
326        assert_eq!(bf_playground.get_pointer_value(), 1);
327    }
328
329    #[test]
330    fn execute_decrement() {
331        let mut bf_playground = BFPlayground::new();
332        let code = "-";
333        bf_playground.execute(code, &mut "".as_bytes(), &mut Vec::new());
334        assert_eq!(bf_playground.get_pointer_value(), 255);
335    }
336
337    #[test]
338    fn execute_move_left() {
339        let mut bf_playground = BFPlayground::new();
340        let code = "<";
341        bf_playground.execute(code, &mut "".as_bytes(), &mut Vec::new());
342        assert_eq!(bf_playground.get_pointer_position(), 29999);
343    }
344
345    #[test]
346    fn execute_move_right() {
347        let mut bf_playground = BFPlayground::new();
348        let code = ">";
349        bf_playground.execute(code, &mut "".as_bytes(), &mut Vec::new());
350        assert_eq!(bf_playground.get_pointer_position(), 1);
351    }
352
353    #[test]
354    fn execute_print() {
355        let mut output = Vec::new();
356        let mut bf_playground = BFPlayground::new();
357        let code = ".";
358        bf_playground.set_pointer_value('a' as u8);
359        bf_playground.execute(code, &mut "".as_bytes(), &mut output);
360        assert_eq!(String::from_utf8(output).unwrap(), "a");
361    }
362
363    #[test]
364    fn execute_read() {
365        let mut input = "a".as_bytes();
366        let mut bf_playground = BFPlayground::new();
367        let code = ",";
368        bf_playground.execute(code, &mut input, &mut Vec::new());
369        assert_eq!(bf_playground.get_pointer_value(), 'a' as u8);
370    }
371
372    #[test]
373    fn execute_loop() {
374        let mut bf_playground = BFPlayground::new();
375        let code = "[-]";
376        bf_playground.set_pointer_value(255);
377        bf_playground.execute(code, &mut "".as_bytes(), &mut Vec::new());
378        assert_eq!(bf_playground.get_pointer_value(), 0);
379    }
380
381    #[test]
382    fn execute_nested_loop() {
383        let mut bf_playground = BFPlayground::new();
384        let code = "[[-]]";
385        bf_playground.set_pointer_value(255);
386        bf_playground.execute(code, &mut "".as_bytes(), &mut Vec::new());
387        assert_eq!(bf_playground.get_pointer_value(), 0);
388    }
389
390}