acdc_parser/model/
title.rs

1use std::ops::Deref;
2
3use serde::{
4    Deserialize, Serialize,
5    de::{Deserializer, SeqAccess, Visitor},
6    ser::Serializer,
7};
8
9use super::inlines::InlineNode;
10
11/// A `Title` represents a title in a document (section titles, block titles, etc.).
12///
13/// Titles contain inline content and can include formatting, links, and other
14/// inline elements.
15///
16/// Serializes as a plain array for backwards compatibility with existing fixtures.
17#[derive(Clone, Debug, Default, PartialEq)]
18#[non_exhaustive]
19pub struct Title(Vec<InlineNode>);
20
21impl Serialize for Title {
22    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
23    where
24        S: Serializer,
25    {
26        self.0.serialize(serializer)
27    }
28}
29
30impl<'de> Deserialize<'de> for Title {
31    fn deserialize<D>(deserializer: D) -> Result<Title, D::Error>
32    where
33        D: Deserializer<'de>,
34    {
35        struct TitleVisitor;
36
37        impl<'de> Visitor<'de> for TitleVisitor {
38            type Value = Title;
39
40            fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
41                formatter.write_str("a sequence of inline nodes")
42            }
43
44            fn visit_seq<A>(self, mut seq: A) -> Result<Title, A::Error>
45            where
46                A: SeqAccess<'de>,
47            {
48                let mut inlines = Vec::new();
49                while let Some(node) = seq.next_element()? {
50                    inlines.push(node);
51                }
52                Ok(Title(inlines))
53            }
54        }
55
56        deserializer.deserialize_seq(TitleVisitor)
57    }
58}
59
60pub type Subtitle = Title;
61
62impl Title {
63    /// Creates a new `Title` with the given inline content.
64    #[must_use]
65    pub fn new(inlines: Vec<InlineNode>) -> Self {
66        Self(inlines)
67    }
68
69    /// Returns `true` if the title has no content.
70    #[must_use]
71    pub fn is_empty(&self) -> bool {
72        self.0.is_empty()
73    }
74
75    /// Returns the number of inline nodes in the title.
76    #[must_use]
77    pub fn len(&self) -> usize {
78        self.0.len()
79    }
80}
81
82impl From<Vec<InlineNode>> for Title {
83    fn from(inlines: Vec<InlineNode>) -> Self {
84        Self(inlines)
85    }
86}
87
88impl AsRef<[InlineNode]> for Title {
89    fn as_ref(&self) -> &[InlineNode] {
90        &self.0
91    }
92}
93
94impl Deref for Title {
95    type Target = [InlineNode];
96
97    fn deref(&self) -> &Self::Target {
98        &self.0
99    }
100}
101
102impl<'a> IntoIterator for &'a Title {
103    type Item = &'a InlineNode;
104    type IntoIter = std::slice::Iter<'a, InlineNode>;
105
106    fn into_iter(self) -> Self::IntoIter {
107        self.0.iter()
108    }
109}