use crate::position::Position;
#[derive(Debug, PartialEq)]
pub struct CharWithPosition {
pub character: char,
pub position: Position,
}
impl CharWithPosition {
pub fn new(character: char, position: Position) -> Self {
Self {
character,
position,
}
}
}
pub struct CharsWithPositionIterator<T>
where
T: Iterator<Item = char>,
{
upstream: T,
current_position: Position,
}
impl<T> CharsWithPositionIterator<T>
where
T: Iterator<Item = char>,
{
pub fn new(upstream: T) -> Self {
Self {
upstream,
current_position: Position::new(0, 0, 0),
}
}
}
impl<T> Iterator for CharsWithPositionIterator<T>
where
T: Iterator<Item = char>,
{
type Item = CharWithPosition;
fn next(&mut self) -> Option<Self::Item> {
match self.upstream.next() {
Some(c) => {
let last_position = self.current_position;
self.current_position.index += 1;
if c == '\n' {
self.current_position.line += 1;
self.current_position.column = 0;
} else {
self.current_position.column += 1;
}
Some(CharWithPosition::new(c, last_position))
}
None => None,
}
}
}
#[cfg(test)]
mod tests {
use crate::{
char_with_position::{CharWithPosition, CharsWithPositionIterator},
position::Position,
};
#[test]
fn test_chars_with_position_iter() {
{
let chars = "a\nmn\nxyz".chars();
let mut char_position_iter = CharsWithPositionIterator::new(chars);
assert_eq!(
char_position_iter.next(),
Some(CharWithPosition::new('a', Position::new(0, 0, 0)))
);
assert_eq!(
char_position_iter.next(),
Some(CharWithPosition::new('\n', Position::new(1, 0, 1)))
);
assert_eq!(
char_position_iter.next(),
Some(CharWithPosition::new('m', Position::new(2, 1, 0)))
);
assert_eq!(
char_position_iter.next(),
Some(CharWithPosition::new('n', Position::new(3, 1, 1)))
);
assert_eq!(
char_position_iter.next(),
Some(CharWithPosition::new('\n', Position::new(4, 1, 2)))
);
assert_eq!(
char_position_iter.next(),
Some(CharWithPosition::new('x', Position::new(5, 2, 0)))
);
assert_eq!(
char_position_iter.next(),
Some(CharWithPosition::new('y', Position::new(6, 2, 1)))
);
assert_eq!(
char_position_iter.next(),
Some(CharWithPosition::new('z', Position::new(7, 2, 2)))
);
assert!(char_position_iter.next().is_none());
}
{
let chars = "\n\r\n\n".chars();
let mut char_position_iter = CharsWithPositionIterator::new(chars);
assert_eq!(
char_position_iter.next(),
Some(CharWithPosition::new('\n', Position::new(0, 0, 0)))
);
assert_eq!(
char_position_iter.next(),
Some(CharWithPosition::new('\r', Position::new(1, 1, 0)))
);
assert_eq!(
char_position_iter.next(),
Some(CharWithPosition::new('\n', Position::new(2, 1, 1)))
);
assert_eq!(
char_position_iter.next(),
Some(CharWithPosition::new('\n', Position::new(3, 2, 0)))
);
assert!(char_position_iter.next().is_none());
}
}
}