// Structured errors for public parser and matcher boundaries.
///|
pub(all) enum RobotsErrorStage {
Input
Line
UserAgent
Rule
Pattern
Utf8
Limit
} derive(Eq)
///|
pub(all) enum RobotsErrorKind {
EmptyInput
MissingColon
EmptyUserAgent
InvalidUserAgent
InvalidRecordName
InvalidPattern
InvalidPercentEncoding
InvalidUtf8
LimitExceeded
RuleBeforeFirstGroup
ControlCharacter
} derive(Eq)
///|
pub(all) suberror RobotsError {
RobotsError(RobotsErrorStage, RobotsErrorKind, Int, Int, String)
}
///|
pub fn robots_error(
stage : RobotsErrorStage,
kind : RobotsErrorKind,
line : Int,
byte_offset : Int,
context : String,
) -> RobotsError {
RobotsError(stage, kind, line, byte_offset, bound_context(context))
}
///|
pub fn RobotsError::stage(self : RobotsError) -> RobotsErrorStage {
match self {
RobotsError(stage, _, _, _, _) => stage
}
}
///|
pub fn RobotsError::kind(self : RobotsError) -> RobotsErrorKind {
match self {
RobotsError(_, kind, _, _, _) => kind
}
}
///|
pub fn RobotsError::line(self : RobotsError) -> Int {
match self {
RobotsError(_, _, line, _, _) => line
}
}
///|
pub fn RobotsError::byte_offset(self : RobotsError) -> Int {
match self {
RobotsError(_, _, _, offset, _) => offset
}
}
///|
pub fn RobotsError::context(self : RobotsError) -> String {
match self {
RobotsError(_, _, _, _, context) => context
}
}
///|
pub fn RobotsErrorStage::to_string(self : RobotsErrorStage) -> String {
match self {
Input => "Input"
Line => "Line"
UserAgent => "UserAgent"
Rule => "Rule"
Pattern => "Pattern"
Utf8 => "Utf8"
Limit => "Limit"
}
}
///|
pub fn RobotsErrorKind::to_string(self : RobotsErrorKind) -> String {
match self {
EmptyInput => "EmptyInput"
MissingColon => "MissingColon"
EmptyUserAgent => "EmptyUserAgent"
InvalidUserAgent => "InvalidUserAgent"
InvalidRecordName => "InvalidRecordName"
InvalidPattern => "InvalidPattern"
InvalidPercentEncoding => "InvalidPercentEncoding"
InvalidUtf8 => "InvalidUtf8"
LimitExceeded => "LimitExceeded"
RuleBeforeFirstGroup => "RuleBeforeFirstGroup"
ControlCharacter => "ControlCharacter"
}
}
///|
pub fn RobotsError::to_display(self : RobotsError) -> String {
let RobotsError(stage, kind, line, offset, context) = self
"\{stage.to_string()}::\{kind.to_string()} at byte \{offset}, line \{line}: \{context}"
}
///|
pub fn max_context_bytes() -> Int {
80
}
///|
fn bound_context(context : String) -> String {
if context.length() <= max_context_bytes() {
context
} else {
let chars = context.to_array()
String::from_array(chars[0:max_context_bytes()]) + "..."
}
}
///|
fn unwrap_robots_error(e : Error) -> RobotsError {
match e {
RobotsError(stage, kind, line, offset, context) =>
RobotsError(stage, kind, line, offset, context)
_ => abort("internal error: unexpected non-RobotsError")
}
}