1extern crate alloc;
2
3use alloc::collections::VecDeque;
4use core::str::Chars;
5
6use crate::iter::Peek;
7
8pub struct Source<'a> {
10 iter: Chars<'a>,
11 src: &'a str,
12 pos: usize,
13 peeked: VecDeque<char>,
14}
15
16impl<'a> Source<'a> {
17 pub fn new(src: &'a str) -> Self {
19 Self {
20 iter: src.chars(),
21 src,
22 pos: 0,
23 peeked: VecDeque::new(),
24 }
25 }
26
27 #[inline]
29 pub fn pos(&self) -> usize {
30 self.pos
31 }
32
33 #[inline]
35 pub fn src(&self) -> &'a str {
36 self.src
37 }
38
39 #[inline]
41 pub fn peek(&mut self) -> Option<char> {
42 self.peek_nth(0)
43 }
44
45 pub fn peek_nth(&mut self, nth: usize) -> Option<char> {
50 self.peeked.extend(
51 self.iter
52 .by_ref()
53 .take((nth + 1).saturating_sub(self.peeked.len())),
54 );
55 self.peeked.get(nth).copied()
56 }
57}
58
59impl<'a> Iterator for Source<'a> {
60 type Item = char;
61
62 fn next(&mut self) -> Option<Self::Item> {
63 self.peeked
64 .pop_front()
65 .or_else(|| self.iter.next())
66 .map(|c| {
67 self.pos += c.len_utf8();
68 c
69 })
70 }
71}
72
73impl<'a> Peek for Source<'a> {
74 type Item = char;
75
76 #[inline]
77 fn peek(&mut self) -> Option<Self::Item> {
78 self.peek()
79 }
80}