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}