// SPDX-License-Identifier: Apache-2.0 OR MIT
//! A punctuated sequence of syntax tree nodes separated by punctuation.
//!
//! Lots of things in Rust are punctuated sequences.
//!
//! - The fields of a struct are `Punctuated<Field, Token![,]>`.
//! - The segments of a path are `Punctuated<PathSegment, Token![::]>`.
//! - The bounds on a generic parameter are `Punctuated<TypeParamBound,
//! Token![+]>`.
//! - The arguments to a function call are `Punctuated<Expr, Token![,]>`.
//!
//! This module provides a common representation for these punctuated sequences
//! in the form of the [`Punctuated<T, P>`] type. We store a vector of pairs of
//! syntax tree node + punctuation, where every node in the sequence is followed
//! by punctuation except for possibly the final one.
//!
//! [`Punctuated<T, P>`]: Punctuated
//!
//! ```text
//! a_function_call(arg1, arg2, arg3);
//! ~~~~^ ~~~~^ ~~~~
//! ```
use crate::drops::{NoDrop, TrivialDrop};
#[cfg(feature = "parsing")]
use crate::error::Result;
#[cfg(feature = "parsing")]
use crate::parse::{Parse, ParseStream};
#[cfg(feature = "parsing")]
use crate::token::Token;
#[cfg(feature = "extra-traits")]
use std::fmt::{self, Debug};
#[cfg(feature = "extra-traits")]
use std::hash::{Hash, Hasher};
#[cfg(any(feature = "full", feature = "derive"))]
use std::iter;
use std::ops::{Index, IndexMut};
use std::option;
use std::slice;
use std::vec;
/// **A punctuated sequence of syntax tree nodes of type `T` separated by
/// punctuation of type `P`.**
///
/// Refer to the [module documentation] for details about punctuated sequences.
///
/// [module documentation]: self
pub struct Punctuated<T, P> {
inner: Vec<(T, P)>,
last: Option<Box<T>>,
}
impl<T, P> Punctuated<T, P> {
/// Creates an empty punctuated sequence.
pub const fn new() -> Self {
Punctuated {
inner: Vec::new(),
last: None,
}
}
/// Determines whether this punctuated sequence is empty, meaning it
/// contains no syntax tree nodes or punctuation.
pub fn is_empty(&self) -> bool {
self.inner.len() == 0 && self.last.is_none()
}
/// Returns the number of syntax tree nodes in this punctuated sequence.
///
/// This is the number of nodes of type `T`, not counting the punctuation of
/// type `P`.
pub fn len(&self) -> usize {
self.inner.len() + if self.last.is_some() { 1 } else { 0 }
}
/// Borrows the first element in this sequence.
pub fn first(&self) -> Option<&T> {
self.iter().next()
}
/// Mutably borrows the first element in this sequence.
pub fn first_mut(&mut self) -> Option<&mut T> {
self.iter_mut().next()
}
/// Borrows the last element in this sequence.
pub fn last(&self) -> Option<&T> {
self.iter().next_back()
}
/// Mutably borrows the last element in this sequence.
pub fn last_mut(&mut self) -> Option<&mut T> {
self.iter_mut().next_back()
}
/// Borrows the element at the given index.
pub fn get(&self, index: usize) -> Option<&T> {
if let Some((value, _punct)) = self.inner.get(index) {
Some(value)
} else if index == self.inner.len() {
self.last.as_deref()
} else {
None
}
}
/// Mutably borrows the element at the given