This commit is contained in:
2026-04-13 08:04:43 -03:00
parent 0486f2a285
commit 3a5a7a17a3
71 changed files with 9385 additions and 0 deletions

1
vendor/arma-rs-proc/.cargo-ok vendored Normal file
View File

@@ -0,0 +1 @@
{"v":1}

View File

@@ -0,0 +1,6 @@
{
"git": {
"sha1": "adfc323899e58f20c05ebb37595d5ca4fd09367f"
},
"path_in_vcs": "arma-rs-proc"
}

42
vendor/arma-rs-proc/Cargo.toml vendored Normal file
View File

@@ -0,0 +1,42 @@
# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
#
# When uploading crates to the registry Cargo will automatically
# "normalize" Cargo.toml files for maximal compatibility
# with all versions of Cargo and also rewrite `path` dependencies
# to registry (e.g., crates.io) dependencies.
#
# If you are reading this file be aware that the original Cargo.toml
# will likely look very different (and much more reasonable).
# See Cargo.toml.orig for the original contents.
[package]
edition = "2021"
name = "arma-rs-proc"
version = "1.11.1"
authors = ["Brett Mayson"]
build = false
autolib = false
autobins = false
autoexamples = false
autotests = false
autobenches = false
description = "proc macros for arma-rs"
readme = false
keywords = ["arma"]
license = "MIT"
repository = "https://github.com/brettmayson/arma-rs"
[lib]
name = "arma_rs_proc"
path = "src/lib.rs"
proc-macro = true
[dependencies.proc-macro2]
version = "1.0.92"
[dependencies.quote]
version = "1.0.37"
[dependencies.syn]
version = "2.0.90"
features = ["full"]

17
vendor/arma-rs-proc/Cargo.toml.orig generated vendored Normal file
View File

@@ -0,0 +1,17 @@
[package]
name = "arma-rs-proc"
description = "proc macros for arma-rs"
version = "1.11.1"
edition = "2021"
authors = ["Brett Mayson"]
repository = "https://github.com/brettmayson/arma-rs"
license = "MIT"
keywords = ["arma"]
[lib]
proc-macro = true
[dependencies]
proc-macro2 = "1.0.92"
quote = "1.0.37"
syn = { version = "2.0.90", features = ["full"] }

View File

@@ -0,0 +1,145 @@
use syn::{Error, Result};
use crate::derive::CombinedErrors;
pub struct ContainerAttributes {
pub transparent: Attribute<bool>,
pub default: Attribute<bool>,
}
impl Default for ContainerAttributes {
fn default() -> Self {
Self {
transparent: Attribute::new(false),
default: Attribute::new(false),
}
}
}
impl ParseAttr for ContainerAttributes {
fn parse_attr(&mut self, meta: syn::meta::ParseNestedMeta) -> Result<()> {
if meta.path.is_ident("transparent") {
return self.transparent.set(&meta, true);
}
if meta.path.is_ident("default") {
return self.default.set(&meta, true);
}
Err(meta.error(format!(
"unknown arma container attribute `{}`",
path_to_string(&meta.path)
)))
}
}
pub struct FieldAttributes {
pub default: Attribute<bool>,
pub from_str: Attribute<bool>,
pub to_string: Attribute<bool>,
}
impl Default for FieldAttributes {
fn default() -> Self {
Self {
default: Attribute::new(false),
from_str: Attribute::new(false),
to_string: Attribute::new(false),
}
}
}
impl ParseAttr for FieldAttributes {
fn parse_attr(&mut self, meta: syn::meta::ParseNestedMeta) -> Result<()> {
if meta.path.is_ident("default") {
return self.default.set(&meta, true);
}
if meta.path.is_ident("from_str") {
return self.from_str.set(&meta, true);
}
if meta.path.is_ident("to_string") {
return self.to_string.set(&meta, true);
}
Err(meta.error(format!(
"unknown arma field attribute `{}`",
path_to_string(&meta.path)
)))
}
}
pub trait ParseAttr {
fn parse_attr(&mut self, meta: syn::meta::ParseNestedMeta) -> Result<()>;
}
pub fn parse_attributes<T>(errors: &mut CombinedErrors, attrs: &[syn::Attribute]) -> T
where
T: ParseAttr + Default + Sized,
{
attrs.iter().fold(T::default(), |mut attributes, attr| {
if !attr.path().is_ident("arma") {
return attributes;
}
let result = attr.parse_nested_meta(|meta| {
if let Err(err) = attributes.parse_attr(meta) {
errors.add(err);
}
Ok(())
});
if let Err(err) = result {
errors.add(err);
}
attributes
})
}
pub struct Attribute<T> {
value: T,
path: Option<syn::Path>,
}
impl<T> Attribute<T> {
fn new(default: T) -> Self {
Self {
value: default,
path: None,
}
}
fn set(&mut self, meta: &syn::meta::ParseNestedMeta, value: T) -> Result<()> {
if self.is_set() {
return Err(meta.error(format!(
"duplicate arma attribute `{}`",
path_to_string(&meta.path)
)));
}
self.value = value;
self.path = Some(meta.path.clone());
Ok(())
}
pub fn is_set(&self) -> bool {
self.path.is_some()
}
pub fn value(&self) -> &T {
&self.value
}
#[must_use]
pub fn error(&self, message: &str) -> Error {
Error::new_spanned(self.path.as_ref().unwrap(), message)
}
}
fn path_to_string(path: &syn::Path) -> String {
path.segments
.iter()
.map(|s| s.ident.to_string())
.collect::<Vec<_>>()
.join("::")
}

