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