#![cfg_attr(docsrs, feature(doc_cfg))]
use std::{
cmp,
fmt::Debug,
hash::Hash,
iter::{Copied, Enumerate},
marker::PhantomData,
slice::Iter,
};
use memchr::memmem;
pub type Span = sourcespan::Span<usize>;
pub trait Item: PartialEq + Eq + PartialOrd + Ord + Hash + Copy + Debug {
fn len(self) -> usize;
}
impl Item for char {
#[inline(always)]
fn len(self) -> usize {
self.len_utf8()
}
}
impl Item for u8 {
#[inline]
fn len(self) -> usize {
1
}
}
pub trait Input: Clone {
type Error;
type Item: Item;
type Iter: Iterator<Item = Self::Item>;
type IterIndices: Iterator<Item = (usize, Self::Item)>;
fn len(&self) -> usize;
fn split_at(self, mid: usize) -> (Self, Self)
where
Self: Sized;
#[inline]
fn split_to(&mut self, at: usize) -> Self {
let (lhs, rhs) = self.clone().split_at(at);
*self = rhs;
lhs
}
#[inline]
fn split_off(&mut self, at: usize) -> Self {
let (lhs, rhs) = self.clone().split_at(at);
*self = lhs;
rhs
}
fn iter(&self) -> Self::Iter;
fn iter_indices(&self) -> Self::IterIndices;
fn start(&self) -> usize;
fn end(&self) -> usize;
#[inline]
fn is_empty(&self) -> bool {
self.len() == 0
}
#[inline]
fn to_span(&self) -> Span {
Span::from(self.start()..self.end())
}
#[inline]
fn to_span_from(&self, offset: usize) -> Span {
Span::from(self.start()..cmp::min(self.start() + offset, self.end()))
}
}
pub trait AsBytes {
fn as_bytes(&self) -> &[u8];
}
impl AsBytes for &str {
#[inline]
fn as_bytes(&self) -> &[u8] {
str::as_bytes(self)
}
}
impl AsBytes for &[u8] {
#[inline]
fn as_bytes(&self) -> &[u8] {
self
}
}
pub trait AsStr {
fn as_str(&self) -> &str;
}
impl AsStr for &str {
#[inline(always)]
fn as_str(&self) -> &str {
self
}
}
impl AsStr for String {
#[inline]
fn as_str(&self) -> &str {
String::as_str(&self)
}
}
pub trait StartWith<Needle> {
fn start_with(&self, prefix: Needle) -> bool;
}
impl<I, Needle> StartWith<Needle> for I
where
I: AsBytes,
Needle: AsBytes,
{
#[inline]
fn start_with(&self, prefix: Needle) -> bool {
self.as_bytes().starts_with(prefix.as_bytes())
}
}
pub trait Find<Needle> {
fn find(&self, prefix: Needle) -> Option<usize>;
}
impl<I, Needle> Find<Needle> for I
where
I: AsBytes,
Needle: AsBytes,
{
#[inline]
fn find(&self, needle: Needle) -> Option<usize> {
memmem::find(self.as_bytes(), needle.as_bytes())
}
}
pub struct Source<S, E> {
offset: usize,
sgement: S,
_marker: PhantomData<E>,
}
impl<S, E> PartialEq for Source<S, E>
where
S: PartialEq,
{
fn eq(&self, other: &Self) -> bool {
self.offset == other.offset
&& self.sgement == other.sgement
&& self._marker == other._marker
}
}
impl<S, E> Eq for Source<S, E> where S: Eq {}
impl<S, E> Debug for Source<S, E>
where
S: Debug,
{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Source")
.field("offset", &self.offset)
.field("sgement", &self.sgement)
.field("_marker", &self._marker)
.finish()
}
}
impl<S, E> Clone for Source<S, E>
where
S: Clone,
{
fn clone(&self) -> Self {
Self {
offset: self.offset.clone(),
sgement: self.sgement.clone(),
_marker: PhantomData,
}
}
}
impl<S, E> From<S> for Source<S, E> {
#[inline]
fn from(value: S) -> Self {
Self {
offset: 0,
sgement: value,
_marker: PhantomData,
}
}
}
impl<S, E> From<(usize, S)> for Source<S, E> {
#[inline]
fn from((offset, value): (usize, S)) -> Self {
Self {
offset,
sgement: value,
_marker: PhantomData,
}
}
}
impl<S, E> AsBytes for Source<S, E>
where
S: AsBytes,
{
#[inline]
fn as_bytes(&self) -> &[u8] {
self.sgement.as_bytes()
}
}
impl<S, E> AsStr for Source<S, E>
where
S: AsStr,
{
#[inline]
fn as_str(&self) -> &str {
self.sgement.as_str()
}
}
#[cfg(feature = "chars")]
impl<'a, E> Input for Source<&'a str, E> {
type Error = E;
type Item = char;
type Iter = std::str::Chars<'a>;
type IterIndices = std::str::CharIndices<'a>;
#[inline]
fn len(&self) -> usize {
self.sgement.len()
}
#[inline]
fn split_at(self, mid: usize) -> (Self, Self)
where
Self: Sized,
{
let (lhs, rhs) = self.sgement.split_at(mid);
((self.offset, lhs).into(), (self.offset + mid, rhs).into())
}
#[inline]
fn iter(&self) -> Self::Iter {
self.sgement.chars()
}
#[inline]
fn iter_indices(&self) -> Self::IterIndices {
self.sgement.char_indices()
}
#[inline]
fn start(&self) -> usize {
self.offset
}
#[inline]
fn end(&self) -> usize {
self.offset + self.sgement.len()
}
}
#[cfg(feature = "bytes")]
impl<'a, E> Input for Source<&'a [u8], E> {
type Error = E;
type Item = u8;
type Iter = Copied<Iter<'a, u8>>;
type IterIndices = Enumerate<Self::Iter>;
#[inline]
fn len(&self) -> usize {
self.sgement.len()
}
#[inline]
fn split_at(self, mid: usize) -> (Self, Self)
where
Self: Sized,
{
let (lhs, rhs) = self.sgement.split_at(mid);
((self.offset, lhs).into(), (self.offset + mid, rhs).into())
}
#[inline]
fn iter(&self) -> Self::Iter {
self.sgement.iter().copied()
}
#[inline]
fn iter_indices(&self) -> Self::IterIndices {
self.iter().enumerate()
}
#[inline]
fn start(&self) -> usize {
self.offset
}
#[inline]
fn end(&self) -> usize {
self.offset + self.sgement.len()
}
}
#[cfg(feature = "bytes")]
pub trait BytesInput<E>:
Input<Item = u8, Error = E>
+ AsBytes
+ StartWith<&'static str>
+ Find<&'static str>
+ Clone
+ Debug
+ Eq
{
}
#[cfg(feature = "bytes")]
pub type Bytes<'a, E> = Source<&'a [u8], E>;
#[cfg(feature = "bytes")]
impl<'a, E> BytesInput<E> for Bytes<'a, E> {}
#[cfg(feature = "chars")]
pub trait CharsInput<E>:
Input<Item = char, Error = E>
+ AsBytes
+ AsStr
+ StartWith<&'static str>
+ Find<&'static str>
+ Clone
+ Debug
+ Eq
{
}
#[cfg(feature = "chars")]
pub type Chars<'a, E> = Source<&'a str, E>;
#[cfg(feature = "chars")]
impl<'a, E> CharsInput<E> for Chars<'a, E> {}