1use proc_macro2::{Span, TokenStream};
73use quote::{format_ident, quote, quote_spanned};
74use syn::spanned::Spanned;
75use syn::{DeriveInput, LitStr};
76
77use crate::externalptr_derive::{SlotKind, is_rsidecar_type, parse_sidecar_info};
78use crate::miniextendr_impl::{ClassSystem, ParsedMethod};
79
80#[derive(#[automatically_derived]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for Setting { }
#[automatically_derived]
impl ::core::clone::Clone for Setting {
#[inline]
fn clone(&self) -> Self { *self }
}Clone, #[automatically_derived]
impl ::core::marker::Copy for Setting { }Copy, #[automatically_derived]
impl ::core::fmt::Debug for Setting {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::write_str(f,
match self {
Setting::Tolerance => "Tolerance",
Setting::Scale => "Scale",
Setting::CheckAttributes => "CheckAttributes",
Setting::CheckNames => "CheckNames",
})
}
}Debug, #[automatically_derived]
impl ::core::marker::StructuralPartialEq for Setting { }
#[automatically_derived]
impl ::core::cmp::PartialEq for Setting {
#[inline]
fn eq(&self, other: &Self) -> bool {
::core::intrinsics::discriminant_value(self) ==
::core::intrinsics::discriminant_value(other)
}
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for Setting { }Eq)]
84enum Setting {
85 Tolerance,
86 Scale,
87 CheckAttributes,
88 CheckNames,
89}
90
91impl Setting {
92 const ALL: [Self; 4] = [
94 Self::Tolerance,
95 Self::Scale,
96 Self::CheckAttributes,
97 Self::CheckNames,
98 ];
99
100 fn rust_name(self) -> &'static str {
102 match self {
103 Self::Tolerance => "tolerance",
104 Self::Scale => "scale",
105 Self::CheckAttributes => "check_attributes",
106 Self::CheckNames => "check_names",
107 }
108 }
109
110 fn r_name(self) -> &'static str {
112 match self {
113 Self::Tolerance => "tolerance",
114 Self::Scale => "scale",
115 Self::CheckAttributes => "check.attributes",
116 Self::CheckNames => "check.names",
117 }
118 }
119
120 fn before_dots(self) -> bool {
122 #[allow(non_exhaustive_omitted_patterns)] match self {
Self::Tolerance | Self::Scale => true,
_ => false,
}matches!(self, Self::Tolerance | Self::Scale)
123 }
124
125 fn from_path(path: &syn::Path) -> Option<Self> {
126 Self::ALL
127 .into_iter()
128 .find(|setting| path.is_ident(setting.rust_name()))
129 }
130
131 fn parse_value(self, meta: &syn::meta::ParseNestedMeta) -> syn::Result<String> {
134 let expr: syn::Expr = meta.value()?.parse()?;
135 let lit = match &expr {
136 syn::Expr::Lit(lit) => Some(&lit.lit),
137 _ => None,
138 };
139 match self {
140 Self::Tolerance | Self::Scale => {
141 let number = match lit {
142 Some(syn::Lit::Float(lit)) => lit.base10_parse::<f64>().ok(),
143 Some(syn::Lit::Int(lit)) => lit.base10_parse::<f64>().ok(),
144 _ => None,
145 };
146 let (kind, example) = if self == Self::Scale {
147 ("a positive", "scale = 1")
148 } else {
149 ("a non-negative", "tolerance = 1e-6")
150 };
151 match number {
152 Some(n) if n.is_finite() && (n > 0.0 || (n == 0.0 && self != Self::Scale)) => {
153 Ok(r_number(n))
154 }
155 _ => Err(syn::Error::new_spanned(
156 &expr,
157 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`{0}` takes {1} number, e.g. `{2}`",
self.rust_name(), kind, example))
})format!(
158 "`{}` takes {kind} number, e.g. `{example}`",
159 self.rust_name()
160 ),
161 )),
162 }
163 }
164 Self::CheckAttributes | Self::CheckNames => match lit {
165 Some(syn::Lit::Bool(lit)) => {
166 Ok(if lit.value { "TRUE" } else { "FALSE" }.to_owned())
167 }
168 _ => Err(syn::Error::new_spanned(
169 &expr,
170 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`{0}` takes `true` or `false`",
self.rust_name()))
})format!("`{}` takes `true` or `false`", self.rust_name()),
171 )),
172 },
173 }
174 }
175}
176
177fn r_number(n: f64) -> String {
180 if n.fract() == 0.0 && n.abs() < 1e15 {
181 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0:.0}", n))
})format!("{n:.0}")
182 } else {
183 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0:?}", n))
})format!("{n:?}")
184 }
185}
186
187type Settings = Vec<(Setting, String)>;
189
190fn push_setting(
192 settings: &mut Settings,
193 setting: Setting,
194 meta: &syn::meta::ParseNestedMeta,
195) -> syn::Result<()> {
196 if settings.iter().any(|(given, _)| *given == setting) {
197 return Err(meta.error(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`{0}` is given twice",
setting.rust_name()))
})format!("`{}` is given twice", setting.rust_name())));
198 }
199 let value = setting.parse_value(meta)?;
200 settings.push((setting, value));
201 Ok(())
202}
203
204fn setting_value(settings: &Settings, setting: Setting) -> Option<&str> {
206 settings
207 .iter()
208 .find(|(given, _)| *given == setting)
209 .map(|(_, value)| value.as_str())
210}
211
212fn parse_struct_settings(input: &DeriveInput) -> syn::Result<Settings> {
214 let mut settings = Settings::new();
215 for attr in input
216 .attrs
217 .iter()
218 .filter(|a| a.path().is_ident("all_equal"))
219 {
220 attr.parse_nested_meta(|meta| {
221 if let Some(setting) = Setting::from_path(&meta.path) {
222 return push_setting(&mut settings, setting, &meta);
223 }
224 let key = path_name(&meta.path);
225 if ["skip", "label", "with"].contains(&key.as_str()) {
226 Err(meta.error(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`{0}` applies to a field; the struct\'s `#[all_equal(...)]` takes `tolerance`, `scale`, `check_attributes` and `check_names`",
key))
})format!(
227 "`{key}` applies to a field; the struct's `#[all_equal(...)]` takes \
228 `tolerance`, `scale`, `check_attributes` and `check_names`"
229 )))
230 } else {
231 Err(meta.error(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("unknown `all_equal` option `{0}`; the struct\'s `#[all_equal(...)]` takes `tolerance`, `scale`, `check_attributes` and `check_names`",
key))
})format!(
232 "unknown `all_equal` option `{key}`; the struct's `#[all_equal(...)]` takes \
233 `tolerance`, `scale`, `check_attributes` and `check_names`"
234 )))
235 }
236 })?;
237 }
238 Ok(settings)
239}
240
241fn path_name(path: &syn::Path) -> String {
242 {
let mut _s = ::quote::__private::TokenStream::new();
::quote::ToTokens::to_tokens(&path, &mut _s);
_s
}quote!(#path).to_string().replace(' ', "")
243}
244
245#[derive(#[automatically_derived]
impl ::core::default::Default for FieldOptions {
#[inline]
fn default() -> Self {
FieldOptions {
skip: ::core::default::Default::default(),
label: ::core::default::Default::default(),
with: ::core::default::Default::default(),
settings: ::core::default::Default::default(),
}
}
}Default)]
251struct FieldOptions {
252 skip: Option<Span>,
254 label: Option<LitStr>,
256 with: Option<LitStr>,
258 settings: Settings,
260}
261
262fn parse_field_options(field: &syn::Field) -> syn::Result<FieldOptions> {
263 let mut options = FieldOptions::default();
264 let mut other: Option<Span> = None;
266 for attr in field
267 .attrs
268 .iter()
269 .filter(|a| a.path().is_ident("all_equal"))
270 {
271 attr.parse_nested_meta(|meta| {
272 let key = path_name(&meta.path);
273 let twice = || meta.error(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`{0}` is given twice", key))
})format!("`{key}` is given twice"));
274 if key == "skip" {
275 if options.skip.is_some() {
276 return Err(twice());
277 }
278 options.skip = Some(meta.path.span());
279 return Ok(());
280 }
281 other.get_or_insert(meta.path.span());
282 match key.as_str() {
283 "label" => {
284 if options.label.is_some() {
285 return Err(twice());
286 }
287 options.label = Some(meta.value()?.parse()?);
288 }
289 "with" => {
290 if options.with.is_some() {
291 return Err(twice());
292 }
293 options.with = Some(meta.value()?.parse()?);
294 }
295 _ => match Setting::from_path(&meta.path) {
296 Some(setting) => push_setting(&mut options.settings, setting, &meta)?,
297 None => {
298 return Err(meta.error(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("unknown `all_equal` option `{0}`; a field takes `skip`, `label = \"...\"`, `with = \"Self::f\"`, `tolerance`, `scale`, `check_attributes` and `check_names`",
key))
})format!(
299 "unknown `all_equal` option `{key}`; a field takes `skip`, \
300 `label = \"...\"`, `with = \"Self::f\"`, `tolerance`, `scale`, \
301 `check_attributes` and `check_names`"
302 )));
303 }
304 },
305 }
306 Ok(())
307 })?;
308 }
309 if let (Some(skip), Some(_)) = (options.skip, other) {
310 return Err(syn::Error::new(
311 skip,
312 "`skip` leaves the field out of the comparison, so it takes no other option",
313 ));
314 }
315 Ok(options)
316}
317
318enum FieldValue {
320 Converted,
322 Getter(syn::Path, Span),
325 Sidecar(usize),
327 Pointer { optional: bool },
330}
331
332struct ClassWrap {
336 class: String,
337 list: bool,
338 optional: bool,
339}
340
341impl ClassWrap {
342 fn r_expression(&self) -> String {
344 let class = &self.class;
345 let wrapped = if self.list {
346 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!(".__MX_WRAP_LIST_RETURN_{0}__(.val)",
class))
})format!(".__MX_WRAP_LIST_RETURN_{class}__(.val)")
347 } else {
348 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!(".__MX_WRAP_RETURN_{0}__(.val)",
class))
})format!(".__MX_WRAP_RETURN_{class}__(.val)")
349 };
350 if self.optional {
351 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("if (is.null(.val)) NULL else {0}",
wrapped))
})format!("if (is.null(.val)) NULL else {wrapped}")
352 } else {
353 wrapped
354 }
355 }
356}
357
358struct ComparedField {
360 member: syn::Member,
361 ty: syn::Type,
362 name: String,
365 label: Option<String>,
366 settings: Settings,
367 value: FieldValue,
368 wrap: Option<ClassWrap>,
370}
371
372impl ComparedField {
373 fn prefix(&self) -> String {
375 match (&self.label, &self.member) {
376 (Some(label), _) => ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("\"{0}: \"",
crate::naming::r_string_escape(label)))
})format!("\"{}: \"", crate::naming::r_string_escape(label)),
377 (None, syn::Member::Named(_)) => ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("paste0(\"Component \", dQuote(\"{0}\"), \": \")",
crate::naming::r_string_escape(&self.name)))
})format!(
378 "paste0(\"Component \", dQuote(\"{}\"), \": \")",
379 crate::naming::r_string_escape(&self.name)
380 ),
381 (None, syn::Member::Unnamed(_)) => ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("\"Component {0}: \"", self.name))
})format!("\"Component {}: \"", self.name),
382 }
383 }
384}
385
386fn class_wrap(ty: &syn::Type) -> Option<ClassWrap> {
392 let (inner, optional) = match option_inner(ty) {
393 Some(inner) => (inner, true),
394 None => (ty, false),
395 };
396 let (class, list) = match ParsedMethod::vec_inner_class_ident(inner) {
397 Some(class) => (class, true),
398 None => (ParsedMethod::inner_class_ident(inner)?, false),
399 };
400 Some(ClassWrap {
401 class: class.to_string(),
402 list,
403 optional,
404 })
405}
406
407fn option_inner(ty: &syn::Type) -> Option<&syn::Type> {
409 let syn::Type::Path(path) = ty else {
410 return None;
411 };
412 let segment = path.path.segments.last()?;
413 if segment.ident != "Option" {
414 return None;
415 }
416 crate::first_type_argument(segment)
417}
418
419fn is_external_ptr(ty: &syn::Type) -> bool {
421 #[allow(non_exhaustive_omitted_patterns)] match ty {
syn::Type::Path(path) if
path.path.segments.last().is_some_and(|segment|
segment.ident == "ExternalPtr") => true,
_ => false,
}matches!(ty, syn::Type::Path(path)
422 if path.path.segments.last().is_some_and(|segment| segment.ident == "ExternalPtr"))
423}
424
425fn getter_path(lit: &LitStr, struct_name: &syn::Ident) -> syn::Result<syn::Path> {
428 let mut path: syn::Path = lit.parse().map_err(|err| {
429 syn::Error::new_spanned(
430 lit,
431 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`with` must be a path to a getter function, e.g. `Self::f`: {0}",
err))
})format!("`with` must be a path to a getter function, e.g. `Self::f`: {err}"),
432 )
433 })?;
434 if let Some(first) = path.segments.first_mut()
435 && first.ident == "Self"
436 {
437 first.ident = syn::Ident::new(&struct_name.to_string(), first.ident.span());
438 }
439 Ok(path)
440}
441
442fn compared_fields(input: &DeriveInput) -> syn::Result<Vec<ComparedField>> {
444 let syn::Data::Struct(data) = &input.data else {
445 return Err(syn::Error::new_spanned(
446 &input.ident,
447 "`AllEqual` derives on a struct: it compares the struct's fields",
448 ));
449 };
450 let slots = parse_sidecar_info(input, ClassSystem::Env)
453 .map(|info| info.slots)
454 .unwrap_or_default();
455 let mut fields = Vec::new();
456 for (i, field) in data.fields.iter().enumerate() {
457 let options = parse_field_options(field)?;
458 if options.skip.is_some() || is_rsidecar_type(field) {
459 continue;
460 }
461 let member = match &field.ident {
462 Some(ident) => syn::Member::Named(ident.clone()),
463 None => syn::Member::Unnamed(syn::Index::from(i)),
464 };
465 let slot = field
466 .ident
467 .as_ref()
468 .and_then(|ident| slots.iter().find(|slot| slot.name == *ident));
469 let name = match (slot, &field.ident) {
470 (Some(slot), _) => slot.r_name.clone(),
471 (None, Some(ident)) => crate::naming::ident_name(ident),
472 (None, None) => (i + 1).to_string(),
473 };
474 let (value, wrap) = if let Some(with) = &options.with {
475 let getter = getter_path(with, &input.ident)?;
476 (FieldValue::Getter(getter, with.span()), None)
477 } else if let Some(slot) = slot
478 && let SlotKind::Sidecar(index) = slot.kind
479 {
480 (FieldValue::Sidecar(index), None)
481 } else if let Some(slot) = slot
482 && let SlotKind::Computed(path) = &slot.kind
483 {
484 (FieldValue::Getter(path.clone(), field.ty.span()), None)
485 } else {
486 let wrap = class_wrap(&field.ty);
487 let optional = option_inner(&field.ty);
488 let value = match &wrap {
489 Some(ClassWrap { list: false, .. })
491 if is_external_ptr(optional.unwrap_or(&field.ty)) =>
492 {
493 FieldValue::Pointer {
494 optional: optional.is_some(),
495 }
496 }
497 _ => FieldValue::Converted,
498 };
499 (value, wrap)
500 };
501 fields.push(ComparedField {
502 member,
503 ty: field.ty.clone(),
504 name,
505 label: options.label.as_ref().map(LitStr::value),
506 settings: options.settings,
507 value,
508 wrap,
509 });
510 }
511 if fields.is_empty() {
512 return Err(syn::Error::new_spanned(
513 &input.ident,
514 "`#[derive(AllEqual)]` has no field to compare: every field is skipped \
515 (`#[all_equal(skip)]`, or the `RSidecar` selector)",
516 ));
517 }
518 Ok(fields)
519}
520
521fn r_method(c_name: &str, struct_settings: &Settings, fields: &[ComparedField]) -> String {
528 let formal = |setting: Setting| match setting_value(struct_settings, setting) {
529 Some(value) => ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0} = {1}", setting.r_name(),
value))
})format!("{} = {value}", setting.r_name()),
530 None => setting.r_name().to_owned(),
531 };
532 let mut formals = ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
["target".to_owned(), "current".to_owned()]))vec!["target".to_owned(), "current".to_owned()];
533 formals.extend(
534 Setting::ALL
535 .into_iter()
536 .filter(|s| s.before_dots())
537 .map(formal),
538 );
539 formals.push("...".to_owned());
540 formals.extend(
541 Setting::ALL
542 .into_iter()
543 .filter(|s| !s.before_dots())
544 .map(formal),
545 );
546
547 let guard =
548 crate::method_return_builder::condition_check_lines_with_default(" ", "environment()");
549 let mut lines = ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[::alloc::__export::must_use({
::alloc::fmt::format(format_args!("function({0}) {{",
formals.join(", ")))
}),
" if (data.class(target) != data.class(current)) {".to_owned(),
" return(gettextf(\"target is %s, current is %s\", data.class(target), \
data.class(current), domain = \"R-base\"))".to_owned(),
" }".to_owned(), " .settings <- list()".to_owned()]))vec![
550 format!("function({}) {{", formals.join(", ")),
551 " if (data.class(target) != data.class(current)) {".to_owned(),
552 " return(gettextf(\"target is %s, current is %s\", data.class(target), \
553 data.class(current), domain = \"R-base\"))"
554 .to_owned(),
555 " }".to_owned(),
556 " .settings <- list()".to_owned(),
557 ];
558 for setting in Setting::ALL {
559 let r = setting.r_name();
560 let set = ::alloc::__export::must_use({
::alloc::fmt::format(format_args!(".settings[\"{0}\"] <- list({0})",
r))
})format!(".settings[\"{r}\"] <- list({r})");
561 lines.push(if setting_value(struct_settings, setting).is_some() {
562 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!(" {0}", set))
})format!(" {set}")
563 } else {
564 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!(" if (!missing({0})) {1}", r, set))
})format!(" if (!missing({r})) {set}")
565 });
566 }
567 lines.push(" .dots <- list(...)".to_owned());
568 lines.push(" .msg <- character(0)".to_owned());
569 for (i, field) in fields.iter().enumerate() {
570 let index = i + 1;
571 lines.push(::alloc::__export::must_use({
::alloc::fmt::format(format_args!(" # `{0}`", field.name))
})format!(" # `{}`", field.name));
572 for (receiver, var) in [("target", ".target"), ("current", ".current")] {
573 lines.push(::alloc::__export::must_use({
::alloc::fmt::format(format_args!(" .val <- .Call({0}, {1}, {2}L)",
c_name, receiver, index))
})format!(" .val <- .Call({c_name}, {receiver}, {index}L)"));
574 lines.extend(guard.iter().cloned());
575 let value = field.wrap.as_ref().map(ClassWrap::r_expression);
576 lines.push(::alloc::__export::must_use({
::alloc::fmt::format(format_args!(" {1} <- {0}",
value.as_deref().unwrap_or(".val"), var))
})format!(" {var} <- {}", value.as_deref().unwrap_or(".val")));
577 }
578 let args = if field.settings.is_empty() {
579 ".settings"
580 } else {
581 lines.push(" .args <- .settings".to_owned());
582 for setting in Setting::ALL {
583 if let Some(value) = setting_value(&field.settings, setting) {
584 lines.push(::alloc::__export::must_use({
::alloc::fmt::format(format_args!(" .args[\"{0}\"] <- list({1})",
setting.r_name(), value))
})format!(
585 " .args[\"{}\"] <- list({value})",
586 setting.r_name()
587 ));
588 }
589 }
590 ".args"
591 };
592 lines.push(::alloc::__export::must_use({
::alloc::fmt::format(format_args!(" .val <- do.call(all.equal, c(list(.target, .current), {0}, .dots))",
args))
})format!(
593 " .val <- do.call(all.equal, c(list(.target, .current), {args}, .dots))"
594 ));
595 lines.push(::alloc::__export::must_use({
::alloc::fmt::format(format_args!(" if (is.character(.val)) .msg <- c(.msg, paste0({0}, .val))",
field.prefix()))
})format!(
596 " if (is.character(.val)) .msg <- c(.msg, paste0({}, .val))",
597 field.prefix()
598 ));
599 }
600 lines.push(" if (length(.msg)) .msg else TRUE".to_owned());
601 lines.push("}".to_owned());
602 lines.join("\n")
603}
604
605fn r_docs(type_name: &str, struct_settings: &Settings, fields: &[ComparedField]) -> String {
607 let listed: Vec<String> = fields
608 .iter()
609 .map(|field| {
610 let fixed: Vec<String> = Setting::ALL
611 .into_iter()
612 .filter_map(|setting| {
613 setting_value(&field.settings, setting)
614 .map(|value| ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`{0} = {1}`", setting.r_name(),
value))
})format!("`{} = {value}`", setting.r_name()))
615 })
616 .collect();
617 if fixed.is_empty() {
618 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`{0}`", field.name))
})format!("`{}`", field.name)
619 } else {
620 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`{0}` ({1})", field.name,
fixed.join(", ")))
})format!("`{}` ({})", field.name, fixed.join(", "))
621 }
622 })
623 .collect();
624 let listed = match &listed[..] {
625 [one] => one.clone(),
626 [init @ .., last] => ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0} and {1}", init.join(", "),
last))
})format!("{} and {last}", init.join(", ")),
627 [] => {
::core::panicking::panic_fmt(format_args!("internal error: entered unreachable code: {0}",
format_args!("a derive compares at least one field")));
}unreachable!("a derive compares at least one field"),
628 };
629 let defaults: Vec<String> = Setting::ALL
630 .into_iter()
631 .filter_map(|setting| {
632 setting_value(struct_settings, setting)
633 .map(|value| ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`{0} = {1}`", setting.r_name(),
value))
})format!("`{} = {value}`", setting.r_name()))
634 })
635 .collect();
636 let defaults = if defaults.is_empty() {
637 String::new()
638 } else {
639 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("\n#\' The type\'s defaults are {0}.",
match &defaults[..] {
[one] => one.clone(),
[init @ .., last] =>
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0} and {1}",
init.join(", "), last))
}),
[] =>
::core::panicking::panic("internal error: entered unreachable code"),
}))
})format!(
640 "\n#' The type's defaults are {}.",
641 match &defaults[..] {
642 [one] => one.clone(),
643 [init @ .., last] => format!("{} and {last}", init.join(", ")),
644 [] => unreachable!(),
645 }
646 )
647 };
648 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("#\' The `all.equal()` method of the Rust type `{0}`, from\n#\' `#[derive(AllEqual)]`. It compares `target` and `current` field by field,\n#\' each field with `all.equal()`, which dispatches on the field\'s own class.\n#\' The fields compared: {1}.\n#\'\n#\' @param target,current The objects to compare.\n#\' @param tolerance,scale,check.attributes,check.names Passed on to the\n#\' comparison of each field when the call or the type gives them, unless\n#\' the field fixes its own; see [base::all.equal()].{2}\n#\' @param ... Passed on to the comparison of each field.\n#\' @return `TRUE` when every field is equal, otherwise a character vector of\n#\' the differences, each prefixed with its field.",
type_name, listed, defaults))
})format!(
649 "#' The `all.equal()` method of the Rust type `{type_name}`, from\n\
650 #' `#[derive(AllEqual)]`. It compares `target` and `current` field by field,\n\
651 #' each field with `all.equal()`, which dispatches on the field's own class.\n\
652 #' The fields compared: {listed}.\n\
653 #'\n\
654 #' @param target,current The objects to compare.\n\
655 #' @param tolerance,scale,check.attributes,check.names Passed on to the\n\
656 #' comparison of each field when the call or the type gives them, unless\n\
657 #' the field fixes its own; see [base::all.equal()].{defaults}\n\
658 #' @param ... Passed on to the comparison of each field.\n\
659 #' @return `TRUE` when every field is equal, otherwise a character vector of\n\
660 #' the differences, each prefixed with its field."
661 )
662}
663
664pub(crate) fn derive_all_equal(input: DeriveInput) -> syn::Result<TokenStream> {
668 if !input.generics.params.is_empty() {
669 return Err(syn::Error::new_spanned(
670 &input.generics,
671 "`AllEqual` does not support generic structs: its `.Call` entry cannot be generic",
672 ));
673 }
674 let struct_settings = parse_struct_settings(&input)?;
675 let fields = compared_fields(&input)?;
676
677 let name = &input.ident;
678 let type_name = crate::naming::ident_name(name);
679 let c_name = crate::naming::all_equal_c_name(&type_name);
680 let c_ident = ::quote::__private::mk_ident(&::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}", c_name))
}), ::quote::__private::Option::None)format_ident!("{c_name}");
681
682 let arms = fields.iter().enumerate().map(|(i, field)| {
683 let index = i32::try_from(i + 1).expect("a struct has fewer than i32::MAX fields");
684 let member = &field.member;
685 let borrow = {
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "let");
::quote::__private::push_ident(&mut _s, "__mx_data");
::quote::__private::push_eq(&mut _s);
::quote::__private::push_ident(&mut _s, "unsafe");
::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, "externalptr");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "sidecar_r_struct");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_lt(&mut _s);
::quote::ToTokens::to_tokens(&name, &mut _s);
::quote::__private::push_gt(&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, "x");
_s
});
_s
});
::quote::__private::push_semi(&mut _s);
::quote::__private::push_ident(&mut _s, "let");
::quote::__private::push_ident(&mut _s, "__mx_value");
::quote::__private::push_colon(&mut _s);
::quote::__private::push_and(&mut _s);
::quote::ToTokens::to_tokens(&name, &mut _s);
::quote::__private::push_eq(&mut _s);
::quote::__private::push_and(&mut _s);
::quote::__private::push_ident(&mut _s, "__mx_data");
::quote::__private::push_semi(&mut _s);
_s
}quote! {
686 let __mx_data = unsafe { ::miniextendr_api::externalptr::sidecar_r_struct::<#name>(x) };
687 let __mx_value: &#name = &__mx_data;
688 };
689 let body = match &field.value {
690 FieldValue::Converted => {
693 let convert = {
let mut _s = ::quote::__private::TokenStream::new();
let _span: ::quote::__private::Span =
::quote::__private::get_span(field.ty.span()).__into_span();
::quote::__private::push_colon2_spanned(&mut _s, _span);
::quote::__private::push_ident_spanned(&mut _s, _span, "miniextendr_api");
::quote::__private::push_colon2_spanned(&mut _s, _span);
::quote::__private::push_ident_spanned(&mut _s, _span, "into_r");
::quote::__private::push_colon2_spanned(&mut _s, _span);
::quote::__private::push_ident_spanned(&mut _s, _span, "IntoR");
::quote::__private::push_colon2_spanned(&mut _s, _span);
::quote::__private::push_ident_spanned(&mut _s, _span, "into_sexp");
::quote::__private::push_group_spanned(&mut _s, _span,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
let _span: ::quote::__private::Span =
::quote::__private::get_span(_span).__into_span();
::quote::__private::push_colon2_spanned(&mut _s, _span);
::quote::__private::push_ident_spanned(&mut _s, _span, "core");
::quote::__private::push_colon2_spanned(&mut _s, _span);
::quote::__private::push_ident_spanned(&mut _s, _span, "clone");
::quote::__private::push_colon2_spanned(&mut _s, _span);
::quote::__private::push_ident_spanned(&mut _s, _span, "Clone");
::quote::__private::push_colon2_spanned(&mut _s, _span);
::quote::__private::push_ident_spanned(&mut _s, _span, "clone");
::quote::__private::push_group_spanned(&mut _s, _span,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
let _span: ::quote::__private::Span =
::quote::__private::get_span(_span).__into_span();
::quote::__private::push_and_spanned(&mut _s, _span);
::quote::__private::push_ident_spanned(&mut _s, _span,
"__mx_value");
::quote::__private::push_dot_spanned(&mut _s, _span);
::quote::ToTokens::to_tokens(&member, &mut _s);
_s
});
::quote::__private::push_comma_spanned(&mut _s, _span);
_s
});
_s
}quote_spanned! {field.ty.span()=>
694 ::miniextendr_api::into_r::IntoR::into_sexp(
695 ::core::clone::Clone::clone(&__mx_value.#member),
696 )
697 };
698 {
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Brace,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::ToTokens::to_tokens(&borrow, &mut _s);
::quote::ToTokens::to_tokens(&convert, &mut _s);
_s
});
_s
}quote! {{ #borrow #convert }}
699 }
700 FieldValue::Getter(path, span) => {
701 let convert = {
let mut _s = ::quote::__private::TokenStream::new();
let _span: ::quote::__private::Span =
::quote::__private::get_span(*span).__into_span();
::quote::__private::push_colon2_spanned(&mut _s, _span);
::quote::__private::push_ident_spanned(&mut _s, _span, "miniextendr_api");
::quote::__private::push_colon2_spanned(&mut _s, _span);
::quote::__private::push_ident_spanned(&mut _s, _span, "into_r");
::quote::__private::push_colon2_spanned(&mut _s, _span);
::quote::__private::push_ident_spanned(&mut _s, _span, "IntoR");
::quote::__private::push_colon2_spanned(&mut _s, _span);
::quote::__private::push_ident_spanned(&mut _s, _span, "into_sexp");
::quote::__private::push_group_spanned(&mut _s, _span,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
let _span: ::quote::__private::Span =
::quote::__private::get_span(_span).__into_span();
::quote::ToTokens::to_tokens(&path, &mut _s);
::quote::__private::push_group_spanned(&mut _s, _span,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
let _span: ::quote::__private::Span =
::quote::__private::get_span(_span).__into_span();
::quote::__private::push_ident_spanned(&mut _s, _span,
"__mx_value");
_s
});
_s
});
_s
}quote_spanned! {*span=>
702 ::miniextendr_api::into_r::IntoR::into_sexp(#path(__mx_value))
703 };
704 {
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Brace,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::ToTokens::to_tokens(&borrow, &mut _s);
::quote::ToTokens::to_tokens(&convert, &mut _s);
_s
});
_s
}quote! {{ #borrow #convert }}
705 }
706 FieldValue::Sidecar(index) => {
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "unsafe");
::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, "externalptr");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "sidecar_r_get");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_lt(&mut _s);
::quote::ToTokens::to_tokens(&name, &mut _s);
::quote::__private::push_gt(&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, "x");
::quote::__private::push_comma(&mut _s);
::quote::ToTokens::to_tokens(&index, &mut _s);
::quote::__private::push_comma(&mut _s);
::quote::__private::push_ident(&mut _s, "true");
_s
});
_s
});
_s
}quote! {
707 unsafe { ::miniextendr_api::externalptr::sidecar_r_get::<#name>(x, #index, true) }
708 },
709 FieldValue::Pointer { optional: false } => {
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Brace,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::ToTokens::to_tokens(&borrow, &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, "into_r");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "IntoR");
::quote::__private::push_colon2(&mut _s);
::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_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "miniextendr_api");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "externalptr");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "ExternalPtr");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "same_object");
::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_ident(&mut _s, "__mx_value");
::quote::__private::push_dot(&mut _s);
::quote::ToTokens::to_tokens(&member, &mut _s);
_s
});
::quote::__private::push_comma(&mut _s);
_s
});
_s
});
_s
}quote! {{
710 #borrow
711 ::miniextendr_api::into_r::IntoR::into_sexp(
712 ::miniextendr_api::externalptr::ExternalPtr::same_object(&__mx_value.#member),
713 )
714 }},
715 FieldValue::Pointer { optional: true } => {
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Brace,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::ToTokens::to_tokens(&borrow, &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, "into_r");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "IntoR");
::quote::__private::push_colon2(&mut _s);
::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_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, "map");
::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, "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, "as_ref");
::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_ident(&mut _s, "__mx_value");
::quote::__private::push_dot(&mut _s);
::quote::ToTokens::to_tokens(&member, &mut _s);
_s
});
::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, "externalptr");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "ExternalPtr");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "same_object");
::quote::__private::push_comma(&mut _s);
_s
});
_s
});
_s
});
_s
}quote! {{
716 #borrow
717 ::miniextendr_api::into_r::IntoR::into_sexp(::core::option::Option::map(
718 ::core::option::Option::as_ref(&__mx_value.#member),
719 ::miniextendr_api::externalptr::ExternalPtr::same_object,
720 ))
721 }},
722 };
723 {
let mut _s = ::quote::__private::TokenStream::new();
::quote::ToTokens::to_tokens(&index, &mut _s);
::quote::__private::push_fat_arrow(&mut _s);
::quote::ToTokens::to_tokens(&body, &mut _s);
::quote::__private::push_comma(&mut _s);
_s
}quote! { #index => #body, }
724 });
725
726 let def_ident = ::quote::__private::mk_ident(&::alloc::__export::must_use({
::alloc::fmt::format(format_args!("__MX_CALL_DEF_ALL_EQUAL_{0}",
type_name))
}), ::quote::__private::Option::None)format_ident!("__MX_CALL_DEF_ALL_EQUAL_{type_name}");
727 let registration = crate::call_method_def::call_method_def(&def_ident, &c_ident, 2);
728 let entry_ident = ::quote::__private::mk_ident(&::alloc::__export::must_use({
::alloc::fmt::format(format_args!("__MX_ALL_EQUAL_{0}",
type_name))
}), ::quote::__private::Option::None)format_ident!("__MX_ALL_EQUAL_{type_name}");
729 let c_doc =
730 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("Generated field reader of the `all.equal()` method of Rust type `{0}`.",
type_name))
})format!("Generated field reader of the `all.equal()` method of Rust type `{type_name}`.");
731 let source_location_doc = crate::source_location_doc(name.span());
732 let start = name.span().start();
733 let source_line = syn::LitInt::new(&start.line.to_string(), name.span());
734 let source_column = syn::LitInt::new(&(start.column + 1).to_string(), name.span());
735 let method = LitStr::new(&r_method(&c_name, &struct_settings, &fields), name.span());
736 let docs = LitStr::new(&r_docs(&type_name, &struct_settings, &fields), name.span());
737
738 Ok({
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_pound(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Bracket,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "doc");
::quote::__private::push_eq(&mut _s);
::quote::ToTokens::to_tokens(&c_doc, &mut _s);
_s
});
::quote::__private::push_pound(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Bracket,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "doc");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "hidden");
_s
});
_s
});
::quote::__private::push_pound(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Bracket,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "unsafe");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "no_mangle");
_s
});
_s
});
::quote::__private::push_pound(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Bracket,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "allow");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "non_snake_case");
_s
});
_s
});
::quote::__private::push_pound(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Bracket,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "allow");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "clippy");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "clone_on_copy");
_s
});
_s
});
::quote::__private::push_ident(&mut _s, "pub");
::quote::__private::push_ident(&mut _s, "unsafe");
::quote::__private::push_ident(&mut _s, "extern");
::quote::__private::parse(&mut _s, "\"C-unwind\"");
::quote::__private::push_ident(&mut _s, "fn");
::quote::ToTokens::to_tokens(&c_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, "x");
::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");
::quote::__private::push_comma(&mut _s);
::quote::__private::push_ident(&mut _s, "i");
::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");
::quote::__private::push_comma(&mut _s);
_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, "let");
::quote::__private::push_ident(&mut _s,
"__miniextendr_deferred_mark");
::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, "deferred_condition");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "mark");
::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, "__miniextendr_value");
::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, "unwind_protect");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "with_r_unwind_protect");
::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_ident(&mut _s, "let");
::quote::__private::push_ident(&mut _s, "__mx_index");
::quote::__private::push_colon(&mut _s);
::quote::__private::push_ident(&mut _s, "i32");
::quote::__private::push_eq(&mut _s);
::quote::__private::push_ident(&mut _s, "match");
::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_colon2(&mut _s);
::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, "i");
_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, "index");
_s
});
::quote::__private::push_fat_arrow(&mut _s);
::quote::__private::push_ident(&mut _s, "index");
::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, "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, "Err");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "err");
_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_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "core");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "panic");
::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::parse(&mut _s,
"\"`all.equal()` reads a field by its position: {err}\"");
_s
});
_s
});
_s
});
::quote::__private::push_semi(&mut _s);
::quote::__private::push_ident(&mut _s, "match");
::quote::__private::push_ident(&mut _s, "__mx_index");
::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 arms, i) = arms.quote_into_iter();
let has_iter = has_iter | i;
<_ as
::quote::__private::CheckHasIterator<true>>::check(has_iter);
while true {
let arms =
match arms.next() {
Some(_x) => ::quote::__private::RepInterp(_x),
None => break,
};
::quote::ToTokens::to_tokens(&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, "panic");
::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::parse(&mut _s,
"\"`all.equal()` compares no field {} of `{}`\"");
::quote::__private::push_comma(&mut _s);
::quote::__private::push_ident(&mut _s, "__mx_index");
::quote::__private::push_comma(&mut _s);
::quote::ToTokens::to_tokens(&type_name, &mut _s);
::quote::__private::push_comma(&mut _s);
_s
});
::quote::__private::push_comma(&mut _s);
_s
});
_s
});
::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, "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
});
::quote::__private::push_semi(&mut _s);
::quote::__private::push_ident(&mut _s, "unsafe");
::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,
"deferred_condition");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "finish");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s,
"__miniextendr_deferred_mark");
::quote::__private::push_comma(&mut _s);
::quote::__private::push_ident(&mut _s,
"__miniextendr_value");
::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, "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_pound(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Bracket,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "doc");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "hidden");
_s
});
_s
});
::quote::ToTokens::to_tokens(®istration, &mut _s);
::quote::__private::push_pound(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Bracket,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "doc");
::quote::__private::push_eq(&mut _s);
::quote::__private::parse(&mut _s,
"r\" The `all.equal()` method\'s R source, via distributed slice.\"");
_s
});
::quote::__private::push_pound(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Bracket,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "doc");
::quote::__private::push_eq(&mut _s);
::quote::ToTokens::to_tokens(&source_location_doc, &mut _s);
_s
});
::quote::__private::push_pound(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Bracket,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "doc");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "hidden");
_s
});
_s
});
::quote::__private::push_pound(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Bracket,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "cfg_attr");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "not");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "target_arch");
::quote::__private::push_eq(&mut _s);
::quote::__private::parse(&mut _s, "\"wasm32\"");
_s
});
::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, "linkme");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s,
"distributed_slice");
::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, "miniextendr_api");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "registry");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "MX_ALL_EQUAL");
_s
});
::quote::__private::push_comma(&mut _s);
::quote::__private::push_ident(&mut _s, "linkme");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "crate");
::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, "linkme");
_s
});
_s
});
_s
});
::quote::__private::push_pound(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Bracket,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "allow");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s,
"non_upper_case_globals");
_s
});
_s
});
::quote::__private::push_ident(&mut _s, "static");
::quote::ToTokens::to_tokens(&entry_ident, &mut _s);
::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, "registry");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "AllEqualEntry");
::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, "registry");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "AllEqualEntry");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Brace,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "rust_type");
::quote::__private::push_colon(&mut _s);
::quote::ToTokens::to_tokens(&type_name, &mut _s);
::quote::__private::push_comma(&mut _s);
::quote::__private::push_ident(&mut _s, "method");
::quote::__private::push_colon(&mut _s);
::quote::ToTokens::to_tokens(&method, &mut _s);
::quote::__private::push_comma(&mut _s);
::quote::__private::push_ident(&mut _s, "docs");
::quote::__private::push_colon(&mut _s);
::quote::ToTokens::to_tokens(&docs, &mut _s);
::quote::__private::push_comma(&mut _s);
::quote::__private::push_ident(&mut _s, "source_file");
::quote::__private::push_colon(&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, "file");
::quote::__private::push_bang(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
::quote::__private::TokenStream::new());
::quote::__private::push_comma(&mut _s);
::quote::__private::push_ident(&mut _s, "source_line");
::quote::__private::push_colon(&mut _s);
::quote::ToTokens::to_tokens(&source_line, &mut _s);
::quote::__private::push_comma(&mut _s);
::quote::__private::push_ident(&mut _s, "source_column");
::quote::__private::push_colon(&mut _s);
::quote::ToTokens::to_tokens(&source_column, &mut _s);
::quote::__private::push_comma(&mut _s);
_s
});
::quote::__private::push_semi(&mut _s);
_s
}quote! {
739 #[doc = #c_doc]
740 #[doc(hidden)]
741 #[unsafe(no_mangle)]
742 #[allow(non_snake_case)]
743 #[allow(clippy::clone_on_copy)]
746 pub unsafe extern "C-unwind" fn #c_ident(
747 x: ::miniextendr_api::SEXP,
748 i: ::miniextendr_api::SEXP,
749 ) -> ::miniextendr_api::SEXP {
750 let __miniextendr_deferred_mark = ::miniextendr_api::deferred_condition::mark();
751 let __miniextendr_value = ::miniextendr_api::unwind_protect::with_r_unwind_protect(
752 || {
753 let __mx_index: i32 = match ::miniextendr_api::TryFromSexp::try_from_sexp(i) {
754 ::core::result::Result::Ok(index) => index,
755 ::core::result::Result::Err(err) => {
756 ::core::panic!("`all.equal()` reads a field by its position: {err}")
757 }
758 };
759 match __mx_index {
760 #(#arms)*
761 _ => ::core::panic!(
762 "`all.equal()` compares no field {} of `{}`",
763 __mx_index,
764 #type_name,
765 ),
766 }
767 },
768 ::core::option::Option::None,
769 );
770 unsafe {
771 ::miniextendr_api::deferred_condition::finish(
772 __miniextendr_deferred_mark,
773 __miniextendr_value,
774 ::core::option::Option::None,
775 )
776 }
777 }
778
779 #[doc(hidden)]
780 #registration
781
782 #[doc = #source_location_doc]
784 #[doc(hidden)]
785 #[cfg_attr(not(target_arch = "wasm32"), ::miniextendr_api::linkme::distributed_slice(::miniextendr_api::registry::MX_ALL_EQUAL), linkme(crate = ::miniextendr_api::linkme))]
786 #[allow(non_upper_case_globals)]
787 static #entry_ident: ::miniextendr_api::registry::AllEqualEntry =
788 ::miniextendr_api::registry::AllEqualEntry {
789 rust_type: #type_name,
790 method: #method,
791 docs: #docs,
792 source_file: ::core::file!(),
793 source_line: #source_line,
794 source_column: #source_column,
795 };
796 })
797}
798
799#[cfg(test)]
800mod tests;