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