Skip to main content

medea_macro/
lib.rs

1#![cfg_attr(any(doc, test), doc = include_str!("../README.md"))]
2#![cfg_attr(not(any(doc, test)), doc = env!("CARGO_PKG_NAME"))]
3#![deny(nonstandard_style, rustdoc::all, trivial_casts, trivial_numeric_casts)]
4#![forbid(non_ascii_idents, unsafe_code)]
5#![warn(
6    clippy::absolute_paths,
7    clippy::allow_attributes,
8    clippy::allow_attributes_without_reason,
9    clippy::as_conversions,
10    clippy::as_pointer_underscore,
11    clippy::as_ptr_cast_mut,
12    clippy::assertions_on_result_states,
13    clippy::branches_sharing_code,
14    clippy::cfg_not_test,
15    clippy::clear_with_drain,
16    clippy::clone_on_ref_ptr,
17    clippy::coerce_container_to_any,
18    clippy::collection_is_never_read,
19    clippy::create_dir,
20    clippy::dbg_macro,
21    clippy::debug_assert_with_mut_call,
22    clippy::decimal_literal_representation,
23    clippy::default_union_representation,
24    clippy::derive_partial_eq_without_eq,
25    clippy::doc_include_without_cfg,
26    clippy::doc_paragraphs_missing_punctuation,
27    clippy::empty_drop,
28    clippy::empty_structs_with_brackets,
29    clippy::equatable_if_let,
30    clippy::empty_enum_variants_with_brackets,
31    clippy::exit,
32    clippy::expect_used,
33    clippy::fallible_impl_from,
34    clippy::filetype_is_file,
35    clippy::float_cmp_const,
36    clippy::fn_to_numeric_cast_any,
37    clippy::get_unwrap,
38    clippy::if_then_some_else_none,
39    clippy::imprecise_flops,
40    clippy::infinite_loop,
41    clippy::iter_on_empty_collections,
42    clippy::iter_on_single_items,
43    clippy::iter_over_hash_type,
44    clippy::iter_with_drain,
45    clippy::large_include_file,
46    clippy::large_stack_frames,
47    clippy::let_underscore_untyped,
48    clippy::literal_string_with_formatting_args,
49    clippy::lossy_float_literal,
50    clippy::map_err_ignore,
51    clippy::map_with_unused_argument_over_ranges,
52    clippy::mem_forget,
53    clippy::missing_assert_message,
54    clippy::missing_asserts_for_indexing,
55    clippy::missing_const_for_fn,
56    clippy::missing_docs_in_private_items,
57    clippy::module_name_repetitions,
58    clippy::multiple_inherent_impl,
59    clippy::multiple_unsafe_ops_per_block,
60    clippy::mutex_atomic,
61    clippy::mutex_integer,
62    clippy::needless_collect,
63    clippy::needless_pass_by_ref_mut,
64    clippy::needless_raw_strings,
65    clippy::needless_type_cast,
66    clippy::non_zero_suggestions,
67    clippy::nonstandard_macro_braces,
68    clippy::option_if_let_else,
69    clippy::or_fun_call,
70    clippy::panic_in_result_fn,
71    clippy::partial_pub_fields,
72    clippy::pathbuf_init_then_push,
73    clippy::pedantic,
74    clippy::precedence_bits,
75    clippy::print_stderr,
76    clippy::print_stdout,
77    clippy::pub_without_shorthand,
78    clippy::rc_buffer,
79    clippy::rc_mutex,
80    clippy::read_zero_byte_vec,
81    clippy::redundant_clone,
82    clippy::redundant_test_prefix,
83    clippy::redundant_type_annotations,
84    clippy::renamed_function_params,
85    clippy::ref_patterns,
86    clippy::rest_pat_in_fully_bound_structs,
87    clippy::return_and_then,
88    clippy::same_name_method,
89    clippy::semicolon_inside_block,
90    clippy::set_contains_or_insert,
91    clippy::shadow_unrelated,
92    clippy::significant_drop_in_scrutinee,
93    clippy::significant_drop_tightening,
94    clippy::single_option_map,
95    clippy::str_to_string,
96    clippy::string_add,
97    clippy::string_lit_as_bytes,
98    clippy::string_lit_chars_any,
99    clippy::string_slice,
100    clippy::suboptimal_flops,
101    clippy::suspicious_operation_groupings,
102    clippy::suspicious_xor_used_as_pow,
103    clippy::tests_outside_test_module,
104    clippy::todo,
105    clippy::too_long_first_doc_paragraph,
106    clippy::trailing_empty_array,
107    clippy::transmute_undefined_repr,
108    clippy::trivial_regex,
109    clippy::try_err,
110    clippy::undocumented_unsafe_blocks,
111    clippy::unimplemented,
112    clippy::uninhabited_references,
113    clippy::unnecessary_safety_comment,
114    clippy::unnecessary_safety_doc,
115    clippy::unnecessary_self_imports,
116    clippy::unnecessary_struct_initialization,
117    clippy::unused_peekable,
118    clippy::unused_result_ok,
119    clippy::unused_trait_names,
120    clippy::unwrap_in_result,
121    clippy::unwrap_used,
122    clippy::use_debug,
123    clippy::use_self,
124    clippy::useless_let_if_seq,
125    clippy::verbose_file_reads,
126    clippy::volatile_composites,
127    clippy::while_float,
128    clippy::wildcard_enum_match_arm,
129    ambiguous_negative_literals,
130    closure_returning_async_block,
131    future_incompatible,
132    impl_trait_redundant_captures,
133    let_underscore_drop,
134    macro_use_extern_crate,
135    meta_variable_misuse,
136    missing_copy_implementations,
137    missing_debug_implementations,
138    missing_docs,
139    redundant_lifetimes,
140    rust_2018_idioms,
141    single_use_lifetimes,
142    unit_bindings,
143    unnameable_types,
144    unreachable_pub,
145    unstable_features,
146    unused,
147    variant_size_differences
148)]
149
150mod caused;
151mod dart_bridge;
152#[cfg(feature = "dart-codegen")]
153mod dart_codegen;
154mod dispatchable;
155mod enum_delegate;
156mod watchers;
157
158#[cfg(test)]
159use async_trait as _;
160#[cfg(test)]
161use medea_jason as _;
162use proc_macro::TokenStream;
163
164/// Delegates function calls to enum variants field.
165/// Variants are expected to have only one field.
166///
167/// # How to use
168///
169/// ```rust
170/// use medea_macro::enum_delegate;
171///
172/// #[enum_delegate(pub fn as_str(&self) -> &str)]
173/// #[enum_delegate(pub fn push_str(&mut self, arg: &str))]
174/// enum MyEnum {
175///     Foo(String),
176///     Bar(String),
177/// }
178///
179/// let mut foo = MyEnum::Foo(String::from("foo"));
180/// foo.push_str("_bar");
181/// assert_eq!(foo.as_str(), "foo_bar")
182/// ```
183///
184/// # Extended example
185///
186/// ```rust
187/// use medea_macro::enum_delegate;
188///
189/// struct SomeState;
190/// struct AnotherState;
191///
192/// struct Context {
193///     some_value: i32,
194/// }
195///
196/// struct Peer<S> {
197///     context: Context,
198///     state: S,
199/// }
200///
201/// impl<T> Peer<T> {
202///     pub fn some_value(&self) -> i32 {
203///         self.context.some_value
204///     }
205///
206///     pub fn function_with_additional_args(&self, some_arg: i32) -> i32 {
207///         some_arg
208///     }
209///
210///     pub fn mutable_function(&mut self) -> i32 {
211///         let old_value = self.context.some_value;
212///         self.context.some_value = 1000;
213///         old_value
214///     }
215/// }
216///
217/// #[enum_delegate(pub fn some_value(&self) -> i32)]
218/// #[enum_delegate(
219///     pub fn function_with_additional_args(&self, some_arg: i32) -> i32
220/// )]
221/// #[enum_delegate(pub fn mutable_function(&mut self) -> i32)]
222/// enum PeerStateMachine {
223///     SomeState(Peer<SomeState>),
224///     AnotherState(Peer<AnotherState>),
225/// }
226///
227/// let mut peer = PeerStateMachine::SomeState(Peer {
228///     context: Context { some_value: 10 },
229///     state: SomeState,
230/// });
231///
232/// assert_eq!(peer.some_value(), 10);
233///
234/// assert_eq!(peer.function_with_additional_args(100), 100);
235///
236/// assert_eq!(peer.mutable_function(), 10);
237/// assert_eq!(peer.some_value(), 1000);
238/// ```
239#[proc_macro_attribute]
240pub fn enum_delegate(args: TokenStream, input: TokenStream) -> TokenStream {
241    enum_delegate::derive(&args, input)
242        .unwrap_or_else(|e| e.to_compile_error().into())
243}
244
245/// Generates a `*Handler` trait and dispatching function for some event,
246/// represented as `enum`.
247///
248/// # How to use
249///
250/// ### 1. Declare `enum` for event variants and a `struct` to handle them.
251///
252/// ```rust
253/// use medea_macro::dispatchable;
254///
255/// #[dispatchable]
256/// enum Event {
257///     Some { new_bar: i32 },
258///     Another,
259///     UnnamedVariant(i32, i32),
260/// }
261///
262/// struct Foo {
263///     bar: i32,
264///     baz: i32,
265/// }
266/// ```
267///
268/// ### 2. Implement handler for your `struct`.
269///
270/// For the given `enum` macro generates a unique trait by adding `Handler`
271/// to the end of its name. Each method of trait is created by `snake_case`'ing
272/// `enum` variants and adding `on_` prefix.
273///
274/// `type Output` is a type which will be returned from all functions of
275/// `EventHandler` trait.
276///
277/// ```rust
278/// # use medea_macro::dispatchable;
279/// #
280/// # #[dispatchable]
281/// # enum Event {
282/// #     Some { new_bar: i32 },
283/// #     Another,
284/// #     UnnamedVariant(i32, i32),
285/// # }
286/// #
287/// # struct Foo {
288/// #     bar: i32,
289/// #     baz: i32,
290/// # }
291/// #
292/// impl EventHandler for Foo {
293///     type Output = i32;
294///
295///     fn on_some(&mut self, new_bar: i32) -> Self::Output {
296///         self.bar = new_bar;
297///         self.bar
298///     }
299///
300///     fn on_another(&mut self) -> Self::Output {
301///         self.bar = 2;
302///         self.bar
303///     }
304///
305///     fn on_unnamed_variant(&mut self, data: (i32, i32)) -> Self::Output {
306///         self.bar = data.0;
307///         self.baz = data.1;
308///         self.bar
309///     }
310/// }
311/// ```
312///
313/// ### 3. Dispatch event with handler
314///
315/// For the given `enum` macro generates `dispatch_with()` method to dispatch
316/// `enum` with a given handler.
317///
318/// ```rust
319/// # use medea_macro::dispatchable;
320/// #
321/// # #[dispatchable]
322/// # enum Event {
323/// #     Some { new_bar: i32 },
324/// #     Another,
325/// #     UnnamedVariant(i32, i32),
326/// # }
327/// #
328/// # struct Foo {
329/// #     bar: i32,
330/// #     baz: i32,
331/// # }
332/// #
333/// # impl EventHandler for Foo {
334/// #    type Output = i32;
335/// #
336/// #    fn on_some(&mut self, new_bar: i32) -> Self::Output {
337/// #        self.bar = new_bar;
338/// #        self.bar
339/// #    }
340/// #
341/// #    fn on_another(&mut self) -> Self::Output {
342/// #        self.bar = 2;
343/// #        self.bar
344/// #    }
345/// #
346/// #    fn on_unnamed_variant(&mut self, data: (i32, i32)) -> Self::Output {
347/// #        self.bar = data.0;
348/// #        self.baz = data.1;
349/// #        self.bar
350/// #    }
351/// # }
352/// #
353/// #
354/// let mut foo = Foo { bar: 0, baz: 0 };
355///
356/// let bar = Event::Some { new_bar: 1 }.dispatch_with(&mut foo);
357/// assert_eq!(foo.bar, 1);
358/// assert_eq!(bar, 1);
359///
360/// let bar = Event::Another.dispatch_with(&mut foo);
361/// assert_eq!(foo.bar, 2);
362/// assert_eq!(bar, 2);
363///
364/// let bar = Event::UnnamedVariant(3, 3).dispatch_with(&mut foo);
365/// assert_eq!(foo.bar, 3);
366/// assert_eq!(foo.baz, 3);
367/// assert_eq!(bar, 3);
368/// ```
369///
370/// # Customize `self` type in handler functions (optional)
371///
372/// By default, all handler functions take `&mut Self`, if this doesn't suit
373/// your case, then you can specify the method receiver manually:
374/// `#[dispatchable(self: Rc<Self>)]`, `#[dispatchable(self: &Self)]`.
375///
376/// You can use any type that is a valid `self` receiver, e.g. `self`, `&self`,
377/// `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or
378/// `self: Pin<P>` (where P is one of the previous, except `Self`).
379///
380/// ```rust
381/// # use std::rc::Rc;
382/// use medea_macro::dispatchable;
383///
384/// #[dispatchable(self: Rc<Self>)]
385/// enum Event {
386///     Variant,
387/// }
388///
389/// struct Foo;
390/// impl EventHandler for Foo {
391///     type Output = ();
392///
393///     fn on_variant(self: Rc<Self>) {}
394/// }
395///
396/// let foo = Rc::new(Foo);
397///
398/// Event::Variant.dispatch_with(foo);
399/// ```
400///
401/// # Async handlers (optional)
402///
403/// It's possible to make handler methods `async`. Rust doesn't support `async`
404/// trait methods at the moment, that's why [`async_trait`] is used.
405///
406/// ```rust
407/// use async_trait::async_trait;
408/// use medea_macro::dispatchable;
409///
410/// #[dispatchable(async_trait(?Send))]
411/// enum Event {
412///     Variant,
413/// }
414///
415/// struct Foo;
416/// #[async_trait(?Send)]
417/// impl EventHandler for Foo {
418///     type Output = ();
419///
420///     async fn on_variant(&mut self) {}
421/// }
422///
423/// let mut foo = Foo;
424///
425/// Event::Variant.dispatch_with(&mut foo);
426/// ```
427///
428/// [`async_trait`]: https://docs.rs/async-trait
429#[proc_macro_attribute]
430pub fn dispatchable(args: TokenStream, input: TokenStream) -> TokenStream {
431    let enum_item = syn::parse_macro_input!(input as dispatchable::Item);
432    let args = syn::parse_macro_input!(args as dispatchable::Args);
433    dispatchable::expand(enum_item, &args)
434}
435
436/// Generates `ComponentState` implementation on provided `impl`.
437///
438/// # Usage
439///
440/// ```rust,ignore
441/// use std::rc::Rc;
442///
443/// use medea_jason::utils::Component;
444/// use medea_macro::{watchers, watch};
445///
446/// struct SenderState {
447///     muted: ObservableCell<bool>,
448///     enabled: ObservableCell<bool>,
449/// }
450///
451/// struct Sender;
452///
453/// type SenderComponent = Component<SenderState, Sender>;
454///
455/// #[watchers]
456/// impl SenderComponent {
457///     #[watch(self.muted.subscribe())]
458///     async fn muted_change_watcher(
459///         ctx: Rc<Sender>,
460///         state: Rc<SenderState>,
461///         new_muted_val: bool
462///     ) -> Result<(), ()> {
463///         Ok(())
464///     }
465///
466///     #[watch(self.enabled.subscribe())]
467///     async fn enabled_change_watcher(
468///         ctx: Rc<Sender>,
469///         state: Rc<SenderState>,
470///         new_enabled_val: bool,
471///     ) -> Result<(), ()> {
472///         Ok(())
473///     }
474/// }
475/// ```
476///
477/// ## `SenderComponent` implementation after macro expansion
478///
479/// ```rust,ignore
480/// impl SenderComponent {
481///     async fn muted_change_watcher(
482///         sender: Rc<Sender>,
483///         state: Rc<SenderState>,
484///         new_muted_val: bool
485///     ) -> Result<(), ()> {
486///         Ok(())
487///     }
488///
489///     async fn enabled_change_watcher(
490///         sender: Rc<Sender>,
491///         state: Rc<SenderState>,
492///         new_enabled_val: bool,
493///     ) -> Result<(), ()> {
494///         Ok(())
495///     }
496/// }
497///
498/// impl ComponentState<Sender> for SenderState {
499///     fn spawn_watchers(&self, s: &mut WatchersSpawner<SenderState, Sender>) {
500///         s.spawn(
501///             self.muted.subscribe(),
502///             SenderComponent::muted_change_watcher,
503///         );
504///         s.spawn(
505///             self.enabled.subscribe(),
506///             SenderComponent::enabled_change_watcher,
507///         );
508///     }
509/// }
510/// ```
511///
512/// __Note__: `ComponentState` implementation is simplified in this example
513///           for better readability.
514///
515/// In reality object and state types will be obtained by casting
516/// `SenderComponent` to the `ComponentTypes` trait and getting types from it.
517#[proc_macro_attribute]
518pub fn watchers(_: TokenStream, input: TokenStream) -> TokenStream {
519    watchers::expand(syn::parse_macro_input!(input))
520        .unwrap_or_else(|e| e.to_compile_error().into())
521}
522
523/// Generate implementation of `Caused` trait for errors represented as enum.
524///
525/// # How to use
526///
527/// ### 1. Declare custom error and enum for error variants.
528///
529/// The `cause()` method returns error if nested error has its type declared
530/// as an argument of the attribute `#[cause(error = path::to::Error)]` or the
531/// error type is assumed to be imported as `Error`.
532///
533/// ```rust
534/// use medea_jason::utils::Caused;
535///
536/// struct MyError;
537///
538/// #[derive(Caused)]
539/// #[cause(error = MyError)]
540/// enum FooError {
541///     Internal,
542///     MyError(MyError),
543/// }
544///
545/// let err = FooError::Internal;
546/// assert!(err.cause().is_none());
547///
548/// let err = FooError::MyError(MyError {});
549/// assert!(err.cause().is_some());
550/// ```
551///
552/// If enum variant has attribute `#[cause]` it will call the `cause()`
553/// method on nested error.
554///
555/// ```rust
556/// # use medea_jason::utils::Caused;
557/// #
558/// # struct MyError;
559/// #
560/// # #[derive(Caused)]
561/// # #[cause(error = MyError)]
562/// # enum FooError {
563/// #     Internal,
564/// #     MyError(MyError),
565/// # }
566/// #
567/// #[derive(Caused)]
568/// #[cause(error = MyError)]
569/// enum BarError {
570///     Foo(#[cause] FooError),
571/// }
572///
573/// let err = BarError::Foo(FooError::Internal);
574/// assert!(err.cause().is_none());
575///
576/// let err = BarError::Foo(FooError::MyError(MyError {}));
577/// assert!(err.cause().is_some());
578/// ```
579#[proc_macro_derive(Caused, attributes(cause))]
580pub fn derive_caused(input: TokenStream) -> TokenStream {
581    syn::parse::<syn::DeriveInput>(input)
582        .and_then(|i| {
583            let mut s = synstructure::Structure::try_new(&i)?;
584            caused::derive(&mut s)
585        })
586        .unwrap_or_else(|e| e.to_compile_error())
587        .into()
588}
589
590/// Generates code for `extern` Dart functions registration and calling.
591///
592/// # Usage
593///
594/// ## Macro call
595///
596/// ```ignore
597/// // Code will be generated in the `peer_connection` module, also you can
598/// // control visibility of this module with a visibility modifier (`pub`).
599/// //
600/// // Module name will be used as a prefix for a registration function.
601/// #[dart_bridge]
602/// mod peer_connection {
603///     use dart_sys::Dart_Handle;
604///
605///     use crate::platform::Error;
606///
607///     extern "C" {
608///         // This documentation will be injected to the generated
609///         // extern function caller:
610///
611///         /// Returns newly created SDP offer of the provided
612///         /// `PeerConnection`.
613///         fn create_offer(peer: Dart_Handle) -> Result<Dart_Handle, Error>;
614///
615///         /// Returns a newly created SDP answer of the provided
616///         /// `PeerConnection`.
617///         fn create_answer(peer: Dart_Handle) -> Result<Dart_Handle, Error>;
618///     }
619/// }
620/// ```
621///
622/// ## Example of the generated code
623///
624/// ```ignore
625/// #[automatically_derived]
626/// mod peer_connection {
627///     use dart_sys::Dart_Handle;
628///
629///     use crate::platform::Error;
630///
631///     type PeerConnectionCreateOfferFunction =
632///         extern "C" fn(peer: Dart_Handle) -> Dart_Handle;
633///     type PeerConnectionCreateAnswerFunction =
634///         extern "C" fn(peer: Dart_Handle) -> Dart_Handle;
635///
636///     static PEER_CONNECTION__CREATE_OFFER__FUNCTION: ::std::sync::OnceLock<
637///         ::send_wrapper::SendWrapper<PeerConnectionCreateOfferFunction>,
638///     > = ::std::sync::OnceLock::new();
639///
640///     static PEER_CONNECTION__CREATE_ANSWER__FUNCTION: ::std::sync::OnceLock<
641///         ::send_wrapper::SendWrapper<PeerConnectionCreateAnswerFunction>,
642///     > = ::std::sync::OnceLock::new();
643///
644///     static PEER_CONNECTION__CREATE_OFFER__ERROR: ::std::sync::LazyLock<
645///         ::send_wrapper::SendWrapper<::std::cell::RefCell<Option<Error>>>,
646///     > = ::std::sync::LazyLock::new(|| {
647///         ::send_wrapper::SendWrapper::new(::std::cell::RefCell::new(None))
648///     });
649///
650///     static PEER_CONNECTION__CREATE_ANSWER__ERROR: ::std::sync::LazyLock<
651///         ::send_wrapper::SendWrapper<::std::cell::RefCell<Option<Error>>>,
652///     > = ::std::sync::LazyLock::new(|| {
653///         ::send_wrapper::SendWrapper::new(::std::cell::RefCell::new(None))
654///     });
655///
656///     #[unsafe(no_mangle)]
657///     pub unsafe extern "C" fn register_peer_connection(
658///         create_offer: PeerConnectionCreateOfferFunction,
659///         create_answer: PeerConnectionCreateAnswerFunction,
660///     ) {
661///         PEER_CONNECTION__CREATE_OFFER__FUNCTION
662///             .set(::send_wrapper::SendWrapper::new(create_offer))
663///             .expect(
664///                 "PEER_CONNECTION__CREATE_OFFER__FUNCTION \
665///                 can only be set once",
666///             );
667///         PEER_CONNECTION__CREATE_ANSWER__FUNCTION
668///             .set(::send_wrapper::SendWrapper::new(create_answer))
669///             .expect(
670///                 "PEER_CONNECTION__CREATE_ANSWER__FUNCTION \
671///                 can only be set once",
672///             );
673///     }
674///
675///     /// Error setter for the `create_offer` function
676///     #[unsafe(no_mangle)]
677///     pub unsafe extern "C" fn peer_connection__create_offer__set_error(
678///         err: Dart_Handle,
679///     ) {
680///         _ = PEER_CONNECTION__CREATE_OFFER__ERROR.replace(
681///             Some(Error::from_handle(err))
682///         );
683///     }
684///
685///     /// Error setter for the `create_answer` function.
686///     #[unsafe(no_mangle)]
687///     pub unsafe extern "C" fn peer_connection__create_answer__set_error(
688///         err: Dart_Handle,
689///     ) {
690///         _ = PEER_CONNECTION__CREATE_ANSWER__ERROR.replace(
691///             Some(Error::from_handle(err))
692///         );
693///     }
694///
695///     /// Returns newly created SDP offer of the provided `PeerConnection`.
696///     pub unsafe fn create_offer(
697///         peer: Dart_Handle,
698///     ) -> Result<Dart_Handle, Error> {
699///         let res = (PEER_CONNECTION__CREATE_OFFER__FUNCTION
700///             .get()
701///             .as_ref()
702///             .expect("PEER_CONNECTION__CREATE_OFFER__FUNCTION is not set"))
703///             (peer);
704///         if let Some(e) = PEER_CONNECTION__CREATE_OFFER__ERROR
705///             .borrow_mut()
706///             .take()
707///         {
708///             Err(e)
709///         } else {
710///             Ok(res)
711///         }
712///     }
713///
714///     /// Returns a newly created SDP answer of the provided
715///     /// `PeerConnection`.
716///     pub unsafe fn create_answer(
717///         peer: Dart_Handle,
718///     ) -> Result<Dart_Handle, Error> {
719///         let res = (PEER_CONNECTION__CREATE_ANSWER__FUNCTION
720///             .get()
721///             .as_ref()
722///             .expect("PEER_CONNECTION__CREATE_ANSWER__FUNCTION is not set"))
723///             (peer);
724///         if let Some(e) = PEER_CONNECTION__CREATE_ANSWER__ERROR
725///             .borrow_mut()
726///             .take()
727///         {
728///             Err(e)
729///         } else {
730///             Ok(res)
731///         }
732///     }
733/// }
734/// ```
735///
736/// ## Generated code usage
737///
738/// ```ignore
739/// struct PeerConnection(Dart_Handle);
740///
741/// impl PeerConnection {
742///     pub async fn create_offer(&self) -> RtcPeerConnectionResult<String> {
743///         let fut = unsafe {
744///             peer_connection::create_offer(self.handle.get())
745///         }.unwrap();
746///
747///         unsafe { FutureFromDart::execute(fut) }
748///             .await
749///             .map_err(RtcPeerConnectionError::CreateOfferFailed)
750///     }
751///
752///     pub async fn create_answer(&self) -> RtcPeerConnectionResult<String> {
753///         let fut = unsafe {
754///             peer_connection::create_offer(self.handle.get())
755///         }.unwrap();
756///
757///         unsafe { FutureFromDart::execute(fut) }
758///             .await
759///             .map_err(RtcPeerConnectionError::CreateAnswerFailed)
760///     }
761/// }
762///
763/// pub enum RtcPeerConnectionError {
764///     CreateOfferFailed(platform::Error),
765///     CreateAnswerFailed(platform::Error),
766/// }
767///
768/// pub type RtcPeerConnectionResult<T> = Result<T, RtcPeerConnectionError>;
769/// ```
770/// ## Dart side code
771///
772/// Also, you need to call registration functions on Dart side:
773/// ```dart
774/// dl.lookupFunction<Void Function(Pointer), void Function(Pointer)>(
775///         'register_peer_connection')(
776///     createOffer_native,
777///     createAnswer_native,
778/// );
779/// ```
780#[proc_macro_attribute]
781pub fn dart_bridge(args: TokenStream, input: TokenStream) -> TokenStream {
782    dart_bridge::expand(args.into(), input.into())
783        .map_or_else(|e| e.to_compile_error().into(), Into::into)
784}