#[derive(Debug)] pub struct Diagnostic { message: String, primary_label_message: Option, error_code: Option, start: usize, end: usize, reporter_file: Option<&'static str>, reporter_line: Option, secondary_labels: Vec, } impl Diagnostic { pub fn new(message: &str, start: usize, end: usize) -> Self { Self { message: message.into(), primary_label_message: None, error_code: None, start, end, reporter_line: None, reporter_file: None, secondary_labels: vec![], } } pub fn message(&self) -> &str { &self.message } pub fn primary_label_message(&self) -> Option<&str> { self.primary_label_message.as_deref() } pub fn error_code(&self) -> Option { self.error_code } pub fn start(&self) -> usize { self.start } pub fn end(&self) -> usize { self.end } pub fn reporter(&self) -> Option<(&'static str, u32)> { if let Some(file) = self.reporter_file { Some((file, self.reporter_line.unwrap())) } else { None } } pub fn secondary_labels(&self) -> &[SecondaryLabel] { &self.secondary_labels } pub fn with_error_code(mut self, code: usize) -> Self { self.error_code = Some(code); self } pub fn with_primary_label_message(mut self, message: &str) -> Self { self.primary_label_message = Some(message.into()); self } pub fn with_reporter(mut self, file: &'static str, line: u32) -> Self { self.reporter_file = Some(file); self.reporter_line = Some(line); self } pub fn with_secondary_labels(mut self, labels: &[SecondaryLabel]) -> Self { self.secondary_labels.extend_from_slice(labels); self } } #[derive(Debug, Clone)] pub struct SecondaryLabel { start: usize, end: usize, message: Option, } impl SecondaryLabel { pub fn new(start: usize, end: usize, message: Option) -> Self { Self { start, end, message, } } pub fn start(&self) -> usize { self.start } pub fn end(&self) -> usize { self.end } pub fn message(&self) -> Option<&str> { self.message.as_deref() } }