1 was the correct depth to traverse

This commit is contained in:
Yehowshua Immanuel 2022-08-04 20:32:01 -04:00
parent 2953c27e84
commit f1074e4340

View file

@ -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;
@ -62,25 +63,25 @@ impl WordReader {
// if we've reached the end of the file on the first attempt to read // if we've reached the end of the file on the first attempt to read
// a line in this for loop, no further attempts are necessary and we // a line in this for loop, no further attempts are necessary and we
if bytes_read == 0 { if bytes_read == 0 {
self.eof = true; self.eof = true;
break; break;
} }
let words = self.buffers[buf_idx].split_ascii_whitespace(); let words = self.buffers[buf_idx].split_ascii_whitespace();
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."
),
} }
} }
} }