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