join_impl/join/
mod.rs

1//!
2//! Macro output generator.
3//!
4
5pub mod config;
6pub mod join_output;
7pub mod name_constructors;
8pub mod parse;
9
10pub use config::Config;
11
12use proc_macro2::TokenStream;
13use quote::ToTokens;
14use syn::Path;
15
16use super::handler::Handler;
17use crate::{action_expr_chain::ActionExprChain, chain::Chain};
18use join_output::JoinOutput;
19use syn::parse_quote;
20
21///
22/// Result of parsing `join!` macro input in trait form.
23///
24pub trait JoinInput {
25    ///
26    /// Object with implementation of `Chain` trait used to generate macro output.
27    ///
28    type Chain: Chain;
29
30    ///
31    /// Optional `join!` macro handler.
32    ///
33    type Handler;
34
35    ///
36    /// Returns custom futures_crate_path taken from macro input if exists.
37    ///
38    fn futures_crate_path(&self) -> Option<&Path>;
39
40    ///
41    /// Returns branches, each of branches is an object implemented `Chain` trait.
42    ///
43    fn branches(&self) -> &[Self::Chain];
44
45    ///
46    /// Returns `Handler` if exists.
47    ///
48    fn handler(&self) -> Option<&Self::Handler>;
49
50    ///
51    /// Returns custom joiner if exists.
52    ///
53    fn joiner(&self) -> Option<&TokenStream>;
54
55    ///
56    /// Returns transpose results configuration if specified.
57    ///
58    fn transpose_results_option(&self) -> Option<bool>;
59
60    ///
61    /// Returns lazy branches configuration if provided.
62    ///
63    fn lazy_branches_option(&self) -> Option<bool>;
64}
65
66///
67/// Default struct which represents result of parsing `join!` macro input.
68///
69pub struct JoinInputDefault {
70    pub futures_crate_path: Option<Path>,
71    pub custom_joiner: Option<TokenStream>,
72    pub transpose_results: Option<bool>,
73    pub lazy_branches: Option<bool>,
74    pub branches: Vec<ActionExprChain>,
75    pub handler: Option<Handler>,
76}
77
78impl JoinInput for JoinInputDefault {
79    type Chain = ActionExprChain;
80    type Handler = Handler;
81
82    fn futures_crate_path(&self) -> Option<&Path> {
83        self.futures_crate_path.as_ref()
84    }
85
86    fn branches(&self) -> &[Self::Chain] {
87        &self.branches
88    }
89
90    fn handler(&self) -> Option<&Self::Handler> {
91        self.handler.as_ref()
92    }
93
94    fn joiner(&self) -> Option<&TokenStream> {
95        self.custom_joiner.as_ref()
96    }
97
98    fn transpose_results_option(&self) -> Option<bool> {
99        self.transpose_results.as_ref().copied()
100    }
101
102    fn lazy_branches_option(&self) -> Option<bool> {
103        self.lazy_branches.as_ref().copied()
104    }
105}
106
107///
108/// Generates output of the `join!` macro based on parsed input and given config.
109///
110pub fn generate_join<T: JoinInput<Chain = ActionExprChain, Handler = Handler>>(
111    join: &T,
112    config: Config,
113) -> TokenStream {
114    let default_futures_crate_path = parse_quote! { ::futures };
115
116    JoinOutput::new(
117        join.branches(),
118        join.handler(),
119        if let Some(futures_crate_path) = join.futures_crate_path() {
120            Some(futures_crate_path)
121        } else if config.is_async {
122            Some(&default_futures_crate_path)
123        } else {
124            None
125        },
126        join.joiner(),
127        join.transpose_results_option(),
128        join.lazy_branches_option(),
129        config,
130    )
131    .unwrap()
132    .into_token_stream()
133}