1use proc_macro2::TokenStream;
55use quote::quote;
56use syn::{Data, DeriveInput, Fields, Type};
57
58use crate::naming::apply_rename_all;
59
60#[derive(#[automatically_derived]
impl ::core::default::Default for RFactorAttrs {
#[inline]
fn default() -> Self {
RFactorAttrs {
rename: ::core::default::Default::default(),
rename_all: ::core::default::Default::default(),
interaction: ::core::default::Default::default(),
sep: ::core::default::Default::default(),
}
}
}Default)]
62struct RFactorAttrs {
63 rename: Option<String>,
65 rename_all: Option<String>,
68 interaction: Option<Vec<String>>,
72 sep: Option<String>,
75}
76
77fn parse_r_factor_attrs(attrs: &[syn::Attribute]) -> syn::Result<RFactorAttrs> {
82 let mut result = RFactorAttrs::default();
83
84 for attr in attrs {
85 if attr.path().is_ident("r_factor") {
86 attr.parse_nested_meta(|meta| {
87 if meta.path.is_ident("rename") {
88 let value: syn::LitStr = meta.value()?.parse()?;
89 result.rename = Some(value.value());
90 } else if meta.path.is_ident("rename_all") {
91 let value: syn::LitStr = meta.value()?.parse()?;
92 result.rename_all = Some(value.value());
93 } else if meta.path.is_ident("interaction") {
94 let _eq: ::syn::token::Eqsyn::Token![=] = meta.input.parse()?;
96 let content;
97 match ::syn::__private::parse_brackets(&meta.input) {
::syn::__private::Ok(brackets) => {
content = brackets.content;
_ = content;
brackets.token
}
::syn::__private::Err(error) => { return ::syn::__private::Err(error); }
};syn::bracketed!(content in meta.input);
98 let levels: syn::punctuated::Punctuated<syn::LitStr, ::syn::token::Commasyn::Token![,]> =
99 content.parse_terminated(|input| input.parse(), ::syn::token::Commasyn::Token![,])?;
100 result.interaction = Some(levels.iter().map(|s| s.value()).collect());
101 } else if meta.path.is_ident("sep") {
102 let value: syn::LitStr = meta.value()?.parse()?;
103 result.sep = Some(value.value());
104 } else {
105 return Err(meta.error("unknown r_factor attribute"));
106 }
107 Ok(())
108 })?;
109 }
110 }
111
112 Ok(result)
113}
114
115pub fn derive_r_factor(input: DeriveInput) -> syn::Result<TokenStream> {
129 let name = &input.ident;
130 let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
131
132 let attrs = parse_r_factor_attrs(&input.attrs)?;
134
135 let variants = match &input.data {
137 Data::Enum(data) => &data.variants,
138 Data::Struct(_) => {
139 return Err(syn::Error::new_spanned(
140 &input,
141 "#[derive(RFactor)] can only be applied to enums",
142 ));
143 }
144 Data::Union(_) => {
145 return Err(syn::Error::new_spanned(
146 &input,
147 "#[derive(RFactor)] can only be applied to enums",
148 ));
149 }
150 };
151
152 if let Some(inner_levels) = &attrs.interaction {
154 derive_interaction_factor(
155 name,
156 &impl_generics,
157 &ty_generics,
158 where_clause,
159 variants,
160 inner_levels,
161 attrs.sep.as_deref().unwrap_or("."),
162 attrs.rename_all.as_deref(),
163 )
164 } else {
165 derive_simple_factor(
166 name,
167 &impl_generics,
168 &ty_generics,
169 where_clause,
170 variants,
171 attrs.rename_all.as_deref(),
172 )
173 }
174}
175
176fn derive_simple_factor(
188 name: &syn::Ident,
189 impl_generics: &syn::ImplGenerics,
190 ty_generics: &syn::TypeGenerics,
191 where_clause: Option<&syn::WhereClause>,
192 variants: &syn::punctuated::Punctuated<syn::Variant, ::syn::token::Commasyn::Token![,]>,
193 rename_all: Option<&str>,
194) -> syn::Result<TokenStream> {
195 let mut level_names = Vec::new();
196 let mut variant_idents = Vec::new();
197
198 for variant in variants {
199 if !#[allow(non_exhaustive_omitted_patterns)] match variant.fields {
Fields::Unit => true,
_ => false,
}matches!(variant.fields, Fields::Unit) {
201 return Err(syn::Error::new_spanned(
202 variant,
203 "#[derive(RFactor)] only supports fieldless (C-style) enum variants \
204 (use #[r_factor(interaction = [...])] for tuple variants)",
205 ));
206 }
207
208 let var_attrs = parse_r_factor_attrs(&variant.attrs)?;
210
211 let level_name = if let Some(r) = var_attrs.rename {
213 r
214 } else {
215 apply_rename_all(&crate::naming::ident_name(&variant.ident), rename_all)
216 };
217
218 level_names.push(level_name);
219 variant_idents.push(&variant.ident);
220 }
221
222 let indices: Vec<i32> = (1..=variant_idents.len() as i32).collect();
224 let level_name_strs: Vec<&str> = level_names.iter().map(|s| s.as_str()).collect();
225
226 Ok({
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "impl");
::quote::ToTokens::to_tokens(&impl_generics, &mut _s);
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "miniextendr_api");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "match_arg");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "MatchArg");
::quote::__private::push_ident(&mut _s, "for");
::quote::ToTokens::to_tokens(&name, &mut _s);
::quote::ToTokens::to_tokens(&ty_generics, &mut _s);
::quote::ToTokens::to_tokens(&where_clause, &mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Brace,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "const");
::quote::__private::push_ident(&mut _s, "CHOICES");
::quote::__private::push_colon(&mut _s);
::quote::__private::push_and(&mut _s);
::quote::__private::push_lifetime(&mut _s, "\'static");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Bracket,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_and(&mut _s);
::quote::__private::push_lifetime(&mut _s, "\'static");
::quote::__private::push_ident(&mut _s, "str");
_s
});
::quote::__private::push_eq(&mut _s);
::quote::__private::push_and(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Bracket,
{
let mut _s = ::quote::__private::TokenStream::new();
{
use ::quote::__private::ext::*;
let mut _first = true;
let has_iter = ::quote::__private::HasIterator::<false>;
#[allow(unused_mut)]
let (mut level_name_strs, i) =
level_name_strs.quote_into_iter();
let has_iter = has_iter | i;
<_ as
::quote::__private::CheckHasIterator<true>>::check(has_iter);
while true {
let level_name_strs =
match level_name_strs.next() {
Some(_x) => ::quote::__private::RepInterp(_x),
None => break,
};
if !_first { ::quote::__private::push_comma(&mut _s); }
_first = false;
::quote::ToTokens::to_tokens(&level_name_strs, &mut _s);
}
}
_s
});
::quote::__private::push_semi(&mut _s);
::quote::__private::push_ident(&mut _s, "fn");
::quote::__private::push_ident(&mut _s, "from_choice");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "choice");
::quote::__private::push_colon(&mut _s);
::quote::__private::push_and(&mut _s);
::quote::__private::push_ident(&mut _s, "str");
_s
});
::quote::__private::push_rarrow(&mut _s);
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "core");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "option");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "Option");
::quote::__private::push_lt(&mut _s);
::quote::__private::push_ident(&mut _s, "Self");
::quote::__private::push_gt(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Brace,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "match");
::quote::__private::push_ident(&mut _s, "choice");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Brace,
{
let mut _s = ::quote::__private::TokenStream::new();
{
use ::quote::__private::ext::*;
let has_iter = ::quote::__private::HasIterator::<false>;
#[allow(unused_mut)]
let (mut level_name_strs, i) =
level_name_strs.quote_into_iter();
let has_iter = has_iter | i;
#[allow(unused_mut)]
let (mut variant_idents, i) =
variant_idents.quote_into_iter();
let has_iter = has_iter | i;
<_ as
::quote::__private::CheckHasIterator<true>>::check(has_iter);
while true {
let level_name_strs =
match level_name_strs.next() {
Some(_x) => ::quote::__private::RepInterp(_x),
None => break,
};
let variant_idents =
match variant_idents.next() {
Some(_x) => ::quote::__private::RepInterp(_x),
None => break,
};
::quote::ToTokens::to_tokens(&level_name_strs, &mut _s);
::quote::__private::push_fat_arrow(&mut _s);
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "core");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "option");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "Option");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "Some");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "Self");
::quote::__private::push_colon2(&mut _s);
::quote::ToTokens::to_tokens(&variant_idents, &mut _s);
_s
});
::quote::__private::push_comma(&mut _s);
}
}
::quote::__private::push_underscore(&mut _s);
::quote::__private::push_fat_arrow(&mut _s);
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "core");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "option");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "Option");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "None");
::quote::__private::push_comma(&mut _s);
_s
});
_s
});
::quote::__private::push_ident(&mut _s, "fn");
::quote::__private::push_ident(&mut _s, "to_choice");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "self");
_s
});
::quote::__private::push_rarrow(&mut _s);
::quote::__private::push_and(&mut _s);
::quote::__private::push_lifetime(&mut _s, "\'static");
::quote::__private::push_ident(&mut _s, "str");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Brace,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "match");
::quote::__private::push_ident(&mut _s, "self");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Brace,
{
let mut _s = ::quote::__private::TokenStream::new();
{
use ::quote::__private::ext::*;
let has_iter = ::quote::__private::HasIterator::<false>;
#[allow(unused_mut)]
let (mut variant_idents, i) =
variant_idents.quote_into_iter();
let has_iter = has_iter | i;
#[allow(unused_mut)]
let (mut level_name_strs, i) =
level_name_strs.quote_into_iter();
let has_iter = has_iter | i;
<_ as
::quote::__private::CheckHasIterator<true>>::check(has_iter);
while true {
let variant_idents =
match variant_idents.next() {
Some(_x) => ::quote::__private::RepInterp(_x),
None => break,
};
let level_name_strs =
match level_name_strs.next() {
Some(_x) => ::quote::__private::RepInterp(_x),
None => break,
};
::quote::__private::push_ident(&mut _s, "Self");
::quote::__private::push_colon2(&mut _s);
::quote::ToTokens::to_tokens(&variant_idents, &mut _s);
::quote::__private::push_fat_arrow(&mut _s);
::quote::ToTokens::to_tokens(&level_name_strs, &mut _s);
::quote::__private::push_comma(&mut _s);
}
}
_s
});
_s
});
_s
});
::quote::__private::push_ident(&mut _s, "impl");
::quote::ToTokens::to_tokens(&impl_generics, &mut _s);
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "miniextendr_api");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "RFactor");
::quote::__private::push_ident(&mut _s, "for");
::quote::ToTokens::to_tokens(&name, &mut _s);
::quote::ToTokens::to_tokens(&ty_generics, &mut _s);
::quote::ToTokens::to_tokens(&where_clause, &mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Brace,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "fn");
::quote::__private::push_ident(&mut _s, "to_level_index");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "self");
_s
});
::quote::__private::push_rarrow(&mut _s);
::quote::__private::push_ident(&mut _s, "i32");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Brace,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "match");
::quote::__private::push_ident(&mut _s, "self");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Brace,
{
let mut _s = ::quote::__private::TokenStream::new();
{
use ::quote::__private::ext::*;
let has_iter = ::quote::__private::HasIterator::<false>;
#[allow(unused_mut)]
let (mut variant_idents, i) =
variant_idents.quote_into_iter();
let has_iter = has_iter | i;
#[allow(unused_mut)]
let (mut indices, i) = indices.quote_into_iter();
let has_iter = has_iter | i;
<_ as
::quote::__private::CheckHasIterator<true>>::check(has_iter);
while true {
let variant_idents =
match variant_idents.next() {
Some(_x) => ::quote::__private::RepInterp(_x),
None => break,
};
let indices =
match indices.next() {
Some(_x) => ::quote::__private::RepInterp(_x),
None => break,
};
::quote::__private::push_ident(&mut _s, "Self");
::quote::__private::push_colon2(&mut _s);
::quote::ToTokens::to_tokens(&variant_idents, &mut _s);
::quote::__private::push_fat_arrow(&mut _s);
::quote::ToTokens::to_tokens(&indices, &mut _s);
::quote::__private::push_comma(&mut _s);
}
}
_s
});
_s
});
::quote::__private::push_ident(&mut _s, "fn");
::quote::__private::push_ident(&mut _s, "from_level_index");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "idx");
::quote::__private::push_colon(&mut _s);
::quote::__private::push_ident(&mut _s, "i32");
_s
});
::quote::__private::push_rarrow(&mut _s);
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "core");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "option");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "Option");
::quote::__private::push_lt(&mut _s);
::quote::__private::push_ident(&mut _s, "Self");
::quote::__private::push_gt(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Brace,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "match");
::quote::__private::push_ident(&mut _s, "idx");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Brace,
{
let mut _s = ::quote::__private::TokenStream::new();
{
use ::quote::__private::ext::*;
let has_iter = ::quote::__private::HasIterator::<false>;
#[allow(unused_mut)]
let (mut indices, i) = indices.quote_into_iter();
let has_iter = has_iter | i;
#[allow(unused_mut)]
let (mut variant_idents, i) =
variant_idents.quote_into_iter();
let has_iter = has_iter | i;
<_ as
::quote::__private::CheckHasIterator<true>>::check(has_iter);
while true {
let indices =
match indices.next() {
Some(_x) => ::quote::__private::RepInterp(_x),
None => break,
};
let variant_idents =
match variant_idents.next() {
Some(_x) => ::quote::__private::RepInterp(_x),
None => break,
};
::quote::ToTokens::to_tokens(&indices, &mut _s);
::quote::__private::push_fat_arrow(&mut _s);
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "core");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "option");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "Option");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "Some");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "Self");
::quote::__private::push_colon2(&mut _s);
::quote::ToTokens::to_tokens(&variant_idents, &mut _s);
_s
});
::quote::__private::push_comma(&mut _s);
}
}
::quote::__private::push_underscore(&mut _s);
::quote::__private::push_fat_arrow(&mut _s);
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "core");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "option");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "Option");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "None");
::quote::__private::push_comma(&mut _s);
_s
});
_s
});
_s
});
::quote::__private::push_ident(&mut _s, "impl");
::quote::ToTokens::to_tokens(&impl_generics, &mut _s);
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "miniextendr_api");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "IntoR");
::quote::__private::push_ident(&mut _s, "for");
::quote::ToTokens::to_tokens(&name, &mut _s);
::quote::ToTokens::to_tokens(&ty_generics, &mut _s);
::quote::ToTokens::to_tokens(&where_clause, &mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Brace,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "type");
::quote::__private::push_ident(&mut _s, "Error");
::quote::__private::push_eq(&mut _s);
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "core");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "convert");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "Infallible");
::quote::__private::push_semi(&mut _s);
::quote::__private::push_ident(&mut _s, "fn");
::quote::__private::push_ident(&mut _s, "try_into_sexp");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "self");
_s
});
::quote::__private::push_rarrow(&mut _s);
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "core");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "result");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "Result");
::quote::__private::push_lt(&mut _s);
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "miniextendr_api");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "SEXP");
::quote::__private::push_comma(&mut _s);
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "core");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "convert");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "Infallible");
::quote::__private::push_gt(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Brace,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "core");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "result");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "Result");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "Ok");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "self");
::quote::__private::push_dot(&mut _s);
::quote::__private::push_ident(&mut _s, "into_sexp");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
::quote::__private::TokenStream::new());
_s
});
_s
});
::quote::__private::push_ident(&mut _s, "unsafe");
::quote::__private::push_ident(&mut _s, "fn");
::quote::__private::push_ident(&mut _s,
"try_into_sexp_unchecked");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "self");
_s
});
::quote::__private::push_rarrow(&mut _s);
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "core");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "result");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "Result");
::quote::__private::push_lt(&mut _s);
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "miniextendr_api");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "SEXP");
::quote::__private::push_comma(&mut _s);
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "core");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "convert");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "Infallible");
::quote::__private::push_gt(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Brace,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "self");
::quote::__private::push_dot(&mut _s);
::quote::__private::push_ident(&mut _s, "try_into_sexp");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
::quote::__private::TokenStream::new());
_s
});
::quote::__private::push_ident(&mut _s, "fn");
::quote::__private::push_ident(&mut _s, "into_sexp");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "self");
_s
});
::quote::__private::push_rarrow(&mut _s);
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "miniextendr_api");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "SEXP");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Brace,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "static");
::quote::__private::push_ident(&mut _s, "LEVELS_CACHE");
::quote::__private::push_colon(&mut _s);
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "std");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "sync");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "OnceLock");
::quote::__private::push_lt(&mut _s);
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "miniextendr_api");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "SEXP");
::quote::__private::push_gt(&mut _s);
::quote::__private::push_eq(&mut _s);
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "std");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "sync");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "OnceLock");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "new");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
::quote::__private::TokenStream::new());
::quote::__private::push_semi(&mut _s);
::quote::__private::push_ident(&mut _s, "let");
::quote::__private::push_ident(&mut _s, "levels");
::quote::__private::push_eq(&mut _s);
::quote::__private::push_star(&mut _s);
::quote::__private::push_ident(&mut _s, "LEVELS_CACHE");
::quote::__private::push_dot(&mut _s);
::quote::__private::push_ident(&mut _s, "get_or_init");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_or_or(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Brace,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "miniextendr_api");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s,
"build_levels_sexp_cached");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_lt(&mut _s);
::quote::__private::push_ident(&mut _s, "Self");
::quote::__private::push_ident(&mut _s, "as");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "miniextendr_api");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "match_arg");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "MatchArg");
::quote::__private::push_gt(&mut _s);
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "CHOICES");
_s
});
_s
});
_s
});
::quote::__private::push_semi(&mut _s);
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "miniextendr_api");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "build_factor");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_and(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Bracket,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_lt(&mut _s);
::quote::__private::push_ident(&mut _s, "Self");
::quote::__private::push_ident(&mut _s, "as");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "miniextendr_api");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "RFactor");
::quote::__private::push_gt(&mut _s);
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "to_level_index");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "self");
_s
});
_s
});
::quote::__private::push_comma(&mut _s);
::quote::__private::push_ident(&mut _s, "levels");
_s
});
_s
});
_s
});
::quote::__private::push_ident(&mut _s, "impl");
::quote::ToTokens::to_tokens(&impl_generics, &mut _s);
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "miniextendr_api");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "TryFromSexp");
::quote::__private::push_ident(&mut _s, "for");
::quote::ToTokens::to_tokens(&name, &mut _s);
::quote::ToTokens::to_tokens(&ty_generics, &mut _s);
::quote::ToTokens::to_tokens(&where_clause, &mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Brace,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "type");
::quote::__private::push_ident(&mut _s, "Error");
::quote::__private::push_eq(&mut _s);
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "miniextendr_api");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "SexpError");
::quote::__private::push_semi(&mut _s);
::quote::__private::push_ident(&mut _s, "const");
::quote::__private::push_ident(&mut _s, "CHARACTER_ONLY");
::quote::__private::push_colon(&mut _s);
::quote::__private::push_ident(&mut _s, "bool");
::quote::__private::push_eq(&mut _s);
::quote::__private::push_ident(&mut _s, "true");
::quote::__private::push_semi(&mut _s);
::quote::__private::push_ident(&mut _s, "fn");
::quote::__private::push_ident(&mut _s, "try_from_sexp");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "sexp");
::quote::__private::push_colon(&mut _s);
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "miniextendr_api");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "SEXP");
_s
});
::quote::__private::push_rarrow(&mut _s);
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "core");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "result");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "Result");
::quote::__private::push_lt(&mut _s);
::quote::__private::push_ident(&mut _s, "Self");
::quote::__private::push_comma(&mut _s);
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "miniextendr_api");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "SexpError");
::quote::__private::push_gt(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Brace,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "miniextendr_api");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "factor_from_sexp");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "sexp");
_s
});
_s
});
_s
});
_s
}quote! {
227 impl #impl_generics ::miniextendr_api::match_arg::MatchArg for #name #ty_generics #where_clause {
228 const CHOICES: &'static [&'static str] = &[#(#level_name_strs),*];
229
230 fn from_choice(choice: &str) -> ::core::option::Option<Self> {
231 match choice {
232 #(#level_name_strs => ::core::option::Option::Some(Self::#variant_idents),)*
233 _ => ::core::option::Option::None,
234 }
235 }
236
237 fn to_choice(self) -> &'static str {
238 match self {
239 #(Self::#variant_idents => #level_name_strs,)*
240 }
241 }
242 }
243
244 impl #impl_generics ::miniextendr_api::RFactor for #name #ty_generics #where_clause {
245 fn to_level_index(self) -> i32 {
246 match self {
247 #(Self::#variant_idents => #indices,)*
248 }
249 }
250
251 fn from_level_index(idx: i32) -> ::core::option::Option<Self> {
252 match idx {
253 #(#indices => ::core::option::Option::Some(Self::#variant_idents),)*
254 _ => ::core::option::Option::None,
255 }
256 }
257 }
258
259 impl #impl_generics ::miniextendr_api::IntoR for #name #ty_generics #where_clause {
260 type Error = ::core::convert::Infallible;
261
262 fn try_into_sexp(self) -> ::core::result::Result<::miniextendr_api::SEXP, ::core::convert::Infallible> {
263 ::core::result::Result::Ok(self.into_sexp())
264 }
265
266 unsafe fn try_into_sexp_unchecked(self) -> ::core::result::Result<::miniextendr_api::SEXP, ::core::convert::Infallible> {
267 self.try_into_sexp()
268 }
269
270 fn into_sexp(self) -> ::miniextendr_api::SEXP {
271 static LEVELS_CACHE: ::std::sync::OnceLock<::miniextendr_api::SEXP> =
272 ::std::sync::OnceLock::new();
273 let levels = *LEVELS_CACHE.get_or_init(|| {
274 ::miniextendr_api::build_levels_sexp_cached(
275 <Self as ::miniextendr_api::match_arg::MatchArg>::CHOICES
276 )
277 });
278 ::miniextendr_api::build_factor(&[<Self as ::miniextendr_api::RFactor>::to_level_index(self)], levels)
279 }
280 }
281
282 impl #impl_generics ::miniextendr_api::TryFromSexp for #name #ty_generics #where_clause {
283 type Error = ::miniextendr_api::SexpError;
284 const CHARACTER_ONLY: bool = true;
285
286 fn try_from_sexp(sexp: ::miniextendr_api::SEXP) -> ::core::result::Result<Self, ::miniextendr_api::SexpError> {
287 ::miniextendr_api::factor_from_sexp(sexp)
288 }
289 }
290 })
291}
292
293#[allow(clippy::too_many_arguments)] fn derive_interaction_factor(
313 name: &syn::Ident,
314 impl_generics: &syn::ImplGenerics,
315 ty_generics: &syn::TypeGenerics,
316 where_clause: Option<&syn::WhereClause>,
317 variants: &syn::punctuated::Punctuated<syn::Variant, ::syn::token::Commasyn::Token![,]>,
318 inner_levels: &[String],
319 sep: &str,
320 rename_all: Option<&str>,
321) -> syn::Result<TokenStream> {
322 let mut outer_names = Vec::new();
323 let mut variant_idents = Vec::new();
324 let mut inner_type: Option<Type> = None;
325
326 for variant in variants {
327 let field_ty = match &variant.fields {
329 Fields::Unnamed(fields) if fields.unnamed.len() == 1 => {
330 fields.unnamed.first().unwrap().ty.clone()
331 }
332 _ => {
333 return Err(syn::Error::new_spanned(
334 variant,
335 "interaction factors require single-field tuple variants: Variant(InnerType)",
336 ));
337 }
338 };
339
340 if let Some(ref existing) = inner_type {
342 if field_ty != *existing {
343 return Err(syn::Error::new_spanned(
344 &variant.fields,
345 "all variants must have the same inner type",
346 ));
347 }
348 } else {
349 inner_type = Some(field_ty);
350 }
351
352 let var_attrs = parse_r_factor_attrs(&variant.attrs)?;
354 let outer_name = if let Some(r) = var_attrs.rename {
355 r
356 } else {
357 apply_rename_all(&crate::naming::ident_name(&variant.ident), rename_all)
358 };
359
360 outer_names.push(outer_name);
361 variant_idents.push(&variant.ident);
362 }
363
364 let inner_type = inner_type.ok_or_else(|| {
365 syn::Error::new_spanned(name, "interaction factor must have at least one variant")
366 })?;
367
368 let n_outer = outer_names.len();
369 let n_inner = inner_levels.len();
370
371 let mut combined_levels = Vec::new();
375 for outer_name in &outer_names {
376 for inner_name in inner_levels {
377 let combined = ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}{1}{2}", outer_name, sep,
inner_name))
})format!("{}{}{}", outer_name, sep, inner_name);
379 combined_levels.push(combined);
380 }
381 }
382 let combined_level_strs: Vec<&str> = combined_levels.iter().map(|s| s.as_str()).collect();
383
384 let n_inner_lit = n_inner as i32;
387 let to_index_arms: Vec<_> = variant_idents
388 .iter()
389 .enumerate()
390 .map(|(outer_idx, var_ident)| {
391 let outer_idx_lit = outer_idx as i32;
392 {
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "Self");
::quote::__private::push_colon2(&mut _s);
::quote::ToTokens::to_tokens(&var_ident, &mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "inner");
_s
});
::quote::__private::push_fat_arrow(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Brace,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "let");
::quote::__private::push_ident(&mut _s, "inner_idx_0");
::quote::__private::push_eq(&mut _s);
::quote::__private::push_lt(&mut _s);
::quote::ToTokens::to_tokens(&inner_type, &mut _s);
::quote::__private::push_ident(&mut _s, "as");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "miniextendr_api");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "RFactor");
::quote::__private::push_gt(&mut _s);
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "to_level_index");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "inner");
_s
});
::quote::__private::push_sub(&mut _s);
::quote::__private::parse(&mut _s, "1");
::quote::__private::push_semi(&mut _s);
::quote::ToTokens::to_tokens(&outer_idx_lit, &mut _s);
::quote::__private::push_star(&mut _s);
::quote::ToTokens::to_tokens(&n_inner_lit, &mut _s);
::quote::__private::push_add(&mut _s);
::quote::__private::push_ident(&mut _s, "inner_idx_0");
::quote::__private::push_add(&mut _s);
::quote::__private::parse(&mut _s, "1");
_s
});
_s
}quote! {
393 Self::#var_ident(inner) => {
394 let inner_idx_0 = <#inner_type as ::miniextendr_api::RFactor>::to_level_index(inner) - 1;
395 #outer_idx_lit * #n_inner_lit + inner_idx_0 + 1
396 }
397 }
398 })
399 .collect();
400
401 let from_index_arms: Vec<_> = (0..n_outer)
405 .map(|outer_idx| {
406 let var_ident = &variant_idents[outer_idx];
407 let start_idx = (outer_idx * n_inner + 1) as i32;
408 let end_idx = ((outer_idx + 1) * n_inner) as i32;
409 {
let mut _s = ::quote::__private::TokenStream::new();
::quote::ToTokens::to_tokens(&start_idx, &mut _s);
::quote::__private::push_dot_dot_eq(&mut _s);
::quote::ToTokens::to_tokens(&end_idx, &mut _s);
::quote::__private::push_fat_arrow(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Brace,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "let");
::quote::__private::push_ident(&mut _s, "inner_idx_1");
::quote::__private::push_eq(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "idx");
::quote::__private::push_sub(&mut _s);
::quote::__private::parse(&mut _s, "1");
_s
});
::quote::__private::push_rem(&mut _s);
::quote::ToTokens::to_tokens(&n_inner_lit, &mut _s);
::quote::__private::push_add(&mut _s);
::quote::__private::parse(&mut _s, "1");
::quote::__private::push_semi(&mut _s);
::quote::__private::push_lt(&mut _s);
::quote::ToTokens::to_tokens(&inner_type, &mut _s);
::quote::__private::push_ident(&mut _s, "as");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "miniextendr_api");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "RFactor");
::quote::__private::push_gt(&mut _s);
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "from_level_index");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "inner_idx_1");
_s
});
::quote::__private::push_dot(&mut _s);
::quote::__private::push_ident(&mut _s, "map");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "Self");
::quote::__private::push_colon2(&mut _s);
::quote::ToTokens::to_tokens(&var_ident, &mut _s);
_s
});
_s
});
_s
}quote! {
410 #start_idx..=#end_idx => {
411 let inner_idx_1 = (idx - 1) % #n_inner_lit + 1;
412 <#inner_type as ::miniextendr_api::RFactor>::from_level_index(inner_idx_1)
413 .map(Self::#var_ident)
414 }
415 }
416 })
417 .collect();
418
419 let inner_level_strs: Vec<&str> = inner_levels.iter().map(|s| s.as_str()).collect();
421
422 Ok({
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "const");
::quote::__private::push_underscore(&mut _s);
::quote::__private::push_colon(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
::quote::__private::TokenStream::new());
::quote::__private::push_eq(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Brace,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "const");
::quote::__private::push_ident(&mut _s, "ACTUAL");
::quote::__private::push_colon(&mut _s);
::quote::__private::push_and(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Bracket,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_and(&mut _s);
::quote::__private::push_ident(&mut _s, "str");
_s
});
::quote::__private::push_eq(&mut _s);
::quote::__private::push_lt(&mut _s);
::quote::ToTokens::to_tokens(&inner_type, &mut _s);
::quote::__private::push_ident(&mut _s, "as");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "miniextendr_api");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "match_arg");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "MatchArg");
::quote::__private::push_gt(&mut _s);
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "CHOICES");
::quote::__private::push_semi(&mut _s);
::quote::__private::push_ident(&mut _s, "const");
::quote::__private::push_ident(&mut _s, "EXPECTED");
::quote::__private::push_colon(&mut _s);
::quote::__private::push_and(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Bracket,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_and(&mut _s);
::quote::__private::push_ident(&mut _s, "str");
_s
});
::quote::__private::push_eq(&mut _s);
::quote::__private::push_and(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Bracket,
{
let mut _s = ::quote::__private::TokenStream::new();
{
use ::quote::__private::ext::*;
let mut _first = true;
let has_iter = ::quote::__private::HasIterator::<false>;
#[allow(unused_mut)]
let (mut inner_level_strs, i) =
inner_level_strs.quote_into_iter();
let has_iter = has_iter | i;
<_ as
::quote::__private::CheckHasIterator<true>>::check(has_iter);
while true {
let inner_level_strs =
match inner_level_strs.next() {
Some(_x) => ::quote::__private::RepInterp(_x),
None => break,
};
if !_first { ::quote::__private::push_comma(&mut _s); }
_first = false;
::quote::ToTokens::to_tokens(&inner_level_strs, &mut _s);
}
}
_s
});
::quote::__private::push_semi(&mut _s);
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "core");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "assert");
::quote::__private::push_bang(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "ACTUAL");
::quote::__private::push_dot(&mut _s);
::quote::__private::push_ident(&mut _s, "len");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
::quote::__private::TokenStream::new());
::quote::__private::push_eq_eq(&mut _s);
::quote::__private::push_ident(&mut _s, "EXPECTED");
::quote::__private::push_dot(&mut _s);
::quote::__private::push_ident(&mut _s, "len");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
::quote::__private::TokenStream::new());
::quote::__private::push_comma(&mut _s);
::quote::__private::parse(&mut _s,
"\"interaction factor: inner type level count mismatch\"");
_s
});
::quote::__private::push_semi(&mut _s);
::quote::__private::push_ident(&mut _s, "let");
::quote::__private::push_ident(&mut _s, "mut");
::quote::__private::push_ident(&mut _s, "i");
::quote::__private::push_eq(&mut _s);
::quote::__private::parse(&mut _s, "0");
::quote::__private::push_semi(&mut _s);
::quote::__private::push_ident(&mut _s, "while");
::quote::__private::push_ident(&mut _s, "i");
::quote::__private::push_lt(&mut _s);
::quote::__private::push_ident(&mut _s, "ACTUAL");
::quote::__private::push_dot(&mut _s);
::quote::__private::push_ident(&mut _s, "len");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
::quote::__private::TokenStream::new());
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Brace,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "let");
::quote::__private::push_ident(&mut _s, "actual_bytes");
::quote::__private::push_eq(&mut _s);
::quote::__private::push_ident(&mut _s, "ACTUAL");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Bracket,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "i");
_s
});
::quote::__private::push_dot(&mut _s);
::quote::__private::push_ident(&mut _s, "as_bytes");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
::quote::__private::TokenStream::new());
::quote::__private::push_semi(&mut _s);
::quote::__private::push_ident(&mut _s, "let");
::quote::__private::push_ident(&mut _s, "expected_bytes");
::quote::__private::push_eq(&mut _s);
::quote::__private::push_ident(&mut _s, "EXPECTED");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Bracket,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "i");
_s
});
::quote::__private::push_dot(&mut _s);
::quote::__private::push_ident(&mut _s, "as_bytes");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
::quote::__private::TokenStream::new());
::quote::__private::push_semi(&mut _s);
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "core");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "assert");
::quote::__private::push_bang(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "actual_bytes");
::quote::__private::push_dot(&mut _s);
::quote::__private::push_ident(&mut _s, "len");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
::quote::__private::TokenStream::new());
::quote::__private::push_eq_eq(&mut _s);
::quote::__private::push_ident(&mut _s, "expected_bytes");
::quote::__private::push_dot(&mut _s);
::quote::__private::push_ident(&mut _s, "len");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
::quote::__private::TokenStream::new());
::quote::__private::push_comma(&mut _s);
::quote::__private::parse(&mut _s,
"\"interaction factor: inner type level string length mismatch\"");
_s
});
::quote::__private::push_semi(&mut _s);
::quote::__private::push_ident(&mut _s, "let");
::quote::__private::push_ident(&mut _s, "mut");
::quote::__private::push_ident(&mut _s, "j");
::quote::__private::push_eq(&mut _s);
::quote::__private::parse(&mut _s, "0");
::quote::__private::push_semi(&mut _s);
::quote::__private::push_ident(&mut _s, "while");
::quote::__private::push_ident(&mut _s, "j");
::quote::__private::push_lt(&mut _s);
::quote::__private::push_ident(&mut _s, "actual_bytes");
::quote::__private::push_dot(&mut _s);
::quote::__private::push_ident(&mut _s, "len");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
::quote::__private::TokenStream::new());
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Brace,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "core");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "assert");
::quote::__private::push_bang(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "actual_bytes");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Bracket,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "j");
_s
});
::quote::__private::push_eq_eq(&mut _s);
::quote::__private::push_ident(&mut _s, "expected_bytes");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Bracket,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "j");
_s
});
::quote::__private::push_comma(&mut _s);
::quote::__private::parse(&mut _s,
"\"interaction factor: inner type level string content mismatch\"");
_s
});
::quote::__private::push_semi(&mut _s);
::quote::__private::push_ident(&mut _s, "j");
::quote::__private::push_add_eq(&mut _s);
::quote::__private::parse(&mut _s, "1");
::quote::__private::push_semi(&mut _s);
_s
});
::quote::__private::push_ident(&mut _s, "i");
::quote::__private::push_add_eq(&mut _s);
::quote::__private::parse(&mut _s, "1");
::quote::__private::push_semi(&mut _s);
_s
});
_s
});
::quote::__private::push_semi(&mut _s);
::quote::__private::push_ident(&mut _s, "impl");
::quote::ToTokens::to_tokens(&impl_generics, &mut _s);
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "miniextendr_api");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "match_arg");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "MatchArg");
::quote::__private::push_ident(&mut _s, "for");
::quote::ToTokens::to_tokens(&name, &mut _s);
::quote::ToTokens::to_tokens(&ty_generics, &mut _s);
::quote::ToTokens::to_tokens(&where_clause, &mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Brace,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "const");
::quote::__private::push_ident(&mut _s, "CHOICES");
::quote::__private::push_colon(&mut _s);
::quote::__private::push_and(&mut _s);
::quote::__private::push_lifetime(&mut _s, "\'static");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Bracket,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_and(&mut _s);
::quote::__private::push_lifetime(&mut _s, "\'static");
::quote::__private::push_ident(&mut _s, "str");
_s
});
::quote::__private::push_eq(&mut _s);
::quote::__private::push_and(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Bracket,
{
let mut _s = ::quote::__private::TokenStream::new();
{
use ::quote::__private::ext::*;
let mut _first = true;
let has_iter = ::quote::__private::HasIterator::<false>;
#[allow(unused_mut)]
let (mut combined_level_strs, i) =
combined_level_strs.quote_into_iter();
let has_iter = has_iter | i;
<_ as
::quote::__private::CheckHasIterator<true>>::check(has_iter);
while true {
let combined_level_strs =
match combined_level_strs.next() {
Some(_x) => ::quote::__private::RepInterp(_x),
None => break,
};
if !_first { ::quote::__private::push_comma(&mut _s); }
_first = false;
::quote::ToTokens::to_tokens(&combined_level_strs, &mut _s);
}
}
_s
});
::quote::__private::push_semi(&mut _s);
::quote::__private::push_ident(&mut _s, "fn");
::quote::__private::push_ident(&mut _s, "from_choice");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "choice");
::quote::__private::push_colon(&mut _s);
::quote::__private::push_and(&mut _s);
::quote::__private::push_ident(&mut _s, "str");
_s
});
::quote::__private::push_rarrow(&mut _s);
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "core");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "option");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "Option");
::quote::__private::push_lt(&mut _s);
::quote::__private::push_ident(&mut _s, "Self");
::quote::__private::push_gt(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Brace,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "let");
::quote::__private::push_ident(&mut _s, "idx_1");
::quote::__private::push_eq(&mut _s);
::quote::__private::push_lt(&mut _s);
::quote::__private::push_ident(&mut _s, "Self");
::quote::__private::push_ident(&mut _s, "as");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "miniextendr_api");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "match_arg");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "MatchArg");
::quote::__private::push_gt(&mut _s);
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "CHOICES");
::quote::__private::push_dot(&mut _s);
::quote::__private::push_ident(&mut _s, "iter");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
::quote::__private::TokenStream::new());
::quote::__private::push_dot(&mut _s);
::quote::__private::push_ident(&mut _s, "position");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_or(&mut _s);
::quote::__private::push_and(&mut _s);
::quote::__private::push_ident(&mut _s, "l");
::quote::__private::push_or(&mut _s);
::quote::__private::push_ident(&mut _s, "l");
::quote::__private::push_eq_eq(&mut _s);
::quote::__private::push_ident(&mut _s, "choice");
_s
});
::quote::__private::push_dot(&mut _s);
::quote::__private::push_ident(&mut _s, "map");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_or(&mut _s);
::quote::__private::push_ident(&mut _s, "i");
::quote::__private::push_or(&mut _s);
::quote::__private::push_ident(&mut _s, "i");
::quote::__private::push_ident(&mut _s, "as");
::quote::__private::push_ident(&mut _s, "i32");
::quote::__private::push_add(&mut _s);
::quote::__private::parse(&mut _s, "1");
_s
});
::quote::__private::push_question(&mut _s);
::quote::__private::push_semi(&mut _s);
::quote::__private::push_lt(&mut _s);
::quote::__private::push_ident(&mut _s, "Self");
::quote::__private::push_ident(&mut _s, "as");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "miniextendr_api");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "RFactor");
::quote::__private::push_gt(&mut _s);
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "from_level_index");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "idx_1");
_s
});
_s
});
::quote::__private::push_ident(&mut _s, "fn");
::quote::__private::push_ident(&mut _s, "to_choice");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "self");
_s
});
::quote::__private::push_rarrow(&mut _s);
::quote::__private::push_and(&mut _s);
::quote::__private::push_lifetime(&mut _s, "\'static");
::quote::__private::push_ident(&mut _s, "str");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Brace,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_lt(&mut _s);
::quote::__private::push_ident(&mut _s, "Self");
::quote::__private::push_ident(&mut _s, "as");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "miniextendr_api");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "match_arg");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "MatchArg");
::quote::__private::push_gt(&mut _s);
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "CHOICES");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Bracket,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_lt(&mut _s);
::quote::__private::push_ident(&mut _s, "Self");
::quote::__private::push_ident(&mut _s, "as");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "miniextendr_api");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "RFactor");
::quote::__private::push_gt(&mut _s);
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "to_level_index");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "self");
_s
});
::quote::__private::push_sub(&mut _s);
::quote::__private::parse(&mut _s, "1");
_s
});
::quote::__private::push_ident(&mut _s, "as");
::quote::__private::push_ident(&mut _s, "usize");
_s
});
_s
});
_s
});
::quote::__private::push_ident(&mut _s, "impl");
::quote::ToTokens::to_tokens(&impl_generics, &mut _s);
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "miniextendr_api");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "RFactor");
::quote::__private::push_ident(&mut _s, "for");
::quote::ToTokens::to_tokens(&name, &mut _s);
::quote::ToTokens::to_tokens(&ty_generics, &mut _s);
::quote::ToTokens::to_tokens(&where_clause, &mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Brace,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "fn");
::quote::__private::push_ident(&mut _s, "to_level_index");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "self");
_s
});
::quote::__private::push_rarrow(&mut _s);
::quote::__private::push_ident(&mut _s, "i32");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Brace,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "match");
::quote::__private::push_ident(&mut _s, "self");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Brace,
{
let mut _s = ::quote::__private::TokenStream::new();
{
use ::quote::__private::ext::*;
let has_iter = ::quote::__private::HasIterator::<false>;
#[allow(unused_mut)]
let (mut to_index_arms, i) =
to_index_arms.quote_into_iter();
let has_iter = has_iter | i;
<_ as
::quote::__private::CheckHasIterator<true>>::check(has_iter);
while true {
let to_index_arms =
match to_index_arms.next() {
Some(_x) => ::quote::__private::RepInterp(_x),
None => break,
};
::quote::ToTokens::to_tokens(&to_index_arms, &mut _s);
}
}
_s
});
_s
});
::quote::__private::push_ident(&mut _s, "fn");
::quote::__private::push_ident(&mut _s, "from_level_index");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "idx");
::quote::__private::push_colon(&mut _s);
::quote::__private::push_ident(&mut _s, "i32");
_s
});
::quote::__private::push_rarrow(&mut _s);
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "core");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "option");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "Option");
::quote::__private::push_lt(&mut _s);
::quote::__private::push_ident(&mut _s, "Self");
::quote::__private::push_gt(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Brace,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "match");
::quote::__private::push_ident(&mut _s, "idx");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Brace,
{
let mut _s = ::quote::__private::TokenStream::new();
{
use ::quote::__private::ext::*;
let has_iter = ::quote::__private::HasIterator::<false>;
#[allow(unused_mut)]
let (mut from_index_arms, i) =
from_index_arms.quote_into_iter();
let has_iter = has_iter | i;
<_ as
::quote::__private::CheckHasIterator<true>>::check(has_iter);
while true {
let from_index_arms =
match from_index_arms.next() {
Some(_x) => ::quote::__private::RepInterp(_x),
None => break,
};
::quote::ToTokens::to_tokens(&from_index_arms, &mut _s);
}
}
::quote::__private::push_underscore(&mut _s);
::quote::__private::push_fat_arrow(&mut _s);
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "core");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "option");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "Option");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "None");
::quote::__private::push_comma(&mut _s);
_s
});
_s
});
_s
});
::quote::__private::push_ident(&mut _s, "impl");
::quote::ToTokens::to_tokens(&impl_generics, &mut _s);
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "miniextendr_api");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "IntoR");
::quote::__private::push_ident(&mut _s, "for");
::quote::ToTokens::to_tokens(&name, &mut _s);
::quote::ToTokens::to_tokens(&ty_generics, &mut _s);
::quote::ToTokens::to_tokens(&where_clause, &mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Brace,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "type");
::quote::__private::push_ident(&mut _s, "Error");
::quote::__private::push_eq(&mut _s);
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "core");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "convert");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "Infallible");
::quote::__private::push_semi(&mut _s);
::quote::__private::push_ident(&mut _s, "fn");
::quote::__private::push_ident(&mut _s, "try_into_sexp");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "self");
_s
});
::quote::__private::push_rarrow(&mut _s);
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "core");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "result");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "Result");
::quote::__private::push_lt(&mut _s);
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "miniextendr_api");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "SEXP");
::quote::__private::push_comma(&mut _s);
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "core");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "convert");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "Infallible");
::quote::__private::push_gt(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Brace,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "core");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "result");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "Result");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "Ok");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "self");
::quote::__private::push_dot(&mut _s);
::quote::__private::push_ident(&mut _s, "into_sexp");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
::quote::__private::TokenStream::new());
_s
});
_s
});
::quote::__private::push_ident(&mut _s, "unsafe");
::quote::__private::push_ident(&mut _s, "fn");
::quote::__private::push_ident(&mut _s,
"try_into_sexp_unchecked");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "self");
_s
});
::quote::__private::push_rarrow(&mut _s);
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "core");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "result");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "Result");
::quote::__private::push_lt(&mut _s);
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "miniextendr_api");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "SEXP");
::quote::__private::push_comma(&mut _s);
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "core");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "convert");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "Infallible");
::quote::__private::push_gt(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Brace,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "self");
::quote::__private::push_dot(&mut _s);
::quote::__private::push_ident(&mut _s, "try_into_sexp");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
::quote::__private::TokenStream::new());
_s
});
::quote::__private::push_ident(&mut _s, "fn");
::quote::__private::push_ident(&mut _s, "into_sexp");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "self");
_s
});
::quote::__private::push_rarrow(&mut _s);
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "miniextendr_api");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "SEXP");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Brace,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "static");
::quote::__private::push_ident(&mut _s, "LEVELS_CACHE");
::quote::__private::push_colon(&mut _s);
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "std");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "sync");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "OnceLock");
::quote::__private::push_lt(&mut _s);
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "miniextendr_api");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "SEXP");
::quote::__private::push_gt(&mut _s);
::quote::__private::push_eq(&mut _s);
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "std");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "sync");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "OnceLock");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "new");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
::quote::__private::TokenStream::new());
::quote::__private::push_semi(&mut _s);
::quote::__private::push_ident(&mut _s, "let");
::quote::__private::push_ident(&mut _s, "levels");
::quote::__private::push_eq(&mut _s);
::quote::__private::push_star(&mut _s);
::quote::__private::push_ident(&mut _s, "LEVELS_CACHE");
::quote::__private::push_dot(&mut _s);
::quote::__private::push_ident(&mut _s, "get_or_init");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_or_or(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Brace,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "miniextendr_api");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s,
"build_levels_sexp_cached");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_lt(&mut _s);
::quote::__private::push_ident(&mut _s, "Self");
::quote::__private::push_ident(&mut _s, "as");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "miniextendr_api");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "match_arg");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "MatchArg");
::quote::__private::push_gt(&mut _s);
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "CHOICES");
_s
});
_s
});
_s
});
::quote::__private::push_semi(&mut _s);
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "miniextendr_api");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "build_factor");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_and(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Bracket,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_lt(&mut _s);
::quote::__private::push_ident(&mut _s, "Self");
::quote::__private::push_ident(&mut _s, "as");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "miniextendr_api");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "RFactor");
::quote::__private::push_gt(&mut _s);
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "to_level_index");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "self");
_s
});
_s
});
::quote::__private::push_comma(&mut _s);
::quote::__private::push_ident(&mut _s, "levels");
_s
});
_s
});
_s
});
::quote::__private::push_ident(&mut _s, "impl");
::quote::ToTokens::to_tokens(&impl_generics, &mut _s);
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "miniextendr_api");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "TryFromSexp");
::quote::__private::push_ident(&mut _s, "for");
::quote::ToTokens::to_tokens(&name, &mut _s);
::quote::ToTokens::to_tokens(&ty_generics, &mut _s);
::quote::ToTokens::to_tokens(&where_clause, &mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Brace,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "type");
::quote::__private::push_ident(&mut _s, "Error");
::quote::__private::push_eq(&mut _s);
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "miniextendr_api");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "SexpError");
::quote::__private::push_semi(&mut _s);
::quote::__private::push_ident(&mut _s, "const");
::quote::__private::push_ident(&mut _s, "CHARACTER_ONLY");
::quote::__private::push_colon(&mut _s);
::quote::__private::push_ident(&mut _s, "bool");
::quote::__private::push_eq(&mut _s);
::quote::__private::push_ident(&mut _s, "true");
::quote::__private::push_semi(&mut _s);
::quote::__private::push_ident(&mut _s, "fn");
::quote::__private::push_ident(&mut _s, "try_from_sexp");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "sexp");
::quote::__private::push_colon(&mut _s);
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "miniextendr_api");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "SEXP");
_s
});
::quote::__private::push_rarrow(&mut _s);
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "core");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "result");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "Result");
::quote::__private::push_lt(&mut _s);
::quote::__private::push_ident(&mut _s, "Self");
::quote::__private::push_comma(&mut _s);
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "miniextendr_api");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "SexpError");
::quote::__private::push_gt(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Brace,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "miniextendr_api");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "factor_from_sexp");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "sexp");
_s
});
_s
});
_s
});
_s
}quote! {
423 const _: () = {
426 const ACTUAL: &[&str] = <#inner_type as ::miniextendr_api::match_arg::MatchArg>::CHOICES;
427 const EXPECTED: &[&str] = &[#(#inner_level_strs),*];
428
429 ::core::assert!(
431 ACTUAL.len() == EXPECTED.len(),
432 "interaction factor: inner type level count mismatch"
433 );
434
435 let mut i = 0;
437 while i < ACTUAL.len() {
438 let actual_bytes = ACTUAL[i].as_bytes();
439 let expected_bytes = EXPECTED[i].as_bytes();
440 ::core::assert!(
441 actual_bytes.len() == expected_bytes.len(),
442 "interaction factor: inner type level string length mismatch"
443 );
444 let mut j = 0;
445 while j < actual_bytes.len() {
446 ::core::assert!(
447 actual_bytes[j] == expected_bytes[j],
448 "interaction factor: inner type level string content mismatch"
449 );
450 j += 1;
451 }
452 i += 1;
453 }
454 };
455
456 impl #impl_generics ::miniextendr_api::match_arg::MatchArg for #name #ty_generics #where_clause {
457 const CHOICES: &'static [&'static str] = &[#(#combined_level_strs),*];
458
459 fn from_choice(choice: &str) -> ::core::option::Option<Self> {
460 let idx_1 = <Self as ::miniextendr_api::match_arg::MatchArg>::CHOICES.iter().position(|&l| l == choice).map(|i| i as i32 + 1)?;
461 <Self as ::miniextendr_api::RFactor>::from_level_index(idx_1)
462 }
463
464 fn to_choice(self) -> &'static str {
465 <Self as ::miniextendr_api::match_arg::MatchArg>::CHOICES[(<Self as ::miniextendr_api::RFactor>::to_level_index(self) - 1) as usize]
466 }
467 }
468
469 impl #impl_generics ::miniextendr_api::RFactor for #name #ty_generics #where_clause {
470 fn to_level_index(self) -> i32 {
471 match self {
472 #(#to_index_arms)*
473 }
474 }
475
476 fn from_level_index(idx: i32) -> ::core::option::Option<Self> {
477 match idx {
478 #(#from_index_arms)*
479 _ => ::core::option::Option::None,
480 }
481 }
482 }
483
484 impl #impl_generics ::miniextendr_api::IntoR for #name #ty_generics #where_clause {
485 type Error = ::core::convert::Infallible;
486
487 fn try_into_sexp(self) -> ::core::result::Result<::miniextendr_api::SEXP, ::core::convert::Infallible> {
488 ::core::result::Result::Ok(self.into_sexp())
489 }
490
491 unsafe fn try_into_sexp_unchecked(self) -> ::core::result::Result<::miniextendr_api::SEXP, ::core::convert::Infallible> {
492 self.try_into_sexp()
493 }
494
495 fn into_sexp(self) -> ::miniextendr_api::SEXP {
496 static LEVELS_CACHE: ::std::sync::OnceLock<::miniextendr_api::SEXP> =
497 ::std::sync::OnceLock::new();
498 let levels = *LEVELS_CACHE.get_or_init(|| {
499 ::miniextendr_api::build_levels_sexp_cached(
500 <Self as ::miniextendr_api::match_arg::MatchArg>::CHOICES
501 )
502 });
503 ::miniextendr_api::build_factor(&[<Self as ::miniextendr_api::RFactor>::to_level_index(self)], levels)
504 }
505 }
506
507 impl #impl_generics ::miniextendr_api::TryFromSexp for #name #ty_generics #where_clause {
508 type Error = ::miniextendr_api::SexpError;
509 const CHARACTER_ONLY: bool = true;
510
511 fn try_from_sexp(sexp: ::miniextendr_api::SEXP) -> ::core::result::Result<Self, ::miniextendr_api::SexpError> {
512 ::miniextendr_api::factor_from_sexp(sexp)
513 }
514 }
515 })
516}
517
518#[cfg(test)]
519mod tests {
520 use super::*;
521
522 #[test]
523 fn test_interaction_levels_generation() {
524 let input: DeriveInput = syn::parse_quote! {
525 #[r_factor(interaction = ["Small", "Large"])]
526 enum ColorSize {
527 Red(Size),
528 Green(Size),
529 Blue(Size),
530 }
531 };
532
533 let result = derive_r_factor(input).unwrap();
534 let code = result.to_string();
535
536 assert!(code.contains("Red.Small"));
538 assert!(code.contains("Red.Large"));
539 assert!(code.contains("Green.Small"));
540 assert!(code.contains("Green.Large"));
541 assert!(code.contains("Blue.Small"));
542 assert!(code.contains("Blue.Large"));
543
544 assert!(code.contains("const _ : () ="));
546 assert!(code.contains("ACTUAL"));
547 assert!(code.contains("EXPECTED"));
548 assert!(code.contains("inner type level count mismatch"));
549 }
550
551 #[test]
552 fn test_interaction_custom_separator() {
553 let input: DeriveInput = syn::parse_quote! {
554 #[r_factor(interaction = ["X", "Y"], sep = "_")]
555 enum AB {
556 A(Inner),
557 B(Inner),
558 }
559 };
560
561 let result = derive_r_factor(input).unwrap();
562 let code = result.to_string();
563
564 assert!(code.contains("A_X"));
566 assert!(code.contains("A_Y"));
567 assert!(code.contains("B_X"));
568 assert!(code.contains("B_Y"));
569 }
570
571 #[test]
572 fn test_interaction_with_rename() {
573 let input: DeriveInput = syn::parse_quote! {
574 #[r_factor(interaction = ["S", "L"], rename_all = "lower")]
575 enum ColorSize {
576 Red(Size),
577 Green(Size),
578 }
579 };
580
581 let result = derive_r_factor(input).unwrap();
582 let code = result.to_string();
583
584 assert!(code.contains("red.S"));
586 assert!(code.contains("red.L"));
587 assert!(code.contains("green.S"));
588 assert!(code.contains("green.L"));
589 }
590}