use miette::{Diagnostic, LabeledSpan};
use thiserror::Error;
use crate::{ShellError, Span, Spanned};
#[derive(Debug, Clone, PartialEq, Error, Diagnostic)]
pub enum NetworkError {
#[error("Network failure")]
#[diagnostic(code(nu::shell::network))]
Generic {
msg: String,
#[label("{msg}")]
span: Span,
},
#[error(transparent)]
#[diagnostic(transparent)]
Dns(DnsError),
}
#[derive(Debug, Clone, PartialEq, Error)]
#[error("DNS Error")]
pub struct DnsError {
pub kind: DnsErrorKind,
pub span: Span,
pub query: Spanned<String>,
}
impl Diagnostic for DnsError {
fn code<'a>(&'a self) -> Option<Box<dyn std::fmt::Display + 'a>> {
self.kind.code()
}
fn labels(&self) -> Option<Box<dyn Iterator<Item = LabeledSpan> + '_>> {
Some(Box::new(
[
LabeledSpan::new_with_span(Some("Could not be resolved".into()), self.query.span),
LabeledSpan::new_with_span(Some(self.kind.to_string()), self.span),
]
.into_iter(),
))
}
fn help<'a>(&'a self) -> Option<Box<dyn std::fmt::Display + 'a>> {
Some(Box::new(format!("While querying \"{}\"", self.query)))
}
}
#[derive(Debug, Clone, PartialEq, Error, Diagnostic)]
pub enum DnsErrorKind {
#[error("Temporary failure in name resolution")]
#[diagnostic(code(nu::shell::network::dns::again))]
Again,
#[error("Name or service is unknown")]
#[diagnostic(code(nu::shell::network::dns::no_name))]
NoName,
#[error("Host exists but has no address records")]
#[diagnostic(code(nu::shell::network::dns::no_data))]
NoData,
#[error("Non recoverable failure in name resolution")]
#[diagnostic(code(nu::shell::network::dns::fail))]
Fail,
}
impl From<DnsError> for ShellError {
fn from(value: DnsError) -> Self {
ShellError::Network(NetworkError::Dns(value))
}
}