Skip to main content

acdc_parser/model/
title.rs

1use std::ops::Deref;
2
3use serde::{Serialize, ser::Serializer};
4
5use super::inlines::InlineNode;
6
7/// A title in a document (section titles, block titles, document title, etc.).
8///
9/// `Title` is a newtype wrapper around `Vec<InlineNode>` that provides convenient
10/// access to inline content. Titles can include formatting, links, and other inline
11/// elements.
12///
13/// # Accessing Content
14///
15/// `Title` implements `Deref<Target=[InlineNode]>`, so you can use slice methods directly:
16///
17/// ```
18/// # use acdc_parser::{Title, InlineNode};
19/// let title = Title::new(vec![/* inline nodes */]);
20///
21/// // Iterate over inline nodes
22/// for node in &title {
23///     // ...
24/// }
25///
26/// // Check if empty
27/// if title.is_empty() {
28///     // ...
29/// }
30///
31/// // Access by index (via deref)
32/// if let Some(first) = title.first() {
33///     // ...
34/// }
35/// ```
36///
37/// # Serialization
38///
39/// Serializes as a plain JSON array of inline nodes for ASG compatibility.
40#[derive(Clone, Debug, Default, PartialEq)]
41#[non_exhaustive]
42pub struct Title<'a>(Vec<InlineNode<'a>>);
43
44impl Serialize for Title<'_> {
45    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
46    where
47        S: Serializer,
48    {
49        self.0.serialize(serializer)
50    }
51}
52
53pub type Subtitle<'a> = Title<'a>;
54
55impl<'a> Title<'a> {
56    /// Creates a new `Title` with the given inline content.
57    #[must_use]
58    pub fn new(inlines: Vec<InlineNode<'a>>) -> Self {
59        Self(inlines)
60    }
61
62    /// Consume the title, returning the underlying inline nodes.
63    #[must_use]
64    pub fn into_inlines(self) -> Vec<InlineNode<'a>> {
65        self.0
66    }
67
68    /// Returns `true` if the title has no content.
69    #[must_use]
70    pub fn is_empty(&self) -> bool {
71        self.0.is_empty()
72    }
73
74    /// Returns the number of inline nodes in the title.
75    #[must_use]
76    pub fn len(&self) -> usize {
77        self.0.len()
78    }
79}
80
81impl<'a> From<Vec<InlineNode<'a>>> for Title<'a> {
82    fn from(inlines: Vec<InlineNode<'a>>) -> Self {
83        Self(inlines)
84    }
85}
86
87impl<'a> AsRef<[InlineNode<'a>]> for Title<'a> {
88    fn as_ref(&self) -> &[InlineNode<'a>] {
89        &self.0
90    }
91}
92
93impl<'a> Deref for Title<'a> {
94    type Target = [InlineNode<'a>];
95
96    fn deref(&self) -> &Self::Target {
97        &self.0
98    }
99}
100
101impl<'a, 'b> IntoIterator for &'b Title<'a> {
102    type Item = &'b InlineNode<'a>;
103    type IntoIter = std::slice::Iter<'b, InlineNode<'a>>;
104
105    fn into_iter(self) -> Self::IntoIter {
106        self.0.iter()
107    }
108}