devela/code/util/
_reexport.rs

1// devela::code::util::_reexport
2//
3//! private reexport meta helper
4//
5
6/// Macro helper for documentation of re-exported items.
7//
8// FIX: unresolved link to `alloc`.
9// IMPROVE: make dependencies safety related to features.
10// IMPROVE: rendered paths with trailing `::`. E.g.:
11// - Re-exported from std::backtrace:: .
12// - Re-exported from [alloc]::boxed:: .
13// - Re-exported from core::array:: IntoIter→ArrayIntoIter.
14// MAYBE: new branch for: either a crate or core (for portable-atomic types).
15macro_rules! reexport {
16    /* re-exports from normal modules */
17
18    // the following 4 arms allows reexporting items from:
19    // `core`, `alloc`, `std` or `no_std`|`std`.
20    //
21    // - Supports multiple re-exported items.
22    // - Renamed items must be all at the end, and each one prefixed with @.
23    //
24    // # Examples
25    // ```
26    // reexport! { rust: core::any, local_module: "any",
27    //     "Represents a globally unique identifier for a type.", TypeId }
28    // ```
29    ( // when the item is available in `core`
30      rust : core $( :: $( $core_path:ident )::+)?,
31      $( local_module: $module_feature:literal, )?
32      $( extra_features: $($extraf:literal),+ $(,)? )?
33      $( tag: $tag:expr, )?
34      doc: $description:literal,
35      $( $item:ident ),*
36      $(@ $item_to_rename:ident as $item_renamed:ident),*
37      $(,)?
38    ) => { $crate::paste! {
39        #[doc(inline)]
40        $( #[doc = $tag] )?
41        #[doc = "<span class='stab portability' title='re-exported from rust&#39;s "
42        "`core`'>`core`</span>"]
43        #[doc = $description]
44        #[doc = "\n\n*Re-exported from [`core" $( "`]::[`" $( $core_path "::" )+ )?
45            "`](https://doc.rust-lang.org/core/" $($( $core_path "/" )+)? ")*"]
46
47        #[doc = $("`" $item_to_rename "`→[`" $item_renamed "`]")* ".\n\n---"]
48
49        #[cfg_attr(feature = "nightly_doc", doc(cfg(all(
50            $( feature = $module_feature, )?
51            $( all($(feature = $extraf),+) )?
52        ))))]
53        #[cfg(all(
54            $( $(feature = $extraf),+ )?
55        ))]
56        pub use core :: $($( $core_path :: )+)? {
57            $( $item ),*
58            $( $item_to_rename as $item_renamed ),*
59        };
60    }};
61    // when the item is available in `alloc`
62    ( rust : alloc $( :: $( $alloc_path:ident )::+)?,
63      $( local_module: $module_feature:literal, )?
64      $( tag: $tag:expr, )?
65      doc: $description:literal,
66      $( $item:ident ),*
67      $(@ $item_to_rename:ident as $item_renamed:ident),*
68      $(,)?
69    ) => { $crate::paste! {
70        #[doc(inline)]
71        #[allow(rustdoc::broken_intra_doc_links)] // TEMP FIX unresolved link to alloc
72        $( #[doc = $tag] )?
73        #[doc = "<span class='stab portability' title='re-exported from rust&#39;s "
74        "`alloc`'>`alloc`</span>"]
75        #[doc = $description]
76        #[doc = "\n\n*Re-exported from [`alloc" $( "`]::[`" $( $alloc_path "::" )+ )?
77            "`](https://doc.rust-lang.org/alloc/" $($( $alloc_path "/" )+)? ")*"]
78
79        #[doc = $("`" $item_to_rename "`→[`" $item_renamed "`]")* ".\n\n---"]
80
81        #[cfg_attr(
82            feature = "nightly_doc",
83            doc(cfg(all(
84                $( feature = $module_feature, )?
85                feature = "alloc"
86            )))
87        )]
88
89        #[cfg(feature = "alloc")]
90        pub use crate::_dep::_alloc :: $($( $alloc_path :: )+)? {
91            $( $item ),*
92            $( $item_to_rename as $item_renamed ),*
93        };
94    }};
95    ( // when the item is available in `std`
96      rust : std $( :: $( $std_path:ident )::+)?,
97      $( local_module: $module_feature:literal, )?
98      $( tag: $tag:expr, )?
99      doc: $description:literal,
100      $( $item:ident ),*
101      $(@ $item_to_rename:ident as $item_renamed:ident),*
102      $(,)?
103    ) => { $crate::paste! {
104        #[doc(inline)]
105        $( #[doc = $tag] )?
106        #[doc = "<span class='stab portability' title='re-exported from rust&#39;s "
107        "`std`'>`std`</span>"]
108        #[doc = $description]
109        #[doc = "\n\n*Re-exported from [`std" $( "`]::[`" $( $std_path "::" )+ )?
110            "`](https://doc.rust-lang.org/std/" $($( $std_path "/" )+)? ")*"]
111
112        #[doc = $("`" $item_to_rename "`→[`" $item_renamed "`]")* ".\n\n---"]
113
114        #[cfg_attr(
115            feature = "nightly_doc",
116            doc(cfg(all(
117                $( feature = $module_feature, )?
118                feature = "std"
119            )))
120        )]
121
122        #[cfg(feature = "std")]
123        pub use std :: $($( $std_path :: )+)? {
124            $( $item ),*
125            $( $item_to_rename as $item_renamed ),*
126        };
127    }};
128    ( // when the item is available in either `no_std` or `std`
129      rust : no_std|std $( :: $( $std_path:ident )::+)?,
130      $( local_module: $module_feature:literal, )?
131      $( tag: $tag:expr, )?
132      doc: $description:literal,
133      $( $item:ident ),*
134      $(@ $item_to_rename:ident as $item_renamed:ident),*
135      $(,)?
136    ) => { $crate::paste! {
137        #[doc(inline)]
138        $( #[doc = $tag] )?
139        /// <span class='stab portability' title='re-exported from rust&#39;s `std`
140        /// or recreated for `no_std`'>`[no_]std`</span>
141        #[doc = $description]
142        #[doc = "\n\n*Re-exported from [`std" $( "`]::[`" $( $std_path "::" )+ )?
143            "`](https://doc.rust-lang.org/std/" $($( $std_path "/" )+)? ")*"]
144
145        #[doc = $("`" $item_to_rename "`→[`" $item_renamed "`]")* ".\n\n---"]
146
147        #[cfg_attr(
148            feature = "nightly_doc",
149            doc(cfg(all(
150                $( feature = $module_feature, )?
151                any(feature = "std", feature = "no_std")
152            )))
153        )]
154
155        #[cfg(feature = "std")]
156        pub use std :: $($( $std_path :: )+)? {
157            $( $item ),*
158            $( $item_to_rename as $item_renamed ),*
159        };
160    }};
161
162    ( // when the item is available in either `not(std)` or `std` (always, more transparent)
163      rust : not(std)|std $( :: $( $std_path:ident )::+)?,
164      $( local_module: $module_feature:literal, )?
165      $( tag: $tag:expr, )?
166      doc: $description:literal,
167      $( $item:ident ),*
168      $(@ $item_to_rename:ident as $item_renamed:ident),*
169      $(,)?
170    ) => { $crate::paste! {
171        #[doc(inline)]
172        $( #[doc = $tag] )?
173        /// <span class='stab portability' title='re-exported from rust&#39;s `std`
174        /// or recreated if `not(std)`'>`?std`</span>
175        #[doc = $description]
176        #[doc = "\n\n*Re-exported from [`std" $( "`]::[`" $( $std_path "::" )+ )?
177            "`](https://doc.rust-lang.org/std/" $($( $std_path "/" )+)? ")*"]
178
179        #[doc = $("`" $item_to_rename "`→[`" $item_renamed "`]")* ".\n\n---"]
180
181        #[cfg_attr(
182            feature = "nightly_doc",
183            doc(cfg(all(
184                $( feature = $module_feature, )?
185            )))
186        )]
187
188        #[cfg(feature = "std")]
189        pub use std :: $($( $std_path :: )+)? {
190            $( $item ),*
191            $( $item_to_rename as $item_renamed ),*
192        };
193    }};
194    (
195      /* external dependencies */
196
197      // Re-exports a non-optional crate
198      crate $dep_str:literal | $dep:ident,
199      doc: $description:literal
200      $(, features: $( $f:literal ),+ )?
201    ) => { $crate::paste! {
202        #[doc = "<span class='stab portability' title='re-exported `" $dep_str
203            "`'>`" $dep_str "`</span>"]
204        #[doc = $description "\n\n---" ]
205        #[doc(inline)]
206        pub use ::$dep;
207    }};
208    (
209      // Re-exports an optional crate
210      //
211      // $dep_safe:    [safe|unsafe] (affects compilation with "safest" feature)
212      // $dep_feat:    the dependency feature that enables it
213      // $dep_name:    the dependency real name
214      // $dep_mod:     the dependency module name (using _ instead of -)
215      // $description: the dependency description
216      // $f:           additional features needed to enable this dependency
217      optional_crate ($dep_safe:tt)
218      $dep_feat:literal, $dep_name:literal, $dep_mod:ident,
219      doc: $description:literal
220      $(, features: $( $f:literal ),+ )?
221    ) => { $crate::paste! {
222        #[cfg(all(feature = $dep_feat $(, $(feature = $f),+ )? ))]
223        $crate::items! {
224            // safety-guard: panics if `safest` is enabled and dependency is not safe
225            #[cfg(feature = "safest")]
226            #[$crate::compile(diff($dep_safe, safe))]
227            const [<SAFEST_ $dep_name:upper>]: () = { panic![concat!["The `", $dep_name,
228            "` dependency is not compatible with the `safest` feature"]] };
229
230            #[doc = "<span class='stab portability' title='re-exported `" $dep_name
231                "`'>`" $dep_name "`</span>"]
232            #[doc = $description "\n\n---" ]
233            #[cfg_attr(
234                feature = "nightly_doc",
235                doc(cfg(all(
236                    feature = $dep_feat $(, $(feature = $f)+ )?
237                )))
238            )]
239            #[doc(inline)]
240            pub use ::$dep_mod;
241        }
242    }};
243    (
244      // re-exports items from an external optional dependency, from any normal module.
245      //
246      // - Supports multiple re-exported items.
247      // - Renamed items must be all at the end, and each one prefixed with @.
248      //
249      // $dep_feat:    the dependency feature
250      // $dep_name:    the dependency name
251      // $dep_mod:     the dependency module
252      // $f:           additional features needed
253      // $description: the dependency description
254      // $item:
255      // $item_to_rename:
256      // $item_renamed:
257      $dep_feat:literal, $dep_name:literal, $dep_mod:ident $( :: $dep_path:path)?,
258      $( features: $( $f:literal ),+ ,)?
259      $( tag: $tag:expr, )?
260      doc: $description:literal,
261      $( $item:ident ),*
262      $(@ $item_to_rename:ident as $item_renamed:ident),*
263      $(,)?
264    ) => { $crate::paste! {
265        #[doc(inline)]
266        $( #[doc = $tag] )?
267        #[doc = "<span class='stab portability' title='re-exported from the `"
268            $dep_name "` crate'>`" $dep_name "`</span>"]
269        #[doc = $description]
270        #[doc = "\n\n*Re-exported from the [`" $dep_name
271            "`](https://docs.rs/" $dep_name " ) crate*"]
272
273        #[doc = $("`" $item_to_rename "`→[`" $item_renamed "`]")* ".\n\n---"]
274
275        // IMPROVE: can't use like this for portable-atomic | core::atomic,
276        // should remove depend from here for the portable-atomic part,
277        // but leave it in the following cfg attribute.
278        // Also, the part of negated features and target_has_atomic
279        // would require a different branch
280        #[cfg_attr(
281            feature = "nightly_doc",
282            doc(cfg(all(
283                feature = $dep_feat $(, $(feature = $f)+ )?
284            )))
285        )]
286
287        #[cfg(all(feature = $dep_feat $(, $(feature = $f),+ )? ))]
288        pub use crate::_dep::$dep_mod $( ::$dep_path )? :: {
289            $( $item ),*
290            $( $item_to_rename as $item_renamed ),*
291        };
292    }};
293    (
294      // re-exports items from an external non-optional dependency, from any normal module.
295      //
296      // - Supports multiple re-exported items.
297      // - Renamed items must be all at the end, and each one prefixed with @.
298      //
299      // in the past it was used for: result::Either
300      non-optional $dep_str:literal | $dep:ident $( :: $dep_path:path)?,
301      $( features: $( $f:literal ),+ ,)?
302      $( local_module: $module_feature:literal ,)?
303      $( tag: $tag:expr, )?
304      doc: $description:literal,
305      $( $item:ident ),*
306      $(@ $item_to_rename:ident as $item_renamed:ident),*
307      $(,)?
308    ) => { $crate::paste! {
309        #[doc(inline)]
310        $( #[doc = $tag] )?
311        #[doc = "<span class='stab portability' title='re-exported from the `" $dep_str
312            "` crate'>`" $dep_str "`</span>"]
313        #[doc = $description]
314        #[doc = "\n\n*Re-exported from the [`" $dep_str
315            "`](https://docs.rs/" $dep_str " ) crate*"]
316
317        #[doc = $("`" $item_to_rename "`→[`" $item_renamed "`]")* ".\n\n---"]
318
319        #[cfg_attr(feature = "nightly_doc", doc(cfg(all(
320            $( feature = $module_feature ,)?
321            $( $( feature = $f ),+ )?
322        ))))]
323        #[cfg(all( $($( feature = $f )+)? ))]
324
325        pub use ::$dep $( ::$dep_path )? :: {
326            $( $item ),*
327            $( $item_to_rename as $item_renamed ),*
328        };
329    }};
330}
331pub(crate) use reexport;