diff options
| author | Sophie Forrest <git@sophieforrest.com> | 2024-08-30 23:35:45 +1200 |
|---|---|---|
| committer | Sophie Forrest <git@sophieforrest.com> | 2024-08-30 23:35:45 +1200 |
| commit | 13b95941183666fadd090314e4e9af33283084cd (patch) | |
| tree | 2831968068a77b7a37a37d1356e9673d4dcc3275 /src | |
| parent | f5f789540ad7d3f7f4f855c9db69d65cfc190ee0 (diff) | |
feat(engine)!: implement u32 engine
Diffstat (limited to 'src')
| -rw-r--r-- | src/engine.rs | 54 | ||||
| -rw-r--r-- | src/executor.rs | 12 | ||||
| -rw-r--r-- | src/lib.rs | 1 | ||||
| -rw-r--r-- | src/main.rs | 1 | ||||
| -rw-r--r-- | src/utility.rs | 5 |
5 files changed, 58 insertions, 15 deletions
diff --git a/src/engine.rs b/src/engine.rs index 8cf2726..6c69bc1 100644 --- a/src/engine.rs +++ b/src/engine.rs @@ -2,11 +2,29 @@ //! //! This predominantly allows implementation of a [`u16`] executor. -use std::io::Read; +use std::io::{Cursor, Read}; +use byteorder::{BigEndian, ReadBytesExt}; use num_traits::{One, Unsigned, WrappingAdd, WrappingSub, Zero}; +use thiserror::Error; -use crate::executor::{self, Error}; +use crate::executor; + +/// Error type for engine errors +#[derive(Debug, Error)] +pub enum Error { + /// Engine ran into an io Error + #[error(transparent)] + Io(#[from] std::io::Error), + + /// Utf16 error from widestring + #[error("could not convert byte to Utf16Str")] + Utf16, + + /// Utf32 error from widestring + #[error("could not convert byte to Utf32Str")] + Utf32, +} /// Generic engine implementation for the Brainfuck interpreter. pub trait Engine { @@ -56,13 +74,39 @@ impl Engine for executor::U16 { std::io::stdin().read_exact(&mut input)?; - let number = ((u16::from(input[0])) << 8i32) | u16::from(input[1]); + let mut reader = Cursor::new(input); - Ok(number) + Ok(reader.read_u16::<BigEndian>()?) } fn write_byte(byte: u16) -> Result<(), Error> { - print!("{}", String::from_utf16_lossy(&[byte])); + print!( + "{}", + widestring::Utf16Str::from_slice(&[byte]).map_err(|_err| Error::Utf16)? + ); + + Ok(()) + } +} + +impl Engine for executor::U32 { + type TapeInner = u32; + + fn read_byte() -> Result<u32, Error> { + let mut input: [u8; 4] = [0; 4]; + + std::io::stdin().read_exact(&mut input)?; + + let mut reader = Cursor::new(input); + + Ok(reader.read_u32::<BigEndian>()?) + } + + fn write_byte(byte: u32) -> Result<(), Error> { + print!( + "{}", + widestring::Utf32Str::from_slice(&[byte]).map_err(|_err| Error::Utf32)? + ); Ok(()) } diff --git a/src/executor.rs b/src/executor.rs index eddf443..da7d676 100644 --- a/src/executor.rs +++ b/src/executor.rs @@ -9,14 +9,14 @@ use crate::{engine::Engine, parser::Instruction}; /// Runtime errors that can occur in brainfuck executor. #[derive(Debug, Diagnostic, Error)] pub enum Error { + /// Brainfuck engine ran into an error at runtime. + #[error(transparent)] + Engine(#[from] crate::engine::Error), + /// Brainfuck code performed an out of bounds index on the tape during /// runtime. #[error("tape indexed out of bounds, attempted index at `{0}`")] IndexOutOfBounds(usize), - - /// Executor was unable to read an input byte from stdin. - #[error("could not read input from stdin")] - ReadInput(#[from] std::io::Error), } /// Struct for executor implementation, allows u8 Engine to be implemented. @@ -27,6 +27,10 @@ pub struct U8; #[derive(Clone, Copy, Debug)] pub struct U16; +/// Struct for executor implementation, allows u32 Engine to be implemented. +#[derive(Clone, Copy, Debug)] +pub struct U32; + /// Executes the provided instruction set, utilising the provided tape.. /// /// # Errors diff --git a/src/lib.rs b/src/lib.rs index b806b4c..2c40797 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -3,7 +3,6 @@ #![feature(custom_inner_attributes)] #![feature(lint_reasons)] #![feature(never_type)] -#![feature(once_cell)] #![feature(test)] #![deny(clippy::complexity)] #![deny(clippy::nursery)] diff --git a/src/main.rs b/src/main.rs index f5c4740..13868a6 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,7 +3,6 @@ #![feature(custom_inner_attributes)] #![feature(lint_reasons)] #![feature(never_type)] -#![feature(once_cell)] #![deny(clippy::complexity)] #![deny(clippy::nursery)] #![deny(clippy::pedantic)] diff --git a/src/utility.rs b/src/utility.rs index 4eba853..514343c 100644 --- a/src/utility.rs +++ b/src/utility.rs @@ -37,10 +37,7 @@ pub fn execute_from_file<E: Engine>( /// This function will return an error if parsing or /// execution fails. See documentation for [`crate::parser::parse`] and /// [`crate::executor::execute`]. -pub fn execute_from_str<E: Engine<TapeInner = u8>>( - input: &str, - tape: &mut [E::TapeInner], -) -> Result<(), Error> { +pub fn execute_from_str<E: Engine>(input: &str, tape: &mut [E::TapeInner]) -> Result<(), Error> { let operator_codes = lex(input); let instructions = parse(input, &operator_codes)?; |