rustmax/
lib.rs

1#![doc = include_str!("../doc-src/root-docs.md")]
2#![allow(clippy::needless_doctest_main)]
3/* ---------- */
4#![no_std]
5
6/* ---------- */
7
8pub mod prelude {
9    //! The `rmx` prelude.
10
11    /* standard library preludes */
12
13    #[cfg(all(feature = "rmx-rustlib-core", not(feature = "rmx-rustlib-std")))]
14    pub use ::core::prelude::rust_2021::*;
15
16    #[cfg(feature = "rmx-rustlib-std")]
17    pub use ::std::prelude::rust_2021::*;
18
19    /* standard library macros */
20
21    #[cfg(feature = "rmx-rustlib-alloc")]
22    pub use ::alloc::{format, vec};
23
24    #[cfg(feature = "rmx-rustlib-alloc")]
25    pub use crate::extras::fmt;
26
27    /* standard library exports that aren't in its prelude */
28
29    // Ordering is recommended by
30    // `clippy::comparison_chain` and if it's
31    // important enough that the compiler suggests
32    // using it instead of comparison operator syntax,
33    // let's put it in the prelude.
34    #[cfg(feature = "rmx-rustlib-core")]
35    pub use ::core::cmp::Ordering;
36
37    /* other preludes */
38
39    #[cfg(feature = "futures")]
40    pub use ::futures::prelude::*;
41
42    /* common non-std imports */
43
44    #[cfg(feature = "anyhow")]
45    pub use ::anyhow::{Context as _, anyhow, bail};
46
47    #[cfg(feature = "anyhow")]
48    pub use crate::extras::{A, AnyError, AnyResult};
49
50    #[cfg(feature = "cfg-if")]
51    pub use ::cfg_if::cfg_if;
52
53    #[cfg(feature = "extension-trait")]
54    pub use ::extension_trait::extension_trait;
55
56    #[cfg(feature = "log")]
57    pub use ::log::{debug, error, info, trace, warn};
58
59    #[cfg(all(feature = "futures", feature = "rmx-feature-default"))]
60    pub use ::futures::{executor::block_on, future::Either};
61
62    #[cfg(feature = "itertools")]
63    pub use ::itertools::Itertools as _;
64
65    #[cfg(feature = "rand")]
66    pub use ::rand::RngCore as _;
67    #[cfg(feature = "rand")]
68    pub use ::rand::Rng as _;
69    #[cfg(feature = "rand")]
70    pub use ::rand::SeedableRng as _;
71    #[cfg(feature = "rand")]
72    pub use ::rand::Fill as _;
73
74    /* extras */
75
76    pub use crate::extras::default;
77
78    #[cfg(feature = "rmx-rustlib-core")]
79    pub use crate::bug;
80
81    #[cfg(feature = "rmx-rustlib-alloc")]
82    pub use crate::extras::S;
83
84    #[cfg(feature = "rmx-rustlib-alloc")]
85    pub use crate::extras::O;
86
87    #[cfg(all(feature = "extension-trait", feature = "anyhow"))]
88    pub use crate::extras::AnyResultExpect as _;
89    #[cfg(feature = "extension-trait")]
90    pub use crate::extras::OptionExpect as _;
91    #[cfg(feature = "extension-trait")]
92    pub use crate::extras::QuickClone as _;
93    #[cfg(feature = "extension-trait")]
94    pub use crate::extras::QuickToOwned as _;
95    #[cfg(feature = "extension-trait")]
96    pub use crate::extras::QuickToString as _;
97    #[cfg(feature = "extension-trait")]
98    pub use crate::extras::RangeExt as _;
99    #[cfg(feature = "extension-trait")]
100    pub use crate::extras::ResultExpect as _;
101    #[cfg(feature = "extension-trait")]
102    pub use crate::extras::ResultIgnore as _;
103}
104
105pub mod extras {
106    //! Additional tidbits defined by `rmx`.
107
108    /// Like 'unimplemented' but shorter to type.
109    #[cfg(feature = "rmx-rustlib-core")]
110    #[macro_export]
111    macro_rules! bug {
112        () => {
113            core::panic!("unexpected case (bug!)")
114        };
115        ($($arg:tt)+) => {
116            core::panic!("unexpected case (bug!): {}", $crate::format_args!($($arg)+))
117        };
118    }
119
120    #[cfg(feature = "anyhow")]
121    pub use ::anyhow::{Error as AnyError, Result as AnyResult, anyhow as A};
122
123    #[cfg(feature = "rmx-rustlib-alloc")]
124    pub use ::alloc::format as fmt;
125
126    pub fn default<T: Default>() -> T {
127        Default::default()
128    }
129
130    pub fn init() {
131        #[cfg(feature = "env_logger")]
132        fn maybe_init_env_logger() {
133            crate::env_logger::Builder::new()
134                .filter_level(log::LevelFilter::Info)
135                .format_timestamp(None)
136                .parse_default_env()
137                .init();
138        }
139        #[cfg(not(feature = "env_logger"))]
140        fn maybe_init_env_logger() {}
141
142        maybe_init_env_logger();
143    }
144
145    pub fn init_crate_name(crate_name: &str) {
146        #[cfg(feature = "env_logger")]
147        fn maybe_init_env_logger(crate_name: &str) {
148            crate::env_logger::Builder::new()
149                .filter_module(crate_name, log::LevelFilter::Info)
150                .format_timestamp(None)
151                .parse_default_env()
152                .init();
153        }
154        #[cfg(not(feature = "env_logger"))]
155        fn maybe_init_env_logger(_crate_name: &str) {}
156
157        maybe_init_env_logger(crate_name);
158    }
159
160    pub fn recurse<F, R>(f: F) -> R
161    where
162        F: FnOnce() -> R,
163    {
164        // todo could grow stack here
165        f()
166    }
167
168    #[cfg(feature = "rmx-rustlib-alloc")]
169    #[allow(non_snake_case)]
170    pub fn S<T>(s: &T) -> crate::alloc::string::String
171    where
172        T: crate::alloc::string::ToString + ?Sized,
173    {
174        crate::alloc::string::ToString::to_string(s)
175    }
176
177    #[cfg(feature = "rmx-rustlib-alloc")]
178    #[allow(non_snake_case)]
179    pub fn O<T>(o: &T) -> T::Owned
180    where
181        T: crate::alloc::borrow::ToOwned + ?Sized,
182    {
183        crate::alloc::borrow::ToOwned::to_owned(o)
184    }
185
186    #[cfg(feature = "extension-trait")]
187    #[extension_trait::extension_trait]
188    pub impl<T> QuickToString for T
189    where
190        T: crate::alloc::string::ToString + ?Sized,
191    {
192        #[allow(non_snake_case)]
193        fn S(&self) -> crate::alloc::string::String {
194            crate::alloc::string::ToString::to_string(self)
195        }
196    }
197
198    #[cfg(feature = "extension-trait")]
199    #[extension_trait::extension_trait]
200    pub impl<T> QuickToOwned for T
201    where
202        T: crate::alloc::borrow::ToOwned,
203    {
204        type Owned = T::Owned;
205
206        #[allow(non_snake_case)]
207        fn O(&self) -> Self::Owned {
208            crate::alloc::borrow::ToOwned::to_owned(self)
209        }
210    }
211
212    #[cfg(feature = "extension-trait")]
213    #[extension_trait::extension_trait]
214    pub impl<T> QuickClone<T> for T
215    where
216        T: Clone,
217    {
218        #[allow(non_snake_case)]
219        fn C(&self) -> T {
220            self.clone()
221        }
222    }
223
224    #[cfg(feature = "extension-trait")]
225    #[extension_trait::extension_trait]
226    pub impl<T> OptionExpect<T> for Option<T> {
227        #[track_caller]
228        #[allow(non_snake_case)]
229        fn X(self) -> T {
230            match self {
231                Some(v) => v,
232                None => panic!("impossible `None` option"),
233            }
234        }
235    }
236
237    #[cfg(feature = "extension-trait")]
238    #[extension_trait::extension_trait]
239    pub impl<T, E> ResultExpect<T, E> for Result<T, E>
240    where
241        E: core::error::Error,
242    {
243        #[track_caller]
244        #[allow(non_snake_case)]
245        fn X(self) -> T {
246            match self {
247                Ok(v) => v,
248                Err(e) => panic!("impossible `Err` result: {e}"),
249            }
250        }
251    }
252
253    #[cfg(all(feature = "extension-trait", feature = "anyhow"))]
254    #[extension_trait::extension_trait]
255    pub impl<T> AnyResultExpect<T> for AnyResult<T> {
256        #[track_caller]
257        #[allow(non_snake_case)]
258        fn X(self) -> T {
259            match self {
260                Ok(v) => v,
261                Err(e) => panic!("impossible `Err` result: {e}"),
262            }
263        }
264    }
265
266    /// Ignore a `Result`.
267    ///
268    /// This is nice because the common idiom of `let _ = ...` is untyped
269    /// and can accidentally be applied to non-`Result` types like `Future`s.
270    #[cfg(feature = "extension-trait")]
271    #[extension_trait::extension_trait]
272    pub impl<T, E> ResultIgnore<T, E> for Result<T, E> {
273        #[track_caller]
274        #[allow(non_snake_case)]
275        fn I(self) {
276            let _ = self;
277        }
278    }
279
280    // todo: define this for generic Range<N>
281    // todo: put this in a crate and elaborate
282    #[cfg(feature = "extension-trait")]
283    #[extension_trait::extension_trait]
284    pub impl RangeExt for core::ops::Range<usize> {
285        fn from_start_len(start: usize, len: usize) -> Option<core::ops::Range<usize>> {
286            Some(start..start.checked_add(len)?)
287        }
288
289        fn subrange(&self, sub: core::ops::Range<usize>) -> Option<core::ops::Range<usize>> {
290            if sub.start >= self.len() || sub.end > self.len() {
291                return None;
292            }
293            let new_start = self.start.checked_add(sub.start);
294            let new_end = self.start.checked_add(sub.end);
295            match (new_start, new_end) {
296                (Some(new_start), Some(new_end)) => Some(new_start..new_end),
297                _ => None,
298            }
299        }
300
301        fn checked_sub(&self, other: usize) -> Option<core::ops::Range<usize>> {
302            let new_start = self.start.checked_sub(other);
303            let new_end = self.end.checked_sub(other);
304            match (new_start, new_end) {
305                (Some(new_start), Some(new_end)) => Some(new_start..new_end),
306                _ => None,
307            }
308        }
309    }
310
311    #[cfg(feature = "rmx-rustlib-std")]
312    pub fn copy_dir_recursive(
313        src: &crate::std::path::Path,
314        dst: &crate::std::path::Path,
315    ) -> crate::std::io::Result<()> {
316        crate::std::fs::create_dir_all(dst)?;
317
318        for entry in crate::std::fs::read_dir(src)? {
319            let entry = entry?;
320            let file_type = entry.file_type()?;
321            let src_path = entry.path();
322            let dst_path = dst.join(entry.file_name());
323
324            if file_type.is_dir() {
325                copy_dir_recursive(&src_path, &dst_path)?;
326            } else {
327                crate::std::fs::copy(&src_path, &dst_path)?;
328            }
329        }
330
331        Ok(())
332    }
333
334    /// Use in constant contexts to assert a type is `Sync + Sync`.p
335    ///
336    /// ```
337    /// # use rustmax as rmx;
338    /// use rmx::extras::assert_send_sync;
339    ///
340    /// struct DbPathGen(());
341    ///
342    /// const _ASSERT_SEND_SYNC: () = assert_send_sync::<DbPathGen>();
343    /// ```
344    pub const fn assert_send_sync<T: Send + Sync>() { }    
345}
346
347/* ---------- */
348
349#[cfg(feature = "rmx-rustlib-core")]
350#[doc(inline)]
351pub extern crate core;
352
353#[cfg(feature = "rmx-rustlib-alloc")]
354#[doc(inline)]
355pub extern crate alloc;
356
357#[cfg(feature = "rmx-rustlib-std")]
358#[doc(inline)]
359pub extern crate std;
360
361#[cfg(feature = "rmx-rustlib-proc_macro")]
362#[doc(inline)]
363pub extern crate proc_macro;
364
365/* ---------- */
366
367#[cfg(feature = "ahash")]
368pub mod ahash {
369    #![doc = include_str!("../doc-src/crate-ahash.md")]
370
371    pub use ::ahash::*;
372}
373
374#[cfg(feature = "anyhow")]
375pub mod anyhow {
376    #![doc = include_str!("../doc-src/crate-anyhow.md")]
377
378    pub use ::anyhow::*;
379}
380
381#[cfg(feature = "axum")]
382pub mod axum {
383    //! Web application framework based on [`tokio`](super::tokio).
384    //!
385    //! See crate [`::axum`].
386
387    pub use ::axum::*;
388}
389
390#[cfg(feature = "backtrace")]
391pub mod backtrace {
392    //! Callstack backtraces on demand.
393    //!
394    //! See crate [`::backtrace`].
395
396    pub use ::backtrace::*;
397}
398
399#[cfg(feature = "base64")]
400pub mod base64 {
401    #![doc = include_str!("../doc-src/crate-base64.md")]
402
403    pub use ::base64::*;
404}
405
406#[cfg(feature = "bindgen")]
407pub mod bindgen {
408    //! Generate Rust bindings to C and C++ libraries.
409    //!
410    //! See crate [`::bindgen`].
411
412    pub use ::bindgen::*;
413}
414
415#[cfg(feature = "bitflags")]
416pub mod bitflags {
417    #![doc = include_str!("../doc-src/crate-bitflags.md")]
418
419    pub use ::bitflags::*;
420}
421
422#[cfg(feature = "blake3")]
423pub mod blake3 {
424    //! The BLAKE3 cryptographic hash function.
425    //!
426    //! See crate [`::blake3`].
427
428    pub use ::blake3::*;
429}
430
431#[cfg(feature = "byteorder")]
432pub mod byteorder {
433    //! Big-endian and little-endian encoding.
434    //!
435    //! See crate [`::byteorder`].
436
437    pub use ::byteorder::*;
438}
439
440#[cfg(feature = "bytes")]
441pub mod bytes {
442    #![doc = include_str!("../doc-src/crate-bytes.md")]
443
444    pub use ::bytes::*;
445}
446
447#[cfg(feature = "cc")]
448pub mod cc {
449    //! A basic cross-platform C compiler driver.
450    //!
451    //! See crate [`::cc`].
452
453    pub use ::cc::*;
454}
455
456#[cfg(feature = "cfg-if")]
457pub mod cfg_if {
458    //! A macro for writing conditional compilation as `if` / `else` blocks.
459    //!
460    //! See crate [`::cfg_if`].
461
462    pub use ::cfg_if::*;
463}
464
465#[cfg(feature = "chrono")]
466pub mod chrono {
467    #![doc = include_str!("../doc-src/crate-chrono.md")]
468
469    pub use ::chrono::*;
470}
471
472#[cfg(feature = "clap")]
473pub mod clap {
474    #![doc = include_str!("../doc-src/crate-clap.md")]
475
476    pub use ::clap::*;
477}
478
479
480#[cfg(feature = "ctrlc")]
481pub mod ctrlc {
482    //! Simple handling of CTRL-C for CLI programs.
483    //!
484    //! See crate [`::ctrlc`].
485
486    pub use ::ctrlc::*;
487}
488
489#[cfg(feature = "crossbeam")]
490pub mod crossbeam {
491    //! Concurrency tools to supplement [`std::sync`], including fast channels.
492    //!
493    //! See crate [`::crossbeam`].
494
495    pub use ::crossbeam::*;
496}
497
498#[cfg(feature = "cxx")]
499pub mod cxx {
500    //! C++ bridge runtime support; paired with [`cxx_build`](super::cxx_build).
501    //!
502    //! See crate [`::cxx`].
503
504    pub use ::cxx::*;
505}
506
507#[cfg(feature = "cxx-build")]
508pub mod cxx_build {
509    //! C++ bridge generator; paired with [`cxx`](super::cxx).
510    //!
511    //! See crate [`::cxx`].
512
513    pub use ::cxx::*;
514}
515
516#[cfg(feature = "derive_more")]
517pub mod derive_more {
518    //! `derive` for more standard traits.
519    //!
520    //! See crate [`::derive_more`].
521
522    pub use ::derive_more::*;
523}
524
525#[cfg(feature = "env_logger")]
526pub mod env_logger {
527    //! A basic logger to use with the [`log`](super::log) crate.
528    //!
529    //! See crate [`::env_logger`].
530
531    pub use ::env_logger::*;
532}
533
534#[cfg(feature = "extension-trait")]
535pub mod extension_trait {
536    //! A macro for defining extension methods to external types.
537    //!
538    //! See crate [`::extension_trait`].
539
540    pub use ::extension_trait::*;
541}
542
543#[cfg(feature = "futures")]
544pub mod futures {
545    #![doc = include_str!("../doc-src/crate-futures.md")]
546
547    pub use ::futures::*;
548}
549
550#[cfg(feature = "hex")]
551pub mod hex {
552    #![doc = include_str!("../doc-src/crate-hex.md")]
553
554    pub use ::hex::*;
555}
556
557#[cfg(feature = "http")]
558pub mod http {
559    //! Shared definitions related to the HTTP protocol.
560    //!
561    //! See crate [`::http`].
562
563    pub use ::http::*;
564}
565
566#[cfg(feature = "hyper")]
567pub mod hyper {
568    //! HTTP, versions 1 and 2.
569    //!
570    //! See crate [`::hyper`].
571
572    pub use ::hyper::*;
573}
574
575#[cfg(feature = "itertools")]
576pub mod itertools {
577    #![doc = include_str!("../doc-src/crate-itertools.md")]
578
579    pub use ::itertools::*;
580}
581
582#[cfg(feature = "jiff")]
583pub mod jiff {
584    #![doc = include_str!("../doc-src/crate-jiff.md")]
585
586    pub use ::jiff::*;
587}
588
589#[cfg(feature = "json5")]
590pub mod json5 {
591    //! JSON5, a superset of JSON with expanded syntax.
592    //!
593    //! See crate [`::json5`].
594
595    pub use ::json5::*;
596}
597
598#[cfg(feature = "libc")]
599pub mod libc {
600    //! Bindings to the C standard library.
601    //!
602    //! See crate [`::libc`].
603
604    pub use ::libc::*;
605}
606
607#[cfg(feature = "log")]
608pub mod log {
609    #![doc = include_str!("../doc-src/crate-log.md")]
610
611    pub use ::log::*;
612}
613
614#[cfg(feature = "mime")]
615pub mod mime {
616    #![doc = include_str!("../doc-src/crate-mime.md")]
617
618    pub use ::mime::*;
619}
620
621#[cfg(feature = "nom")]
622pub mod nom {
623    //! An efficient parser combinator.
624    //!
625    //! See crate [`::nom`].
626
627    pub use ::nom::*;
628}
629
630#[cfg(feature = "num-bigint")]
631pub mod num_bigint {
632    #![doc = include_str!("../doc-src/crate-num-bigint.md")]
633
634    pub use ::num_bigint::*;
635}
636
637#[cfg(feature = "num_cpus")]
638pub mod num_cpus {
639    //! Get the number of CPUS on a machine.
640    //!
641    //! See crate [`::num_cpus`].
642
643    pub use ::num_cpus::*;
644}
645
646#[cfg(feature = "num_enum")]
647pub mod num_enum {
648    //! Conversions between numbers and enums.
649    //!
650    //! See crate [`::num_enum`].
651
652    pub use ::num_enum::*;
653}
654
655#[cfg(feature = "proc-macro2")]
656pub mod proc_macro2 {
657    //! A preferred wrapper around the standard [`proc_macro`] crate.
658    //!
659    //! See crate [`::proc_macro2`].
660
661    pub use ::proc_macro2::*;
662}
663
664#[cfg(feature = "proptest")]
665pub mod proptest {
666    #![doc = include_str!("../doc-src/crate-proptest.md")]
667
668    pub use ::proptest::*;
669}
670
671#[cfg(feature = "quote")]
672pub mod quote {
673    //! The `quote!` macro for turning code blocks into source tokens.
674    //!
675    //! See crate [`::quote`].
676
677    pub use ::quote::*;
678}
679
680#[cfg(feature = "rand")]
681pub mod rand {
682    #![doc = include_str!("../doc-src/crate-rand.md")]
683
684    pub use ::rand::*;
685}
686
687#[cfg(feature = "rand_chacha")]
688pub mod rand_chacha {
689    //! The ChaCha cryptographically-secure random number generators.
690    //!
691    //! See crate [`::rand_chacha`].
692
693    pub use ::rand_chacha::*;
694}
695
696#[cfg(feature = "rand_pcg")]
697pub mod rand_pcg {
698    //! The PCG non-cryptographically-secure random number generators.
699    //!
700    //! See crate [`::rand_pcg`].
701
702    pub use ::rand_pcg::*;
703}
704
705#[cfg(feature = "rayon")]
706pub mod rayon {
707    #![doc = include_str!("../doc-src/crate-rayon.md")]
708
709    pub use ::rayon::*;
710}
711
712#[cfg(feature = "regex")]
713pub mod regex {
714    #![doc = include_str!("../doc-src/crate-regex.md")]
715
716    pub use ::regex::*;
717}
718
719#[cfg(feature = "reqwest")]
720pub mod reqwest {
721    //! Simple HTTP requests, synchronous and asynchronous.
722    //!
723    //! See crate [`::reqwest`].
724
725    pub use ::reqwest::*;
726}
727
728
729#[cfg(feature = "rustyline")]
730pub mod rustyline {
731    //! Command-line input reading with history.
732    //!
733    //! See crate [`::rustyline`].
734
735    pub use ::rustyline::*;
736}
737
738#[cfg(feature = "semver")]
739pub mod semver {
740    #![doc = include_str!("../doc-src/crate-semver.md")]
741
742    pub use ::semver::*;
743}
744
745#[cfg(feature = "serde")]
746pub mod serde {
747    #![doc = include_str!("../doc-src/crate-serde.md")]
748
749    pub use ::serde::*;
750}
751
752#[cfg(feature = "serde_json")]
753pub mod serde_json {
754    #![doc = include_str!("../doc-src/crate-serde_json.md")]
755
756    pub use ::serde_json::*;
757}
758
759#[cfg(feature = "sha2")]
760pub mod sha2 {
761    //! The SHA2 cryptographic hash functions.
762    //!
763    //! See crate [`::sha2`].
764
765    pub use ::sha2::*;
766}
767
768#[cfg(feature = "socket2")]
769pub mod socket2 {
770    //! Low-level network socket programming beyond [`std::net`].
771    //!
772    //! See crate [`::socket2`].
773
774    pub use ::socket2::*;
775}
776
777#[cfg(feature = "static_assertions")]
778pub mod static_assertions {
779    //! Compile-time assertions about constants, types, etc.
780    //!
781    //! See crate [`::static_assertions`].
782
783    pub use ::static_assertions::*;
784}
785
786#[cfg(feature = "syn")]
787pub mod syn {
788    //! A Rust parser used by procedural macros.
789    //!
790    //! See crate [`::syn`].
791
792    pub use ::syn::*;
793}
794
795#[cfg(feature = "tempfile")]
796pub mod tempfile {
797    #![doc = include_str!("../doc-src/crate-tempfile.md")]
798
799    pub use ::tempfile::*;
800}
801
802#[cfg(feature = "tera")]
803pub mod tera {
804    //! A text template engine based on Jinja2.
805    //!
806    //! See crate [`::tera`].
807
808    pub use ::tera::*;
809}
810
811#[cfg(feature = "termcolor")]
812pub mod termcolor {
813    //! Cross-platform library for writing colored output to the terminal.
814    //!
815    //! See crate [`::termcolor`].
816
817    pub use ::termcolor::*;
818}
819
820#[cfg(feature = "thiserror")]
821pub mod thiserror {
822    #![doc = include_str!("../doc-src/crate-thiserror.md")]
823
824    pub use ::thiserror::*;
825}
826
827#[cfg(feature = "tokio")]
828pub mod tokio {
829    #![doc = include_str!("../doc-src/crate-tokio.md")]
830
831    pub use ::tokio::*;
832}
833
834#[cfg(feature = "tower")]
835pub mod tower {
836    //! Service request/response abstraction (HTTP middleware)
837    //! for [`tokio`](super::tokio) and [`axum`](super::axum).
838    //!
839    //! See crate [`::tower`].
840
841    pub use ::tower::*;
842}
843
844#[cfg(feature = "toml")]
845pub mod toml {
846    #![doc = include_str!("../doc-src/crate-toml.md")]
847
848    pub use ::toml::*;
849}
850
851#[cfg(feature = "unicode-segmentation")]
852pub mod unicode_segmentation {
853    //! Splitting strings on grapheme cluster, word, and sentence boundaries.
854    //!
855    //! See crate [`::unicode_segmentation`].
856
857    pub use ::unicode_segmentation::*;
858}
859
860#[cfg(feature = "url")]
861pub mod url {
862    #![doc = include_str!("../doc-src/crate-url.md")]
863
864    pub use ::url::*;
865}
866
867#[cfg(feature = "walkdir")]
868pub mod walkdir {
869    #![doc = include_str!("../doc-src/crate-walkdir.md")]
870
871    pub use ::walkdir::*;
872}
873
874#[cfg(feature = "xshell")]
875pub mod xshell {
876    //! A Swiss-army knife for writing shell-style scripts in Rust.
877    //!
878    //! See crate [`::xshell`].
879
880    pub use ::xshell::*;
881}