1 | //! A punctuated sequence of syntax tree nodes separated by punctuation. |
2 | //! |
3 | //! Lots of things in Rust are punctuated sequences. |
4 | //! |
5 | //! - The fields of a struct are `Punctuated<Field, Token![,]>`. |
6 | //! - The segments of a path are `Punctuated<PathSegment, Token![::]>`. |
7 | //! - The bounds on a generic parameter are `Punctuated<TypeParamBound, |
8 | //! Token![+]>`. |
9 | //! - The arguments to a function call are `Punctuated<Expr, Token![,]>`. |
10 | //! |
11 | //! This module provides a common representation for these punctuated sequences |
12 | //! in the form of the [`Punctuated<T, P>`] type. We store a vector of pairs of |
13 | //! syntax tree node + punctuation, where every node in the sequence is followed |
14 | //! by punctuation except for possibly the final one. |
15 | //! |
16 | //! [`Punctuated<T, P>`]: Punctuated |
17 | //! |
18 | //! ```text |
19 | //! a_function_call(arg1, arg2, arg3); |
20 | //! ~~~~^ ~~~~^ ~~~~ |
21 | //! ``` |
22 | |
23 | use crate::drops::{NoDrop, TrivialDrop}; |
24 | #[cfg (feature = "parsing" )] |
25 | use crate::error::Result; |
26 | #[cfg (feature = "parsing" )] |
27 | use crate::parse::{Parse, ParseStream}; |
28 | #[cfg (feature = "parsing" )] |
29 | use crate::token::Token; |
30 | #[cfg (feature = "extra-traits" )] |
31 | use std::fmt::{self, Debug}; |
32 | #[cfg (feature = "extra-traits" )] |
33 | use std::hash::{Hash, Hasher}; |
34 | #[cfg (any(feature = "full" , feature = "derive" ))] |
35 | use std::iter; |
36 | use std::ops::{Index, IndexMut}; |
37 | use std::option; |
38 | use std::slice; |
39 | use std::vec; |
40 | |
41 | /// **A punctuated sequence of syntax tree nodes of type `T` separated by |
42 | /// punctuation of type `P`.** |
43 | /// |
44 | /// Refer to the [module documentation] for details about punctuated sequences. |
45 | /// |
46 | /// [module documentation]: self |
47 | pub struct Punctuated<T, P> { |
48 | inner: Vec<(T, P)>, |
49 | last: Option<Box<T>>, |
50 | } |
51 | |
52 | impl<T, P> Punctuated<T, P> { |
53 | /// Creates an empty punctuated sequence. |
54 | pub const fn new() -> Self { |
55 | Punctuated { |
56 | inner: Vec::new(), |
57 | last: None, |
58 | } |
59 | } |
60 | |
61 | /// Determines whether this punctuated sequence is empty, meaning it |
62 | /// contains no syntax tree nodes or punctuation. |
63 | pub fn is_empty(&self) -> bool { |
64 | self.inner.len() == 0 && self.last.is_none() |
65 | } |
66 | |
67 | /// Returns the number of syntax tree nodes in this punctuated sequence. |
68 | /// |
69 | /// This is the number of nodes of type `T`, not counting the punctuation of |
70 | /// type `P`. |
71 | pub fn len(&self) -> usize { |
72 | self.inner.len() + if self.last.is_some() { 1 } else { 0 } |
73 | } |
74 | |
75 | /// Borrows the first element in this sequence. |
76 | pub fn first(&self) -> Option<&T> { |
77 | self.iter().next() |
78 | } |
79 | |
80 | /// Mutably borrows the first element in this sequence. |
81 | pub fn first_mut(&mut self) -> Option<&mut T> { |
82 | self.iter_mut().next() |
83 | } |
84 | |
85 | /// Borrows the last element in this sequence. |
86 | pub fn last(&self) -> Option<&T> { |
87 | self.iter().next_back() |
88 | } |
89 | |
90 | /// Mutably borrows the last element in this sequence. |
91 | pub fn last_mut(&mut self) -> Option<&mut T> { |
92 | self.iter_mut().next_back() |
93 | } |
94 | |
95 | /// Borrows the element at the given index. |
96 | pub fn get(&self, index: usize) -> Option<&T> { |
97 | if let Some((value, _punct)) = self.inner.get(index) { |
98 | Some(value) |
99 | } else if index == self.inner.len() { |
100 | self.last.as_deref() |
101 | } else { |
102 | None |
103 | } |
104 | } |
105 | |
106 | /// Mutably borrows the element at the given index. |
107 | pub fn get_mut(&mut self, index: usize) -> Option<&mut T> { |
108 | let inner_len = self.inner.len(); |
109 | if let Some((value, _punct)) = self.inner.get_mut(index) { |
110 | Some(value) |
111 | } else if index == inner_len { |
112 | self.last.as_deref_mut() |
113 | } else { |
114 | None |
115 | } |
116 | } |
117 | |
118 | /// Returns an iterator over borrowed syntax tree nodes of type `&T`. |
119 | pub fn iter(&self) -> Iter<T> { |
120 | Iter { |
121 | inner: Box::new(NoDrop::new(PrivateIter { |
122 | inner: self.inner.iter(), |
123 | last: self.last.as_ref().map(Box::as_ref).into_iter(), |
124 | })), |
125 | } |
126 | } |
127 | |
128 | /// Returns an iterator over mutably borrowed syntax tree nodes of type |
129 | /// `&mut T`. |
130 | pub fn iter_mut(&mut self) -> IterMut<T> { |
131 | IterMut { |
132 | inner: Box::new(NoDrop::new(PrivateIterMut { |
133 | inner: self.inner.iter_mut(), |
134 | last: self.last.as_mut().map(Box::as_mut).into_iter(), |
135 | })), |
136 | } |
137 | } |
138 | |
139 | /// Returns an iterator over the contents of this sequence as borrowed |
140 | /// punctuated pairs. |
141 | pub fn pairs(&self) -> Pairs<T, P> { |
142 | Pairs { |
143 | inner: self.inner.iter(), |
144 | last: self.last.as_ref().map(Box::as_ref).into_iter(), |
145 | } |
146 | } |
147 | |
148 | /// Returns an iterator over the contents of this sequence as mutably |
149 | /// borrowed punctuated pairs. |
150 | pub fn pairs_mut(&mut self) -> PairsMut<T, P> { |
151 | PairsMut { |
152 | inner: self.inner.iter_mut(), |
153 | last: self.last.as_mut().map(Box::as_mut).into_iter(), |
154 | } |
155 | } |
156 | |
157 | /// Returns an iterator over the contents of this sequence as owned |
158 | /// punctuated pairs. |
159 | pub fn into_pairs(self) -> IntoPairs<T, P> { |
160 | IntoPairs { |
161 | inner: self.inner.into_iter(), |
162 | last: self.last.map(|t| *t).into_iter(), |
163 | } |
164 | } |
165 | |
166 | /// Appends a syntax tree node onto the end of this punctuated sequence. The |
167 | /// sequence must already have a trailing punctuation, or be empty. |
168 | /// |
169 | /// Use [`push`] instead if the punctuated sequence may or may not already |
170 | /// have trailing punctuation. |
171 | /// |
172 | /// [`push`]: Punctuated::push |
173 | /// |
174 | /// # Panics |
175 | /// |
176 | /// Panics if the sequence is nonempty and does not already have a trailing |
177 | /// punctuation. |
178 | pub fn push_value(&mut self, value: T) { |
179 | assert!( |
180 | self.empty_or_trailing(), |
181 | "Punctuated::push_value: cannot push value if Punctuated is missing trailing punctuation" , |
182 | ); |
183 | |
184 | self.last = Some(Box::new(value)); |
185 | } |
186 | |
187 | /// Appends a trailing punctuation onto the end of this punctuated sequence. |
188 | /// The sequence must be non-empty and must not already have trailing |
189 | /// punctuation. |
190 | /// |
191 | /// # Panics |
192 | /// |
193 | /// Panics if the sequence is empty or already has a trailing punctuation. |
194 | pub fn push_punct(&mut self, punctuation: P) { |
195 | assert!( |
196 | self.last.is_some(), |
197 | "Punctuated::push_punct: cannot push punctuation if Punctuated is empty or already has trailing punctuation" , |
198 | ); |
199 | |
200 | let last = self.last.take().unwrap(); |
201 | self.inner.push((*last, punctuation)); |
202 | } |
203 | |
204 | /// Removes the last punctuated pair from this sequence, or `None` if the |
205 | /// sequence is empty. |
206 | pub fn pop(&mut self) -> Option<Pair<T, P>> { |
207 | if self.last.is_some() { |
208 | self.last.take().map(|t| Pair::End(*t)) |
209 | } else { |
210 | self.inner.pop().map(|(t, p)| Pair::Punctuated(t, p)) |
211 | } |
212 | } |
213 | |
214 | /// Removes the trailing punctuation from this punctuated sequence, or |
215 | /// `None` if there isn't any. |
216 | pub fn pop_punct(&mut self) -> Option<P> { |
217 | if self.last.is_some() { |
218 | None |
219 | } else { |
220 | let (t, p) = self.inner.pop()?; |
221 | self.last = Some(Box::new(t)); |
222 | Some(p) |
223 | } |
224 | } |
225 | |
226 | /// Determines whether this punctuated sequence ends with a trailing |
227 | /// punctuation. |
228 | pub fn trailing_punct(&self) -> bool { |
229 | self.last.is_none() && !self.is_empty() |
230 | } |
231 | |
232 | /// Returns true if either this `Punctuated` is empty, or it has a trailing |
233 | /// punctuation. |
234 | /// |
235 | /// Equivalent to `punctuated.is_empty() || punctuated.trailing_punct()`. |
236 | pub fn empty_or_trailing(&self) -> bool { |
237 | self.last.is_none() |
238 | } |
239 | |
240 | /// Appends a syntax tree node onto the end of this punctuated sequence. |
241 | /// |
242 | /// If there is not a trailing punctuation in this sequence when this method |
243 | /// is called, the default value of punctuation type `P` is inserted before |
244 | /// the given value of type `T`. |
245 | pub fn push(&mut self, value: T) |
246 | where |
247 | P: Default, |
248 | { |
249 | if !self.empty_or_trailing() { |
250 | self.push_punct(Default::default()); |
251 | } |
252 | self.push_value(value); |
253 | } |
254 | |
255 | /// Inserts an element at position `index`. |
256 | /// |
257 | /// # Panics |
258 | /// |
259 | /// Panics if `index` is greater than the number of elements previously in |
260 | /// this punctuated sequence. |
261 | pub fn insert(&mut self, index: usize, value: T) |
262 | where |
263 | P: Default, |
264 | { |
265 | assert!( |
266 | index <= self.len(), |
267 | "Punctuated::insert: index out of range" , |
268 | ); |
269 | |
270 | if index == self.len() { |
271 | self.push(value); |
272 | } else { |
273 | self.inner.insert(index, (value, Default::default())); |
274 | } |
275 | } |
276 | |
277 | /// Clears the sequence of all values and punctuation, making it empty. |
278 | pub fn clear(&mut self) { |
279 | self.inner.clear(); |
280 | self.last = None; |
281 | } |
282 | |
283 | /// Parses zero or more occurrences of `T` separated by punctuation of type |
284 | /// `P`, with optional trailing punctuation. |
285 | /// |
286 | /// Parsing continues until the end of this parse stream. The entire content |
287 | /// of this parse stream must consist of `T` and `P`. |
288 | #[cfg (feature = "parsing" )] |
289 | #[cfg_attr (docsrs, doc(cfg(feature = "parsing" )))] |
290 | pub fn parse_terminated(input: ParseStream) -> Result<Self> |
291 | where |
292 | T: Parse, |
293 | P: Parse, |
294 | { |
295 | Self::parse_terminated_with(input, T::parse) |
296 | } |
297 | |
298 | /// Parses zero or more occurrences of `T` using the given parse function, |
299 | /// separated by punctuation of type `P`, with optional trailing |
300 | /// punctuation. |
301 | /// |
302 | /// Like [`parse_terminated`], the entire content of this stream is expected |
303 | /// to be parsed. |
304 | /// |
305 | /// [`parse_terminated`]: Punctuated::parse_terminated |
306 | #[cfg (feature = "parsing" )] |
307 | #[cfg_attr (docsrs, doc(cfg(feature = "parsing" )))] |
308 | pub fn parse_terminated_with<'a>( |
309 | input: ParseStream<'a>, |
310 | parser: fn(ParseStream<'a>) -> Result<T>, |
311 | ) -> Result<Self> |
312 | where |
313 | P: Parse, |
314 | { |
315 | let mut punctuated = Punctuated::new(); |
316 | |
317 | loop { |
318 | if input.is_empty() { |
319 | break; |
320 | } |
321 | let value = parser(input)?; |
322 | punctuated.push_value(value); |
323 | if input.is_empty() { |
324 | break; |
325 | } |
326 | let punct = input.parse()?; |
327 | punctuated.push_punct(punct); |
328 | } |
329 | |
330 | Ok(punctuated) |
331 | } |
332 | |
333 | /// Parses one or more occurrences of `T` separated by punctuation of type |
334 | /// `P`, not accepting trailing punctuation. |
335 | /// |
336 | /// Parsing continues as long as punctuation `P` is present at the head of |
337 | /// the stream. This method returns upon parsing a `T` and observing that it |
338 | /// is not followed by a `P`, even if there are remaining tokens in the |
339 | /// stream. |
340 | #[cfg (feature = "parsing" )] |
341 | #[cfg_attr (docsrs, doc(cfg(feature = "parsing" )))] |
342 | pub fn parse_separated_nonempty(input: ParseStream) -> Result<Self> |
343 | where |
344 | T: Parse, |
345 | P: Token + Parse, |
346 | { |
347 | Self::parse_separated_nonempty_with(input, T::parse) |
348 | } |
349 | |
350 | /// Parses one or more occurrences of `T` using the given parse function, |
351 | /// separated by punctuation of type `P`, not accepting trailing |
352 | /// punctuation. |
353 | /// |
354 | /// Like [`parse_separated_nonempty`], may complete early without parsing |
355 | /// the entire content of this stream. |
356 | /// |
357 | /// [`parse_separated_nonempty`]: Punctuated::parse_separated_nonempty |
358 | #[cfg (feature = "parsing" )] |
359 | #[cfg_attr (docsrs, doc(cfg(feature = "parsing" )))] |
360 | pub fn parse_separated_nonempty_with<'a>( |
361 | input: ParseStream<'a>, |
362 | parser: fn(ParseStream<'a>) -> Result<T>, |
363 | ) -> Result<Self> |
364 | where |
365 | P: Token + Parse, |
366 | { |
367 | let mut punctuated = Punctuated::new(); |
368 | |
369 | loop { |
370 | let value = parser(input)?; |
371 | punctuated.push_value(value); |
372 | if !P::peek(input.cursor()) { |
373 | break; |
374 | } |
375 | let punct = input.parse()?; |
376 | punctuated.push_punct(punct); |
377 | } |
378 | |
379 | Ok(punctuated) |
380 | } |
381 | } |
382 | |
383 | #[cfg (feature = "clone-impls" )] |
384 | #[cfg_attr (docsrs, doc(cfg(feature = "clone-impls" )))] |
385 | impl<T, P> Clone for Punctuated<T, P> |
386 | where |
387 | T: Clone, |
388 | P: Clone, |
389 | { |
390 | fn clone(&self) -> Self { |
391 | Punctuated { |
392 | inner: self.inner.clone(), |
393 | last: self.last.clone(), |
394 | } |
395 | } |
396 | |
397 | fn clone_from(&mut self, other: &Self) { |
398 | self.inner.clone_from(&other.inner); |
399 | self.last.clone_from(&other.last); |
400 | } |
401 | } |
402 | |
403 | #[cfg (feature = "extra-traits" )] |
404 | #[cfg_attr (docsrs, doc(cfg(feature = "extra-traits" )))] |
405 | impl<T, P> Eq for Punctuated<T, P> |
406 | where |
407 | T: Eq, |
408 | P: Eq, |
409 | { |
410 | } |
411 | |
412 | #[cfg (feature = "extra-traits" )] |
413 | #[cfg_attr (docsrs, doc(cfg(feature = "extra-traits" )))] |
414 | impl<T, P> PartialEq for Punctuated<T, P> |
415 | where |
416 | T: PartialEq, |
417 | P: PartialEq, |
418 | { |
419 | fn eq(&self, other: &Self) -> bool { |
420 | let Punctuated { inner: &Vec<(T, P)>, last: &Option> } = self; |
421 | *inner == other.inner && *last == other.last |
422 | } |
423 | } |
424 | |
425 | #[cfg (feature = "extra-traits" )] |
426 | #[cfg_attr (docsrs, doc(cfg(feature = "extra-traits" )))] |
427 | impl<T, P> Hash for Punctuated<T, P> |
428 | where |
429 | T: Hash, |
430 | P: Hash, |
431 | { |
432 | fn hash<H: Hasher>(&self, state: &mut H) { |
433 | let Punctuated { inner: &Vec<(T, P)>, last: &Option> } = self; |
434 | inner.hash(state); |
435 | last.hash(state); |
436 | } |
437 | } |
438 | |
439 | #[cfg (feature = "extra-traits" )] |
440 | #[cfg_attr (docsrs, doc(cfg(feature = "extra-traits" )))] |
441 | impl<T: Debug, P: Debug> Debug for Punctuated<T, P> { |
442 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
443 | let mut list: DebugList<'_, '_> = f.debug_list(); |
444 | for (t: &T, p: &P) in &self.inner { |
445 | list.entry(t); |
446 | list.entry(p); |
447 | } |
448 | if let Some(last: &Box) = &self.last { |
449 | list.entry(last); |
450 | } |
451 | list.finish() |
452 | } |
453 | } |
454 | |
455 | impl<T, P> FromIterator<T> for Punctuated<T, P> |
456 | where |
457 | P: Default, |
458 | { |
459 | fn from_iter<I: IntoIterator<Item = T>>(i: I) -> Self { |
460 | let mut ret: Punctuated = Punctuated::new(); |
461 | ret.extend(iter:i); |
462 | ret |
463 | } |
464 | } |
465 | |
466 | impl<T, P> Extend<T> for Punctuated<T, P> |
467 | where |
468 | P: Default, |
469 | { |
470 | fn extend<I: IntoIterator<Item = T>>(&mut self, i: I) { |
471 | for value: T in i { |
472 | self.push(value); |
473 | } |
474 | } |
475 | } |
476 | |
477 | impl<T, P> FromIterator<Pair<T, P>> for Punctuated<T, P> { |
478 | fn from_iter<I: IntoIterator<Item = Pair<T, P>>>(i: I) -> Self { |
479 | let mut ret: Punctuated = Punctuated::new(); |
480 | do_extend(&mut ret, i.into_iter()); |
481 | ret |
482 | } |
483 | } |
484 | |
485 | impl<T, P> Extend<Pair<T, P>> for Punctuated<T, P> |
486 | where |
487 | P: Default, |
488 | { |
489 | fn extend<I: IntoIterator<Item = Pair<T, P>>>(&mut self, i: I) { |
490 | if !self.empty_or_trailing() { |
491 | self.push_punct(P::default()); |
492 | } |
493 | do_extend(self, i.into_iter()); |
494 | } |
495 | } |
496 | |
497 | fn do_extend<T, P, I>(punctuated: &mut Punctuated<T, P>, i: I) |
498 | where |
499 | I: Iterator<Item = Pair<T, P>>, |
500 | { |
501 | let mut nomore: bool = false; |
502 | for pair: Pair in i { |
503 | if nomore { |
504 | panic!("punctuated extended with items after a Pair::End" ); |
505 | } |
506 | match pair { |
507 | Pair::Punctuated(a: T, b: P) => punctuated.inner.push((a, b)), |
508 | Pair::End(a: T) => { |
509 | punctuated.last = Some(Box::new(a)); |
510 | nomore = true; |
511 | } |
512 | } |
513 | } |
514 | } |
515 | |
516 | impl<T, P> IntoIterator for Punctuated<T, P> { |
517 | type Item = T; |
518 | type IntoIter = IntoIter<T>; |
519 | |
520 | fn into_iter(self) -> Self::IntoIter { |
521 | let mut elements: Vec = Vec::with_capacity(self.len()); |
522 | elements.extend(self.inner.into_iter().map(|pair: (T, P)| pair.0)); |
523 | elements.extend(self.last.map(|t: Box| *t)); |
524 | |
525 | IntoIter { |
526 | inner: elements.into_iter(), |
527 | } |
528 | } |
529 | } |
530 | |
531 | impl<'a, T, P> IntoIterator for &'a Punctuated<T, P> { |
532 | type Item = &'a T; |
533 | type IntoIter = Iter<'a, T>; |
534 | |
535 | fn into_iter(self) -> Self::IntoIter { |
536 | Punctuated::iter(self) |
537 | } |
538 | } |
539 | |
540 | impl<'a, T, P> IntoIterator for &'a mut Punctuated<T, P> { |
541 | type Item = &'a mut T; |
542 | type IntoIter = IterMut<'a, T>; |
543 | |
544 | fn into_iter(self) -> Self::IntoIter { |
545 | Punctuated::iter_mut(self) |
546 | } |
547 | } |
548 | |
549 | impl<T, P> Default for Punctuated<T, P> { |
550 | fn default() -> Self { |
551 | Punctuated::new() |
552 | } |
553 | } |
554 | |
555 | /// An iterator over borrowed pairs of type `Pair<&T, &P>`. |
556 | /// |
557 | /// Refer to the [module documentation] for details about punctuated sequences. |
558 | /// |
559 | /// [module documentation]: self |
560 | pub struct Pairs<'a, T: 'a, P: 'a> { |
561 | inner: slice::Iter<'a, (T, P)>, |
562 | last: option::IntoIter<&'a T>, |
563 | } |
564 | |
565 | impl<'a, T, P> Iterator for Pairs<'a, T, P> { |
566 | type Item = Pair<&'a T, &'a P>; |
567 | |
568 | fn next(&mut self) -> Option<Self::Item> { |
569 | self.inner |
570 | .next() |
571 | .map(|(t: &T, p: &P)| Pair::Punctuated(t, p)) |
572 | .or_else(|| self.last.next().map(Pair::End)) |
573 | } |
574 | |
575 | fn size_hint(&self) -> (usize, Option<usize>) { |
576 | (self.len(), Some(self.len())) |
577 | } |
578 | } |
579 | |
580 | impl<'a, T, P> DoubleEndedIterator for Pairs<'a, T, P> { |
581 | fn next_back(&mut self) -> Option<Self::Item> { |
582 | self.last |
583 | .next() |
584 | .map(Pair::End) |
585 | .or_else(|| self.inner.next_back().map(|(t: &T, p: &P)| Pair::Punctuated(t, p))) |
586 | } |
587 | } |
588 | |
589 | impl<'a, T, P> ExactSizeIterator for Pairs<'a, T, P> { |
590 | fn len(&self) -> usize { |
591 | self.inner.len() + self.last.len() |
592 | } |
593 | } |
594 | |
595 | // No Clone bound on T or P. |
596 | impl<'a, T, P> Clone for Pairs<'a, T, P> { |
597 | fn clone(&self) -> Self { |
598 | Pairs { |
599 | inner: self.inner.clone(), |
600 | last: self.last.clone(), |
601 | } |
602 | } |
603 | } |
604 | |
605 | /// An iterator over mutably borrowed pairs of type `Pair<&mut T, &mut P>`. |
606 | /// |
607 | /// Refer to the [module documentation] for details about punctuated sequences. |
608 | /// |
609 | /// [module documentation]: self |
610 | pub struct PairsMut<'a, T: 'a, P: 'a> { |
611 | inner: slice::IterMut<'a, (T, P)>, |
612 | last: option::IntoIter<&'a mut T>, |
613 | } |
614 | |
615 | impl<'a, T, P> Iterator for PairsMut<'a, T, P> { |
616 | type Item = Pair<&'a mut T, &'a mut P>; |
617 | |
618 | fn next(&mut self) -> Option<Self::Item> { |
619 | self.inner |
620 | .next() |
621 | .map(|(t: &mut T, p: &mut P)| Pair::Punctuated(t, p)) |
622 | .or_else(|| self.last.next().map(Pair::End)) |
623 | } |
624 | |
625 | fn size_hint(&self) -> (usize, Option<usize>) { |
626 | (self.len(), Some(self.len())) |
627 | } |
628 | } |
629 | |
630 | impl<'a, T, P> DoubleEndedIterator for PairsMut<'a, T, P> { |
631 | fn next_back(&mut self) -> Option<Self::Item> { |
632 | self.last |
633 | .next() |
634 | .map(Pair::End) |
635 | .or_else(|| self.inner.next_back().map(|(t: &mut T, p: &mut P)| Pair::Punctuated(t, p))) |
636 | } |
637 | } |
638 | |
639 | impl<'a, T, P> ExactSizeIterator for PairsMut<'a, T, P> { |
640 | fn len(&self) -> usize { |
641 | self.inner.len() + self.last.len() |
642 | } |
643 | } |
644 | |
645 | /// An iterator over owned pairs of type `Pair<T, P>`. |
646 | /// |
647 | /// Refer to the [module documentation] for details about punctuated sequences. |
648 | /// |
649 | /// [module documentation]: self |
650 | pub struct IntoPairs<T, P> { |
651 | inner: vec::IntoIter<(T, P)>, |
652 | last: option::IntoIter<T>, |
653 | } |
654 | |
655 | impl<T, P> Iterator for IntoPairs<T, P> { |
656 | type Item = Pair<T, P>; |
657 | |
658 | fn next(&mut self) -> Option<Self::Item> { |
659 | self.inner |
660 | .next() |
661 | .map(|(t: T, p: P)| Pair::Punctuated(t, p)) |
662 | .or_else(|| self.last.next().map(Pair::End)) |
663 | } |
664 | |
665 | fn size_hint(&self) -> (usize, Option<usize>) { |
666 | (self.len(), Some(self.len())) |
667 | } |
668 | } |
669 | |
670 | impl<T, P> DoubleEndedIterator for IntoPairs<T, P> { |
671 | fn next_back(&mut self) -> Option<Self::Item> { |
672 | self.last |
673 | .next() |
674 | .map(Pair::End) |
675 | .or_else(|| self.inner.next_back().map(|(t: T, p: P)| Pair::Punctuated(t, p))) |
676 | } |
677 | } |
678 | |
679 | impl<T, P> ExactSizeIterator for IntoPairs<T, P> { |
680 | fn len(&self) -> usize { |
681 | self.inner.len() + self.last.len() |
682 | } |
683 | } |
684 | |
685 | impl<T, P> Clone for IntoPairs<T, P> |
686 | where |
687 | T: Clone, |
688 | P: Clone, |
689 | { |
690 | fn clone(&self) -> Self { |
691 | IntoPairs { |
692 | inner: self.inner.clone(), |
693 | last: self.last.clone(), |
694 | } |
695 | } |
696 | } |
697 | |
698 | /// An iterator over owned values of type `T`. |
699 | /// |
700 | /// Refer to the [module documentation] for details about punctuated sequences. |
701 | /// |
702 | /// [module documentation]: self |
703 | pub struct IntoIter<T> { |
704 | inner: vec::IntoIter<T>, |
705 | } |
706 | |
707 | impl<T> Iterator for IntoIter<T> { |
708 | type Item = T; |
709 | |
710 | fn next(&mut self) -> Option<Self::Item> { |
711 | self.inner.next() |
712 | } |
713 | |
714 | fn size_hint(&self) -> (usize, Option<usize>) { |
715 | (self.len(), Some(self.len())) |
716 | } |
717 | } |
718 | |
719 | impl<T> DoubleEndedIterator for IntoIter<T> { |
720 | fn next_back(&mut self) -> Option<Self::Item> { |
721 | self.inner.next_back() |
722 | } |
723 | } |
724 | |
725 | impl<T> ExactSizeIterator for IntoIter<T> { |
726 | fn len(&self) -> usize { |
727 | self.inner.len() |
728 | } |
729 | } |
730 | |
731 | impl<T> Clone for IntoIter<T> |
732 | where |
733 | T: Clone, |
734 | { |
735 | fn clone(&self) -> Self { |
736 | IntoIter { |
737 | inner: self.inner.clone(), |
738 | } |
739 | } |
740 | } |
741 | |
742 | /// An iterator over borrowed values of type `&T`. |
743 | /// |
744 | /// Refer to the [module documentation] for details about punctuated sequences. |
745 | /// |
746 | /// [module documentation]: self |
747 | pub struct Iter<'a, T: 'a> { |
748 | inner: Box<NoDrop<dyn IterTrait<'a, T> + 'a>>, |
749 | } |
750 | |
751 | trait IterTrait<'a, T: 'a>: Iterator<Item = &'a T> + DoubleEndedIterator + ExactSizeIterator { |
752 | fn clone_box(&self) -> Box<NoDrop<dyn IterTrait<'a, T> + 'a>>; |
753 | } |
754 | |
755 | struct PrivateIter<'a, T: 'a, P: 'a> { |
756 | inner: slice::Iter<'a, (T, P)>, |
757 | last: option::IntoIter<&'a T>, |
758 | } |
759 | |
760 | impl<'a, T, P> TrivialDrop for PrivateIter<'a, T, P> |
761 | where |
762 | slice::Iter<'a, (T, P)>: TrivialDrop, |
763 | option::IntoIter<&'a T>: TrivialDrop, |
764 | { |
765 | } |
766 | |
767 | #[cfg (any(feature = "full" , feature = "derive" ))] |
768 | pub(crate) fn empty_punctuated_iter<'a, T>() -> Iter<'a, T> { |
769 | Iter { |
770 | inner: Box::new(NoDrop::new(iter::empty())), |
771 | } |
772 | } |
773 | |
774 | // No Clone bound on T. |
775 | impl<'a, T> Clone for Iter<'a, T> { |
776 | fn clone(&self) -> Self { |
777 | Iter { |
778 | inner: self.inner.clone_box(), |
779 | } |
780 | } |
781 | } |
782 | |
783 | impl<'a, T> Iterator for Iter<'a, T> { |
784 | type Item = &'a T; |
785 | |
786 | fn next(&mut self) -> Option<Self::Item> { |
787 | self.inner.next() |
788 | } |
789 | |
790 | fn size_hint(&self) -> (usize, Option<usize>) { |
791 | (self.len(), Some(self.len())) |
792 | } |
793 | } |
794 | |
795 | impl<'a, T> DoubleEndedIterator for Iter<'a, T> { |
796 | fn next_back(&mut self) -> Option<Self::Item> { |
797 | self.inner.next_back() |
798 | } |
799 | } |
800 | |
801 | impl<'a, T> ExactSizeIterator for Iter<'a, T> { |
802 | fn len(&self) -> usize { |
803 | self.inner.len() |
804 | } |
805 | } |
806 | |
807 | impl<'a, T, P> Iterator for PrivateIter<'a, T, P> { |
808 | type Item = &'a T; |
809 | |
810 | fn next(&mut self) -> Option<Self::Item> { |
811 | self.inner |
812 | .next() |
813 | .map(|pair: &'a (T, P)| &pair.0) |
814 | .or_else(|| self.last.next()) |
815 | } |
816 | } |
817 | |
818 | impl<'a, T, P> DoubleEndedIterator for PrivateIter<'a, T, P> { |
819 | fn next_back(&mut self) -> Option<Self::Item> { |
820 | self.last |
821 | .next() |
822 | .or_else(|| self.inner.next_back().map(|pair: &'a (T, P)| &pair.0)) |
823 | } |
824 | } |
825 | |
826 | impl<'a, T, P> ExactSizeIterator for PrivateIter<'a, T, P> { |
827 | fn len(&self) -> usize { |
828 | self.inner.len() + self.last.len() |
829 | } |
830 | } |
831 | |
832 | // No Clone bound on T or P. |
833 | impl<'a, T, P> Clone for PrivateIter<'a, T, P> { |
834 | fn clone(&self) -> Self { |
835 | PrivateIter { |
836 | inner: self.inner.clone(), |
837 | last: self.last.clone(), |
838 | } |
839 | } |
840 | } |
841 | |
842 | impl<'a, T, I> IterTrait<'a, T> for I |
843 | where |
844 | T: 'a, |
845 | I: DoubleEndedIterator<Item = &'a T> |
846 | + ExactSizeIterator<Item = &'a T> |
847 | + Clone |
848 | + TrivialDrop |
849 | + 'a, |
850 | { |
851 | fn clone_box(&self) -> Box<NoDrop<dyn IterTrait<'a, T> + 'a>> { |
852 | Box::new(NoDrop::new(self.clone())) |
853 | } |
854 | } |
855 | |
856 | /// An iterator over mutably borrowed values of type `&mut T`. |
857 | /// |
858 | /// Refer to the [module documentation] for details about punctuated sequences. |
859 | /// |
860 | /// [module documentation]: self |
861 | pub struct IterMut<'a, T: 'a> { |
862 | inner: Box<NoDrop<dyn IterMutTrait<'a, T, Item = &'a mut T> + 'a>>, |
863 | } |
864 | |
865 | trait IterMutTrait<'a, T: 'a>: |
866 | DoubleEndedIterator<Item = &'a mut T> + ExactSizeIterator<Item = &'a mut T> |
867 | { |
868 | } |
869 | |
870 | struct PrivateIterMut<'a, T: 'a, P: 'a> { |
871 | inner: slice::IterMut<'a, (T, P)>, |
872 | last: option::IntoIter<&'a mut T>, |
873 | } |
874 | |
875 | impl<'a, T, P> TrivialDrop for PrivateIterMut<'a, T, P> |
876 | where |
877 | slice::IterMut<'a, (T, P)>: TrivialDrop, |
878 | option::IntoIter<&'a mut T>: TrivialDrop, |
879 | { |
880 | } |
881 | |
882 | #[cfg (any(feature = "full" , feature = "derive" ))] |
883 | pub(crate) fn empty_punctuated_iter_mut<'a, T>() -> IterMut<'a, T> { |
884 | IterMut { |
885 | inner: Box::new(NoDrop::new(iter::empty())), |
886 | } |
887 | } |
888 | |
889 | impl<'a, T> Iterator for IterMut<'a, T> { |
890 | type Item = &'a mut T; |
891 | |
892 | fn next(&mut self) -> Option<Self::Item> { |
893 | self.inner.next() |
894 | } |
895 | |
896 | fn size_hint(&self) -> (usize, Option<usize>) { |
897 | (self.len(), Some(self.len())) |
898 | } |
899 | } |
900 | |
901 | impl<'a, T> DoubleEndedIterator for IterMut<'a, T> { |
902 | fn next_back(&mut self) -> Option<Self::Item> { |
903 | self.inner.next_back() |
904 | } |
905 | } |
906 | |
907 | impl<'a, T> ExactSizeIterator for IterMut<'a, T> { |
908 | fn len(&self) -> usize { |
909 | self.inner.len() |
910 | } |
911 | } |
912 | |
913 | impl<'a, T, P> Iterator for PrivateIterMut<'a, T, P> { |
914 | type Item = &'a mut T; |
915 | |
916 | fn next(&mut self) -> Option<Self::Item> { |
917 | self.inner |
918 | .next() |
919 | .map(|pair: &'a mut (T, P)| &mut pair.0) |
920 | .or_else(|| self.last.next()) |
921 | } |
922 | } |
923 | |
924 | impl<'a, T, P> DoubleEndedIterator for PrivateIterMut<'a, T, P> { |
925 | fn next_back(&mut self) -> Option<Self::Item> { |
926 | self.last |
927 | .next() |
928 | .or_else(|| self.inner.next_back().map(|pair: &'a mut (T, P)| &mut pair.0)) |
929 | } |
930 | } |
931 | |
932 | impl<'a, T, P> ExactSizeIterator for PrivateIterMut<'a, T, P> { |
933 | fn len(&self) -> usize { |
934 | self.inner.len() + self.last.len() |
935 | } |
936 | } |
937 | |
938 | impl<'a, T, I> IterMutTrait<'a, T> for I |
939 | where |
940 | T: 'a, |
941 | I: DoubleEndedIterator<Item = &'a mut T> + ExactSizeIterator<Item = &'a mut T> + 'a, |
942 | { |
943 | } |
944 | |
945 | /// A single syntax tree node of type `T` followed by its trailing punctuation |
946 | /// of type `P` if any. |
947 | /// |
948 | /// Refer to the [module documentation] for details about punctuated sequences. |
949 | /// |
950 | /// [module documentation]: self |
951 | pub enum Pair<T, P> { |
952 | Punctuated(T, P), |
953 | End(T), |
954 | } |
955 | |
956 | impl<T, P> Pair<T, P> { |
957 | /// Extracts the syntax tree node from this punctuated pair, discarding the |
958 | /// following punctuation. |
959 | pub fn into_value(self) -> T { |
960 | match self { |
961 | Pair::Punctuated(t, _) | Pair::End(t) => t, |
962 | } |
963 | } |
964 | |
965 | /// Borrows the syntax tree node from this punctuated pair. |
966 | pub fn value(&self) -> &T { |
967 | match self { |
968 | Pair::Punctuated(t, _) | Pair::End(t) => t, |
969 | } |
970 | } |
971 | |
972 | /// Mutably borrows the syntax tree node from this punctuated pair. |
973 | pub fn value_mut(&mut self) -> &mut T { |
974 | match self { |
975 | Pair::Punctuated(t, _) | Pair::End(t) => t, |
976 | } |
977 | } |
978 | |
979 | /// Borrows the punctuation from this punctuated pair, unless this pair is |
980 | /// the final one and there is no trailing punctuation. |
981 | pub fn punct(&self) -> Option<&P> { |
982 | match self { |
983 | Pair::Punctuated(_, p) => Some(p), |
984 | Pair::End(_) => None, |
985 | } |
986 | } |
987 | |
988 | /// Mutably borrows the punctuation from this punctuated pair, unless the |
989 | /// pair is the final one and there is no trailing punctuation. |
990 | /// |
991 | /// # Example |
992 | /// |
993 | /// ``` |
994 | /// # use proc_macro2::Span; |
995 | /// # use syn::punctuated::Punctuated; |
996 | /// # use syn::{parse_quote, Token, TypeParamBound}; |
997 | /// # |
998 | /// # let mut punctuated = Punctuated::<TypeParamBound, Token![+]>::new(); |
999 | /// # let span = Span::call_site(); |
1000 | /// # |
1001 | /// punctuated.insert(0, parse_quote!('lifetime)); |
1002 | /// if let Some(punct) = punctuated.pairs_mut().next().unwrap().punct_mut() { |
1003 | /// punct.span = span; |
1004 | /// } |
1005 | /// ``` |
1006 | pub fn punct_mut(&mut self) -> Option<&mut P> { |
1007 | match self { |
1008 | Pair::Punctuated(_, p) => Some(p), |
1009 | Pair::End(_) => None, |
1010 | } |
1011 | } |
1012 | |
1013 | /// Creates a punctuated pair out of a syntax tree node and an optional |
1014 | /// following punctuation. |
1015 | pub fn new(t: T, p: Option<P>) -> Self { |
1016 | match p { |
1017 | Some(p) => Pair::Punctuated(t, p), |
1018 | None => Pair::End(t), |
1019 | } |
1020 | } |
1021 | |
1022 | /// Produces this punctuated pair as a tuple of syntax tree node and |
1023 | /// optional following punctuation. |
1024 | pub fn into_tuple(self) -> (T, Option<P>) { |
1025 | match self { |
1026 | Pair::Punctuated(t, p) => (t, Some(p)), |
1027 | Pair::End(t) => (t, None), |
1028 | } |
1029 | } |
1030 | } |
1031 | |
1032 | #[cfg (feature = "clone-impls" )] |
1033 | #[cfg_attr (docsrs, doc(cfg(feature = "clone-impls" )))] |
1034 | impl<T, P> Pair<&T, &P> { |
1035 | pub fn cloned(self) -> Pair<T, P> |
1036 | where |
1037 | T: Clone, |
1038 | P: Clone, |
1039 | { |
1040 | match self { |
1041 | Pair::Punctuated(t: &T, p: &P) => Pair::Punctuated(t.clone(), p.clone()), |
1042 | Pair::End(t: &T) => Pair::End(t.clone()), |
1043 | } |
1044 | } |
1045 | } |
1046 | |
1047 | #[cfg (feature = "clone-impls" )] |
1048 | #[cfg_attr (docsrs, doc(cfg(feature = "clone-impls" )))] |
1049 | impl<T, P> Clone for Pair<T, P> |
1050 | where |
1051 | T: Clone, |
1052 | P: Clone, |
1053 | { |
1054 | fn clone(&self) -> Self { |
1055 | match self { |
1056 | Pair::Punctuated(t: &T, p: &P) => Pair::Punctuated(t.clone(), p.clone()), |
1057 | Pair::End(t: &T) => Pair::End(t.clone()), |
1058 | } |
1059 | } |
1060 | } |
1061 | |
1062 | #[cfg (feature = "clone-impls" )] |
1063 | #[cfg_attr (docsrs, doc(cfg(feature = "clone-impls" )))] |
1064 | impl<T, P> Copy for Pair<T, P> |
1065 | where |
1066 | T: Copy, |
1067 | P: Copy, |
1068 | { |
1069 | } |
1070 | |
1071 | impl<T, P> Index<usize> for Punctuated<T, P> { |
1072 | type Output = T; |
1073 | |
1074 | fn index(&self, index: usize) -> &Self::Output { |
1075 | if index == self.len() - 1 { |
1076 | match &self.last { |
1077 | Some(t: &Box) => t, |
1078 | None => &self.inner[index].0, |
1079 | } |
1080 | } else { |
1081 | &self.inner[index].0 |
1082 | } |
1083 | } |
1084 | } |
1085 | |
1086 | impl<T, P> IndexMut<usize> for Punctuated<T, P> { |
1087 | fn index_mut(&mut self, index: usize) -> &mut Self::Output { |
1088 | if index == self.len() - 1 { |
1089 | match &mut self.last { |
1090 | Some(t: &mut Box) => t, |
1091 | None => &mut self.inner[index].0, |
1092 | } |
1093 | } else { |
1094 | &mut self.inner[index].0 |
1095 | } |
1096 | } |
1097 | } |
1098 | |
1099 | #[cfg (all(feature = "fold" , any(feature = "full" , feature = "derive" )))] |
1100 | pub(crate) fn fold<T, P, V, F>( |
1101 | punctuated: Punctuated<T, P>, |
1102 | fold: &mut V, |
1103 | mut f: F, |
1104 | ) -> Punctuated<T, P> |
1105 | where |
1106 | V: ?Sized, |
1107 | F: FnMut(&mut V, T) -> T, |
1108 | { |
1109 | Punctuated { |
1110 | inner: punctuatedimpl Iterator |
1111 | .inner |
1112 | .into_iter() |
1113 | .map(|(t: T, p: P)| (f(fold, t), p)) |
1114 | .collect(), |
1115 | last: match punctuated.last { |
1116 | Some(t: Box) => Some(Box::new(f(fold, *t))), |
1117 | None => None, |
1118 | }, |
1119 | } |
1120 | } |
1121 | |
1122 | #[cfg (feature = "printing" )] |
1123 | mod printing { |
1124 | use crate::punctuated::{Pair, Punctuated}; |
1125 | use proc_macro2::TokenStream; |
1126 | use quote::{ToTokens, TokenStreamExt}; |
1127 | |
1128 | #[cfg_attr (docsrs, doc(cfg(feature = "printing" )))] |
1129 | impl<T, P> ToTokens for Punctuated<T, P> |
1130 | where |
1131 | T: ToTokens, |
1132 | P: ToTokens, |
1133 | { |
1134 | fn to_tokens(&self, tokens: &mut TokenStream) { |
1135 | tokens.append_all(self.pairs()); |
1136 | } |
1137 | } |
1138 | |
1139 | #[cfg_attr (docsrs, doc(cfg(feature = "printing" )))] |
1140 | impl<T, P> ToTokens for Pair<T, P> |
1141 | where |
1142 | T: ToTokens, |
1143 | P: ToTokens, |
1144 | { |
1145 | fn to_tokens(&self, tokens: &mut TokenStream) { |
1146 | match self { |
1147 | Pair::Punctuated(a, b) => { |
1148 | a.to_tokens(tokens); |
1149 | b.to_tokens(tokens); |
1150 | } |
1151 | Pair::End(a) => a.to_tokens(tokens), |
1152 | } |
1153 | } |
1154 | } |
1155 | } |
1156 | |