abi_stable_derive/
concat_and_ranges.rs
1use syn::{
2 parse::{Parse, ParseStream},
3 punctuated::Punctuated,
4 Error, Ident, Token,
5};
6
7use proc_macro2::TokenStream as TokenStream2;
8
9use quote::quote;
10
11#[derive(Debug, Clone)]
14struct StringAndVariable {
15 variable: Ident,
16 string: String,
17}
18
19#[derive(Debug, Clone)]
20struct ConcatenatedStrings {
21 concatenated: Ident,
22 strings: Punctuated<StringAndVariable, Token![,]>,
23}
24
25impl Parse for StringAndVariable {
26 fn parse(input: ParseStream) -> Result<Self, Error> {
27 let variable = input.parse()?;
28 let _: Token![=] = input.parse()?;
29 let string = input.parse::<syn::LitStr>()?.value();
30
31 Ok(Self { variable, string })
32 }
33}
34
35impl Parse for ConcatenatedStrings {
36 fn parse(input: ParseStream) -> Result<Self, Error> {
37 let concatenated = input.parse::<Ident>()?;
38
39 let paren_tokens;
40 let _ = syn::parenthesized!(paren_tokens in input);
41
42 let strings = paren_tokens.parse_terminated(Parse::parse)?;
43
44 Ok(Self {
45 concatenated,
46 strings,
47 })
48 }
49}
50
51pub fn macro_impl(input: TokenStream2) -> Result<TokenStream2, syn::Error> {
52 let ConcatenatedStrings {
53 concatenated: conc_ident,
54 strings,
55 } = syn::parse2::<ConcatenatedStrings>(input)?;
56
57 let capacity = strings.iter().map(|sav| sav.string.len() + 1).sum();
58
59 let mut concatenated = String::with_capacity(capacity);
60 let mut starts = Vec::<u16>::with_capacity(strings.len());
61 let mut lengths = Vec::<u16>::with_capacity(strings.len());
62
63 for sav in &strings {
64 let start = concatenated.len() as u16;
65 starts.push(start);
66 concatenated.push_str(&sav.string);
67 lengths.push(concatenated.len() as u16 - start);
68 concatenated.push(';');
69 }
70
71 let concat_len = concatenated.len();
72 let variable = strings.iter().map(|x| &x.variable);
73
74 Ok(quote!(
75 use abi_stable::{
76 std_types::RStr,
77 type_layout::StartLen,
78 };
79 pub const #conc_ident:RStr<'static>=unsafe{
80 RStr::from_raw_parts( #concatenated.as_ptr() ,#concat_len )
81 };
82
83 #(
84 pub const #variable:StartLen= StartLen::new(#starts,#lengths);
85 )*
86 ))
87}