mxmlextrema_as3parser/util/
character_reader.rsuse std::str::CharIndices;
#[derive(Clone)]
pub struct CharacterReader<'a> {
length: usize,
start_offset: usize,
char_indices: CharIndices<'a>,
}
impl<'a> CharacterReader<'a> {
pub fn from_offset(value: &'a str, offset: usize) -> Self {
CharacterReader { length: value.len(), start_offset: offset, char_indices: value[offset..].char_indices() }
}
pub fn has_remaining(&self) -> bool {
self.clone().char_indices.next().is_some()
}
pub fn reached_end(&self) -> bool {
self.clone().char_indices.next().is_none()
}
pub fn skip_in_place(&mut self) {
self.next();
}
pub fn skip_count_in_place(&mut self, count: usize) {
for _ in 0..count {
if self.next().is_none() {
break;
}
}
}
pub fn index(&self) -> usize {
self.clone().char_indices.next().map_or(self.length, |(i, _)| self.start_offset + i)
}
pub fn next_or_zero(&mut self) -> char {
self.char_indices.next().map_or('\x00', |(_, cp)| cp)
}
pub fn peek(&self) -> Option<char> {
self.clone().char_indices.next().map(|(_, cp)| cp)
}
pub fn peek_or_zero(&self) -> char {
self.clone().next_or_zero()
}
pub fn peek_at(&self, index: usize) -> Option<char> {
let mut indices = self.clone().char_indices;
for _ in 0..index {
if indices.next().is_none() {
break;
}
}
indices.next().map(|(_, cp)| cp)
}
pub fn peek_at_or_zero(&self, index: usize) -> char {
self.peek_at(index).unwrap_or('\x00')
}
pub fn peek_seq(&self, num_code_points: u64) -> String {
let mut r = String::new();
let mut next_indices = self.char_indices.clone();
for _ in 0..num_code_points {
match next_indices.next() {
None => {
break;
},
Some(cp) => {
r.push(cp.1);
}
}
}
r
}
}
impl<'a> From<&'a str> for CharacterReader<'a> {
fn from(value: &'a str) -> Self {
CharacterReader { length: value.len(), start_offset: 0, char_indices: value.char_indices() }
}
}
impl<'a> From<&'a String> for CharacterReader<'a> {
fn from(value: &'a String) -> Self {
CharacterReader { length: value.len(), start_offset: 0, char_indices: value.char_indices() }
}
}
impl<'a> Iterator for CharacterReader<'a> {
type Item = char;
fn next(&mut self) -> Option<Self::Item> {
self.char_indices.next().map(|(_, cp)| cp)
}
}
#[cfg(test)]
mod test {
use super::CharacterReader;
#[test]
fn test() {
let mut reader = CharacterReader::from("foo");
assert!(reader.has_remaining());
assert_eq!(reader.peek_seq(5), "foo");
assert_eq!(reader.peek_seq(1), "f");
assert_eq!(reader.peek_or_zero(), 'f');
for _ in 0..3 {
reader.next();
}
assert_eq!(reader.peek_or_zero(), '\x00');
assert!(reader.reached_end());
}
}