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_ALLOCATOR = "๐Ÿงบ"; // ๐Ÿงฎ, (basket, abacus)
237        EMOJI_ATOMIC = "โš›๏ธ"; // โš›๏ธ,๐Ÿ”ฌ,๐ŸŒ
238        EMOJI_DATA_STRUCTURE = "๐Ÿ“ฆ"; // ๐Ÿ“ฆ,๐Ÿงฉ,๐Ÿ—‚๏ธ,
239        EMOJI_ERROR = "๐Ÿšฉ"; // โŒ,๐Ÿšซ,๐Ÿ“›,๐Ÿšง,๐Ÿ“‰,๐Ÿšฉ,
240        // EMOJI_ERROR_COMPOSITE = "+"; // ๐Ÿ“Ž,๐Ÿงฉ,๐Ÿ“ฆ,๐Ÿ–‡๏ธ,๐Ÿ—‚๏ธ,
241        EMOJI_EXPERIMENTAL = "๐Ÿงช";
242        EMOJI_FAKE = "๐ŸŽญ"; // ๐ŸŽญ, ๐Ÿ‘ป, ๐Ÿฆ„, ๐Ÿ›
243        EMOJI_FFI = "๐Ÿ›ก๏ธ"; // ๐Ÿ›ก๏ธ, โœ…
244        EMOJI_FONT = "๐Ÿ…ต"; // ๐Ÿ…ต,, ๐Ÿ…ฐ, โ„ฑ, ๐”‰, ๐•ฑ, ๐…
245        EMOJI_FMT = "๐Ÿ–น"; // ๐Ÿ–น, ๐Ÿ“„, ๐Ÿ“, ๐Ÿ„ต, โœŽ, โ„ฑ, ๐”ฝ
246        EMOJI_GEOM = "๐Ÿ“";
247        EMOJI_ITERATOR = "๐Ÿ”„"; // ๐Ÿ”„,
248        EMOJI_NAMESPACE = "๐ŸŒ"; // ๐ŸŒ,๐Ÿ“›,
249        EMOJI_NICHE = "โš—๏ธ"; // โš—๏ธ,โ™Ÿ๏ธ,๐Ÿงฉ,๐Ÿงฎ,
250        EMOJI_NON_STANDARD = "โš ๏ธ";
251        EMOJI_NO = "โˆ…"; // โˆ…, โŠ˜, โฌ›
252        EMOJI_NUM = "๐Ÿ™"; // ๐Ÿ”ข, ๐Ÿ”Ÿ, โถ, โž€, ๐Ÿ™
253        EMOJI_PRIMITIVE = "โš™๏ธ"; // โš™๏ธ,
254        EMOJI_QUANT = "๐Ÿ“";
255        EMOJI_RAND = "๐ŸŽฒ"; // ๐ŸŽฒ, ๐ŸŽฐ, ๐Ÿ”€
256        EMOJI_RESULT = "โš–๏ธ"; // โš–๏ธ,โ†”๏ธ,โœ…,๐Ÿ—ณ,
257        EMOJI_TEXT = "๐“"; // ๐“, ๐“ฃ, ๐”ธ, ๐Ÿ„ฐ
258        EMOJI_TIME = "๐Ÿ•˜"; // ๐Ÿ•˜, โณ, ๐Ÿ“…
259        //
260        SPAN_OPEN = "<span class='stab portability' title=";
261        // SPAN_OPEN = "<span class='tag-emoji' title=";
262        //
263        TAG_ALLOCATOR = concat!(crate::SPAN_OPEN!(), "'Allocator-related item'>",
264            crate::EMOJI_ALLOCATOR!(), "</span>");
265        TAG_ATOMIC = concat!(crate::SPAN_OPEN!(), "'Atomic-related item'>",
266            crate::EMOJI_ATOMIC!(), "</span>");
267        TAG_DATA_STRUCTURE =
268            concat!(crate::SPAN_OPEN!(), "'General-purpose data structure'>",
269            crate::EMOJI_DATA_STRUCTURE!(), "</span>");
270        TAG_ERROR = concat!(crate::SPAN_OPEN!(), "'Individual error type'>",
271            crate::EMOJI_ERROR!(), "</span>");
272        TAG_ERROR_COMPOSITE =
273            concat!(crate::SPAN_OPEN!(), "'Composite error type'>",
274            crate::EMOJI_ERROR!(), "+</span>");
275        TAG_EXPERIMENTAL = concat!(
276            "<span class='stab portability' title='Experimental functionality'>",
277            crate::EMOJI_EXPERIMENTAL!(), "</span>");
278        TAG_FAKE = concat!(crate::SPAN_OPEN!(), "'A fake implementation for testing.'>",
279            crate::EMOJI_FAKE!() ,"</span>");
280        TAG_FFI = concat!("<span class='stab portability' title='Ffi-safe version'>",
281            crate::EMOJI_FFI!(), "</span>");
282        TAG_FONT = concat!("<span class='stab portability' title='Font-related item'>",
283            crate::EMOJI_FONT!(), "</span>");
284        TAG_FMT =
285            concat!(crate::SPAN_OPEN!(), "'Text Formatting & Representation item'>",
286            crate::EMOJI_FMT!(), "</span>");
287        TAG_GEOM =
288            concat!(crate::SPAN_OPEN!(), "'Geometric multi-dimensional item'>",
289            crate::EMOJI_GEOM!(), "</span>");
290        TAG_ITERATOR = concat!(crate::SPAN_OPEN!(), "'Iterator or iterator adapter'>",
291            crate::EMOJI_ITERATOR!(), "</span>");
292        TAG_NAMESPACE = concat!(crate::SPAN_OPEN!(), "'Namespaced functionality'>",
293            crate::EMOJI_NAMESPACE!(), "</span>");
294        TAG_NICHE = concat!(crate::SPAN_OPEN!(), "'Type with niche-based memory optimizations'>",
295            crate::EMOJI_NICHE!(), "</span>");
296        TAG_NON_STANDARD = concat!(
297            "<span class='stab portability' title='Non-standard. Expect poor cross-compatibility'>",
298            crate::EMOJI_NON_STANDARD!(), "</span>");
299        TAG_NO = concat!(crate::SPAN_OPEN!(), "'Absence, emptiness, or a no-op effect'>",
300            crate::EMOJI_NO!(), "</span>");
301        TAG_NUM = concat!(crate::SPAN_OPEN!(), "'Numeric value-related item'>",
302            crate::EMOJI_NUM!(), "</span>");
303        TAG_PRIMITIVE = concat!(crate::SPAN_OPEN!(), "'Rust primitive type'>",
304            crate::EMOJI_PRIMITIVE!(), "</span>");
305        TAG_QUANT = concat!(crate::SPAN_OPEN!(), "'1-dimensional measurement or quantity'>",
306            crate::EMOJI_QUANT!(), "</span>");
307        TAG_RAND = concat!(crate::SPAN_OPEN!(), "'Randomness-related item'>",
308            crate::EMOJI_RAND!(), "</span>");
309        TAG_RESULT = concat!(crate::SPAN_OPEN!(), "'Resolution or outcome-related item'>",
310            crate::EMOJI_RESULT!() ,"</span>");
311        TAG_TEXT = concat!(crate::SPAN_OPEN!(), "'Text-related type'>",
312            crate::EMOJI_TEXT!() ,"</span>");
313        TAG_TIME = concat!(crate::SPAN_OPEN!(), "'Time-related type'>",
314            crate::EMOJI_TIME!() ,"</span>");
315
316        TAG_MAYBE_STD = concat!(crate::SPAN_OPEN!(),
317            "'re-exported from rust&#39;s `std` or recreated if `not(std)`'>`?std`</span>");
318
319        /* optional dependencies */
320
321        // used in: work::sync::atomic
322        TAG_ATOMIC_CORE_PORTABLE = concat!(crate::SPAN_OPEN!(),
323            "'re-exported either from `core` or from the `portable-atomic` crate'>",
324            "`?core`</span>");
325        DOC_ATOMIC_CORE_PORTABLE = concat!("*Re-exported either from `core` or from the ",
326            "[`portable-atomic`](https://docs.rs/portable-atomic)* crate.\n\n---");
327
328        // used in: work::sync::re-exports and work::future::re-exports
329        TAG_ATOMIC_ALLOC_PORTABLE_UTIL = concat!(crate::SPAN_OPEN!(),
330            "'re-exported either from `alloc` or from the `portable-atomic-util` crate'>",
331            "`?alloc`</span>");
332        DOC_ATOMIC_ALLOC_PORTABLE_UTIL = concat!("*Re-exported either from `alloc` or from the ",
333            "[`portable-atomic-util`](https://docs.rs/portable-atomic-util)* crate.\n\n---");
334    }
335}
336pub(crate) use tags::*;