summary refs log tree commit diff
path: root/src/engine.rs
diff options
context:
space:
mode:
authorSophie Forrest <git@sophieforrest.com>2024-08-30 23:35:45 +1200
committerSophie Forrest <git@sophieforrest.com>2024-08-30 23:35:45 +1200
commit13b95941183666fadd090314e4e9af33283084cd (patch)
tree2831968068a77b7a37a37d1356e9673d4dcc3275 /src/engine.rs
parentf5f789540ad7d3f7f4f855c9db69d65cfc190ee0 (diff)
feat(engine)!: implement u32 engine
Diffstat (limited to '')
-rw-r--r--src/engine.rs54
1 files changed, 49 insertions, 5 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(())
 	}