124
vendor/arma-rs-proc/src/derive/data.rs vendored Normal file
View File

@@ -0,0 +1,124 @@
use proc_macro2::{Span, TokenStream};
use quote::ToTokens;
use syn::{Error, Result};
use crate::derive::{
attributes::{parse_attributes, ContainerAttributes, FieldAttributes},
r#struct, CombinedErrors,
};
pub struct ContainerData {
pub attributes: ContainerAttributes,
pub ident: syn::Ident,
pub generics: syn::Generics,
pub data: Data,
}
pub enum Data {
Struct(StructData),
}
pub enum StructData {
Map(Vec<FieldNamed>),
Tuple(Vec<FieldUnnamed>),
NewType(FieldUnnamed),
}
impl ContainerData {
pub fn from_input(errors: &mut CombinedErrors, input: syn::DeriveInput) -> Result<Self> {
let data = match input.data {
syn::Data::Struct(data) => Data::Struct(StructData::new(errors, data)?),
syn::Data::Enum(_) => Err(Error::new(Span::call_site(), "enums aren't supported"))?,
syn::Data::Union(_) => Err(Error::new(Span::call_site(), "unions aren't supported"))?,
};
let attributes = parse_attributes::<ContainerAttributes>(errors, &input.attrs);
Ok(Self {
attributes,
ident: input.ident,
generics: input.generics,
data,
})
}
pub fn validate_attributes(&self, errors: &mut CombinedErrors) {
match self.data {
Data::Struct(ref data) => {
r#struct::validate_attributes(errors, &self.attributes, data);
}
}
}
pub fn impl_into_arma(&self) -> TokenStream {
match self.data {
Data::Struct(ref data) => r#struct::impl_into_arma(&self.attributes, data),
}
}
pub fn impl_from_arma(&self) -> TokenStream {
match self.data {
Data::Struct(ref data) => r#struct::impl_from_arma(&self.attributes, data),
}
}
}
pub struct FieldNamed {
pub attributes: FieldAttributes,
pub ident: syn::Ident,
pub name: String,
pub _ty: syn::Type,
}
pub struct FieldUnnamed {
pub attributes: FieldAttributes,
pub index: syn::Index,
pub ty: syn::Type,
}
impl FieldNamed {
pub fn new(errors: &mut CombinedErrors, field: syn::Field) -> Self {
let ident = field.ident.unwrap();
let name = ident.to_string();
Self {
attributes: parse_attributes::<FieldAttributes>(errors, &field.attrs),
ident,
name,
_ty: field.ty,
}
}
}
impl FieldUnnamed {
pub fn new(errors: &mut CombinedErrors, field: syn::Field, index: usize) -> Self {
Self {
attributes: parse_attributes::<FieldAttributes>(errors, &field.attrs),
index: syn::Index::from(index),
ty: field.ty,
}
}
}
pub trait Field {
fn attributes(&self) -> &FieldAttributes;
fn token(&self) -> TokenStream;
}
impl Field for FieldNamed {
fn attributes(&self) -> &FieldAttributes {
&self.attributes
}
fn token(&self) -> TokenStream {
self.ident.to_token_stream()
}
}
impl Field for FieldUnnamed {
fn attributes(&self) -> &FieldAttributes {
&self.attributes
}
fn token(&self) -> TokenStream {
self.index.to_token_stream()
}
}

