pub mod maxflow;
pub mod graph;
pub use self::graph::read as read_graph;
use std::error;
use std::fmt;
use std::io;
use std::str::{FromStr, SplitWhitespace};
#[derive(Debug)]
pub enum DimacsError {
Io(io::Error),
Format { line: usize, msg: String },
Data { line: usize, msg: String },
}
impl From<io::Error> for DimacsError {
fn from(err: io::Error) -> Self {
DimacsError::Io(err)
}
}
impl fmt::Display for DimacsError {
fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
use self::DimacsError::*;
match self {
Io(err) => err.fmt(fmt),
Format { line, msg } => write!(fmt, "Format error on line {}: {}", line, msg),
Data { line, msg } => write!(fmt, "Data error on line {}: {}", line, msg),
}
}
}
impl error::Error for DimacsError {
fn cause(&self) -> Option<&error::Error> {
match self {
DimacsError::Io(err) => Some(err),
_ => None,
}
}
}
pub struct Tokens<'a> {
it: SplitWhitespace<'a>,
pub line: usize,
}
impl<'a> Iterator for Tokens<'a> {
type Item = &'a str;
fn next(&mut self) -> Option<&'a str> {
self.it.next()
}
}
impl<'a> Tokens<'a> {
fn str(&mut self) -> Result<&'a str, DimacsError> {
self.it.next().ok_or_else(|| DimacsError::Format {
line: self.line,
msg: "expected token".to_string(),
})
}
fn number<T>(&mut self) -> Result<T, DimacsError>
where
T: FromStr,
T::Err: fmt::Display,
{
try!(self.it.next().ok_or_else(|| DimacsError::Format {
line: self.line,
msg: "expected number".to_string(),
})).parse()
.or_else(|e| {
Err(DimacsError::Format {
line: self.line,
msg: format!("{}", e),
})
})
}
fn end(&mut self) -> Result<(), DimacsError> {
if let Some(s) = self.it.next() {
Err(DimacsError::Format {
line: self.line,
msg: format!("unexpected token at end of line: {}", s),
})
} else {
Ok(())
}
}
}
pub fn read_dimacs<R, F>(fin: &mut R, f: &mut F) -> Result<(), DimacsError>
where
R: io::BufRead,
F: FnMut(char, &mut Tokens) -> Result<(), DimacsError>,
{
let mut nline = 0;
let mut line = String::new();
while {
line.clear();
fin.read_line(&mut line)
}? > 0
{
nline += 1;
let mut it = line.chars();
while let Some(c) = it.next() {
match c {
_ if char::is_whitespace(c) => continue,
'c' | '\n' => break,
_ => {
let mut tok = Tokens {
it: it.as_str().split_whitespace(),
line: nline,
};
try!(f(c, &mut tok));
break;
}
}
}
}
Ok(())
}