1pub mod max;
20pub mod min;
21
22pub mod graph;
23pub use self::graph::read as read_graph;
24
25use std::error;
26use std::fmt;
27use std::io::{self, BufRead, BufReader, Read};
28use std::str::{FromStr, SplitWhitespace};
29
30#[derive(Debug)]
32pub enum Error {
33 Io(io::Error),
34 Format { line: usize, msg: String },
35 Data { line: usize, msg: String },
36}
37
38impl From<io::Error> for Error {
39 fn from(err: io::Error) -> Self {
40 Error::Io(err)
41 }
42}
43
44impl fmt::Display for Error {
45 fn fmt(&self, fmt: &mut fmt::Formatter) -> std::result::Result<(), fmt::Error> {
46 use self::Error::*;
47 match self {
48 Io(err) => err.fmt(fmt),
49 Format { line, msg } => write!(fmt, "Format error on line {}: {}", line, msg),
50 Data { line, msg } => write!(fmt, "Data error on line {}: {}", line, msg),
51 }
52 }
53}
54
55impl error::Error for Error {
56 fn cause(&self) -> Option<&dyn error::Error> {
57 match self {
58 Error::Io(err) => Some(err),
59 _ => None,
60 }
61 }
62}
63
64pub type Result<T> = std::result::Result<T, Error>;
65
66pub struct DimacsReader<R: Read> {
67 io: BufReader<R>,
68
69 line: String,
70 line_number: usize,
71}
72
73impl<R: Read> DimacsReader<R> {
74 pub fn new(reader: R) -> Self {
75 DimacsReader {
76 io: BufReader::new(reader),
77 line: String::new(),
78 line_number: 0,
79 }
80 }
81
82 fn read_line(&mut self) -> Result<Option<Tokens>> {
83 let line = &mut self.line;
84 loop {
85 line.clear();
86 if self.io.read_line(line)? == 0 {
87 return Ok(None);
88 }
89
90 self.line_number += 1;
91 for (i, c) in line.char_indices() {
92 if char::is_whitespace(c) {
93 continue;
94 }
95 if c == 'c' || c == '\n' {
96 break;
97 }
98 return Ok(Some(Tokens {
99 it: line[i..].split_whitespace(),
100 line: self.line_number,
101 }));
102 }
103 }
104 }
105
106 fn expect_line(&mut self, descriptor: char) -> Result<Tokens> {
111 let line_number = self.line_number;
112 let mut toks = self.read_line()?.ok_or_else(|| Error::Format {
113 line: line_number,
114 msg: format!("unexpected end of file, expected '{}' line", descriptor),
115 })?;
116 match toks.next() {
117 Some(d) if d.len() == 1 && d.starts_with(descriptor) => Ok(toks),
118 Some(d) => Err(Error::Format {
119 line: line_number,
120 msg: format!("unexpected line, expected '{}', got '{}'", descriptor, d),
121 }),
122 None => Err(Error::Format {
123 line: line_number,
124 msg: "unexpected empty line".to_string(),
125 }),
126 }
127 }
128
129 fn read_one_line_of(&mut self, descriptors: &[&str]) -> Result<Option<(&str, Tokens)>> {
134 let line_number = self.line_number;
135 if let Some(mut toks) = self.read_line()? {
136 match toks.next() {
137 Some(d) if descriptors.iter().any(|&desc| d.starts_with(desc)) => Ok(Some((d, toks))),
138 Some(d) => Err(Error::Format {
139 line: line_number,
140 msg: format!(
141 "unexpected line, expected on of '{}', got '{}'",
142 descriptors.join("', '"),
143 d
144 ),
145 }),
146 None => Err(Error::Format {
147 line: line_number,
148 msg: "unexpected empty line".to_string(),
149 }),
150 }
151 } else {
152 Ok(None)
153 }
154 }
155}
156
157pub struct Tokens<'a> {
159 it: SplitWhitespace<'a>,
160 pub line: usize,
161}
162
163impl<'a> Iterator for Tokens<'a> {
164 type Item = &'a str;
165
166 fn next(&mut self) -> Option<&'a str> {
167 self.it.next()
168 }
169}
170
171impl<'a> Tokens<'a> {
172 pub fn expect(&mut self, tok: &str) -> Result<()> {
174 let nxt = self.str()?;
175 if nxt == tok {
176 Ok(())
177 } else {
178 Err(Error::Format {
179 line: self.line,
180 msg: format!("expected '{}', got '{}", tok, nxt),
181 })
182 }
183 }
184
185 pub fn expect_one_of(&mut self, toks: &[&str]) -> Result<()> {
187 let nxt = self.str()?;
188 if toks.iter().any(|&tok| tok == nxt) {
189 Ok(())
190 } else {
191 Err(Error::Format {
192 line: self.line,
193 msg: format!("expected one of '{}', got '{}", toks.join("', '"), nxt),
194 })
195 }
196 }
197
198 pub fn str(&mut self) -> Result<&'a str> {
200 self.it.next().ok_or_else(|| Error::Format {
201 line: self.line,
202 msg: "expected token".to_string(),
203 })
204 }
205
206 pub fn number<T>(&mut self) -> Result<T>
208 where
209 T: FromStr,
210 T::Err: fmt::Display,
211 {
212 self.it
213 .next()
214 .ok_or_else(|| Error::Format {
215 line: self.line,
216 msg: "expected number".to_string(),
217 })?
218 .parse()
219 .map_err(|e| Error::Format {
220 line: self.line,
221 msg: format!("{}", e),
222 })
223 }
224
225 pub fn end(&mut self) -> Result<()> {
227 if let Some(s) = self.it.next() {
228 Err(Error::Format {
229 line: self.line,
230 msg: format!("unexpected token at end of line: {}", s),
231 })
232 } else {
233 Ok(())
234 }
235 }
236}
237
238fn read_dimacs<R, F>(fin: &mut R, f: &mut F) -> Result<()>
245where
246 R: io::BufRead,
247 F: FnMut(char, &mut Tokens) -> Result<()>,
248{
249 let mut nline = 0;
250 let mut line = String::new();
251
252 while {
253 line.clear();
254 fin.read_line(&mut line)
255 }? > 0
256 {
257 nline += 1;
258 let mut it = line.chars();
259 while let Some(c) = it.next() {
260 match c {
261 _ if char::is_whitespace(c) => continue,
262 'c' | '\n' => break,
263 _ => {
264 let mut tok = Tokens {
265 it: it.as_str().split_whitespace(),
266 line: nline,
267 };
268 f(c, &mut tok)?;
269 break;
270 }
271 }
272 }
273 }
274
275 Ok(())
276}