1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
/*
 * Copyright 2022, Isaac Woods
 * SPDX-License-Identifier: MPL-2.0
 */

#![no_std]
#![feature(decl_macro, type_ascription, extern_types)]

#[cfg(test)]
#[macro_use]
extern crate std;

cfg_if::cfg_if! {
    if #[cfg(feature = "has_alloc")] {
        extern crate alloc;

        #[doc(hidden)]
        pub mod alloc_reexport {
            #[doc(hidden)]
            pub use ::alloc::*;
        }

        #[macro_use]
        pub mod downcast;
    }
}

mod binary_pretty_print;
pub mod bitmap;
mod init_guard;
pub mod math;
#[macro_use]
pub mod pin;
pub mod linker;
pub mod ranges;

pub use self::{binary_pretty_print::BinaryPrettyPrint, init_guard::InitGuard};

/// This macro should be called at the beginning of functions that create logic errors if they are
/// called more than once. Most commonly this is used for initialization functions.
pub macro assert_first_call
{
    () =>
    {
        assert_first_call!("ASSERTION FAILED: function has already been called");
    },

    ($($arg:tt)+) =>
    {{
        fn assert_first_call()
        {
            use $crate::core_reexport::sync::atomic::{AtomicBool,
                                     ATOMIC_BOOL_INIT,
                                     Ordering};

            static CALLED : AtomicBool = ATOMIC_BOOL_INIT;
            let called = CALLED.swap(true, Ordering::Relaxed);
            assert!(!called, $($arg)+);
        }
        assert_first_call();
    }}
}

/*
 * These are used in macros to prevent weird issues if the user crate does something weird like re-exports
 * another crate as `core` or `alloc`.
 */
#[doc(hidden)]
pub mod core_reexport {
    #[doc(hidden)]
    pub use core::*;
}