# End in syn::parse - Rust
Pseudo-token used for peeking the end of a parse stream.

syn::parse

# Struct End

Source

    pub struct End;

Expand description

Pseudo-token used for peeking the end of a parse stream.

This type is only useful as an argument to one of the following functions:

- `ParseStream::peek`
- `ParseStream::peek2`
- `ParseStream::peek3`
- `Lookahead1::peek`

The peek will return `true` if there are no remaining tokens after that point in the parse stream.

## §Example

Suppose we are parsing attributes containing core::fmt inspired formatting arguments:

- `#[fmt("simple example")]`
- `#[fmt("interpolation e{}ample", self.x)]`
- `#[fmt("interpolation e{x}ample")]`

and we want to recognize the cases where no interpolation occurs so that more efficient code can be generated.

The following implementation uses `input.peek(Token![,]) && input.peek2(End)` to recognize the case of a trailing comma without consuming the comma from the parse stream, because if it isn’t a trailing comma, that same comma needs to be parsed as part of `args`.

    use proc_macro2::TokenStream;
    use quote::quote;
    use syn::parse::{End, Parse, ParseStream, Result};
    use syn::{parse_quote, Attribute, LitStr, Token};

    struct FormatArgs {
        template: LitStr,  // "...{}..."
        args: TokenStream, // , self.x
    }

    impl Parse for FormatArgs {
        fn parse(input: ParseStream) -> Result<Self> {
            let template: LitStr = input.parse()?;

            let args = if input.is_empty()
                || input.peek(Token![,]) && input.peek2(End)
            {
                input.parse::<Option<Token![,]>>()?;
                TokenStream::new()
            } else {
                input.parse()?
            };

            Ok(FormatArgs {
                template,
                args,
            })
        }
    }

    fn main() -> Result<()> {
        let attrs: Vec<Attribute> = parse_quote! {
            #[fmt("simple example")]
            #[fmt("interpolation e{}ample", self.x)]
            #[fmt("interpolation e{x}ample")]
        };

        for attr in &attrs {
            let FormatArgs { template, args } = attr.parse_args()?;
            let requires_fmt_machinery =
                !args.is_empty() || template.value().contains(['{', '}']);
            let out = if requires_fmt_machinery {
                quote! {
                    ::core::write!(__formatter, #template #args)
                }
            } else {
                quote! {
                    __formatter.write_str(#template)
                }
            };
            println!("{}", out);
        }
        Ok(())
    }

Implementing this parsing logic without `peek2(End)` is more clumsy because we’d need a parse stream actually advanced past the comma before being able to find out whether there is anything after it. It would look something like:

    use syn::parse::discouraged::Speculative as _;

    let ahead = input.fork();
    ahead.parse::<Option<Token![,]>>()?;
    let args = if ahead.is_empty() {
        input.advance_to(&ahead);
        TokenStream::new()
    } else {
        input.parse()?
    };

or:

    use quote::ToTokens as _;

    let comma: Option<Token![,]> = input.parse()?;
    let mut args = TokenStream::new();
    if !input.is_empty() {
        comma.to_tokens(&mut args);
        input.parse::<TokenStream>()?.to_tokens(&mut args);
    }

## Trait Implementations§

Source §

### impl Clone for End

Source §

#### fn clone(&self) -> Self

Returns a copy of the value. Read more
1.0.0 · Source §

#### fn clone_from(&mut self, source: &Self)

Performs copy-assignment from `source`. Read more
Source §

### impl Copy for End

Source §

### impl Peek for End

## Auto Trait Implementations§

§

### impl Freeze for End

§

### impl RefUnwindSafe for End

§

### impl Send for End

§

### impl Sync for End

§

### impl Unpin for End

§

### impl UnwindSafe for End

## Blanket Implementations§

Source §

### impl<T> Any for T
where T: 'static + ?Sized,

Source §

#### fn type_id(&self) -> TypeId

Gets the `TypeId` of `self`. Read more
Source §

### impl<T> Borrow<T> for T
where T: ?Sized,

Source §

#### fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source §

### impl<T> BorrowMut<T> for T
where T: ?Sized,

Source §

#### fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source §

### impl<T> CloneToUninit for T
where T: Clone,

Source §

#### unsafe fn clone_to_uninit(&self, dst: *mut u8)

🔬This is a nightly-only experimental API. (`clone_to_uninit`)
Performs copy-assignment from `self` to `dst`. Read more
Source §

### impl<T> From<T> for T

Source §

#### fn from(t: T) -> T

Returns the argument unchanged.

Source §

### impl<T, U> Into<U> for T
where U: From<T>,

Source §

#### fn into(self) -> U

Calls `U::from(self)`.

That is, this conversion is whatever the implementation of `From<T> for U` chooses to do.

Source §

### impl<T> ToOwned for T
where T: Clone,

Source §

#### type Owned = T

The resulting type after obtaining ownership.
Source §

#### fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source §

#### fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source §

### impl<T> Token for T
where T: CustomToken,

Source §

#### fn peek(cursor: Cursor<'_>) -> bool

Source §

#### fn display() -> &'static str

Source §

### impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source §

#### type Error = Infallible

The type returned in the event of a conversion error.
Source §

#### fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source §

### impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source §

#### type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source §

#### fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.