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
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
//! Allocator for swc.
//!
//! # Features
//!
//! - `scoped`: Enable `scoped` mode.
//!
//! # Modes
//!
//! ## Default mode
//!
//! In default mode, [crate::boxed::Box] and [crate::vec::Vec] are identical to
//! the original types in [std].
//!
//! ## Scoped mode
//!
//! - You need to enable `scoped` feature to use this mode.
//!
//! In `scoped` mode you can use [FastAlloc] to make [crate::boxed::Box] and
//! [crate::vec::Vec] very fast.
//!
//! In this mode, you need to be careful while using [crate::boxed::Box] and
//! [crate::vec::Vec]. You should ensure that [Allocator] outlives all
//! [crate::boxed::Box] and [crate::vec::Vec] created in the scope.
//!
//! Recommened way to use this mode is to wrap the whole operations in
//! a call to [Allocator::scope].

#![allow(clippy::needless_doctest_main)]
#![cfg_attr(docsrs, feature(doc_cfg))]
#![cfg_attr(
    feature = "nightly",
    feature(allocator_api, fundamental, with_negative_coherence, box_into_inner)
)]
#![deny(missing_docs)]
#![allow(clippy::derivable_impls)]

pub use crate::alloc::Allocator;

mod alloc;
#[cfg(feature = "nightly")]
pub mod boxed;
pub mod collections;
#[cfg(feature = "nightly")]
pub mod vec;

/// Box<T> and Vec<T> depeding on the feature.
pub mod maybe {
    #[cfg(not(feature = "nightly"))]
    pub use std::{boxed, vec};

    #[cfg(feature = "nightly")]
    pub use crate::{boxed, vec};
}

/// Fast allocator, effectively working as a cache.
///
/// This type implements [Default] and [Copy]. This type is intended to stored
/// in a variable or a field in a struct before allocating code, and used as the
/// seocnd argument in [crate::boxed::Box::new_in] and
/// [crate::vec::Vec::new_in].
///
/// [crate::boxed::Box::new] and [crate::vec::Vec::new] are slower than using
/// this field because they use [FastAlloc::default] internally, which is slower
/// than store [FastAlloc] in a variable.
///
///
///
/// # Misc
///
/// It implements [`std::alloc::Allocator`]. So it can be used as the
/// second argument for [`std::boxed::Box`] and
/// [`std::vec::Vec`]. But you should prefer using
/// [`crate::boxed::Box`] and [`crate::vec::Vec`], which is a wrapper around the
/// original types.
#[derive(Clone, Copy)]
pub struct FastAlloc {
    #[cfg(feature = "scoped")]
    alloc: Option<&'static Allocator>,
}

impl FastAlloc {
    /// [crate::boxed::Box] or [crate::vec::Vec] created with this instance is
    /// managed by the global allocator and it can outlive the
    /// [crate::Allocator] instance used for [Allocator::scope].
    pub const fn global() -> Self {
        Self {
            #[cfg(feature = "scoped")]
            alloc: None,
        }
    }
}

/// This expands to the given tokens if the `nightly` feature is enabled.
#[cfg(feature = "nightly")]
#[macro_export]
macro_rules! nightly_only {
    (
        $($item:item)*
    ) => {
        $(
            #[cfg_attr(docsrs, doc(cfg(feature = "nightly")))]
            $item
        )*
    };
}

/// This expands to the given tokens if the `nightly` feature is enabled.
#[cfg(not(feature = "nightly"))]
#[macro_export]
macro_rules! nightly_only {
    (
        $($item:item)*
    ) => {};
}

/// Usage: `swc_allocator::Type!(Vec<T>)` or `swc_allocator::Type!(Box<T>)`.
#[macro_export]
macro_rules! Type {
    (Box<$($tt:tt)*>) => {
        #[cfg(feature = "nightly")]
        $crate::boxed::Box<$crate::Type!($($tt)*)>

        #[cfg(not(feature = "nightly"))]
        std::boxed::Box<$crate::Type!($($tt)*)>
    };

    (Vec<$($tt:tt)*>) => {
        #[cfg(feature = "nightly")]
        $crate::vec::Vec<$crate::Type!($($tt)*)>

        #[cfg(not(feature = "nightly"))]
        std::vec::Vec<$crate::Type!($($tt)*)>
    };

    ($t:ty) => {
        $t
    };
}