lex_extension/wire/
inline.rs1use serde::{Deserialize, Serialize};
13
14#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
17#[serde(tag = "kind", rename_all = "snake_case")]
18#[non_exhaustive]
19pub enum WireInline {
20 Text { text: String },
22 Bold { children: Vec<WireInline> },
24 Italic { children: Vec<WireInline> },
26 Code { text: String },
28 Math { text: String },
30 Reference {
33 ref_kind: RefKind,
34 target: String,
35 #[serde(skip_serializing_if = "Option::is_none")]
36 label: Option<String>,
37 },
38}
39
40#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize)]
48#[serde(rename_all = "snake_case")]
49#[non_exhaustive]
50pub enum RefKind {
51 Url,
52 Citation,
53 Footnote,
54 Session,
55 File,
56 Placeholder,
57 Unsure,
58 General,
59}
60
61impl<'de> Deserialize<'de> for RefKind {
62 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
63 where
64 D: serde::Deserializer<'de>,
65 {
66 let s = String::deserialize(deserializer)?;
67 Ok(match s.as_str() {
68 "url" => Self::Url,
69 "citation" => Self::Citation,
70 "footnote" => Self::Footnote,
71 "session" => Self::Session,
72 "file" => Self::File,
73 "placeholder" => Self::Placeholder,
74 "unsure" => Self::Unsure,
75 _ => Self::General,
76 })
77 }
78}
79
80#[cfg(test)]
81mod tests {
82 use super::*;
83
84 #[test]
85 fn text_inline_round_trips() {
86 let i = WireInline::Text {
87 text: "hello".into(),
88 };
89 let s = serde_json::to_string(&i).unwrap();
90 assert_eq!(s, r#"{"kind":"text","text":"hello"}"#);
91 let back: WireInline = serde_json::from_str(&s).unwrap();
92 assert_eq!(back, i);
93 }
94
95 #[test]
96 fn bold_with_nested_text() {
97 let i = WireInline::Bold {
98 children: vec![WireInline::Text {
99 text: "loud".into(),
100 }],
101 };
102 let s = serde_json::to_string(&i).unwrap();
103 assert_eq!(
104 s,
105 r#"{"kind":"bold","children":[{"kind":"text","text":"loud"}]}"#
106 );
107 }
108
109 #[test]
110 fn reference_url_round_trips() {
111 let i = WireInline::Reference {
112 ref_kind: RefKind::Url,
113 target: "https://example.com".into(),
114 label: None,
115 };
116 let s = serde_json::to_string(&i).unwrap();
117 assert_eq!(
118 s,
119 r#"{"kind":"reference","ref_kind":"url","target":"https://example.com"}"#
120 );
121 let back: WireInline = serde_json::from_str(&s).unwrap();
122 assert_eq!(back, i);
123 }
124
125 #[test]
126 fn reference_with_label() {
127 let i = WireInline::Reference {
128 ref_kind: RefKind::Footnote,
129 target: "1".into(),
130 label: Some("note one".into()),
131 };
132 let s = serde_json::to_string(&i).unwrap();
133 let back: WireInline = serde_json::from_str(&s).unwrap();
134 assert_eq!(back, i);
135 }
136
137 #[test]
138 fn unknown_ref_kind_falls_back_to_general() {
139 let kind: RefKind = serde_json::from_str(r#""acronym""#).unwrap();
140 assert_eq!(kind, RefKind::General);
141 }
142}