abi_stable/macros.rs
1#[macro_use]
2mod internal;
3
4#[macro_use]
5mod nul_str_macros;
6
7/// Can be used to construct [`CompGenericParams`],
8/// when manually implementing [`StableAbi`].
9///
10/// This stores indices and ranges for the type and/or const parameters taken
11/// from the [`SharedVars`] stored in the same [`TypeLayout`] where this is stored.
12///
13/// # Syntax
14///
15/// `tl_genparams!( (<lifetime>),* ; <convertible_to_startlen>; <convertible_to_startlen> )`
16///
17/// `<convertible_to_startlen>` is a range of indices into a slice:
18///
19/// -` `: No elements.
20///
21/// -`i`: Uses the `i`th element.
22///
23/// -`i..j`: Uses the elements from i up to j (exclusive).
24///
25/// -`i..=j`: Uses the elements from i up to j (inclusive).
26///
27/// -`x: StartLen`: Uses the elements from `x.start()` up to `x.end()` (exclusive).
28///
29/// For type parameters, this conceptually references the elements from
30/// the slice returned by [`SharedVars::type_layouts`].
31///
32/// For const parameters, this conceptually references the elements from
33/// the slice returned by [`SharedVars::constants`].
34///
35///
36/// # Example
37///
38/// ```rust
39/// use abi_stable::{
40/// type_layout::CompGenericParams,
41/// tl_genparams,
42/// };
43///
44/// const NO_ARGUMENTS: CompGenericParams = tl_genparams!(;;);
45///
46/// const THREE_TYPE_ARGUMENTS: CompGenericParams = tl_genparams!(; 0..=2;);
47///
48/// const ALL_ARGUMENTS: CompGenericParams = tl_genparams!('a,'b,'c,'d; 0; 0..3);
49///
50/// ```
51///
52///
53///
54/// [`MonoTypeLayout`]: ./type_layout/struct.MonoTypeLayout.html
55/// [`TypeLayout`]: ./type_layout/struct.TypeLayout.html
56/// [`SharedVars`]: ./type_layout/struct.SharedVars.html
57/// [`SharedVars::type_layouts`]: ./type_layout/struct.SharedVars.html#method.type_layouts
58/// [`SharedVars::constants`]: ./type_layout/struct.SharedVars.html#method.constants
59/// [`StableAbi`]: ./trait.StableAbi.html
60/// [`CompGenericParams`]: ./type_layout/struct.CompGenericParams.html
61///
62#[macro_export]
63macro_rules! tl_genparams {
64 ( $($lt:lifetime),* $(,)? ; $($ty:expr)? ; $($const_p:expr)? ) => ({
65 #[allow(unused_parens)]
66 let ty_param_range =
67 $crate::type_layout::StartLenConverter( ($($ty)?) ).to_start_len();
68
69 #[allow(unused_parens)]
70 let const_param_range=
71 $crate::type_layout::StartLenConverter( ($($const_p)?) ).to_start_len();
72
73 $crate::type_layout::CompGenericParams::new(
74 $crate::nulstr_trunc!($crate::pmr::concat!($(stringify!($lt),",",)*)),
75 $crate::pmr::count_tts!(($($lt)*)) as u8,
76 ty_param_range,
77 const_param_range,
78 )
79 })
80}
81
82///////////////////////////////////////////////////////////////////////
83
84/// Equivalent to `?` for [`RResult`].
85///
86/// Accepts both `Result` and `RResult` arguments.
87///
88/// # Example
89///
90/// Defining an extern function that returns a result.
91///
92/// ```
93/// use abi_stable::{
94/// std_types::{RResult, ROk, RBoxError, RStr, Tuple3},
95/// rtry,
96/// sabi_extern_fn,
97/// };
98///
99///
100/// #[sabi_extern_fn]
101/// fn parse_tuple(s: RStr<'_>) -> RResult<Tuple3<u32, u32, u32>, RBoxError> {
102/// let mut iter = s.split(',').map(|x| x.trim());
103/// ROk(Tuple3(
104/// rtry!(iter.next().unwrap_or("").parse().map_err(RBoxError::new)),
105/// rtry!(iter.next().unwrap_or("").parse().map_err(RBoxError::new)),
106/// rtry!(iter.next().unwrap_or("").parse().map_err(RBoxError::new)),
107/// ))
108/// }
109///
110/// assert_eq!(parse_tuple("3, 5, 8".into()).unwrap(), Tuple3(3, 5, 8));
111/// parse_tuple("".into()).unwrap_err();
112///
113///
114/// ```
115///
116/// [`RResult`]: ./std_types/enum.RResult.html
117#[macro_export]
118macro_rules! rtry {
119 ($expr:expr) => {{
120 match $crate::pmr::RResult::from($expr) {
121 $crate::pmr::ROk(x) => x,
122 $crate::pmr::RErr(x) => return $crate::pmr::RErr($crate::pmr::From::from(x)),
123 }
124 }};
125}
126
127/// Equivalent to `?` for [`ROption`].
128///
129/// Accepts both `Option` and `ROption` arguments.
130///
131/// # Example
132///
133/// ```rust
134/// use abi_stable::{
135/// std_types::{ROption, RSome, RNone},
136/// rtry_opt,
137/// sabi_extern_fn,
138/// };
139///
140///
141/// #[sabi_extern_fn]
142/// fn funct(arg: ROption<u32>) -> ROption<u32> {
143/// let value = rtry_opt!(Some(3));
144/// RSome(value + rtry_opt!(arg))
145/// }
146///
147/// assert_eq!(funct(RSome(5)), RSome(8));
148/// assert_eq!(funct(RNone), RNone::<u32>);
149///
150/// ```
151///
152/// [`ROption`]: ./std_types/enum.ROption.html
153#[macro_export]
154macro_rules! rtry_opt {
155 ($expr:expr) => {{
156 match $crate::pmr::ROption::from($expr) {
157 $crate::pmr::RSome(x) => x,
158 $crate::pmr::RNone => return $crate::pmr::RNone,
159 }
160 }};
161}
162
163///////////////////////////////////////////////////////////////////////
164
165macro_rules! check_unerased {
166 (
167 $this:ident,$res:expr
168 ) => {
169 if let Err(e) = $res {
170 return Err(e.map(move |_| $this));
171 }
172 };
173}
174
175///////////////////////////////////////////////////////////////////////
176
177/// Use this to make sure that you handle panics inside `extern fn` correctly.
178///
179/// This macro causes an abort if a panic reaches this point.
180///
181/// It does not prevent functions inside from using `::std::panic::catch_unwind`
182/// to catch the panic.
183///
184/// # Early returns
185///
186/// This macro by default wraps the passed code in a closure so that any
187/// early returns that happen inside don't interfere with the macro generated code.
188///
189/// If you don't have an early return (a `return`/`continue`/`break`/`?`/etc.)
190/// in the code passed to this macro you can use
191/// `extern_fn_panic_handling!{no_early_return; <code here> }`,
192/// which *might* be cheaper(this has not been tested yet).
193///
194/// # Example
195///
196/// ```
197/// use std::fmt;
198///
199/// use abi_stable::{
200/// extern_fn_panic_handling,
201/// std_types::RString,
202/// };
203///
204///
205/// pub extern "C" fn print_debug<T>(this: &T, buf: &mut RString)
206/// where
207/// T: fmt::Debug,
208/// {
209/// extern_fn_panic_handling! {
210/// use std::fmt::Write;
211///
212/// println!("{:?}", this);
213/// }
214/// }
215/// ```
216///
217/// # Example, no_early_return
218///
219///
220/// ```
221/// use std::fmt;
222///
223/// use abi_stable::{
224/// extern_fn_panic_handling,
225/// std_types::RString,
226/// };
227///
228///
229/// pub extern "C" fn print_debug<T>(this: &T, buf: &mut RString)
230/// where
231/// T: fmt::Debug,
232/// {
233/// extern_fn_panic_handling!{no_early_return;
234/// use std::fmt::Write;
235///
236/// println!("{:?}", this);
237/// }
238/// }
239///
240/// ```
241///
242/// # Returing in `no_early_return`
243///
244/// Attempting to do any kind of returning from inside of
245/// `extern_fn_panic_handling!{no_early_return}`
246/// will cause an abort:
247///
248/// ```should_panic
249/// use abi_stable::extern_fn_panic_handling;
250///
251/// pub extern "C" fn function() {
252/// extern_fn_panic_handling!{no_early_return;
253/// return;
254/// }
255/// }
256///
257/// function();
258///
259/// ```
260///
261///
262#[macro_export]
263macro_rules! extern_fn_panic_handling {
264 (no_early_return; $($fn_contents:tt)* ) => ({
265 let aborter_guard = {
266 use $crate::utils::{AbortBomb,PanicInfo};
267 #[allow(dead_code)]
268 const BOMB:AbortBomb = AbortBomb{
269 fuse: &PanicInfo{file:file!(),line:line!()}
270 };
271 BOMB
272 };
273
274 let res = {
275 $($fn_contents)*
276 };
277
278 ::std::mem::forget(aborter_guard);
279
280 res
281 });
282 ( $($fn_contents:tt)* ) => (
283 #[allow(clippy::redundant_closure_call)]
284 {
285 $crate::extern_fn_panic_handling!{
286 no_early_return;
287 let a = $crate::marker_type::NotCopyNotClone;
288 (move||{
289 {a};
290 {
291 $($fn_contents)*
292 }
293 })()
294 }
295 }
296 )
297}
298
299///////////////////////////////////////////////////////////////////////////////////////////
300
301/// Constructs a [`Tag`](./type_layout/tagging/struct.Tag.html),
302/// a dynamically typed value for users to check extra properties about their types
303/// when doing runtime type checking.
304///
305/// Note that this macro is not recursive,
306/// you need to invoke it every time you construct an array/map/set inside of the macro.
307///
308/// For more examples look in the [tagging module](./type_layout/tagging/index.html)
309///
310/// # Example
311///
312/// Using tags to store the traits the type requires,
313/// so that if this changes it can be reported as an error.
314///
315/// This will cause an error if the binary and dynamic library disagree about the values inside
316/// the "required traits" map entry .
317///
318/// In real code this should be written in a
319/// way that keeps the tags and the type bounds in sync.
320///
321/// ```rust
322/// use abi_stable::{
323/// tag,
324/// type_layout::Tag,
325/// StableAbi,
326/// };
327///
328/// const TAGS: Tag = tag!{{
329/// "required traits" => tag![["Copy"]],
330/// }};
331///
332///
333/// #[repr(C)]
334/// #[derive(StableAbi)]
335/// #[sabi(bound(T: Copy))]
336/// #[sabi(tag = TAGS)]
337/// struct Value<T>{
338/// value: T,
339/// }
340///
341///
342/// ```
343///
344/// [`Tag`]: ./type_layout/tagging/struct.Tag.html
345///
346#[macro_export]
347macro_rules! tag {
348 ([ $( $elem:expr ),* $(,)? ])=>{{
349 use $crate::type_layout::tagging::{Tag,FromLiteral};
350
351 Tag::arr($crate::rslice![
352 $( FromLiteral($elem).to_tag(), )*
353 ])
354 }};
355 ({ $( $key:expr=>$value:expr ),* $(,)? })=>{{
356 use $crate::type_layout::tagging::{FromLiteral,Tag};
357
358 Tag::map($crate::rslice![
359 $(
360 Tag::kv(
361 FromLiteral($key).to_tag(),
362 FromLiteral($value).to_tag(),
363 ),
364 )*
365 ])
366 }};
367 ({ $( $key:expr ),* $(,)? })=>{{
368 use $crate::type_layout::tagging::{Tag,FromLiteral};
369
370 Tag::set($crate::rslice![
371 $(
372 FromLiteral($key).to_tag(),
373 )*
374 ])
375 }};
376 ($expr:expr) => {{
377 $crate::type_layout::tagging::FromLiteral($expr).to_tag()
378 }};
379}
380
381///////////////////////////////////////////////////////////////////////////////
382
383#[allow(unused_macros)]
384macro_rules! assert_matches {
385 ( $(|)? $($pat:pat_param)|* =$expr:expr)=>{{
386 let ref value=$expr;
387 assert!(
388 matches!(*value, $($pat)|* ),
389 "pattern did not match the value:\n\t\
390 {:?}
391 ",
392 *value
393 );
394 }};
395}
396
397///////////////////////////////////////////////////////////////////////////////
398
399/// Constructs an [`ItemInfo`], with information about the place where it's called.
400///
401/// [`ItemInfo`]: ./type_layout/struct.ItemInfo.html
402#[macro_export]
403macro_rules! make_item_info {
404 () => {
405 $crate::type_layout::ItemInfo::new(
406 concat!(env!("CARGO_PKG_NAME"), ";", env!("CARGO_PKG_VERSION")),
407 line!(),
408 $crate::type_layout::ModPath::inside($crate::nulstr_trunc!(module_path!())),
409 )
410 };
411}
412
413///////////////////////////////////////////////////////////////////////////////
414
415/// Constructs an [`RVec`] using the same syntax that the [`std::vec`] macro uses.
416///
417/// # Example
418///
419/// ```
420///
421/// use abi_stable::{
422/// rvec,
423/// std_types::RVec,
424/// };
425///
426/// assert_eq!(RVec::<u32>::new(), rvec![]);
427/// assert_eq!(RVec::from(vec![0]), rvec![0]);
428/// assert_eq!(RVec::from(vec![0, 3]), rvec![0, 3]);
429/// assert_eq!(RVec::from(vec![0, 3, 6]), rvec![0, 3, 6]);
430/// assert_eq!(RVec::from(vec![1; 10]), rvec![1; 10]);
431///
432/// ```
433///
434/// [`RVec`]: ./std_types/struct.RVec.html
435///
436/// [`std::vec`]: https://doc.rust-lang.org/std/macro.vec.html
437#[macro_export]
438macro_rules! rvec {
439 ( $( $anything:tt )* ) => (
440 $crate::std_types::RVec::from($crate::pmr::vec![ $($anything)* ])
441 )
442}
443
444///////////////////////////////////////////////////////////////////////////////
445
446/// Use this macro to construct a `abi_stable::std_types::Tuple*`
447/// with the values passed to the macro.
448///
449/// # Example
450///
451/// ```
452/// use abi_stable::{
453/// rtuple,
454/// std_types::{Tuple1, Tuple2, Tuple3, Tuple4},
455/// };
456///
457/// assert_eq!(rtuple!(), ());
458///
459/// assert_eq!(rtuple!(3), Tuple1(3));
460///
461/// assert_eq!(rtuple!(3, 5), Tuple2(3, 5));
462///
463/// assert_eq!(rtuple!(3, 5, 8), Tuple3(3, 5, 8));
464///
465/// assert_eq!(rtuple!(3, 5, 8, 9), Tuple4(3, 5, 8, 9));
466///
467/// ```
468///
469#[macro_export]
470macro_rules! rtuple {
471 () => {
472 ()
473 };
474 ($v0:expr $(,)* ) => {
475 $crate::std_types::Tuple1($v0)
476 };
477 ($v0:expr,$v1:expr $(,)* ) => {
478 $crate::std_types::Tuple2($v0, $v1)
479 };
480 ($v0:expr,$v1:expr,$v2:expr $(,)* ) => {
481 $crate::std_types::Tuple3($v0, $v1, $v2)
482 };
483 ($v0:expr,$v1:expr,$v2:expr,$v3:expr $(,)* ) => {
484 $crate::std_types::Tuple4($v0, $v1, $v2, $v3)
485 };
486}
487
488/// Use this macro to get the type of a `Tuple*` with the types passed to the macro.
489///
490/// # Example
491///
492/// ```
493/// use abi_stable::{
494/// std_types::{Tuple1, Tuple2, Tuple3, Tuple4},
495/// RTuple,
496/// };
497///
498/// let tuple0: RTuple!() = ();
499///
500/// let tuple1: RTuple!(i32) = Tuple1(3);
501///
502/// let tuple2: RTuple!(i32, i32) = Tuple2(3, 5);
503///
504/// let tuple3: RTuple!(i32, i32, u32) = Tuple3(3, 5, 8);
505///
506/// let tuple4: RTuple!(i32, i32, u32, u32) = Tuple4(3, 5, 8, 9);
507/// ```
508///
509#[macro_export]
510macro_rules! RTuple {
511 () => (
512 ()
513 );
514 ($v0:ty $(,)* ) => (
515 $crate::std_types::Tuple1<$v0>
516 );
517 ($v0:ty,$v1:ty $(,)* ) => (
518 $crate::std_types::Tuple2<$v0,$v1>
519 );
520 ($v0:ty,$v1:ty,$v2:ty $(,)* ) => (
521 $crate::std_types::Tuple3<$v0,$v1,$v2>
522 );
523 ($v0:ty,$v1:ty,$v2:ty,$v3:ty $(,)* ) => (
524 $crate::std_types::Tuple4<$v0,$v1,$v2,$v3>
525 );
526}
527
528///////////////////////////////////////////////////////////////////////////////
529
530/// A macro to construct [`RSlice`]s.
531///
532/// When this macro doesn't work(due to lifetime issues),
533/// you'll have to separately create a slice,
534/// then pass it to the [`RSlice::from_slice`] const function.
535///
536/// # Examples
537///
538/// ```
539/// use abi_stable::{
540/// std_types::RSlice,
541/// rslice,
542/// };
543///
544///
545/// const EMPTY: RSlice<'_, u8> = rslice![];
546/// // `RSlice<'_, T>`s can be compared with `&[T]`s
547/// assert_eq!(EMPTY, <&[u8]>::default());
548///
549/// const FOO: RSlice<'_,u8> = rslice![1, 2, 3, 5, 8, 13];
550/// assert_eq!(FOO[..], [1, 2, 3, 5, 8, 13]);
551///
552/// ```
553///
554/// [`RSlice`]: ./std_types/struct.RSlice.html
555///
556/// [`RSlice::from_slice`]: ./std_types/struct.RSlice.html#method.from_slice
557///
558#[macro_export]
559macro_rules! rslice {
560 ( $( $elem:expr ),* $(,)* ) => {
561 $crate::std_types::RSlice::from_slice(&[ $($elem),* ])
562 };
563}
564
565///////////////////////////////////////////////////////////////////////////////
566
567/// Constructs [`RStr`] constants from `&'static str` constants.
568///
569/// # Examples
570///
571/// ```
572/// use abi_stable::{
573/// std_types::RStr,
574/// rstr,
575/// };
576///
577///
578/// const FOO: RStr<'_> = rstr!("");
579/// // `RStr<'_>`s can be compared with `&str`s
580/// assert_eq!(FOO, "");
581///
582/// const BAR_STR: &str = "1235813";
583/// // constructing `RStr<'_>` from a `&str` non-literal constant
584/// const BAR: RStr<'_> = rstr!(BAR_STR);
585/// assert_eq!(BAR, "1235813");
586/// ```
587///
588/// [`RStr`]: ./std_types/struct.RStr.html
589///
590#[macro_export]
591macro_rules! rstr {
592 ( $str:expr ) => {{
593 const __SABI_RSTR: $crate::std_types::RStr<'static> =
594 $crate::std_types::RStr::from_str($str);
595 __SABI_RSTR
596 }};
597}
598
599/// Constructs a RStr with the concatenation of the passed in strings,
600/// and variables with the range for the individual strings.
601macro_rules! multi_str {
602 (
603 $( #[$mod_attr:meta] )*
604 mod $module:ident {
605 $( const $variable:ident=$string:literal; )*
606 }
607 ) => (
608 $( #[$mod_attr] )*
609 mod $module{
610 $crate::abi_stable_derive::concatenated_and_ranges!{
611 CONCATENATED( $($variable=$string),* )
612 }
613 }
614 )
615}
616
617/// Constructs a `&'static SharedVars`
618macro_rules! make_shared_vars{
619 (
620 impl[$($impl_gen:tt)*] $type:ty
621 $(where[$($where_clause:tt)*])?;
622
623 let ($mono_shared_vars:ident,$shared_vars:ident) ={
624 $(
625 strings={
626 $( $variable:ident : $string:literal ),* $(,)*
627 },
628 )?
629 $( lifetime_indices=[ $($lifetime_indices:expr),* $(,)* ], )?
630 $( type_layouts=[ $($ty_layout:ty),* $(,)* ], )?
631 $( prefix_type_layouts=[ $($prefix_ty_layout:ty),* $(,)* ], )?
632 $( constant=[ $const_ty:ty => $constants:expr ], )?
633 };
634 )=>{
635 multi_str!{
636 #[allow(non_upper_case_globals)]
637 mod _inner_multi_str_mod{
638 $( $( const $variable = $string; )* )?
639 }
640 }
641 $( use _inner_multi_str_mod::{$($variable,)*}; )?
642
643 #[allow(non_upper_case_globals)]
644 const $mono_shared_vars:&'static $crate::type_layout::MonoSharedVars=
645 &$crate::type_layout::MonoSharedVars::new(
646 _inner_multi_str_mod::CONCATENATED,
647 rslice![ $( $($lifetime_indices),* )? ],
648 );
649
650 struct __ACPromoted<T>(T);
651
652 impl<$($impl_gen)*> __ACPromoted<$type>
653 where $($($where_clause)*)?
654 {
655 const CONST_PARAM: &'static [$crate::abi_stability::ConstGeneric] = {
656 &[
657 $($crate::abi_stability::ConstGeneric::new(&$constants),)?
658 ]
659 };
660
661 const SHARED_VARS: &'static $crate::type_layout::SharedVars = {
662 &$crate::type_layout::SharedVars::new(
663 $mono_shared_vars,
664 rslice![
665 $( $( $crate::pmr::get_type_layout::<$ty_layout>,)* )?
666 $( $( $crate::pmr::get_prefix_field_type_layout::<$prefix_ty_layout>,)* )?
667 ],
668 $crate::std_types::RSlice::from_slice(Self::CONST_PARAM),
669 )
670 };
671 }
672
673 let $shared_vars=__ACPromoted::<Self>::SHARED_VARS;
674 }
675}
676
677///////////////////////////////////////////////////////////////////////////////
678
679/// Allows declaring a [`StaticRef`] inherent associated `const`ant
680/// from possibly non-`'static` references.
681///
682/// This only works in inherent implementations.
683///
684/// This does not work in:
685///
686/// - trait definitions
687/// - trait implementations.
688/// - modules: to define a non-associated constant.
689///
690/// # Example
691///
692/// ### Basic
693///
694/// ```rust
695/// use abi_stable::staticref;
696///
697/// struct NONE_REF<T>(T);
698///
699/// impl<T> NONE_REF<T> {
700/// // Declares a `StaticRef<Option<T>>` that points to a `None`, for any `T`.
701/// staticref!(const V: Option<T> = None);
702/// }
703///
704/// let none_string: &'static Option<String> = NONE_REF::<String>::V.get();
705/// assert_eq!(none_string, &None::<String>);
706///
707/// ```
708///
709/// ### More realistic
710///
711/// This example demonstrates how you can construct a pointer to a vtable,
712/// constructed at compile-time.
713///
714/// ```rust
715/// use abi_stable::{
716/// StableAbi,
717/// extern_fn_panic_handling,
718/// staticref,
719/// pointer_trait::CallReferentDrop,
720/// prefix_type::{PrefixTypeTrait, WithMetadata},
721/// };
722///
723/// use std::{
724/// mem::ManuallyDrop,
725/// ops::Deref,
726/// };
727///
728/// fn main(){
729/// let boxed = BoxLike::new(100);
730///
731/// assert_eq!(*boxed, 100);
732/// assert_eq!(boxed.into_inner(), 100);
733/// }
734///
735/// /// An ffi-safe `Box<T>`
736/// #[repr(C)]
737/// #[derive(StableAbi)]
738/// pub struct BoxLike<T> {
739/// data: *mut T,
740///
741/// vtable: VTable_Ref<T>,
742///
743/// _marker: std::marker::PhantomData<T>,
744/// }
745///
746/// impl<T> BoxLike<T>{
747/// pub fn new(value: T) -> Self {
748/// let box_ = Box::new(value);
749///
750/// Self{
751/// data: Box::into_raw(box_),
752/// vtable: VTable::VTABLE,
753/// _marker: std::marker::PhantomData,
754/// }
755/// }
756///
757/// /// Extracts the value this owns.
758/// pub fn into_inner(self) -> T{
759/// let this = ManuallyDrop::new(self);
760/// unsafe{
761/// // Must copy this before calling `self.vtable.destructor()`
762/// // because otherwise it would be reading from a dangling pointer.
763/// let ret = this.data.read();
764/// this.vtable.destructor()(this.data,CallReferentDrop::No);
765/// ret
766/// }
767/// }
768/// }
769///
770///
771/// impl<T> Drop for BoxLike<T>{
772/// fn drop(&mut self){
773/// unsafe{
774/// self.vtable.destructor()(self.data, CallReferentDrop::Yes)
775/// }
776/// }
777/// }
778///
779/// // `#[sabi(kind(Prefix))]` Declares this type as being a prefix-type,
780/// // generating both of these types:
781/// //
782/// // - VTable_Prefix`: A struct with the fields up to (and including) the field with the
783/// // `#[sabi(last_prefix_field)]` attribute.
784/// //
785/// // - VTable_Ref`: An ffi-safe pointer to `VTable`,with methods to get `VTable`'s fields.
786/// //
787/// #[repr(C)]
788/// #[derive(StableAbi)]
789/// #[sabi(kind(Prefix))]
790/// struct VTable<T>{
791/// #[sabi(last_prefix_field)]
792/// destructor: unsafe extern "C" fn(*mut T, CallReferentDrop),
793/// }
794///
795/// impl<T> VTable<T>{
796/// staticref!(const VTABLE_VAL: WithMetadata<Self> = WithMetadata::new(
797/// Self{
798/// destructor: destroy_box::<T>,
799/// },
800/// ));
801///
802/// const VTABLE: VTable_Ref<T> = {
803/// VTable_Ref( Self::VTABLE_VAL.as_prefix() )
804/// };
805/// }
806///
807/// unsafe extern "C" fn destroy_box<T>(v: *mut T, call_drop: CallReferentDrop) {
808/// extern_fn_panic_handling! {
809/// let mut box_ = Box::from_raw(v as *mut ManuallyDrop<T>);
810/// if call_drop == CallReferentDrop::Yes {
811/// ManuallyDrop::drop(&mut *box_);
812/// }
813/// drop(box_);
814/// }
815/// }
816///
817///
818/// impl<T> Deref for BoxLike<T> {
819/// type Target=T;
820///
821/// fn deref(&self)->&T{
822/// unsafe{
823/// &(*self.data)
824/// }
825/// }
826/// }
827/// ```
828///
829/// [`StaticRef`]: ./sabi_types/struct.StaticRef.html
830#[macro_export]
831macro_rules! staticref{
832 (
833 $(
834 $(#[$attr:meta])* $vis:vis const $name:ident : $ty:ty = $expr:expr
835 );*
836 $(;)?
837 )=>{
838 $crate::pmr::paste!{
839 $(
840 #[allow(unused_parens)]
841 #[doc(hidden)]
842 const [<$name _NHPMWYD3NJA>] : *const ($ty) = &($expr);
843
844 #[allow(unused_parens)]
845 $(#[$attr])*
846 $vis const $name : $crate::sabi_types::StaticRef<($ty)> = unsafe{
847 $crate::sabi_types::StaticRef::from_raw(
848 Self::[<$name _NHPMWYD3NJA>]
849 )
850 };
851 )*
852 }
853
854 };
855}
856
857///////////////////////////////////////////////////////////////////////////////
858
859#[allow(unused_macros)]
860macro_rules! delegate_interface_serde {
861 (
862 impl[$($impl_header:tt)* ] Traits<$this:ty> for $interf:ty ;
863 lifetime=$lt:lifetime;
864 delegate_to=$delegates_to:ty;
865 ) => (
866 impl<$($impl_header)*> $crate::nonexhaustive_enum::SerializeEnum<$this> for $interf
867 where
868 $this:$crate::nonexhaustive_enum::GetEnumInfo,
869 $delegates_to:
870 $crate::nonexhaustive_enum::SerializeEnum<$this>
871 {
872 type Proxy=<
873 $delegates_to as
874 $crate::nonexhaustive_enum::SerializeEnum<$this>
875 >::Proxy;
876
877 fn serialize_enum<'a>(
878 this:&'a $this
879 ) -> Result<Self::Proxy, $crate::std_types::RBoxError>{
880 <$delegates_to>::serialize_enum(this)
881 }
882 }
883
884 impl<$lt,$($impl_header)* S,I>
885 $crate::nonexhaustive_enum::DeserializeEnum<
886 $lt,
887 $crate::nonexhaustive_enum::NonExhaustive<$this,S,I>
888 >
889 for $interf
890 where
891 $this:$crate::nonexhaustive_enum::GetEnumInfo+$lt,
892 $delegates_to:
893 $crate::nonexhaustive_enum::DeserializeEnum<
894 $lt,
895 $crate::nonexhaustive_enum::NonExhaustive<$this,S,I>
896 >
897 {
898 type Proxy=<
899 $delegates_to as
900 $crate::nonexhaustive_enum::DeserializeEnum<
901 $lt,
902 $crate::nonexhaustive_enum::NonExhaustive<$this,S,I>
903 >
904 >::Proxy;
905
906 fn deserialize_enum(
907 s: Self::Proxy
908 ) -> Result<
909 $crate::nonexhaustive_enum::NonExhaustive<$this,S,I>,
910 $crate::std_types::RBoxError
911 >
912 {
913 <$delegates_to as
914 $crate::nonexhaustive_enum::DeserializeEnum<
915 $crate::nonexhaustive_enum::NonExhaustive<$this,S,I>
916 >
917 >::deserialize_enum(s)
918 }
919 }
920 )
921}