use nom::{Input, Needed};
use std::iter::{Enumerate, Skip, Take};
use syn::{Path, PathSegment, punctuated::Iter as PunctuatedIter};
type SegmentIter<'a> = Take<Skip<PunctuatedIter<'a, PathSegment>>>;
#[derive(Clone, Copy)]
pub(crate) struct PathSegmentInput<'a> {
path: &'a Path,
start: usize,
end: usize,
}
impl<'a> PathSegmentInput<'a> {
pub(crate) fn new(path: &'a Path) -> Self {
Self {
path,
start: 0,
end: path.segments.len(),
}
}
}
impl<'a> Input for PathSegmentInput<'a> {
type Item = &'a PathSegment;
type Iter = SegmentIter<'a>;
type IterIndices = Enumerate<Self::Iter>;
fn input_len(&self) -> usize {
self.end - self.start
}
fn take(&self, index: usize) -> Self {
assert!(index <= self.input_len(), "segment index out of bounds");
Self {
path: self.path,
start: self.start,
end: self.start + index,
}
}
fn take_from(&self, index: usize) -> Self {
assert!(index <= self.input_len(), "segment index out of bounds");
Self {
path: self.path,
start: self.start + index,
end: self.end,
}
}
fn take_split(&self, index: usize) -> (Self, Self) {
(self.take_from(index), self.take(index))
}
fn position<P>(&self, predicate: P) -> Option<usize>
where
P: Fn(Self::Item) -> bool,
{
self.iter_elements().position(predicate)
}
fn iter_elements(&self) -> Self::Iter {
self.path
.segments
.iter()
.skip(self.start)
.take(self.input_len())
}
fn iter_indices(&self) -> Self::IterIndices {
self.iter_elements().enumerate()
}
fn slice_index(&self, count: usize) -> Result<usize, Needed> {
if self.input_len() >= count {
Ok(count)
} else {
Err(Needed::new(count - self.input_len()))
}
}
}