acdc_parser/model/
anchor.rs1use serde::{
4 Deserialize, Serialize,
5 de::{self, Deserializer, MapAccess, Visitor},
6 ser::{SerializeMap, Serializer},
7};
8
9use super::inlines::InlineNode;
10use super::location::Location;
11use super::title::Title;
12
13#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
17#[non_exhaustive]
18pub struct Anchor {
19 pub id: String,
20 #[serde(default, skip_serializing_if = "Option::is_none")]
21 pub xreflabel: Option<String>,
22 pub location: Location,
23}
24
25impl Anchor {
26 #[must_use]
28 pub fn new(id: String, location: Location) -> Self {
29 Self {
30 id,
31 xreflabel: None,
32 location,
33 }
34 }
35
36 #[must_use]
38 pub fn with_xreflabel(mut self, xreflabel: Option<String>) -> Self {
39 self.xreflabel = xreflabel;
40 self
41 }
42}
43
44#[derive(Clone, Debug, PartialEq)]
48#[non_exhaustive]
49pub struct TocEntry {
50 pub id: String,
52 pub title: Title,
54 pub level: u8,
56 pub xreflabel: Option<String>,
58}
59
60impl Serialize for TocEntry {
61 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
62 where
63 S: Serializer,
64 {
65 let mut state = serializer.serialize_map(None)?;
66 state.serialize_entry("id", &self.id)?;
67 state.serialize_entry("title", &self.title)?;
68 state.serialize_entry("level", &self.level)?;
69 if self.xreflabel.is_some() {
70 state.serialize_entry("xreflabel", &self.xreflabel)?;
71 }
72 state.end()
73 }
74}
75
76impl<'de> Deserialize<'de> for TocEntry {
77 fn deserialize<D>(deserializer: D) -> Result<TocEntry, D::Error>
78 where
79 D: Deserializer<'de>,
80 {
81 struct TocEntryVisitor;
82
83 impl<'de> Visitor<'de> for TocEntryVisitor {
84 type Value = TocEntry;
85
86 fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
87 formatter.write_str("struct TocEntry")
88 }
89
90 fn visit_map<V>(self, mut map: V) -> Result<TocEntry, V::Error>
91 where
92 V: MapAccess<'de>,
93 {
94 let mut id = None;
95 let mut title: Option<Vec<InlineNode>> = None;
96 let mut level = None;
97 let mut xreflabel = None;
98
99 while let Some(key) = map.next_key::<String>()? {
100 match key.as_str() {
101 "id" => id = Some(map.next_value()?),
102 "title" => title = Some(map.next_value()?),
103 "level" => level = Some(map.next_value()?),
104 "xreflabel" => xreflabel = Some(map.next_value()?),
105 _ => {
106 let _ = map.next_value::<de::IgnoredAny>()?;
107 }
108 }
109 }
110
111 Ok(TocEntry {
112 id: id.ok_or_else(|| de::Error::missing_field("id"))?,
113 title: title.unwrap_or_default().into(),
114 level: level.ok_or_else(|| de::Error::missing_field("level"))?,
115 xreflabel,
116 })
117 }
118 }
119
120 deserializer.deserialize_map(TocEntryVisitor)
121 }
122}