1use crate::hir::types::Span;
8
9#[derive(Debug, Clone, PartialEq, Eq)]
11pub enum HirError {
12 Malformed { code: &'static str, message: String },
14 IncompatibleProtocol { expected: String, received: String },
17 UnsupportedNode { kind: String, span: Option<Span> },
19 Invalid {
21 code: &'static str,
22 message: String,
23 span: Option<Span>,
24 },
25}
26
27impl HirError {
28 pub fn code(&self) -> &'static str {
30 match self {
31 HirError::Malformed { code, .. } => code,
32 HirError::IncompatibleProtocol { .. } => "incompatible-protocol",
33 HirError::UnsupportedNode { .. } => "unsupported-node",
34 HirError::Invalid { code, .. } => code,
35 }
36 }
37
38 pub fn message(&self) -> String {
40 match self {
41 HirError::Malformed { message, .. } => message.clone(),
42 HirError::IncompatibleProtocol { expected, received } => {
43 format!("incompatible protocol: expected {expected}, received {received}")
44 }
45 HirError::UnsupportedNode { kind, .. } => {
46 format!("unsupported node kind '{kind}'")
47 }
48 HirError::Invalid { message, .. } => message.clone(),
49 }
50 }
51
52 pub fn span(&self) -> Option<&Span> {
54 match self {
55 HirError::UnsupportedNode { span, .. } => span.as_ref(),
56 HirError::Invalid { span, .. } => span.as_ref(),
57 _ => None,
58 }
59 }
60}
61
62impl std::fmt::Display for HirError {
63 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
64 write!(f, "{}: {}", self.code(), self.message())
65 }
66}
67
68impl std::error::Error for HirError {}
69
70impl From<serde_json::Error> for HirError {
71 fn from(error: serde_json::Error) -> Self {
72 HirError::Malformed {
73 code: "malformed-payload",
74 message: error.to_string(),
75 }
76 }
77}
78
79pub(crate) fn invalid(
81 code: &'static str,
82 message: impl Into<String>,
83 span: Option<Span>,
84) -> HirError {
85 HirError::Invalid {
86 code,
87 message: message.into(),
88 span,
89 }
90}