use std::str::FromStr;
use crate::errors::ParseError;
use crate::tl::{Category, Definition};
pub(crate) struct TlIterator<'a> {
lines: std::str::Lines<'a>,
category: Category,
pending: String,
ready: std::collections::VecDeque<Result<Definition, ParseError>>,
eof: bool,
}
impl<'a> TlIterator<'a> {
pub(crate) fn new(src: &'a str) -> Self {
Self {
lines: src.lines(),
category: Category::Types,
pending: String::new(),
ready: std::collections::VecDeque::new(),
eof: false,
}
}
fn handle_separator(&mut self, line: &str) -> bool {
let trimmed = line.trim();
match trimmed {
"---functions---" => {
self.category = Category::Functions;
true
}
"---types---" => {
self.category = Category::Types;
true
}
_ => false,
}
}
fn strip_comment(line: &str) -> &str {
let code = if let Some(idx) = line.find("//") {
&line[..idx]
} else {
line
};
code.trim()
}
fn flush_pending(&mut self) {
let raw = std::mem::take(&mut self.pending);
for part in raw.split(';') {
let part = part.trim();
if part.is_empty() {
continue;
}
let category = self.category;
let result = Definition::from_str(part).map(|mut d| {
d.category = category;
d
});
self.ready.push_back(result);
}
}
}
impl<'a> Iterator for TlIterator<'a> {
type Item = Result<Definition, ParseError>;
fn next(&mut self) -> Option<Self::Item> {
loop {
if let Some(item) = self.ready.pop_front() {
return Some(item);
}
if self.eof {
if !self.pending.trim().is_empty() {
self.flush_pending();
continue; }
return None;
}
let line = match self.lines.next() {
Some(l) => l,
None => {
self.eof = true;
continue; }
};
let trimmed = Self::strip_comment(line);
if trimmed.is_empty() {
continue;
}
if self.handle_separator(trimmed) {
continue;
}
if !self.pending.is_empty() {
self.pending.push(' ');
}
self.pending.push_str(trimmed);
if self.pending.contains(';') {
let raw = std::mem::take(&mut self.pending);
let mut parts = raw.split(';').peekable();
while let Some(part) = parts.next() {
let part = part.trim();
if parts.peek().is_none() {
if !part.is_empty() {
self.pending = part.to_string();
}
} else if !part.is_empty() {
let category = self.category;
let result = Definition::from_str(part).map(|mut d| {
d.category = category;
d
});
self.ready.push_back(result);
}
}
}
}
}
}