use std::{
cell::RefCell,
ops::{Deref, Range, RangeFrom, RangeTo},
rc::Rc,
str::{CharIndices, Chars},
};
use indexmap::IndexSet;
use nom::{Compare, FindSubstring, InputIter, InputLength, InputTake, Slice, UnspecializedInput};
use crate::bundle::Key;
#[derive(Clone, Debug)]
pub(in crate::text::reader) struct ParseState<'a> {
input: &'a str,
keys_in_discovery_order: Rc<RefCell<IndexSet<Key<'a>>>>,
}
impl<'a> ParseState<'a> {
pub fn new(input: &'a str) -> Self {
Self {
input,
keys_in_discovery_order: Default::default(),
}
}
pub fn encounter_key(&self, key: Key<'a>) -> bool {
self.keys_in_discovery_order.borrow_mut().insert(key)
}
pub fn input(&self) -> &'a str {
self.input
}
pub fn take_keys(&self) -> IndexSet<Key<'a>> {
self.keys_in_discovery_order.take()
}
}
impl Compare<&str> for ParseState<'_> {
fn compare(&self, t: &str) -> nom::CompareResult {
self.input.compare(t)
}
fn compare_no_case(&self, t: &str) -> nom::CompareResult {
self.input.compare_no_case(t)
}
}
impl Compare<&[u8]> for ParseState<'_> {
fn compare(&self, t: &[u8]) -> nom::CompareResult {
self.input.compare(t)
}
fn compare_no_case(&self, t: &[u8]) -> nom::CompareResult {
self.input.compare_no_case(t)
}
}
impl Deref for ParseState<'_> {
type Target = str;
fn deref(&self) -> &Self::Target {
self.input
}
}
impl FindSubstring<&str> for ParseState<'_> {
fn find_substring(&self, substr: &str) -> Option<usize> {
self.input.find_substring(substr)
}
}
impl<'a> InputIter for ParseState<'a> {
type Item = char;
type Iter = CharIndices<'a>;
type IterElem = Chars<'a>;
fn iter_indices(&self) -> Self::Iter {
self.input.char_indices()
}
fn iter_elements(&self) -> Self::IterElem {
self.input.chars()
}
fn position<P>(&self, predicate: P) -> Option<usize>
where
P: Fn(Self::Item) -> bool,
{
self.input.position(predicate)
}
fn slice_index(&self, count: usize) -> Result<usize, nom::Needed> {
self.input.slice_index(count)
}
}
impl InputLength for ParseState<'_> {
fn input_len(&self) -> usize {
self.input.input_len()
}
}
impl InputTake for ParseState<'_> {
fn take(&self, count: usize) -> Self {
ParseState {
input: self.input.take(count),
keys_in_discovery_order: self.keys_in_discovery_order.clone(),
}
}
fn take_split(&self, count: usize) -> (Self, Self) {
let (suffix, prefix) = self.input.take_split(count);
(
ParseState {
input: suffix,
keys_in_discovery_order: self.keys_in_discovery_order.clone(),
},
ParseState {
input: prefix,
keys_in_discovery_order: self.keys_in_discovery_order.clone(),
},
)
}
}
impl Slice<Range<usize>> for ParseState<'_> {
fn slice(&self, range: Range<usize>) -> Self {
Self {
input: self.input.slice(range),
keys_in_discovery_order: self.keys_in_discovery_order.clone(),
}
}
}
impl Slice<RangeFrom<usize>> for ParseState<'_> {
fn slice(&self, range: RangeFrom<usize>) -> Self {
Self {
input: self.input.slice(range),
keys_in_discovery_order: self.keys_in_discovery_order.clone(),
}
}
}
impl Slice<RangeTo<usize>> for ParseState<'_> {
fn slice(&self, range: RangeTo<usize>) -> Self {
Self {
input: self.input.slice(range),
keys_in_discovery_order: self.keys_in_discovery_order.clone(),
}
}
}
impl UnspecializedInput for ParseState<'_> {}