explicitly allow input as a parameter if file open fails

This commit is contained in:
Rowan 2025-01-05 22:57:00 -06:00
parent 9d83ad1ccf
commit 33968095ec

View file

@ -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<T1, T2 = T1> {
Owned(T1),
Borrowed(T2),
}
impl Input {
fn into_reader(self) -> Box<dyn BufRead> {
match self {
Input::File(file) => Box::new(BufReader::new(file)),
Input::Stdin(stdin) => Box::new(stdin.lock()),
type StringBuf<'a> = MaybeOwned<String, &'a [u8]>;
struct StringReader<'a> {
inner: StringBuf<'a>,
index: usize,
}
impl<'a> From<String> 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<StringBuf<'a>> 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<usize> {
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<dyn BufRead> {
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<Self, Self::Error> {
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<String> for Input {
impl TryFrom<String> for Input<'_> {
type Error = io::Error;
fn try_from(value: String) -> StdResult<Self, Self::Error> {
@ -279,14 +353,15 @@ impl Program {
}
fn step(&mut self) -> Result<State> {
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),
}
}