#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub struct Match {
start: usize,
end: usize,
}
impl Match {
#[inline]
pub fn new(start: usize, end: usize) -> Match {
debug_assert!(start <= end);
Match { start, end }
}
#[inline]
pub fn zero(offset: usize) -> Match {
Match {
start: offset,
end: offset,
}
}
#[inline]
pub fn start(&self) -> usize {
self.start
}
#[inline]
pub fn end(&self) -> usize {
self.end
}
#[inline]
pub fn with_end(&self, end: usize) -> Match {
debug_assert!(self.start <= end);
Match { end, ..*self }
}
#[inline]
pub fn offset(&self, amount: usize) -> Match {
Match {
start: self.start + amount,
end: self.end + amount,
}
}
#[inline]
pub fn len(&self) -> usize {
self.end - self.start
}
#[inline]
pub fn is_empty(&self) -> bool {
self.len() == 0
}
}
impl std::ops::Index<Match> for [u8] {
type Output = [u8];
#[inline]
fn index(&self, index: Match) -> &[u8] {
&self[index.start..index.end]
}
}
impl std::ops::IndexMut<Match> for [u8] {
#[inline]
fn index_mut(&mut self, index: Match) -> &mut [u8] {
&mut self[index.start..index.end]
}
}
impl std::ops::Index<Match> for str {
type Output = str;
#[inline]
fn index(&self, index: Match) -> &str {
&self[index.start..index.end]
}
}
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub struct LineTerminator(u8);
impl LineTerminator {
#[inline]
pub fn byte(byte: u8) -> LineTerminator {
LineTerminator(byte)
}
#[inline]
pub fn as_byte(&self) -> u8 {
self.0
}
#[inline]
pub fn as_bytes(&self) -> &[u8] {
std::slice::from_ref(&self.0)
}
}
impl Default for LineTerminator {
#[inline]
fn default() -> LineTerminator {
LineTerminator(b'\n')
}
}
#[derive(Debug, Eq, PartialEq)]
pub struct NoError(());
impl std::error::Error for NoError {}
impl std::fmt::Display for NoError {
fn fmt(&self, _: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
unreachable!("NoError should never be instantiated")
}
}
pub trait Matcher {
type Error: std::fmt::Display;
fn find_at(&self, haystack: &[u8], at: usize) -> Result<Option<Match>, Self::Error>;
#[inline]
fn find(&self, haystack: &[u8]) -> Result<Option<Match>, Self::Error> {
self.find_at(haystack, 0)
}
#[inline]
fn line_terminator(&self) -> Option<LineTerminator> {
None
}
}
impl<M: Matcher> Matcher for &M {
type Error = M::Error;
#[inline]
fn find_at(&self, haystack: &[u8], at: usize) -> Result<Option<Match>, Self::Error> {
(*self).find_at(haystack, at)
}
#[inline]
fn find(&self, haystack: &[u8]) -> Result<Option<Match>, Self::Error> {
(*self).find(haystack)
}
#[inline]
fn line_terminator(&self) -> Option<LineTerminator> {
(*self).line_terminator()
}
}