Skip to main content

acdc_parser/model/
attribution.rs

1use std::ops::Deref;
2
3use serde::{Serialize, ser::Serializer};
4
5use super::inlines::InlineNode;
6
7/// An attribution in a blockquote (the author/source of the quote).
8///
9/// `Attribution` is a newtype wrapper around `Vec<InlineNode>` that provides
10/// convenient access to inline content. Attributions can include formatting,
11/// links, and other inline elements.
12///
13/// # Serialization
14///
15/// Serializes as a plain JSON array of inline nodes.
16#[derive(Clone, Debug, Default, PartialEq)]
17#[non_exhaustive]
18pub struct Attribution<'a>(Vec<InlineNode<'a>>);
19
20impl Serialize for Attribution<'_> {
21    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
22    where
23        S: Serializer,
24    {
25        self.0.serialize(serializer)
26    }
27}
28
29impl<'a> Attribution<'a> {
30    /// Creates a new `Attribution` with the given inline content.
31    #[must_use]
32    pub fn new(inlines: Vec<InlineNode<'a>>) -> Self {
33        Self(inlines)
34    }
35
36    /// Returns `true` if the attribution has no content.
37    #[must_use]
38    pub fn is_empty(&self) -> bool {
39        self.0.is_empty()
40    }
41
42    /// Returns the number of inline nodes in the attribution.
43    #[must_use]
44    pub fn len(&self) -> usize {
45        self.0.len()
46    }
47
48    /// Mutable access to the underlying inline nodes (used by the post-parse
49    /// source remap pass to rewrite their locations).
50    pub(crate) fn inlines_mut(&mut self) -> &mut [InlineNode<'a>] {
51        &mut self.0
52    }
53}
54
55impl<'a> From<Vec<InlineNode<'a>>> for Attribution<'a> {
56    fn from(inlines: Vec<InlineNode<'a>>) -> Self {
57        Self(inlines)
58    }
59}
60
61impl<'a> AsRef<[InlineNode<'a>]> for Attribution<'a> {
62    fn as_ref(&self) -> &[InlineNode<'a>] {
63        &self.0
64    }
65}
66
67impl<'a> Deref for Attribution<'a> {
68    type Target = [InlineNode<'a>];
69
70    fn deref(&self) -> &Self::Target {
71        &self.0
72    }
73}
74
75impl<'a, 'b> IntoIterator for &'b Attribution<'a> {
76    type Item = &'b InlineNode<'a>;
77    type IntoIter = std::slice::Iter<'b, InlineNode<'a>>;
78
79    fn into_iter(self) -> Self::IntoIter {
80        self.0.iter()
81    }
82}
83
84/// A citation title in a blockquote (the title of the cited work).
85///
86/// `CiteTitle` is a newtype wrapper around `Vec<InlineNode>` that provides
87/// convenient access to inline content.
88///
89/// # Serialization
90///
91/// Serializes as a plain JSON array of inline nodes.
92#[derive(Clone, Debug, Default, PartialEq)]
93#[non_exhaustive]
94pub struct CiteTitle<'a>(Vec<InlineNode<'a>>);
95
96impl Serialize for CiteTitle<'_> {
97    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
98    where
99        S: Serializer,
100    {
101        self.0.serialize(serializer)
102    }
103}
104
105impl<'a> CiteTitle<'a> {
106    /// Creates a new `CiteTitle` with the given inline content.
107    #[must_use]
108    pub fn new(inlines: Vec<InlineNode<'a>>) -> Self {
109        Self(inlines)
110    }
111
112    /// Returns `true` if the cite title has no content.
113    #[must_use]
114    pub fn is_empty(&self) -> bool {
115        self.0.is_empty()
116    }
117
118    /// Returns the number of inline nodes in the cite title.
119    #[must_use]
120    pub fn len(&self) -> usize {
121        self.0.len()
122    }
123
124    /// Mutable access to the underlying inline nodes (used by the post-parse
125    /// source remap pass to rewrite their locations).
126    pub(crate) fn inlines_mut(&mut self) -> &mut [InlineNode<'a>] {
127        &mut self.0
128    }
129}
130
131impl<'a> From<Vec<InlineNode<'a>>> for CiteTitle<'a> {
132    fn from(inlines: Vec<InlineNode<'a>>) -> Self {
133        Self(inlines)
134    }
135}
136
137impl<'a> AsRef<[InlineNode<'a>]> for CiteTitle<'a> {
138    fn as_ref(&self) -> &[InlineNode<'a>] {
139        &self.0
140    }
141}
142
143impl<'a> Deref for CiteTitle<'a> {
144    type Target = [InlineNode<'a>];
145
146    fn deref(&self) -> &Self::Target {
147        &self.0
148    }
149}
150
151impl<'a, 'b> IntoIterator for &'b CiteTitle<'a> {
152    type Item = &'b InlineNode<'a>;
153    type IntoIter = std::slice::Iter<'b, InlineNode<'a>>;
154
155    fn into_iter(self) -> Self::IntoIter {
156        self.0.iter()
157    }
158}