72
vendor/arma-rs-proc/src/derive/mod.rs vendored Normal file
View File

@@ -0,0 +1,72 @@
mod attributes;
mod data;
mod r#struct;
use proc_macro2::TokenStream;
use quote::quote;
use syn::{DeriveInput, Result};
use data::ContainerData;
pub fn generate_from_arma(input: DeriveInput) -> Result<TokenStream> {
let container = parse_container_data(input)?;
let body = container.impl_from_arma();
let ident = container.ident;
let (impl_generics, ty_generics, where_clause) = container.generics.split_for_impl();
Ok(quote! {
#[automatically_derived]
impl #impl_generics arma_rs::FromArma for #ident #ty_generics #where_clause {
fn from_arma(func_input: String) -> Result<Self, arma_rs::FromArmaError> {
#body
}
}
})
}
pub fn generate_into_arma(input: DeriveInput) -> Result<TokenStream> {
let container = parse_container_data(input)?;
let body = container.impl_into_arma();
let ident = container.ident;
let (impl_generics, ty_generics, where_clause) = container.generics.split_for_impl();
Ok(quote! {
#[automatically_derived]
impl #impl_generics arma_rs::IntoArma for #ident #ty_generics #where_clause {
fn to_arma(&self) -> arma_rs::Value {
#body
}
}
})
}
fn parse_container_data(input: DeriveInput) -> Result<ContainerData> {
let mut errors = CombinedErrors::new();
let container = ContainerData::from_input(&mut errors, input)?;
container.validate_attributes(&mut errors);
errors.into_result().and(Ok(container))
}
pub struct CombinedErrors {
root: Option<syn::Error>,
}
impl CombinedErrors {
fn new() -> Self {
Self { root: None }
}
pub fn add(&mut self, error: syn::Error) {
match &mut self.root {
Some(root) => root.combine(error),
None => self.root = Some(error),
}
}
pub fn into_result(self) -> Result<()> {
match self.root {
Some(error) => Err(error),
None => Ok(()),
}
}
}

View File

