//! Executor engine implementation for Brainfuck interpreter. //! //! This predominantly allows implementation of a [`u16`] executor. use std::io::Read; use num_traits::{One, Unsigned, WrappingAdd, WrappingSub, Zero}; use crate::executor::{self, Error}; /// Generic engine implementation for the Brainfuck interpreter. pub trait Engine { /// Inner type of the Tape. type TapeInner: Clone + Copy + Unsigned + WrappingAdd + WrappingSub + One + Zero; /// Read one byte from stdin. /// /// # Errors /// /// This function will return an error if it is unable to read from stdin, /// or if it indexes out of bounds. fn read_byte() -> Result; /// Write the provided byte to stdout. /// /// # Errors /// /// This function will return an error if it is unable to write a byte to /// stdout. fn write_byte(byte: Self::TapeInner) -> Result<(), Error>; } impl Engine for executor::U8 { type TapeInner = u8; fn read_byte() -> Result { let mut input: [u8; 1] = [0; 1]; std::io::stdin().read_exact(&mut input)?; Ok(input[0]) } fn write_byte(byte: u8) -> Result<(), Error> { print!("{}", char::from(byte)); Ok(()) } } impl Engine for executor::U16 { type TapeInner = u16; fn read_byte() -> Result { let mut input: [u8; 2] = [0; 2]; std::io::stdin().read_exact(&mut input)?; let number = ((u16::from(input[0])) << 8i32) | u16::from(input[1]); Ok(number) } fn write_byte(byte: u16) -> Result<(), Error> { print!("{}", String::from_utf16_lossy(&[byte])); Ok(()) } }