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}