1 was the correct depth to traverse
This commit is contained in:
parent
2953c27e84
commit
f1074e4340
|
@ -1,11 +1,11 @@
|
||||||
use std::fs::File;
|
|
||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
|
use std::fs::File;
|
||||||
|
use std::io;
|
||||||
|
use std::io::prelude::*;
|
||||||
use std::slice;
|
use std::slice;
|
||||||
use std::str;
|
use std::str;
|
||||||
use std::io::prelude::*;
|
|
||||||
use std::io;
|
|
||||||
|
|
||||||
use backtrace::{ Backtrace, BacktraceFrame, BacktraceSymbol };
|
use backtrace::{Backtrace, BacktraceFrame, BacktraceSymbol};
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub(super) struct Line(pub(super) usize);
|
pub(super) struct Line(pub(super) usize);
|
||||||
|
@ -14,34 +14,33 @@ pub(super) struct Word(pub(super) usize);
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub(super) struct Cursor(pub(super) Line, pub(super) Word);
|
pub(super) struct Cursor(pub(super) Line, pub(super) Word);
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub(super) enum FileStatus{Eof}
|
pub(super) enum FileStatus {
|
||||||
|
Eof,
|
||||||
pub struct WordReader {
|
|
||||||
reader : io::BufReader<File>,
|
|
||||||
eof : bool,
|
|
||||||
buffers : Vec<String>,
|
|
||||||
curr_line : usize,
|
|
||||||
str_slices : VecDeque<(*const u8, usize, Cursor)>,
|
|
||||||
curr_slice : Option<(*const u8, usize, Cursor)>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct WordReader {
|
||||||
|
reader: io::BufReader<File>,
|
||||||
|
eof: bool,
|
||||||
|
buffers: Vec<String>,
|
||||||
|
curr_line: usize,
|
||||||
|
str_slices: VecDeque<(*const u8, usize, Cursor)>,
|
||||||
|
curr_slice: Option<(*const u8, usize, Cursor)>,
|
||||||
|
}
|
||||||
|
|
||||||
impl WordReader {
|
impl WordReader {
|
||||||
pub(super) fn new(file : File) -> WordReader {
|
pub(super) fn new(file: File) -> WordReader {
|
||||||
let reader = io::BufReader::new(file);
|
let reader = io::BufReader::new(file);
|
||||||
WordReader {
|
WordReader {
|
||||||
reader : reader,
|
reader: reader,
|
||||||
eof : false,
|
eof: false,
|
||||||
buffers : vec![],
|
buffers: vec![],
|
||||||
curr_line : 0,
|
curr_line: 0,
|
||||||
str_slices : VecDeque::new(),
|
str_slices: VecDeque::new(),
|
||||||
curr_slice : None
|
curr_slice: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub(super) fn next_word(&mut self) -> Result<(&str, Cursor), FileStatus> {
|
pub(super) fn next_word(&mut self) -> Result<(&str, Cursor), FileStatus> {
|
||||||
|
|
||||||
// although reaching the eof is not technically an error, in most cases,
|
// although reaching the eof is not technically an error, in most cases,
|
||||||
// we treat it like one in the rest of the codebase.
|
// we treat it like one in the rest of the codebase.
|
||||||
|
|
||||||
|
@ -50,7 +49,9 @@ impl WordReader {
|
||||||
if self.str_slices.is_empty() {
|
if self.str_slices.is_empty() {
|
||||||
self.buffers.clear();
|
self.buffers.clear();
|
||||||
|
|
||||||
if self.eof {return Err(FileStatus::Eof)}
|
if self.eof {
|
||||||
|
return Err(FileStatus::Eof);
|
||||||
|
}
|
||||||
|
|
||||||
let num_buffers = 10;
|
let num_buffers = 10;
|
||||||
|
|
||||||
|
@ -71,16 +72,16 @@ impl WordReader {
|
||||||
for word in words.enumerate() {
|
for word in words.enumerate() {
|
||||||
let (word_idx, word) = word;
|
let (word_idx, word) = word;
|
||||||
let position = Cursor(Line(self.curr_line), Word(word_idx + 1));
|
let position = Cursor(Line(self.curr_line), Word(word_idx + 1));
|
||||||
self.str_slices.push_back((word.as_ptr(), word.len(), position))
|
self.str_slices
|
||||||
|
.push_back((word.as_ptr(), word.len(), position))
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// if after we've attempted to read in more content from the file,
|
// if after we've attempted to read in more content from the file,
|
||||||
// there are still no words...
|
// there are still no words...
|
||||||
if self.str_slices.is_empty() {
|
if self.str_slices.is_empty() {
|
||||||
return Err(FileStatus::Eof)
|
return Err(FileStatus::Eof);
|
||||||
}
|
}
|
||||||
|
|
||||||
// if we make it here, we return the next word
|
// if we make it here, we return the next word
|
||||||
|
@ -94,15 +95,12 @@ impl WordReader {
|
||||||
|
|
||||||
pub(super) fn curr_word(&mut self) -> Result<(&str, Cursor), FileStatus> {
|
pub(super) fn curr_word(&mut self) -> Result<(&str, Cursor), FileStatus> {
|
||||||
match &self.curr_slice {
|
match &self.curr_slice {
|
||||||
Some(slice) => {
|
Some(slice) => unsafe {
|
||||||
unsafe {
|
let (ptr, len, position) = slice.clone();
|
||||||
let (ptr, len, position) = slice.clone();
|
let slice = slice::from_raw_parts(ptr, len);
|
||||||
let slice = slice::from_raw_parts(ptr, len);
|
Ok((str::from_utf8(slice).unwrap(), position))
|
||||||
Ok((str::from_utf8(slice).unwrap(), position))
|
},
|
||||||
}
|
None => Err(FileStatus::Eof),
|
||||||
|
|
||||||
}
|
|
||||||
None => {Err(FileStatus::Eof)}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -110,31 +108,38 @@ impl WordReader {
|
||||||
fn previous_symbol(level: u32) -> Option<BacktraceSymbol> {
|
fn previous_symbol(level: u32) -> Option<BacktraceSymbol> {
|
||||||
let (trace, curr_file, curr_line) = (Backtrace::new(), file!(), line!());
|
let (trace, curr_file, curr_line) = (Backtrace::new(), file!(), line!());
|
||||||
let frames = trace.frames();
|
let frames = trace.frames();
|
||||||
frames.iter()
|
frames
|
||||||
.flat_map(BacktraceFrame::symbols)
|
.iter()
|
||||||
.skip_while(|s| s.filename().map(|p| !p.ends_with(curr_file)).unwrap_or(true)
|
.flat_map(BacktraceFrame::symbols)
|
||||||
|| s.lineno() != Some(curr_line))
|
.skip_while(|s| {
|
||||||
.nth(1 + level as usize).cloned()
|
s.filename()
|
||||||
|
.map(|p| !p.ends_with(curr_file))
|
||||||
|
.unwrap_or(true)
|
||||||
|
|| s.lineno() != Some(curr_line)
|
||||||
|
})
|
||||||
|
.nth(1 + level as usize)
|
||||||
|
.cloned()
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<FileStatus> for String {
|
impl From<FileStatus> for String {
|
||||||
fn from(f: FileStatus) -> String {
|
fn from(f: FileStatus) -> String {
|
||||||
let sym = previous_symbol(2);
|
let sym = previous_symbol(1);
|
||||||
let filename = sym
|
let filename = sym
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.and_then(BacktraceSymbol::filename)
|
.and_then(BacktraceSymbol::filename)
|
||||||
.map_or(None, |path| {path.to_str()})
|
.map_or(None, |path| path.to_str())
|
||||||
.unwrap_or("(Couldn't determine filename)");
|
.unwrap_or("(Couldn't determine filename)");
|
||||||
let lineno = sym
|
let lineno = sym
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.and_then(BacktraceSymbol::lineno)
|
.and_then(BacktraceSymbol::lineno)
|
||||||
.map_or(None, |path| {Some(path.to_string())})
|
.map_or(None, |path| Some(path.to_string()))
|
||||||
.unwrap_or("(Couldn't determine line number)".to_string());
|
.unwrap_or("(Couldn't determine line number)".to_string());
|
||||||
|
|
||||||
match f {
|
match f {
|
||||||
FileStatus::Eof => format!(
|
FileStatus::Eof => format!(
|
||||||
"Error near {filename}:{lineno} \
|
"Error near {filename}:{lineno} \
|
||||||
No more words left in vcd file."),
|
No more words left in vcd file."
|
||||||
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in a new issue