borrowize 0.3.0

Derive borrowed view structs from owned Rust structs.
Documentation
//! `nom` input adapter for `syn` path segments.

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>>>;

/// `nom` input window over `syn` path segments.
///
/// This lets parser combinators consume segment counts directly from the
/// already-tokenised path without allocating a joined string or a temporary
/// segment slice.
#[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()))
        }
    }
}