@@ -0,0 +1,162 @@
use proc_macro2::TokenStream;
use quote::quote;
use crate::derive::{
attributes::ContainerAttributes,
data::{Field, FieldNamed, FieldUnnamed, StructData},
};
pub fn impl_from_arma(attributes: &ContainerAttributes, data: &StructData) -> TokenStream {
// For simplicity sake we assume that theres no conflicts and everything has already been validated
match &data {
StructData::Map(fields) => map_struct(attributes, fields),
StructData::Tuple(fields) => tuple_struct(attributes, fields),
StructData::NewType(field) => newtype_struct(attributes, field),
}
}
fn map_struct(attributes: &ContainerAttributes, fields: &[FieldNamed]) -> TokenStream {
if *attributes.transparent.value() {
return newtype_struct(attributes, fields.first().unwrap());
}
let mut setup = TokenStream::new();
setup.extend(quote! {
let mut input_as_values = std::collections::HashMap::<String, arma_rs::Value>::default();
let input_pairs: Vec<(String, arma_rs::Value)> = FromArma::from_arma(func_input)?;
for (k, v) in input_pairs {
if input_as_values.insert(k.clone(), v).is_some() {
return Err(arma_rs::FromArmaError::DuplicateField(k));
}
}
});
if *attributes.default.value() {
setup.extend(quote! {
let container_default: Self = std::default::Default::default();
});
};
let field_bodies = fields.iter().map(|field| {
let (ident, name) = (&field.ident, &field.name);
let some_match = if *field.attributes.from_str.value() {
quote!(input_value
.to_string()
.parse()
.map_err(arma_rs::FromArmaError::custom)?)
} else {
quote!(arma_rs::FromArma::from_arma(input_value.to_string())?)
};
let none_match = if *field.attributes.default.value() {
quote!(std::default::Default::default())
} else if *attributes.default.value() {
quote!(container_default.#ident)
} else {
quote!(return Err(arma_rs::FromArmaError::MissingField(#name.to_string())))
};
quote! {
#ident: match input_as_values.remove(#name) {
Some(input_value) => #some_match,
None => #none_match,
}
}
});
let check_unknown = quote! {
if let Some(unknown) = input_as_values.keys().next() {
return Err(arma_rs::FromArmaError::UnknownField(unknown.clone()));
}
};
quote! {
#setup
let result = Self {
#(#field_bodies),*
};
#check_unknown
Ok(result)
}
}
fn tuple_struct(attributes: &ContainerAttributes, fields: &[FieldUnnamed]) -> TokenStream {
let mut setup = TokenStream::new();
setup.extend(quote! {
let input_as_values: Vec<arma_rs::Value> = arma_rs::FromArma::from_arma(func_input)?;
let mut input_as_values = input_as_values.into_iter();
});
if *attributes.default.value() {
setup.extend(quote! {
let container_default: Self = std::default::Default::default();
});
};
let expected_len = fields.len();
let field_bodies = fields.iter().map(|field| {
let index = &field.index;
let some_match = if *field.attributes.from_str.value() {
quote!(input_value
.to_string()
.parse()
.map_err(arma_rs::FromArmaError::custom)?)
} else {
quote!(arma_rs::FromArma::from_arma(input_value.to_string())?)
};
let none_match = if *field.attributes.default.value() {
quote!(std::default::Default::default())
} else if *attributes.default.value() {
quote!(container_default.#index)
} else {
quote!(return Err(arma_rs::FromArmaError::InvalidLength {
expected: #expected_len,
actual: #index,
}))
};
quote! {
match input_as_values.next() {
Some(input_value) => #some_match,
None => #none_match,
}
}
});
let check_unknown = quote! {
let remaining = input_as_values.len();
if remaining > 0 {
return Err(arma_rs::FromArmaError::InvalidLength {
expected: #expected_len,
actual: #expected_len + remaining,
});
}
};
quote! {
#setup
let result = Self (
#(#field_bodies),*
);
#check_unknown
Ok(result)
}
}
fn newtype_struct(_attributes: &ContainerAttributes, field: &impl Field) -> TokenStream {
let token = field.token();
let field_body = if *field.attributes().from_str.value() {
quote!(func_input.parse().map_err(arma_rs::FromArmaError::custom)?)
} else {
quote!(arma_rs::FromArma::from_arma(func_input)?)
};
quote! {
Ok(Self {
#token: #field_body
})
}
}

View File

@@ -0,0 +1,72 @@
use proc_macro2::TokenStream;
use quote::quote;
use crate::derive::{
attributes::ContainerAttributes,
data::{Field, FieldNamed, FieldUnnamed, StructData},
};
pub fn impl_into_arma(attributes: &ContainerAttributes, data: &StructData) -> TokenStream {
// For simplicity sake we assume that theres no conflicts and everything has already been validated
match &data {
StructData::Map(fields) => map_struct(attributes, fields),
StructData::Tuple(fields) => tuple_struct(attributes, fields),
StructData::NewType(field) => newtype_struct(attributes, field),
}
}
fn map_struct(attributes: &ContainerAttributes, fields: &[FieldNamed]) -> TokenStream {
if *attributes.transparent.value() {
return newtype_struct(attributes, fields.first().unwrap());
}
let field_bodies = fields.iter().map(|field| {
let (ident, name) = (&field.ident, &field.name);
let (key, value) = if *field.attributes.to_string.value() {
(quote!(#name.to_string()), quote!(self.#ident.to_string()))
} else {
(quote!(#name.to_string()), quote!(self.#ident))
};
quote!((#key, arma_rs::IntoArma::to_arma(&#value)))
});
quote! {
std::collections::HashMap::<String, arma_rs::Value>::from([
#(#field_bodies),*
]).to_arma()
}
}
fn tuple_struct(_attributes: &ContainerAttributes, fields: &[FieldUnnamed]) -> TokenStream {
let field_bodies = fields.iter().map(|field| {
let index = &field.index;
if *field.attributes.to_string.value() {
quote!(self.#index.to_string())
} else {
quote!(self.#index)
}
});
quote! {
Vec::<arma_rs::Value>::from([
#(arma_rs::IntoArma::to_arma(&#field_bodies)),*
]).to_arma()
}
}
fn newtype_struct(_attributes: &ContainerAttributes, field: &impl Field) -> TokenStream {
let token = field.token();
let field_body = if *field.attributes().to_string.value() {
quote!(self.#token.to_string())
} else {
quote!(self.#token)
};
quote! {
arma_rs::IntoArma::to_arma(&#field_body)
}
}

View File

@@ -0,0 +1,62 @@
mod from;
mod into;
mod validate;
use proc_macro2::Span;
use syn::{Error, Result};
pub use from::impl_from_arma;
pub use into::impl_into_arma;
pub use validate::validate_attributes;
use crate::derive::{
data::{FieldNamed, FieldUnnamed, StructData},
CombinedErrors,
};
impl StructData {
pub fn new(errors: &mut CombinedErrors, data: syn::DataStruct) -> Result<Self> {
match data.fields {
syn::Fields::Unit => Err(Error::new(
Span::call_site(),
"unit-like structs aren't supported",
)),
syn::Fields::Named(fields) => {
if fields.named.is_empty() {
return Err(Error::new(
Span::call_site(),
"unit-like structs aren't supported",
));
}
let fields = fields
.named
.into_iter()
.map(|f| FieldNamed::new(errors, f))
.collect::<_>();
Ok(Self::Map(fields))
}
syn::Fields::Unnamed(fields) => {
if fields.unnamed.is_empty() {
return Err(Error::new(
Span::call_site(),
"unit-like structs aren't supported",
));
}
if fields.unnamed.len() == 1 {
let field = FieldUnnamed::new(errors, fields.unnamed[0].clone(), 0);
Ok(Self::NewType(field))
} else {
let fields = fields
.unnamed
.into_iter()
.enumerate()
.map(|(i, f)| FieldUnnamed::new(errors, f, i))
.collect::<_>();
Ok(Self::Tuple(fields))
}
}
}
}
}

View File

@@ -0,0 +1,89 @@
use syn::Error;
use crate::derive::{
attributes::{Attribute, ContainerAttributes, FieldAttributes},
data::StructData,
CombinedErrors,
};
pub fn validate_attributes(
errors: &mut CombinedErrors,
attributes: &ContainerAttributes,
data: &StructData,
) {
if *attributes.transparent.value() {
match data {
StructData::Map(fields) if fields.len() > 1 => {
errors.add(
attributes
.transparent
.error("#[arma(transparent)] structs must have exactly one field"),
);
}
StructData::Tuple(_) => {
errors.add(
attributes
.transparent
.error("#[arma(transparent)] cannot be used on tuple like structs"),
);
}
_ => {}
}
}
if let Some(attr) = get_default_attr(attributes, data) {
match data {
StructData::Map(_) if *attributes.transparent.value() => {
errors.add(
attr.error("#[arma(default)] and #[arma(transparent)] cannot be used together"),
);
}
StructData::NewType(_) => {
errors.add(attr.error("#[arma(default)] cannot be used on new type structs"));
}
_ => {}
}
}
if let StructData::Tuple(fields) = data {
let mut index_first_default = None;
for (index, field) in fields.iter().enumerate() {
match index_first_default {
None => {
if field.attributes.default.is_set() {
index_first_default = Some(index);
}
}
Some(index) => {
if !field.attributes.default.is_set() {
errors.add(Error::new_spanned(&field.ty,
format!("field must have #[arma(default)] because previous field {} has #[arma(default)]", index)
));
}
}
}
}
}
}
fn get_default_attr<'a>(
attributes: &'a ContainerAttributes,
data: &'a StructData,
) -> Option<&'a Attribute<bool>> {
if *attributes.default.value() {
return Some(&attributes.default);
}
field_attributes(data)
.iter()
.find(|attr| *attr.default.value())
.map(|f| &f.default)
}
fn field_attributes(data: &StructData) -> Vec<&FieldAttributes> {
match data {
StructData::Map(fields) => fields.iter().map(|f| &f.attributes).collect(),
StructData::Tuple(fields) => fields.iter().map(|f| &f.attributes).collect(),
StructData::NewType(field) => vec![&field.attributes],
}
}

159
vendor/arma-rs-proc/src/lib.rs vendored Normal file
View File

@@ -0,0 +1,159 @@
mod derive;
use proc_macro::TokenStream;
use proc_macro2::{Ident, Span};
use quote::quote;
use syn::{DeriveInput, Error, ItemFn};
#[proc_macro_attribute]
/// Used to generate the necessary boilerplate for an Arma extension.
/// It should be applied to a function that takes no arguments and returns an extension.
pub fn arma(_attr: TokenStream, item: TokenStream) -> TokenStream {
let ast = syn::parse_macro_input!(item as ItemFn);
let init = ast.sig.ident.clone();
let extern_type = if cfg!(windows) { "stdcall" } else { "C" };
let ext_init = quote! {
if RV_EXTENSION.is_none() {
RV_EXTENSION = Some(#init());
}
};
#[cfg(all(target_os = "windows", target_arch = "x86"))]
let prefix = "safe32_";
#[cfg(not(all(target_os = "windows", target_arch = "x86")))]
let prefix = "";
macro_rules! fn_ident {
( $name:literal ) => {
Ident::new(&format!("{prefix}{}", $name), Span::call_site())
};
}
let versionfn = fn_ident!("RVExtensionVersion");
let noargfn = fn_ident!("RVExtension");
let argfn = fn_ident!("RVExtensionArgs");
let callbackfn = fn_ident!("RVExtensionRegisterCallback");
let contextfn = fn_ident!("RVExtensionContext");
TokenStream::from(quote! {
use arma_rs::libc as arma_rs_libc;
static mut RV_EXTENSION: Option<Extension> = None;
#[cfg(all(target_os="windows", target_arch="x86"))]
arma_rs::link_args::windows! {
unsafe {
raw("/EXPORT:_RVExtensionVersion@8=_safe32_RVExtensionVersion@8");
raw("/EXPORT:_RVExtension@12=_safe32_RVExtension@12");
raw("/EXPORT:_RVExtensionArgs@20=_safe32_RVExtensionArgs@20");
raw("/EXPORT:_RVExtensionRegisterCallback@4=_safe32_RVExtensionRegisterCallback@4");
raw("/EXPORT:_RVExtensionContext@8=_safe32_RVExtensionContext@8");
}
}
/// Returns extension version, called by Arma on extension load.
/// This function is generated by the [`arma_rs::arma`] proc macro.
#[no_mangle]
#[doc(hidden)]
pub unsafe extern #extern_type fn #versionfn(output: *mut arma_rs_libc::c_char, size: arma_rs_libc::size_t) -> arma_rs_libc::c_int {
#ext_init
if let Some(ext) = &RV_EXTENSION {
arma_rs::write_cstr(ext.version().to_string(), output, size);
}
0
}
/// Run extension function, called by Arma on `callExtension` without arguments.
/// This function is generated by the [`arma_rs::arma`] proc macro.
#[no_mangle]
#[doc(hidden)]
pub unsafe extern #extern_type fn #noargfn(output: *mut arma_rs_libc::c_char, size: arma_rs_libc::size_t, function: *mut arma_rs_libc::c_char) {
#ext_init
if let Some(ext) = &RV_EXTENSION {
if ext.allow_no_args() {
ext.handle_call(function, output, size, None, None, true);
}
}
}
/// Run extension function with arguments, called by Arma on `callExtension` with arguments.
/// This function is generated by the [`arma_rs::arma`] proc macro.
#[no_mangle]
#[doc(hidden)]
pub unsafe extern #extern_type fn #argfn(output: *mut arma_rs_libc::c_char, size: arma_rs_libc::size_t, function: *mut arma_rs_libc::c_char, args: *mut *mut arma_rs_libc::c_char, arg_count: arma_rs_libc::c_int) -> arma_rs_libc::c_int {
#ext_init
if let Some(ext) = &RV_EXTENSION {
ext.handle_call(function, output, size, Some(args), Some(arg_count), true)
} else {
0
}
}
/// Set extension callback, called by Arma on extension load.
/// This function is generated by the [`arma_rs::arma`] proc macro.
#[no_mangle]
#[doc(hidden)]
pub unsafe extern #extern_type fn #callbackfn(callback: arma_rs::Callback) {
#ext_init
if let Some(ext) = &mut RV_EXTENSION {
ext.register_callback(callback);
ext.run_callbacks();
}
}
/// Provide extension call context, called by Arma on `callExtension`.
/// This function is generated by the [`arma_rs::arma`] proc macro.
#[no_mangle]
#[doc(hidden)]
pub unsafe extern #extern_type fn #contextfn(args: *mut *mut arma_rs_libc::c_char, arg_count: arma_rs_libc::c_int) {
#ext_init
if let Some(ext) = &mut RV_EXTENSION {
ext.handle_call_context(args, arg_count);
}
}
#ast
})
}
/// Derive implementation of `FromArma`, only supports structs.
/// - Map structs are converted from an hashmap.
/// - Tuple structs are converted from an array.
/// - Newtype structs directly use's the value's `FromArma` implementation.
/// - Unit-like structs are not supported.
///
/// ### Container Attributes
/// - `#[arma(transparent)]`: treat single field map structs as if its a newtype structs.
/// - `#[arma(default)]`: any missing field will be filled by the structs `Default` implementation.
///
/// ### Field Attributes
/// - `#[arma(from_str)]`: use the types `std::str::FromStr` instead of `FromArma`.
/// - `#[arma(default)]`: if missing use its `Default` implementation (takes precedence over container).
#[proc_macro_derive(FromArma, attributes(arma))]
pub fn derive_from_arma(item: TokenStream) -> TokenStream {
let input = syn::parse_macro_input!(item as DeriveInput);
derive::generate_from_arma(input)
.unwrap_or_else(Error::into_compile_error)
.into()
}
/// Derive implementation of `IntoArma`, only supports structs.
/// - Map structs are converted to an hashmap.
/// - Tuple structs are converted to an array.
/// - Newtype structs directly use's the value's `IntoArma` implementation.
/// - Unit-like structs are not supported.
///
/// ### Container Attributes
/// - `#[arma(transparent)]`: treat single field map structs as if its a newtype structs.
///
/// ### Field Attributes
/// - `#[arma(to_string)]`: use the types `std::string::ToString` instead of `IntoArma`.
#[proc_macro_derive(IntoArma, attributes(arma))]
pub fn derive_into_arma(item: TokenStream) -> TokenStream {
let input = syn::parse_macro_input!(item as DeriveInput);
derive::generate_into_arma(input)
.unwrap_or_else(Error::into_compile_error)
.into()
}