monostate_impl/
lib.rs

1#![cfg_attr(not(check_cfg), allow(unexpected_cfgs))]
2#![allow(
3    clippy::cast_lossless,
4    clippy::manual_range_contains,
5    clippy::match_same_arms,
6    clippy::needless_pass_by_value,
7    clippy::uninlined_format_args,
8    clippy::unnecessary_wraps
9)]
10#![cfg_attr(all(test, exhaustive), feature(non_exhaustive_omitted_patterns_lint))]
11
12use proc_macro::TokenStream;
13use proc_macro2::{Ident, Literal, Span, TokenStream as TokenStream2};
14use quote::{quote, ToTokens};
15use std::mem;
16use syn::{parse_macro_input, Error, Lit, LitInt, Result};
17
18// Branching factor of the MustBeStr tuple type parameter.
19const K: usize = 6;
20
21#[allow(non_snake_case)]
22#[proc_macro]
23pub fn MustBe(input: TokenStream) -> TokenStream {
24    let lit = match ::syn::parse::<Lit>(input) {
    ::syn::__private::Ok(data) => data,
    ::syn::__private::Err(err) => {
        return ::syn::__private::TokenStream::from(err.to_compile_error());
    }
}parse_macro_input!(input as Lit);
25
26    #[cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
27    let expanded = match lit {
28        Lit::Str(lit) => must_be_str(lit.value()),
29        Lit::Byte(lit) => must_be_byte(lit.value()),
30        Lit::Char(lit) => must_be_char(lit.value()),
31        Lit::Int(lit) => must_be_int(lit),
32        Lit::Bool(lit) => must_be_bool(lit.value),
33        Lit::ByteStr(_) | Lit::CStr(_) | Lit::Float(_) | Lit::Verbatim(_) => unsupported(lit),
34        _ => unsupported(lit),
35    };
36
37    expanded.unwrap_or_else(Error::into_compile_error).into()
38}
39
40// We encode the chars at two consecutive levels of a K-ary tree.
41//
42// Suppose K=3, then strings "", "a", "ab", "abc", … would be encoded to:
43//     ()
44//     (a)
45//     (a, b)
46//     (a, b, c)
47//     (a, b, (c, d))
48//     (a, b, (c, d, e))
49//     (a, (b, c), (d, e, f))
50//     (a, (b, c, d), (e, f, g))
51//     ((a, b), (c, d, e), (f, g, h))
52//     ((a, b, c), (d, e, f), (g, h, i))
53//     ((a, b, c), (d, e, f), (g, h, (i, j)))
54//     ((a, b, c), (d, e, f), (g, h, (i, j, k)))
55//     ((a, b, c), (d, e, f), (g, (h, i), (j, k l)))
56//
57// That last one in tree form is:
58//           ╷
59//      ┌────┴┬──────┐
60//     ┌┴┬─┐ ┌┴┬─┐ ┌─┴┬───┐
61//     a b c d e f g ┌┴┐ ┌┴┬─┐
62//                   h i j k l
63
64enum StrNode {
65    Char(char),
66    Tuple(Vec<StrNode>),
67}
68
69impl ToTokens for StrNode {
70    fn to_tokens(&self, tokens: &mut TokenStream2) {
71        tokens.extend(match self {
72            StrNode::Char(ch) => {
73                if let 'A'..='Z' | 'a'..='z' = ch {
74                    let mut buf = [0];
75                    let name = ch.encode_utf8(&mut buf);
76                    let ident = Ident::new(name, Span::call_site());
77                    {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "monostate");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "alphabet");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::ToTokens::to_tokens(&ident, &mut _s);
    _s
}quote!(::monostate::alphabet::#ident)
78                } else {
79                    match ch.len_utf8() {
80                        1 => {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "monostate");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "alphabet");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "char");
    ::quote::__private::push_lt(&mut _s);
    ::quote::ToTokens::to_tokens(&ch, &mut _s);
    ::quote::__private::push_gt(&mut _s);
    _s
}quote!(::monostate::alphabet::char<#ch>),
81                        2 => {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "monostate");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "alphabet");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "two");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "char");
    ::quote::__private::push_lt(&mut _s);
    ::quote::ToTokens::to_tokens(&ch, &mut _s);
    ::quote::__private::push_gt(&mut _s);
    _s
}quote!(::monostate::alphabet::two::char<#ch>),
82                        3 => {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "monostate");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "alphabet");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "three");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "char");
    ::quote::__private::push_lt(&mut _s);
    ::quote::ToTokens::to_tokens(&ch, &mut _s);
    ::quote::__private::push_gt(&mut _s);
    _s
}quote!(::monostate::alphabet::three::char<#ch>),
83                        4 => {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "monostate");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "alphabet");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "four");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "char");
    ::quote::__private::push_lt(&mut _s);
    ::quote::ToTokens::to_tokens(&ch, &mut _s);
    ::quote::__private::push_gt(&mut _s);
    _s
}quote!(::monostate::alphabet::four::char<#ch>),
84                        _ => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
85                    }
86                }
87            }
88            StrNode::Tuple(vec) => {
89                let len = vec.len();
90                if !(len >= 2 && len <= K) {
    { ::core::panicking::panic_fmt(format_args!("len={0}", len)); }
};assert!(len >= 2 && len <= K, "len={}", len);
91                {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Parenthesis,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            {
                use ::quote::__private::ext::*;
                let mut _i = 0usize;
                let has_iter =
                    ::quote::__private::ThereIsNoIteratorInRepetition;
                #[allow(unused_mut)]
                let (mut vec, i) = vec.quote_into_iter();
                let has_iter = has_iter | i;
                let _: ::quote::__private::HasIterator = has_iter;
                while true {
                    let vec =
                        match vec.next() {
                            Some(_x) => ::quote::__private::RepInterp(_x),
                            None => break,
                        };
                    if _i > 0 { ::quote::__private::push_comma(&mut _s); }
                    _i += 1;
                    ::quote::ToTokens::to_tokens(&vec, &mut _s);
                }
            }
            _s
        });
    _s
}quote!((#(#vec),*))
92            }
93        });
94    }
95}
96
97fn must_be_str(value: String) -> Result<TokenStream2> {
98    if value.is_empty() {
99        return Ok({
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "monostate");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "MustBeStr");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_lt(&mut _s);
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Parenthesis,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "monostate");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "alphabet");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "len");
            ::quote::__private::push_lt(&mut _s);
            ::quote::__private::parse(&mut _s, "0");
            ::quote::__private::push_gt(&mut _s);
            ::quote::__private::push_comma(&mut _s);
            ::quote::__private::push_group(&mut _s,
                ::quote::__private::Delimiter::Parenthesis,
                ::quote::__private::TokenStream::new());
            _s
        });
    ::quote::__private::push_gt(&mut _s);
    _s
}quote! {
100            ::monostate::MustBeStr::<(::monostate::alphabet::len<0>, ())>
101        });
102    }
103    let mut nodes = Vec::new();
104    for ch in value.chars() {
105        nodes.push(StrNode::Char(ch));
106    }
107    // Find largest power of K smaller than len.
108    let mut pow = 1;
109    while pow * K < nodes.len() {
110        pow *= K;
111    }
112    while nodes.len() > 1 {
113        // Number of nodes in excess of the smaller of the two tree levels.
114        let overage = nodes.len() - pow;
115        // Every group of K-1 nodes which are beyond the smaller tree level can
116        // be combined with 1 node from the smaller tree level to form a
117        // K-tuple node. The number of tuples that need to be formed is
118        // ceil[overage / (K-1)].
119        let num_tuple_nodes = (overage + K - 2) / (K - 1);
120        // Number of nodes left needing to be inserted into a tuple.
121        let mut remainder = num_tuple_nodes + overage;
122        // Index of next node to be inserted into a tuple.
123        let mut read = nodes.len() - remainder;
124        // Index of the tuple currently being inserted into.
125        let mut write = read;
126        // True if we haven't yet made a Vec to hold the current tuple.
127        let mut make_tuple = true;
128        while let Some(node) = nodes.get_mut(read) {
129            let next = mem::replace(node, StrNode::Char('\0'));
130            if make_tuple {
131                nodes[write] = StrNode::Tuple(Vec::with_capacity(K));
132            }
133            if let StrNode::Tuple(vec) = &mut nodes[write] {
134                vec.push(next);
135            } else {
136                ::core::panicking::panic("internal error: entered unreachable code");unreachable!();
137            }
138            remainder -= 1;
139            make_tuple = remainder % K == 0;
140            write += make_tuple as usize;
141            read += 1;
142        }
143        nodes.truncate(pow);
144        pow /= K;
145    }
146    let len = Literal::usize_unsuffixed(value.len());
147    let encoded = &nodes[0];
148    Ok({
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "monostate");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "MustBeStr");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_lt(&mut _s);
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Parenthesis,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "monostate");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "alphabet");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "len");
            ::quote::__private::push_lt(&mut _s);
            ::quote::ToTokens::to_tokens(&len, &mut _s);
            ::quote::__private::push_gt(&mut _s);
            ::quote::__private::push_comma(&mut _s);
            ::quote::ToTokens::to_tokens(&encoded, &mut _s);
            _s
        });
    ::quote::__private::push_gt(&mut _s);
    _s
}quote! {
149        ::monostate::MustBeStr::<(::monostate::alphabet::len<#len>, #encoded)>
150    })
151}
152
153fn must_be_byte(value: u8) -> Result<TokenStream2> {
154    Ok({
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "monostate");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "MustBeU8");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_lt(&mut _s);
    ::quote::ToTokens::to_tokens(&value, &mut _s);
    ::quote::__private::push_gt(&mut _s);
    _s
}quote!(::monostate::MustBeU8::<#value>))
155}
156
157fn must_be_char(value: char) -> Result<TokenStream2> {
158    Ok({
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "monostate");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "MustBeChar");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_lt(&mut _s);
    ::quote::ToTokens::to_tokens(&value, &mut _s);
    ::quote::__private::push_gt(&mut _s);
    _s
}quote!(::monostate::MustBeChar::<#value>))
159}
160
161fn must_be_int(lit: LitInt) -> Result<TokenStream2> {
162    let token = lit.token();
163    match lit.suffix() {
164        "u8" => Ok({
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "monostate");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "MustBeU8");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_lt(&mut _s);
    ::quote::ToTokens::to_tokens(&token, &mut _s);
    ::quote::__private::push_gt(&mut _s);
    _s
}quote!(::monostate::MustBeU8::<#token>)),
165        "u16" => Ok({
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "monostate");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "MustBeU16");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_lt(&mut _s);
    ::quote::ToTokens::to_tokens(&token, &mut _s);
    ::quote::__private::push_gt(&mut _s);
    _s
}quote!(::monostate::MustBeU16::<#token>)),
166        "u32" => Ok({
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "monostate");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "MustBeU32");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_lt(&mut _s);
    ::quote::ToTokens::to_tokens(&token, &mut _s);
    ::quote::__private::push_gt(&mut _s);
    _s
}quote!(::monostate::MustBeU32::<#token>)),
167        "u64" => Ok({
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "monostate");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "MustBeU64");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_lt(&mut _s);
    ::quote::ToTokens::to_tokens(&token, &mut _s);
    ::quote::__private::push_gt(&mut _s);
    _s
}quote!(::monostate::MustBeU64::<#token>)),
168        "u128" => Ok({
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "monostate");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "MustBeU128");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_lt(&mut _s);
    ::quote::ToTokens::to_tokens(&token, &mut _s);
    ::quote::__private::push_gt(&mut _s);
    _s
}quote!(::monostate::MustBeU128::<#token>)),
169        "i8" => Ok({
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "monostate");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "MustBeI8");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_lt(&mut _s);
    ::quote::ToTokens::to_tokens(&token, &mut _s);
    ::quote::__private::push_gt(&mut _s);
    _s
}quote!(::monostate::MustBeI8::<#token>)),
170        "i16" => Ok({
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "monostate");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "MustBeI16");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_lt(&mut _s);
    ::quote::ToTokens::to_tokens(&token, &mut _s);
    ::quote::__private::push_gt(&mut _s);
    _s
}quote!(::monostate::MustBeI16::<#token>)),
171        "i32" => Ok({
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "monostate");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "MustBeI32");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_lt(&mut _s);
    ::quote::ToTokens::to_tokens(&token, &mut _s);
    ::quote::__private::push_gt(&mut _s);
    _s
}quote!(::monostate::MustBeI32::<#token>)),
172        "i64" => Ok({
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "monostate");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "MustBeI64");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_lt(&mut _s);
    ::quote::ToTokens::to_tokens(&token, &mut _s);
    ::quote::__private::push_gt(&mut _s);
    _s
}quote!(::monostate::MustBeI64::<#token>)),
173        "i128" => Ok({
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "monostate");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "MustBeI128");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_lt(&mut _s);
    ::quote::ToTokens::to_tokens(&token, &mut _s);
    ::quote::__private::push_gt(&mut _s);
    _s
}quote!(::monostate::MustBeI128::<#token>)),
174        "" => {
175            if lit.base10_digits().starts_with('-') {
176                Ok({
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "monostate");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "MustBeNegInt");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_lt(&mut _s);
    ::quote::ToTokens::to_tokens(&token, &mut _s);
    ::quote::__private::push_gt(&mut _s);
    _s
}quote!(::monostate::MustBeNegInt::<#token>))
177            } else {
178                Ok({
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "monostate");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "MustBePosInt");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_lt(&mut _s);
    ::quote::ToTokens::to_tokens(&token, &mut _s);
    ::quote::__private::push_gt(&mut _s);
    _s
}quote!(::monostate::MustBePosInt::<#token>))
179            }
180        }
181        suffix @ ("usize" | "isize") => {
182            let msg = ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("serde data model only uses consistently sized integer types, not {0}",
                suffix))
    })format!(
183                "serde data model only uses consistently sized integer types, not {}",
184                suffix,
185            );
186            Err(Error::new(lit.span(), msg))
187        }
188        suffix => {
189            let msg = ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("unsupported integers suffix `{0}`",
                suffix))
    })format!("unsupported integers suffix `{}`", suffix);
190            Err(Error::new(lit.span(), msg))
191        }
192    }
193}
194
195fn must_be_bool(value: bool) -> Result<TokenStream2> {
196    Ok({
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "monostate");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "MustBeBool");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_lt(&mut _s);
    ::quote::ToTokens::to_tokens(&value, &mut _s);
    ::quote::__private::push_gt(&mut _s);
    _s
}quote!(::monostate::MustBeBool::<#value>))
197}
198
199fn unsupported(lit: Lit) -> Result<TokenStream2> {
200    Err(Error::new(lit.span(), "unsupported monostate literal kind"))
201}