use driver_lang::{DriverError, Pipeline, Session, Stage};
struct Config {
max_value: i64,
}
struct Lex;
impl Stage<Config> for Lex {
type Input = &'static str;
type Output = Vec<i64>;
fn name(&self) -> &'static str {
"lex"
}
fn run(
&mut self,
input: &'static str,
session: &mut Session<Config>,
) -> Result<Vec<i64>, DriverError> {
let mut values = Vec::new();
for token in input.split_whitespace() {
match token.parse::<i64>() {
Ok(value) => values.push(value),
Err(_) => {
session.warn(format!("ignoring non-integer token `{token}`"));
}
}
}
if values.is_empty() {
return Err(DriverError::new("no integers to sum"));
}
Ok(values)
}
}
struct Check;
impl Stage<Config> for Check {
type Input = Vec<i64>;
type Output = Vec<i64>;
fn name(&self) -> &'static str {
"check"
}
fn run(
&mut self,
input: Vec<i64>,
session: &mut Session<Config>,
) -> Result<Vec<i64>, DriverError> {
let cap = session.config().max_value;
for &value in &input {
if value > cap {
session.error(format!("value {value} exceeds cap {cap}"));
}
}
session.abort_if_errors()?;
Ok(input)
}
}
struct Sum;
impl Stage<Config> for Sum {
type Input = Vec<i64>;
type Output = i64;
fn name(&self) -> &'static str {
"sum"
}
fn run(&mut self, input: Vec<i64>, _session: &mut Session<Config>) -> Result<i64, DriverError> {
Ok(input.iter().sum())
}
}
fn run_line(line: &'static str, max_value: i64) {
let mut driver = Pipeline::new(Lex).then(Check).then(Sum);
let mut session = Session::new(Config { max_value });
println!("input: {line:?} (cap {max_value})");
match driver.run(line, &mut session) {
Ok(total) => println!(" => {total}"),
Err(error) => println!(" => failed: {error}"),
}
for diagnostic in session.take_diagnostics() {
println!(" {diagnostic}");
}
println!();
}
fn main() {
run_line("10 20 oops 30", 100);
run_line("5 250 400", 100);
run_line("nothing numeric here", 100);
}