abi_stable_derive/
lib.rs
1#![recursion_limit = "192"]
4#![allow(clippy::field_reassign_with_default)]
5#![allow(clippy::derive_partial_eq_without_eq)]
6#![deny(unreachable_patterns)]
7#![deny(unused_doc_comments)]
8#![deny(unconditional_recursion)]
9
10extern crate proc_macro;
11
12#[proc_macro_derive(StableAbi, attributes(sabi))]
13pub fn derive_stable_abi(input: TokenStream1) -> TokenStream1 {
14 parse_or_compile_err(input, stable_abi::derive).into()
15}
16
17#[doc(hidden)]
18#[proc_macro]
19#[allow(non_snake_case)]
20pub fn impl_InterfaceType(input: TokenStream1) -> TokenStream1 {
21 parse_or_compile_err(input, impl_interfacetype::the_macro).into()
22}
23
24#[proc_macro_attribute]
25pub fn export_root_module(attr: TokenStream1, item: TokenStream1) -> TokenStream1 {
26 crate::export_root_module_impl::export_root_module_attr(attr, item)
27}
28
29#[proc_macro_attribute]
30pub fn sabi_extern_fn(attr: TokenStream1, item: TokenStream1) -> TokenStream1 {
31 crate::sabi_extern_fn_impl::sabi_extern_fn(attr, item)
32}
33
34#[proc_macro_attribute]
35pub fn sabi_trait(_attr: TokenStream1, item: TokenStream1) -> TokenStream1 {
36 parse_or_compile_err(item, sabi_trait::derive_sabi_trait).into()
37}
38
39#[doc(hidden)]
40#[proc_macro]
41pub fn concatenated_and_ranges(input: TokenStream1) -> TokenStream1 {
42 parse_or_compile_err(input, concat_and_ranges::macro_impl).into()
43}
44
45#[proc_macro_derive(GetStaticEquivalent, attributes(sabi))]
46pub fn derive_get_static_equivalent(input: TokenStream1) -> TokenStream1 {
47 parse_or_compile_err(input, get_static_equivalent::derive).into()
48}
49
50#[doc(hidden)]
51#[proc_macro]
52pub fn construct_abi_header(_: TokenStream1) -> TokenStream1 {
53 let abi_major = env!("CARGO_PKG_VERSION_MAJOR").parse::<u32>().unwrap();
54 let abi_minor = env!("CARGO_PKG_VERSION_MINOR").parse::<u32>().unwrap();
55 quote!(
56 pub const ABI_HEADER:AbiHeader=AbiHeader{
57 magic_string:*b"abi stable library for Rust ",
58 abi_major:#abi_major,
59 abi_minor:#abi_minor,
60 _priv:(),
61 };
62 )
63 .into()
64}
65
66#[doc(hidden)]
68#[proc_macro]
69pub fn get_root_module_static(_: TokenStream1) -> TokenStream1 {
70 let export_name = syn::Ident::new(
71 &abi_stable_shared::mangled_root_module_loader_name(),
72 proc_macro2::Span::call_site(),
73 );
74 quote!( crate::#export_name ).into()
75}
76
77#[doc(hidden)]
78#[proc_macro]
79pub fn __const_mangled_root_module_loader_name(_: TokenStream1) -> TokenStream1 {
80 let name = abi_stable_shared::mangled_root_module_loader_name();
81 let name_nulled = format!("{}\0", name);
82
83 quote!(
84 const PRIV_MANGLED_ROOT_MODULE_LOADER_NAME: &str = #name;
85 const PRIV_MANGLED_ROOT_MODULE_LOADER_NAME_NUL: &str = #name_nulled;
86 )
87 .into()
88}
89
90#[macro_use]
93mod utils;
94
95mod arenas;
96mod attribute_parsing;
97mod common_tokens;
98mod composite_collections;
99mod concat_and_ranges;
100mod export_root_module_impl;
101mod fn_pointer_extractor;
102mod get_static_equivalent;
103mod ignored_wrapper;
104mod impl_interfacetype;
105mod lifetimes;
106mod literals_constructors;
107mod my_visibility;
108mod parse_utils;
109mod sabi_extern_fn_impl;
110mod set_span_visitor;
111mod workaround;
112
113#[cfg(test)]
114mod input_code_range_tests;
115
116#[doc(hidden)]
117pub(crate) mod stable_abi;
118
119#[doc(hidden)]
120pub(crate) mod sabi_trait;
121
122use proc_macro::TokenStream as TokenStream1;
123use proc_macro2::TokenStream as TokenStream2;
124
125use syn::{DeriveInput, ItemFn};
126
127use quote::{quote, quote_spanned, ToTokens};
128
129#[allow(unused_imports)]
130use core_extensions::SelfOps;
131
132#[allow(unused_imports)]
133use crate::{
134 arenas::{AllocMethods, Arenas},
135 utils::PrintDurationOnDrop,
136};
137
138#[cfg(test)]
139pub(crate) fn derive_stable_abi_from_str(s: &str) -> Result<TokenStream2, syn::Error> {
140 syn::parse_str(s).and_then(stable_abi::derive)
141}
142
143#[cfg(test)]
144pub(crate) fn derive_sabi_trait_str(item: &str) -> Result<TokenStream2, syn::Error> {
145 syn::parse_str(item).and_then(sabi_trait::derive_sabi_trait)
146}
147
148fn parse_or_compile_err<P, F>(input: TokenStream1, f: F) -> TokenStream2
151where
152 P: syn::parse::Parse,
153 F: FnOnce(P) -> Result<TokenStream2, syn::Error>,
154{
155 syn::parse::<P>(input)
156 .and_then(f)
157 .unwrap_or_else(|e| e.to_compile_error())
158}