Lines
86.96 %
Functions
92.31 %
Branches
100 %
use core::iter::Peekable;
use core::ops::Range;
use core::str::CharIndices;
#[derive(Debug, Clone)]
pub struct CharIterator<'a> {
pub source: &'a str,
chars: Peekable<CharIndices<'a>>,
last: Option<(usize, char)>,
marked_start: usize,
}
impl<'a> CharIterator<'a> {
#[inline]
pub fn new(source: &'a str) -> Self {
Self {
source,
chars: source.char_indices().peekable(),
last: None,
marked_start: 0,
pub const fn last_offset(&self) -> usize {
if let Some((offset, _)) = self.last {
offset
} else {
0
pub const fn current_offset(&self) -> usize {
if let Some((offset, ch)) = self.last {
offset + ch.len_utf8()
pub fn mark_start(&mut self) {
self.marked_start = self.current_offset();
pub const fn marked_range(&self) -> Range<usize> {
self.marked_start..self.current_offset()
pub fn marked_str(&self) -> &'a str {
&self.source[self.marked_range()]
pub const fn last_char_range(&self) -> Range<usize> {
offset..(offset + ch.len_utf8())
0..0
pub fn next_char_and_index(&mut self) -> Option<(usize, char)> {
let current = self.chars.next()?;
self.last = Some(current);
Some(current)
pub fn peek(&mut self) -> Option<char> {
self.peek_full().map(|(_, ch)| ch)
pub fn peek_full(&mut self) -> Option<(usize, char)> {
self.chars.peek().copied()
impl<'a> Iterator for CharIterator<'a> {
type Item = char;
fn next(&mut self) -> Option<Self::Item> {
self.next_char_and_index().map(|(_, ch)| ch)