File: repeat.rs

package info (click to toggle)
rustc 1.85.0%2Bdfsg3-1
  • links: PTS, VCS
  • area: main
  • in suites: experimental, forky, sid, trixie
  • size: 893,396 kB
  • sloc: xml: 158,127; python: 35,830; javascript: 19,497; cpp: 19,002; sh: 17,245; ansic: 13,127; asm: 4,376; makefile: 1,051; perl: 29; lisp: 29; ruby: 19; sql: 11
file content (49 lines) | stat: -rw-r--r-- 1,712 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
extern crate proc_macro;
use proc_macro::{Ident, Group, TokenStream, TokenTree as Tt};

// This constant has to be above the ALLOCATING_ALGO_THRESHOLD
// constant in inherent_impls_overlap.rs
const REPEAT_COUNT: u32 = 501;

#[proc_macro]
/// Repeats the input many times, while replacing idents
/// named "IDENT" with "id_$v", where v is a counter.
pub fn repeat_with_idents(input: TokenStream) -> TokenStream {
    let mut res = Vec::new();
    fn visit_stream(res: &mut Vec<Tt>, stream :TokenStream, v: u32) {
        let mut stream_iter = stream.into_iter();
        while let Some(tt) = stream_iter.next() {
            match tt {
                Tt::Group(group) => {
                    let tt = Tt::Group(visit_group(group, v));
                    res.push(tt);
                },
                Tt::Ident(id) => {
                    let id = if &id.to_string() == "IDENT" {
                        Ident::new(&format!("id_{}", v), id.span())
                    } else {
                        id
                    };
                    res.push(Tt::Ident(id));
                },
                Tt::Punct(p) => {
                    res.push(Tt::Punct(p));
                },
                Tt::Literal(lit) => {
                    res.push(Tt::Literal(lit));
                },
            }
        }
    }
    fn visit_group(group :Group, v: u32) -> Group {
        let mut res = Vec::new();
        visit_stream(&mut res, group.stream(), v);
        let stream = res.into_iter().collect();
        let delim = group.delimiter();
        Group::new(delim, stream)
    }
    for v in 0 .. REPEAT_COUNT {
        visit_stream(&mut res, input.clone(), v)
    }
    res.into_iter().collect()
}