#[cfg(feature = "std")]
use std::string::String;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct SequenceMetadata {
pub number: u16,
pub name: &'static str,
pub description: Option<&'static str>,
pub typical_severity: Option<&'static str>,
pub hints: &'static [&'static str],
pub related: &'static [&'static str],
pub introduced: Option<&'static str>,
}
impl SequenceMetadata {
pub const fn has_metadata(&self) -> bool {
self.description.is_some()
|| self.typical_severity.is_some()
|| !self.hints.is_empty()
|| !self.related.is_empty()
|| self.introduced.is_some()
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct DiagnosticRuntime {
pub severity: crate::Severity,
pub namespace: Option<&'static str>,
pub namespace_hash: Option<&'static str>,
pub component: &'static str,
pub primary: &'static str,
pub sequence: &'static str,
pub sequence_value: u16,
pub code: &'static str,
pub message: &'static str,
pub fields: &'static [&'static str],
pub pii_fields: &'static [&'static str],
pub contains_pii: bool,
pub role: Option<&'static str>,
pub tags: &'static [&'static str],
pub related_codes: &'static [&'static str],
pub hints_runtime: &'static [&'static str],
pub hints_both: &'static [&'static str],
#[cfg(feature = "metadata")]
pub hints_runtime_gated: &'static [(&'static str, &'static str)],
#[cfg(feature = "metadata")]
pub hints_both_gated: &'static [(&'static str, &'static str)],
#[cfg(feature = "metadata")]
pub tags_gated: &'static [(&'static str, &'static str)],
#[cfg(feature = "metadata")]
pub related_codes_gated: &'static [(&'static str, &'static str)],
pub hash: &'static str,
}
#[cfg(feature = "metadata")]
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct CodeSnippetDef {
pub language: Option<&'static str>,
pub wrong: Option<&'static str>,
pub correct: Option<&'static str>,
pub explanation: Option<&'static str>,
pub role: &'static str,
}
#[cfg(feature = "metadata")]
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct DiagnosticDocs {
pub description: Option<&'static str>,
pub code_snippets: &'static [CodeSnippetDef],
pub docs_url: Option<&'static str>,
pub introduced: Option<&'static str>,
pub deprecated: Option<&'static str>,
pub hints_compiletime: &'static [&'static str],
pub see_also: &'static [&'static str],
#[cfg(feature = "metadata")]
pub hints_compiletime_gated: &'static [(&'static str, &'static str)],
#[cfg(feature = "metadata")]
pub see_also_gated: &'static [(&'static str, &'static str)],
}
#[cfg(feature = "metadata")]
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct DiagnosticComplete {
pub runtime: DiagnosticRuntime,
pub docs: Option<DiagnosticDocs>,
}
#[cfg(feature = "metadata")]
impl crate::traits::ErrorMetadata for DiagnosticComplete {
fn code(&self) -> &'static str {
self.runtime.code
}
fn description(&self) -> Option<&'static str> {
self.docs.as_ref().and_then(|d| d.description)
}
fn hints(&self) -> &'static [&'static str] {
self.runtime.hints_runtime
}
fn role(&self) -> crate::traits::Role {
match self.runtime.role {
Some("Public") => crate::traits::Role::Public,
Some("Developer") => crate::traits::Role::Developer,
Some("Internal") => crate::traits::Role::Internal,
_ => crate::traits::Role::Public, }
}
fn docs_url(&self) -> Option<&'static str> {
self.docs.as_ref().and_then(|d| d.docs_url)
}
fn examples(&self) -> &'static [&'static str] {
&[]
}
fn related_codes(&self) -> &'static [&'static str] {
self.runtime.related_codes
}
fn since_version(&self) -> Option<&'static str> {
self.docs.as_ref().and_then(|d| d.introduced)
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct DiagnosticMetadata {
pub severity: crate::Severity,
pub component: &'static str,
pub primary: &'static str,
pub sequence: &'static str,
pub sequence_value: u16,
pub message: &'static str,
pub fields: &'static [&'static str],
pub description: Option<&'static str>,
pub hints: &'static [&'static str],
#[cfg(feature = "metadata")]
pub code_snippets: &'static [CodeSnippetDef],
pub role: Option<&'static str>,
pub tags: &'static [&'static str],
pub related_codes: &'static [&'static str],
pub docs_url: Option<&'static str>,
pub introduced: Option<&'static str>,
pub deprecated: Option<&'static str>,
}
impl DiagnosticRuntime {
#[cfg(feature = "metadata")]
pub const INIT_WITH_DEFAULTS: Self = Self {
severity: crate::Severity::Error,
namespace: None,
namespace_hash: None,
component: "",
primary: "",
sequence: "",
sequence_value: 0,
code: "",
message: "",
fields: &[],
pii_fields: &[],
contains_pii: false,
role: None,
tags: &[],
related_codes: &[],
hints_runtime: &[],
hints_both: &[],
hints_runtime_gated: &[],
hints_both_gated: &[],
tags_gated: &[],
related_codes_gated: &[],
hash: "",
};
#[cfg(not(feature = "metadata"))]
pub const INIT_WITH_DEFAULTS: Self = Self {
severity: crate::Severity::Error,
namespace: None,
namespace_hash: None,
component: "",
primary: "",
sequence: "",
sequence_value: 0,
code: "",
message: "",
fields: &[],
pii_fields: &[],
contains_pii: false,
role: None,
tags: &[],
related_codes: &[],
hints_runtime: &[],
hints_both: &[],
hash: "",
};
pub const fn code_parts(&self) -> (&'static str, &'static str, &'static str, &'static str) {
let severity_str = match self.severity {
crate::Severity::Error => "E",
crate::Severity::Warning => "W",
crate::Severity::Info => "I",
crate::Severity::Critical => "C",
crate::Severity::Blocked => "B",
crate::Severity::Trace => "T",
crate::Severity::Help => "H",
crate::Severity::Success => "S",
crate::Severity::Completed => "K",
};
(severity_str, self.component, self.primary, self.sequence)
}
#[cfg(feature = "std")]
pub fn full_code(&self) -> String {
let (sev, comp, prim, seq) = self.code_parts();
std::format!("{}.{}.{}.{}", sev, comp, prim, seq)
}
#[cfg(feature = "std")]
pub fn canonical_code(&self) -> String {
let severity_str = match self.severity {
crate::Severity::Error => "E",
crate::Severity::Warning => "W",
crate::Severity::Info => "I",
crate::Severity::Critical => "C",
crate::Severity::Blocked => "B",
crate::Severity::Trace => "T",
crate::Severity::Help => "H",
crate::Severity::Success => "S",
crate::Severity::Completed => "K",
};
std::format!(
"{}.{}.{}.{:03}",
severity_str,
self.component.to_ascii_uppercase(),
self.primary.to_ascii_uppercase(),
self.sequence_value
)
}
pub const fn has_fields(&self) -> bool {
!self.fields.is_empty()
}
pub const fn has_hints(&self) -> bool {
!self.hints_runtime.is_empty() || !self.hints_both.is_empty()
}
pub fn all_hints(&self) -> impl Iterator<Item = &&'static str> {
self.hints_runtime.iter().chain(self.hints_both.iter())
}
pub const fn has_namespace(&self) -> bool {
self.namespace.is_some()
}
pub const fn compact_id(&self) -> &'static str {
self.hash
}
#[cfg(feature = "std")]
pub fn combined_id(&self) -> std::string::String {
match self.namespace_hash {
Some(ns_hash) => std::format!("{}-{}", ns_hash, self.hash),
None => std::string::String::from(self.hash),
}
}
}
#[cfg(feature = "metadata")]
impl DiagnosticDocs {
pub const fn has_hints(&self) -> bool {
!self.hints_compiletime.is_empty()
}
pub const fn has_comprehensive_docs(&self) -> bool {
self.description.is_some()
|| !self.code_snippets.is_empty()
|| self.docs_url.is_some()
|| !self.hints_compiletime.is_empty()
}
}
#[cfg(feature = "metadata")]
impl DiagnosticComplete {
pub const fn code_parts(&self) -> (&'static str, &'static str, &'static str, &'static str) {
self.runtime.code_parts()
}
#[cfg(feature = "std")]
pub fn full_code(&self) -> String {
self.runtime.full_code()
}
#[cfg(feature = "std")]
pub fn canonical_code(&self) -> String {
self.runtime.canonical_code()
}
pub fn all_hints(&self) -> impl Iterator<Item = &'static str> + '_ {
let runtime_hints = self.runtime.hints_runtime.iter().copied();
let both_hints = self.runtime.hints_both.iter().copied();
let compile_hints = self
.docs
.as_ref()
.map(|d| d.hints_compiletime.iter().copied())
.into_iter()
.flatten();
runtime_hints.chain(both_hints).chain(compile_hints)
}
}
impl DiagnosticMetadata {
pub const fn code_parts(&self) -> (&'static str, &'static str, &'static str, &'static str) {
let severity_str = match self.severity {
crate::Severity::Error => "E",
crate::Severity::Warning => "W",
crate::Severity::Info => "I",
crate::Severity::Critical => "C",
crate::Severity::Blocked => "B",
crate::Severity::Trace => "T",
crate::Severity::Help => "H",
crate::Severity::Success => "S",
crate::Severity::Completed => "K",
};
(severity_str, self.component, self.primary, self.sequence)
}
#[cfg(feature = "std")]
pub fn full_code(&self) -> String {
let (sev, comp, prim, seq) = self.code_parts();
std::format!("{}.{}.{}.{}", sev, comp, prim, seq)
}
pub const fn has_fields(&self) -> bool {
!self.fields.is_empty()
}
pub const fn has_hints(&self) -> bool {
!self.hints.is_empty()
}
}