scarb_ui/components/typed.rs
1use console::Style;
2use serde::{Serialize, Serializer};
3
4use crate::Message;
5
6/// Generic textual message with _type_ prefix.
7///
8/// Use this message type to display any kinds of warnings, errors etc.
9/// The type prefix can be stylized in text mode.
10#[derive(Serialize)]
11pub struct TypedMessage<'a> {
12 r#type: &'a str,
13 message: &'a str,
14
15 #[serde(skip_serializing_if = "Option::is_none")]
16 code: Option<&'a str>,
17
18 #[serde(skip)]
19 type_style: Option<&'a str>,
20 #[serde(skip)]
21 skip_type_for_text: bool,
22}
23
24impl<'a> TypedMessage<'a> {
25 /// Create a message with the given type, its style and the message text proper.
26 pub fn styled(ty: &'a str, type_style: &'a str, message: &'a str) -> Self {
27 Self {
28 r#type: ty,
29 message,
30 type_style: Some(type_style),
31 skip_type_for_text: false,
32 code: None,
33 }
34 }
35
36 /// Create a message that does not print type prefix in text mode.
37 ///
38 /// ## Example
39 /// Scarb uses this for emitting Cairo compiler diagnostics.
40 /// In text mode it prints the diagnostic as-is, while in JSON mode it wraps it as:
41 /// ```json
42 /// {"type":"diagnostic","message":"<diagnostic>"}
43 /// ```
44 pub fn naked_text(ty: &'a str, message: &'a str) -> Self {
45 Self {
46 r#type: ty,
47 message,
48 type_style: None,
49 skip_type_for_text: true,
50 code: None,
51 }
52 }
53
54 /// Sometimes, a message may be associated with a short machine-readable descriptor.
55 /// For example, some compilers associate numerical *codes* with various kinds of errors
56 /// that can be produced.
57 /// The optional `code` field allows carrying this information.
58 /// This will be shown as suffix in text mode, and as a `code` field in structured mode.
59 pub fn with_code(self, code: &'a str) -> Self {
60 Self {
61 code: Some(code),
62 ..self
63 }
64 }
65}
66
67impl Message for TypedMessage<'_> {
68 fn text(self) -> String {
69 if self.skip_type_for_text {
70 self.message.to_string()
71 } else {
72 format!(
73 "{}: {}",
74 self.type_style
75 .map(Style::from_dotted_str)
76 .unwrap_or_default()
77 .apply_to(format!(
78 "{}{}",
79 self.r#type,
80 self.code.map(|c| format!("[{c}]")).unwrap_or_default()
81 )),
82 self.message
83 )
84 }
85 }
86
87 fn structured<S: Serializer>(self, ser: S) -> Result<S::Ok, S::Error> {
88 self.serialize(ser)
89 }
90}