Skip to content

Commit 0aeaccc

Browse files
committed
Optimize state
1 parent 01b7d63 commit 0aeaccc

File tree

1 file changed

+76
-38
lines changed

1 file changed

+76
-38
lines changed

src/exercise.rs

Lines changed: 76 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
use regex::Regex;
22
use serde::Deserialize;
3-
use std::env;
43
use std::fmt::{self, Display, Formatter};
54
use std::fs::{self, remove_file, File};
6-
use std::io::Read;
5+
use std::io::{self, BufRead, BufReader};
76
use std::path::PathBuf;
87
use std::process::{self, Command};
8+
use std::{array, env, mem};
99

1010
const RUSTC_COLOR_ARGS: &[&str] = &["--color", "always"];
1111
const RUSTC_EDITION_ARGS: &[&str] = &["--edition", "2021"];
1212
const RUSTC_NO_DEBUG_ARGS: &[&str] = &["-C", "strip=debuginfo"];
13-
const I_AM_DONE_REGEX: &str = r"(?m)^\s*///?\s*I\s+AM\s+NOT\s+DONE";
13+
const I_AM_DONE_REGEX: &str = r"^\s*///?\s*I\s+AM\s+NOT\s+DONE";
1414
const CONTEXT: usize = 2;
1515
const CLIPPY_CARGO_TOML_PATH: &str = "./exercises/22_clippy/Cargo.toml";
1616

@@ -205,51 +205,89 @@ path = "{}.rs""#,
205205
}
206206

207207
pub fn state(&self) -> State {
208-
let mut source_file = File::open(&self.path).unwrap_or_else(|e| {
208+
let source_file = File::open(&self.path).unwrap_or_else(|e| {
209209
panic!(
210210
"We were unable to open the exercise file {}! {e}",
211211
self.path.display()
212212
)
213213
});
214-
215-
let source = {
216-
let mut s = String::new();
217-
source_file.read_to_string(&mut s).unwrap_or_else(|e| {
218-
panic!(
219-
"We were unable to read the exercise file {}! {e}",
220-
self.path.display()
221-
)
222-
});
223-
s
214+
let mut source_reader = BufReader::new(source_file);
215+
let mut read_line = |buf: &mut String| -> io::Result<_> {
216+
let n = source_reader.read_line(buf)?;
217+
if buf.ends_with('\n') {
218+
buf.pop();
219+
if buf.ends_with('\r') {
220+
buf.pop();
221+
}
222+
}
223+
Ok(n)
224224
};
225225

226226
let re = Regex::new(I_AM_DONE_REGEX).unwrap();
227-
228-
if !re.is_match(&source) {
229-
return State::Done;
227+
let mut matched_line_ind: usize = 0;
228+
let mut prev_lines: [_; CONTEXT] = array::from_fn(|_| String::with_capacity(256));
229+
let mut line = String::with_capacity(256);
230+
231+
loop {
232+
match read_line(&mut line) {
233+
Ok(0) => break,
234+
Ok(_) => {
235+
if re.is_match(&line) {
236+
let mut context = Vec::with_capacity(2 * CONTEXT + 1);
237+
for (ind, prev_line) in prev_lines
238+
.into_iter()
239+
.rev()
240+
.take(matched_line_ind)
241+
.enumerate()
242+
{
243+
context.push(ContextLine {
244+
line: prev_line,
245+
// TODO
246+
number: matched_line_ind - CONTEXT + ind + 1,
247+
important: false,
248+
});
249+
}
250+
251+
context.push(ContextLine {
252+
line,
253+
number: matched_line_ind + 1,
254+
important: true,
255+
});
256+
257+
for ind in 0..CONTEXT {
258+
let mut next_line = String::with_capacity(256);
259+
let Ok(n) = read_line(&mut next_line) else {
260+
break;
261+
};
262+
263+
if n == 0 {
264+
break;
265+
}
266+
267+
context.push(ContextLine {
268+
line: next_line,
269+
number: matched_line_ind + ind + 2,
270+
important: false,
271+
});
272+
}
273+
274+
return State::Pending(context);
275+
}
276+
277+
matched_line_ind += 1;
278+
for prev_line in &mut prev_lines {
279+
mem::swap(&mut line, prev_line);
280+
}
281+
line.clear();
282+
}
283+
Err(e) => panic!(
284+
"We were unable to read the exercise file {}! {e}",
285+
self.path.display()
286+
),
287+
}
230288
}
231289

232-
let matched_line_index = source
233-
.lines()
234-
.enumerate()
235-
.find_map(|(i, line)| if re.is_match(line) { Some(i) } else { None })
236-
.expect("This should not happen at all");
237-
238-
let min_line = ((matched_line_index as i32) - (CONTEXT as i32)).max(0) as usize;
239-
let max_line = matched_line_index + CONTEXT;
240-
241-
let context = source
242-
.lines()
243-
.enumerate()
244-
.filter(|&(i, _)| i >= min_line && i <= max_line)
245-
.map(|(i, line)| ContextLine {
246-
line: line.to_string(),
247-
number: i + 1,
248-
important: i == matched_line_index,
249-
})
250-
.collect();
251-
252-
State::Pending(context)
290+
State::Done
253291
}
254292

255293
// Check that the exercise looks to be solved using self.state()

0 commit comments

Comments
 (0)