synkit_core/
repeated.rs

1use std::marker::PhantomData;
2
3/// A single item in a [`Repeated`] sequence, holding a value and optional separator.
4///
5/// # Type Parameters
6///
7/// - `T`: The value type (phantom, for type safety)
8/// - `Sep`: The separator type (phantom, for type safety)
9/// - `Spanned`: The actual spanned wrapper type containing the value
10#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
11#[derive(Debug, Clone, PartialEq)]
12pub struct RepeatedItem<T, Sep, Spanned> {
13    /// The spanned value.
14    pub value: Spanned,
15    /// The optional trailing separator (e.g., comma, semicolon).
16    pub sep: Option<Spanned>,
17    #[cfg_attr(feature = "serde", serde(skip))]
18    _marker: PhantomData<(T, Sep)>,
19}
20
21impl<T, Sep, Spanned> RepeatedItem<T, Sep, Spanned> {
22    /// Create a new repeated item with the given value and optional separator.
23    pub fn new(value: Spanned, sep: Option<Spanned>) -> Self {
24        Self {
25            value,
26            sep,
27            _marker: PhantomData,
28        }
29    }
30}
31
32/// A sequence of repeated items with separators.
33///
34/// Similar to [`Punctuated`](crate::Punctuated) but stores items as
35/// [`RepeatedItem`] pairs for cases where you need to preserve the
36/// exact separator tokens.
37///
38/// # Type Parameters
39///
40/// - `T`: The value type (phantom, for type safety)
41/// - `Sep`: The separator type (phantom, for type safety)
42/// - `Spanned`: The actual spanned wrapper type
43#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
44#[derive(Debug, Clone, PartialEq)]
45pub struct Repeated<T, Sep, Spanned> {
46    /// The items in the sequence.
47    pub values: Vec<RepeatedItem<T, Sep, Spanned>>,
48    #[cfg_attr(feature = "serde", serde(skip))]
49    _marker: PhantomData<(T, Sep)>,
50}
51
52impl<T, Sep, Spanned> Repeated<T, Sep, Spanned> {
53    /// Create an empty `Repeated` with no pre-allocated capacity.
54    #[inline]
55    pub fn empty() -> Self {
56        Self {
57            values: Vec::new(),
58            _marker: PhantomData,
59        }
60    }
61
62    /// Create an empty `Repeated` with pre-allocated capacity.
63    ///
64    /// This is useful when you know approximately how many items will be added,
65    /// as it avoids repeated reallocations during parsing.
66    ///
67    /// # Example
68    /// ```ignore
69    /// // Pre-allocate for ~8 items (common for JSON arrays)
70    /// let mut repeated = Repeated::<Item, Comma, Spanned>::with_capacity(8);
71    /// ```
72    #[inline]
73    pub fn with_capacity(capacity: usize) -> Self {
74        Self {
75            values: Vec::with_capacity(capacity),
76            _marker: PhantomData,
77        }
78    }
79
80    /// Create from an existing vector of items.
81    #[inline]
82    pub fn from_values(values: Vec<RepeatedItem<T, Sep, Spanned>>) -> Self {
83        Self {
84            values,
85            _marker: PhantomData,
86        }
87    }
88
89    /// Returns the number of items.
90    #[inline]
91    pub fn len(&self) -> usize {
92        self.values.len()
93    }
94
95    /// Returns true if empty.
96    #[inline]
97    pub fn is_empty(&self) -> bool {
98        self.values.is_empty()
99    }
100
101    /// Returns the current capacity.
102    #[inline]
103    pub fn capacity(&self) -> usize {
104        self.values.capacity()
105    }
106
107    /// Reserves capacity for at least `additional` more items.
108    ///
109    /// Use this before parsing when you have a size hint.
110    #[inline]
111    pub fn reserve(&mut self, additional: usize) {
112        self.values.reserve(additional);
113    }
114
115    /// Shrinks the capacity to match the length.
116    ///
117    /// Call after parsing is complete to release unused memory.
118    #[inline]
119    pub fn shrink_to_fit(&mut self) {
120        self.values.shrink_to_fit();
121    }
122
123    /// Returns an iterator over the items.
124    #[inline]
125    pub fn iter(&self) -> impl Iterator<Item = &RepeatedItem<T, Sep, Spanned>> {
126        self.values.iter()
127    }
128
129    /// Returns a mutable iterator over the items.
130    #[inline]
131    pub fn iter_mut(&mut self) -> impl Iterator<Item = &mut RepeatedItem<T, Sep, Spanned>> {
132        self.values.iter_mut()
133    }
134
135    /// Push a new item.
136    #[inline]
137    pub fn push(&mut self, item: RepeatedItem<T, Sep, Spanned>) {
138        self.values.push(item);
139    }
140
141    /// Clear all items, keeping allocated capacity.
142    ///
143    /// Useful for reusing a `Repeated` buffer across multiple parse operations.
144    #[inline]
145    pub fn clear(&mut self) {
146        self.values.clear();
147    }
148}
149
150impl<T, Sep, Spanned> Default for Repeated<T, Sep, Spanned> {
151    fn default() -> Self {
152        Self::empty()
153    }
154}
155
156impl<T, Sep, Spanned> IntoIterator for Repeated<T, Sep, Spanned> {
157    type Item = RepeatedItem<T, Sep, Spanned>;
158    type IntoIter = std::vec::IntoIter<Self::Item>;
159
160    fn into_iter(self) -> Self::IntoIter {
161        self.values.into_iter()
162    }
163}
164
165impl<'a, T, Sep, Spanned> IntoIterator for &'a Repeated<T, Sep, Spanned> {
166    type Item = &'a RepeatedItem<T, Sep, Spanned>;
167    type IntoIter = std::slice::Iter<'a, RepeatedItem<T, Sep, Spanned>>;
168
169    fn into_iter(self) -> Self::IntoIter {
170        self.values.iter()
171    }
172}
173
174impl<T, Sep, Spanned> std::ops::Deref for Repeated<T, Sep, Spanned> {
175    type Target = Vec<RepeatedItem<T, Sep, Spanned>>;
176
177    #[inline]
178    fn deref(&self) -> &Self::Target {
179        &self.values
180    }
181}
182
183impl<T, Sep, Spanned> std::ops::DerefMut for Repeated<T, Sep, Spanned> {
184    #[inline]
185    fn deref_mut(&mut self) -> &mut Self::Target {
186        &mut self.values
187    }
188}
189
190impl<T, Sep, Spanned> AsRef<[RepeatedItem<T, Sep, Spanned>]> for Repeated<T, Sep, Spanned> {
191    #[inline]
192    fn as_ref(&self) -> &[RepeatedItem<T, Sep, Spanned>] {
193        &self.values
194    }
195}
196
197impl<T, Sep, Spanned> AsMut<[RepeatedItem<T, Sep, Spanned>]> for Repeated<T, Sep, Spanned> {
198    #[inline]
199    fn as_mut(&mut self) -> &mut [RepeatedItem<T, Sep, Spanned>] {
200        &mut self.values
201    }
202}