abi_stable_derive/
lib.rs

1//! An implementation detail of abi_stable.
2
3#![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/// This is used by testing/version_compatibility to access the exported static.
67#[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///////////////////////////////////////////////////////////////////////////////
91
92#[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
148////////////////////////////////////////////////////////////////////////////////
149
150fn 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}