explicitly allow input as a parameter if file open fails
This commit is contained in:
parent
9d83ad1ccf
commit
33968095ec
1 changed files with 90 additions and 18 deletions
108
src/main.rs
108
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<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),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue