devela/code/util/
_doc.rs

1// devela::code::util::_doc
2//
3//! private doc meta helpers
4//
5// TOC
6// - doc_!
7// - doc_availability!
8// - doc_miri_warn!
9// - std_core!
10// - EMOJI_*!, TAG_*!
11//
12// TODO: try to use paste! instead of concat!, since it's faster.
13
14/// Generates a formatted meta-documentation string.
15macro_rules! doc_ {
16    (@meta_start) => {
17        "<br/><i style='margin-left:0em;'></i><span style='font-size:90%;word-spacing:0px'>"
18    };
19    (@meta_start_nobr) => {
20        concat!(
21            "<i style='margin-left:0em;margin-top:-2em;'></i>",
22            "<span style='font-size:90%;word-spacing:0px'>",
23        )
24    };
25    (@meta_end) => { "</span>" };
26    (@meta_end_hr) => { "</span><hr/>" };
27    // (newline) => { "<br/><br/>" };
28    (newline) => { "<br/><br style='display:block;content:\"\";margin-top:10px;' />" };
29
30    /* list of submodules */
31
32    // IMPROVE:MAYBE pass optional feature-gate arg for each module
33    ( // no submodules:
34        modules: $path:path; $self:ident) => {
35        concat!(
36            $crate::doc_!(@meta_start),
37            "[", stringify!($self), "][mod@", stringify!($path), "::", stringify!($self), "]",
38            $crate::doc_!(@meta_end),
39        )
40    };
41    ( // with submodules:
42        modules: $path:path; $self:ident: $($mod:ident),+ $(,)?) => {
43        concat!(
44            $crate::doc_!(@meta_start),
45            "[", stringify!($self), "][mod@", stringify!($path), "::", stringify!($self), "]::{",
46            $crate::doc_!(@modules: $path; $self: $($mod),+), "}",
47            $crate::doc_!(@meta_end),
48        )
49    };
50    // Handles the list of modules ensuring commas are only added between elements.
51    (@modules: $path:path; $self:ident: $first:ident $(, $rest:ident)*) => {
52        concat!(
53            "[", stringify!($first), "](mod@",
54                stringify!($path), "::", stringify!($self), "::",
55                stringify!($first), ")",
56            $(
57                ", [", stringify!($rest), "](mod@", stringify!($path), "::",
58                stringify!($self), "::", stringify!($rest), ")"
59            ),*
60        )
61    };
62
63    /* list of std modules */
64
65    (extends: $($mod:ident),+ $(,)?) => {
66        concat!(
67            $crate::doc_!(@meta_start_nobr), "Extends: ",
68            $crate::std_core!(), "::{", $crate::doc_!(@extends: $($mod),+), "}",
69            $crate::doc_!(@meta_end_hr),
70        )
71    };
72    // Handles the list of modules ensuring commas are only added between elements.
73    (@extends: $first:ident $(, $rest:ident)*) => {
74        concat!(
75            "[", stringify!($first), "](mod@", $crate::std_core!(), "::", stringify!($first), ")",
76            $( ", [", stringify!($rest), "](mod@", $crate::std_core!(), "::", stringify!($rest), ")" ),*
77        )
78    };
79    (
80    // Shows the `Vendored` doc section and links to the info line.
81    //
82    // $crate_id: the crate's name and html id anchor on the docs.
83    vendor: $crate_id:literal) => { concat!(
84        "\n\n# Vendored\n\nThis is adapted work from [",
85        $crate_id, "][crate::_info::vendored#", $crate_id, "].\n\n"
86    )};
87    (
88    // Shows the `Vendored` doc section and links to the *modifications* module.
89    vendor: $crate_id:literal, module:$mod_id:ident) => { concat!(
90        "\n\n# Vendored\n\nThis is adapted work from [",
91        $crate_id, "][crate::_info::vendored::", $mod_id, "].\n\n"
92    )};
93    (
94    // Assumes the path is in current directory. Used in `_info/vendored`.
95    //
96    // $crate_id:  the crate's name and html id anchor on the docs.
97    // $text_path: the path to the text file to include, explaining the modifications.
98    //
99    // MAYBE: link to crate
100    // MAYBE: add more information
101    vendor_mod: $crate_id:literal, $mod_id:ident) => {
102        #[doc = concat!(
103            "# `", $crate_id,
104            "` modifications\n\n[*(↑)*][crate::_info::vendored#", $crate_id, "] ",
105            include_str!(concat!("./", $crate_id, ".md"))
106        )]
107        pub mod $mod_id {}
108    };
109    // (
110    // // Does not assume the path. TEMP: unused
111    //
112    // // $crate_id:  the crate's name and html id anchor on the docs.
113    // // $text_path: the path to the text file to include, explaining the modifications.
114    // vendor_mod: $crate_id:literal, $text_path:literal) => { concat!(
115    //     "# ", $crate_id, "\n\n[*(↑)*][crate::_info::vendored#", $crate_id, "] ",
116    //     include_str!($text_path),
117    // )};
118}
119pub(crate) use doc_;
120
121/// Generates a formatted documentation string for conditional availability.
122///
123/// It's intended to be used like this:
124/// ```txt
125/// #[doc = crate::doc_availability!(feature = "one")]
126/// #[doc = crate::doc_availability!(all(feature = "one", feature = "two")]
127/// #[doc = crate::doc_availability!(any(feature = "one", feature = "two")]
128/// ```
129#[allow(unused_macros)]
130macro_rules! doc_availability {
131    (feature = $feat:literal) => {
132        $crate::doc_availability!{@wrap
133            "Available on <strong>crate feature ",
134            $crate::doc_availability!{@code $feat},
135            "</strong> only."
136        }
137    };
138
139    // Handle one or more required features
140    ( all( $(feature = $feat:literal),+ ) ) => {
141        $crate::doc_availability!{@wrap
142            "Available on <strong>crate features ",
143            $crate::doc_availability!{@join_features_and $($feat),+},
144            "</strong> only."
145        }
146    };
147    // Handle one or more alternative features
148    ( any( $(feature = $feat:literal),+ ) ) => {
149        $crate::doc_availability!{@wrap
150            "Available on <strong>crate features ",
151            $crate::doc_availability!{@join_features_or $($feat),+},
152            "</strong> only."
153        }
154    };
155
156    /* helper arms */
157
158    // Outer wrap
159    (@wrap $($strings:tt)+) => {
160        concat!(
161            "<div class='item-info' style='margin-left:0;'>",
162            "<div class='stab portability'>",
163            $($strings)+,
164            "</div></div>"
165        )
166    };
167
168    // code-formatted literal
169    (@code $string:literal) => {
170        concat!("<code style='background:none'>", $string, "</code>")
171    };
172
173    // single arm for joining features with "and"
174    (@join_features_and $first:literal $(, $rest:literal)*) => {
175        concat!(
176            $crate::doc_availability!{@code $first}
177            $(
178                , " and ", $crate::doc_availability!{@code $rest}
179            )*
180        )
181    };
182    // single arm for joining features with "or"
183    (@join_features_or $first:literal $(, $rest:literal)*) => {
184        concat!(
185            $crate::doc_availability!{@code $first}
186            $(
187                , " or ", $crate::doc_availability!{@code $rest}
188            )*
189        )
190    };
191}
192#[allow(unused_imports)]
193pub(crate) use doc_availability;
194
195/// Generates a formatted documentation string for a miri warning.
196#[allow(unused_macros)]
197macro_rules! doc_miri_warn {
198    (tag) => {
199        concat!(
200            "<span class='stab portability' ",
201            "title='Fails to compile with Miri.'>",
202            "<code>⚠️</code></span>"
203        )
204    };
205    (body $(, url: $url:literal)?) => {
206        concat!(
207            "<div class='warning'>",
208            "Fails to compile with Miri.",
209            $( "<p><em>See <a href = '", $url, "'>", $url, "</a>.</em></p>", )?
210            "</div>"
211        )
212    };
213}
214#[allow(unused_imports)]
215pub(crate) use doc_miri_warn;
216
217/// Returns the string literal "std" if `std` is enabled, or "core" otherwise.
218#[cfg(feature = "std")]
219macro_rules! std_core {
220    () => {
221        "std"
222    };
223}
224#[cfg(not(feature = "std"))]
225macro_rules! std_core {
226    () => {
227        "core"
228    };
229}
230pub(crate) use std_core;
231
232/// Private tags definitions for visual type categorization in documentation.
233mod tags {
234    #![allow(unused)]
235    crate::CONST! { pub(crate),
236        EMOJI_ATOMIC = "⚛️"; // ⚛️,🔬,🌐
237        EMOJI_DATA_STRUCTURE = "📦"; // 📦,🧩,🗂️,
238        EMOJI_ERROR = "🚩"; // ❌,🚫,📛,🚧,📉,🚩,
239        // EMOJI_COMPOSITE = "+"; // 📎,🧩,📦,🖇️,🗂️,
240        EMOJI_EXPERIMENTAL = "🧪";
241        EMOJI_NON_STANDARD = "⚠️";
242        EMOJI_ITERATOR = "🔄"; // 🔄,
243        EMOJI_NAMESPACE = "🌐"; // 🌐,📛,
244        EMOJI_PRIMITIVE = "⚙️"; // ⚙️,
245        EMOJI_RESULT = "⚖️"; // ⚖️,↔️,✅,🗳,
246        //
247        TAG_ATOMIC = concat!("<span class='stab portability' title='Atomic-related item'>",
248            crate::EMOJI_ATOMIC!(), "</span>");
249        TAG_DATA_STRUCTURE =
250            concat!("<span class='stab portability' title='A generic data structure'>",
251            crate::EMOJI_DATA_STRUCTURE!(), "</span>");
252        TAG_ERROR = concat!("<span class='stab portability' title='Individual error type'>",
253            crate::EMOJI_ERROR!(), "</span>");
254        TAG_ERROR_COMPOSITE =
255            concat!("<span class='stab portability' title='Composite error type'>",
256            crate::EMOJI_ERROR!(), "+</span>");
257        TAG_ITERATOR = concat!("<span class='stab portability' title='Iterator-related item'>",
258            crate::EMOJI_ITERATOR!(), "</span>");
259        TAG_NAMESPACE = concat!("<span class='stab portability' title='Namespaced functionality'>",
260            crate::EMOJI_NAMESPACE!(), "</span>");
261        TAG_PRIMITIVE = concat!("<span class='stab portability' title='Rust primitive'>",
262            crate::EMOJI_PRIMITIVE!(), "</span>");
263        TAG_RESULT = concat!("<span class='stab portability' title='Result type'>",
264            crate::EMOJI_RESULT!() ,"</span>");
265
266        TAG_EXPERIMENTAL = concat!(
267            "<span class='stab portability' title='Experimental functionality'>",
268            crate::EMOJI_EXPERIMENTAL!(), "</span>");
269        TAG_NON_STANDARD = concat!(
270            "<span class='stab portability' title='Non-standard. Expect poor cross-compatibility'>",
271            crate::EMOJI_NON_STANDARD!(), "</span>");
272
273        TAG_MAYBE_STD = "<span class='stab portability'
274    title='re-exported from rust&#39;s `std` or recreated if `not(std)`'>`?std`</span>";
275
276        /* optional dependencies */
277
278        // used in: work::sync::atomic
279        TAG_ATOMIC_CORE_PORTABLE = concat!("<span class='stab portability' ",
280            "title='re-exported either from `core` or from the `portable-atomic` crate'>",
281            "`?core`</span>");
282        DOC_ATOMIC_CORE_PORTABLE = concat!("*Re-exported either from `core` or from the ",
283            "[`portable-atomic`](https://docs.rs/portable-atomic)* crate.\n\n---");
284
285        // used in: work::sync::re-exports and work::future::re-exports
286        TAG_ATOMIC_ALLOC_PORTABLE_UTIL = concat!("<span class='stab portability' ",
287            "title='re-exported either from `alloc` or from the `portable-atomic-util` crate'>",
288            "`?alloc`</span>");
289        DOC_ATOMIC_ALLOC_PORTABLE_UTIL = concat!("*Re-exported either from `alloc` or from the ",
290            "[`portable-atomic-util`](https://docs.rs/portable-atomic-util)* crate.\n\n---");
291    }
292}
293pub(crate) use tags::*;