use std::fmt;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub struct Loc {
pub line: u32,
pub column: u32,
}
impl Loc {
pub const UNKNOWN: Loc = Loc { line: 0, column: 0 };
pub const fn new(line: u32, column: u32) -> Self {
Self { line, column }
}
pub fn is_unknown(self) -> bool {
self.line == 0 && self.column == 0
}
}
impl fmt::Display for Loc {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}:{}", self.line, self.column)
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum CssErrorKind {
InvalidColor(String),
InvalidSelector(String),
InvalidLength(String),
UndefinedVariable(String),
CircularVariable(String),
UnknownProperty(String),
Io(String),
}
impl fmt::Display for CssErrorKind {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::InvalidColor(v) => write!(f, "invalid color: {v}"),
Self::InvalidSelector(v) => write!(f, "invalid selector: {v}"),
Self::InvalidLength(v) => write!(f, "invalid length: {v}"),
Self::UndefinedVariable(v) => write!(f, "undefined variable: {v}"),
Self::CircularVariable(v) => write!(f, "circular variable reference: {v}"),
Self::UnknownProperty(v) => write!(f, "unknown property: {v}"),
Self::Io(v) => write!(f, "io error: {v}"),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct CssError {
pub kind: CssErrorKind,
pub loc: Option<Loc>,
}
impl CssError {
pub fn from_kind(kind: CssErrorKind) -> Self {
Self { kind, loc: None }
}
pub fn invalid_color(msg: impl Into<String>) -> Self {
Self::from_kind(CssErrorKind::InvalidColor(msg.into()))
}
pub fn invalid_selector(msg: impl Into<String>) -> Self {
Self::from_kind(CssErrorKind::InvalidSelector(msg.into()))
}
pub fn invalid_length(msg: impl Into<String>) -> Self {
Self::from_kind(CssErrorKind::InvalidLength(msg.into()))
}
pub fn undefined_variable(msg: impl Into<String>) -> Self {
Self::from_kind(CssErrorKind::UndefinedVariable(msg.into()))
}
pub fn circular_variable(msg: impl Into<String>) -> Self {
Self::from_kind(CssErrorKind::CircularVariable(msg.into()))
}
pub fn unknown_property(msg: impl Into<String>) -> Self {
Self::from_kind(CssErrorKind::UnknownProperty(msg.into()))
}
pub fn io(msg: impl Into<String>) -> Self {
Self::from_kind(CssErrorKind::Io(msg.into()))
}
pub fn at(mut self, line: u32, column: u32) -> Self {
self.loc = Some(Loc::new(line, column));
self
}
pub fn with_loc(mut self, loc: Loc) -> Self {
self.loc = Some(loc);
self
}
pub fn kind(&self) -> &CssErrorKind {
&self.kind
}
}
impl fmt::Display for CssError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self.loc {
Some(loc) if !loc.is_unknown() => write!(f, "{} at line {}:{}", self.kind, loc.line, loc.column),
_ => write!(f, "{}", self.kind),
}
}
}
impl std::error::Error for CssError {}
pub type Result<T> = std::result::Result<T, CssError>;