From 33968095ecc937f0081ac54cb71622b0c25b88f2 Mon Sep 17 00:00:00 2001 From: rowan Date: Sun, 5 Jan 2025 22:57:00 -0600 Subject: [PATCH] explicitly allow input as a parameter if file open fails --- src/main.rs | 108 +++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 90 insertions(+), 18 deletions(-) diff --git a/src/main.rs b/src/main.rs index d058a12..032f5c5 100644 --- a/src/main.rs +++ b/src/main.rs @@ -4,35 +4,109 @@ use std::fmt::Debug; use std::fs::File; use std::io::{BufRead, BufReader, Read}; use std::num::TryFromIntError; +use std::ops::Deref; use std::result::Result as StdResult; use std::{env, fs, io}; -enum Input { - File(fs::File), - Stdin(io::Stdin), +enum MaybeOwned { + Owned(T1), + Borrowed(T2), } -impl Input { - fn into_reader(self) -> Box { - match self { - Input::File(file) => Box::new(BufReader::new(file)), - Input::Stdin(stdin) => Box::new(stdin.lock()), +type StringBuf<'a> = MaybeOwned; + +struct StringReader<'a> { + inner: StringBuf<'a>, + index: usize, +} + +impl<'a> From for StringReader<'a> { + fn from(value: String) -> Self { + StringReader::new(MaybeOwned::Owned(value)) + } +} + +impl<'a> From<&'a [u8]> for StringReader<'a> { + fn from(value: &'a [u8]) -> Self { + StringReader::new(MaybeOwned::Borrowed(value)) + } +} + +impl<'a> From> for StringReader<'a> { + fn from(value: StringBuf<'a>) -> Self { + match value { + MaybeOwned::Owned(s) => s.into(), + MaybeOwned::Borrowed(s) => s.into(), } } } -impl TryFrom<&str> for Input { +impl<'a> StringReader<'a> { + pub fn new(inner: StringBuf<'a>) -> Self { + Self { inner, index: 0 } + } +} + +impl<'a> Deref for StringReader<'a> { + type Target = [u8]; + + fn deref(&self) -> &Self::Target { + match &self.inner { + MaybeOwned::Owned(s) => s.as_bytes(), + MaybeOwned::Borrowed(s) => s, + } + } +} + +impl<'a> Read for StringReader<'a> { + fn read(&mut self, buf: &mut [u8]) -> io::Result { + let len = (self.len() - self.index).min(buf.len()); + buf.copy_from_slice(&self[self.index..len]); + Ok(len) + } +} + +impl<'a> BufRead for StringReader<'a> { + fn fill_buf(&mut self) -> io::Result<&[u8]> { + Ok(self) + } + + fn consume(&mut self, amt: usize) { + self.index += amt.max(self.len()); + } +} + +enum Input<'a> { + File(fs::File), + Stdin(io::Stdin), + String(StringBuf<'a>), +} + +impl<'a: 'static> Input<'a> { + fn into_reader(self) -> Box { + match self { + Input::File(file) => Box::new(BufReader::new(file)), + Input::Stdin(stdin) => Box::new(stdin.lock()), + Input::String(str) => Box::new(StringReader::from(str)), + } + } +} + +impl TryFrom<&str> for Input<'_> { type Error = io::Error; fn try_from(value: &str) -> StdResult { match value { "-" => Ok(Self::Stdin(io::stdin())), - path => File::open(path).map(Self::File), + path => match File::open(path) { + Ok(file) => Ok(Self::File(file)), + Err(_) => Ok(Input::String(MaybeOwned::Owned(path.to_owned()))), + }, } } } -impl TryFrom for Input { +impl TryFrom for Input<'_> { type Error = io::Error; fn try_from(value: String) -> StdResult { @@ -279,14 +353,15 @@ impl Program { } fn step(&mut self) -> Result { - if let Some((a, b, c)) = self.next_instruction() { - if b == -1 && a > -1 { + match self.next_instruction() { + Some((a, -1, c)) if a > -1 => { let ax = self.get_isize_as_usize(a)?.try_into()?; char::from_u32(ax).inspect(|c| print!("{c}")); let counter = c.try_into()?; Ok(State::Continue(counter)) - } else if a > -1 && b > -1 { + } + Some((a, b, c)) if a > -1 && b > -1 => { let ax = self.get_isize(a)?; let bx = self.get_isize(b)?; let next = bx - ax; @@ -298,11 +373,8 @@ impl Program { let counter = c.try_into()?; Ok(State::Continue(counter)) } - } else { - Ok(State::Halt) } - } else { - Ok(State::Halt) + _ => Ok(State::Halt), } }