use std::fmt;
use thiserror::Error;
#[derive(Error, Debug, Clone, PartialEq, Eq)]
pub enum Error {
#[error("parse error at position {position}: {message}")]
Parse {
position: usize,
message: String,
},
#[error("invalid escape sequence '\\{char}' at position {position}")]
InvalidEscape {
char: char,
position: usize,
},
#[error("unclosed {kind} starting at position {position}")]
Unclosed {
kind: &'static str,
position: usize,
},
#[error("invalid quantifier at position {position}: {message}")]
InvalidQuantifier {
position: usize,
message: String,
},
#[error("invalid character class at position {position}: {message}")]
InvalidCharClass {
position: usize,
message: String,
},
#[error("invalid fuzziness specification at position {position}: {message}")]
InvalidFuzziness {
position: usize,
message: String,
},
#[error("invalid backreference \\{group} at position {position}: {message}")]
InvalidBackreference {
group: usize,
position: usize,
message: String,
},
#[error("empty pattern not allowed")]
EmptyPattern,
#[error("pattern too complex: {message}")]
TooComplex {
message: String,
},
#[error("match timed out after {duration:?}")]
Timeout {
duration: std::time::Duration,
},
}
impl Error {
#[must_use]
pub fn parse(position: usize, message: impl Into<String>) -> Self {
Error::Parse {
position,
message: message.into(),
}
}
#[must_use]
pub fn invalid_escape(char: char, position: usize) -> Self {
Error::InvalidEscape { char, position }
}
#[must_use]
pub fn unclosed(kind: &'static str, position: usize) -> Self {
Error::Unclosed { kind, position }
}
#[must_use]
pub fn invalid_quantifier(position: usize, message: impl Into<String>) -> Self {
Error::InvalidQuantifier {
position,
message: message.into(),
}
}
#[must_use]
pub fn invalid_char_class(position: usize, message: impl Into<String>) -> Self {
Error::InvalidCharClass {
position,
message: message.into(),
}
}
#[must_use]
pub fn invalid_fuzziness(position: usize, message: impl Into<String>) -> Self {
Error::InvalidFuzziness {
position,
message: message.into(),
}
}
#[must_use]
pub fn invalid_backreference(
group: usize,
position: usize,
message: impl Into<String>,
) -> Self {
Error::InvalidBackreference {
group,
position,
message: message.into(),
}
}
}
pub type Result<T> = std::result::Result<T, Error>;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Span {
pub start: usize,
pub end: usize,
}
impl Span {
#[must_use]
pub fn new(start: usize, end: usize) -> Self {
Span { start, end }
}
#[must_use]
pub fn at(position: usize) -> Self {
Span {
start: position,
end: position + 1,
}
}
}
impl fmt::Display for Span {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if self.start == self.end || self.start + 1 == self.end {
write!(f, "position {}", self.start)
} else {
write!(f, "positions {}-{}", self.start, self.end)
}
}
}