tstr_proc_macros/
nested_tuple_compute.rs

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
50
51
//! Wraps the input type in nested tuples

use crate::{
    used_proc_macro::{Span, TokenStream},
    utils::{paren, punct_token},
};

use std::iter;

#[cfg(test)]
mod tests;

#[must_use]
pub(crate) fn compute<T, F>(input: &[T], span: Span, func: &mut F) -> TokenStream
where
    F: FnMut(&[T], &mut TokenStream),
{
    let mut out = TokenStream::new();

    if input.is_empty() {
        out.extend(std::iter::once(paren(span, |_| ())));
    } else if input.len() <= CHUNK_SIZE {
        func(input, &mut out);
    } else {
        let tt = paren(span, |out| {
            let lower_power = find_smaller_power(input.len());

            for chunk in input.chunks(lower_power) {
                out.extend(compute(chunk, span, func));
                out.extend(punct_token(',', span));
            }
        });
        out.extend(iter::once(tt));
    }

    out
}

const CHUNK_SIZE: usize = 8;

fn find_smaller_power(than: usize) -> usize {
    let mut curr = 1;
    loop {
        let next = curr * 8;
        if next >= than {
            break curr;
        } else {
            curr = next;
        }
    }
}