socketry_markdown/
message.rs1use crate::unist::{Point, Position};
6use alloc::{boxed::Box, fmt, string::String};
7
8#[derive(Clone, Debug, PartialEq)]
9pub struct Message {
10 pub place: Option<Box<Place>>,
12 pub reason: String,
14 pub rule_id: Box<String>,
16 pub source: Box<String>,
18}
19
20impl fmt::Display for Message {
21 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
22 if let Some(ref place) = self.place {
23 write!(f, "{place}: ")?;
24 }
25
26 write!(f, "{} ({}:{})", self.reason, self.source, self.rule_id)
27 }
28}
29
30#[derive(Clone, Debug, PartialEq)]
32pub enum Place {
33 Position(Position),
35 Point(Point),
37}
38
39impl fmt::Display for Place {
40 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
41 match self {
42 Place::Position(position) => write!(
43 f,
44 "{}:{}-{}:{}",
45 position.start.line, position.start.column, position.end.line, position.end.column
46 ),
47 Place::Point(point) => write!(f, "{}:{}", point.line, point.column),
48 }
49 }
50}
51
52#[cfg(test)]
53mod tests {
54 use super::{Message, Place};
55 use crate::unist::{Point, Position};
56 use alloc::boxed::Box;
57 use alloc::string::ToString;
58 use core::fmt::Write as _;
59
60 struct FailingWriter;
61
62 impl core::fmt::Write for FailingWriter {
63 fn write_str(&mut self, _value: &str) -> core::fmt::Result {
64 Err(core::fmt::Error)
65 }
66 }
67
68 #[test]
69 fn displays_a_message_with_its_place() {
70 let message = Message {
71 place: Some(Box::new(Place::Point(Point::new(2, 3, 4)))),
72 reason: "invalid value".into(),
73 rule_id: Box::new("example".into()),
74 source: Box::new("parser".into()),
75 };
76
77 assert_eq!(message.to_string(), "2:3: invalid value (parser:example)");
78
79 let message = Message {
80 place: Some(Box::new(Place::Position(Position::new(1, 2, 3, 4, 5, 6)))),
81 reason: "invalid range".into(),
82 rule_id: Box::new("example".into()),
83 source: Box::new("parser".into()),
84 };
85
86 assert_eq!(
87 message.to_string(),
88 "1:2-4:5: invalid range (parser:example)"
89 );
90
91 let message = Message {
92 place: None,
93 reason: "invalid without a location".into(),
94 rule_id: Box::new("example".into()),
95 source: Box::new("parser".into()),
96 };
97 assert_eq!(
98 message.to_string(),
99 "invalid without a location (parser:example)"
100 );
101
102 let mut writer = FailingWriter;
103 assert!(write!(&mut writer, "{message}").is_err());
104
105 let message = Message {
106 place: Some(Box::new(Place::Point(Point::new(2, 3, 4)))),
107 reason: "invalid value".into(),
108 rule_id: Box::new("example".into()),
109 source: Box::new("parser".into()),
110 };
111 assert!(write!(&mut writer, "{message}").is_err());
112 }
113}