blob: 04c51983b464bfc2b76741a6709ad9353651041e [file] [log] [blame]
#![allow(deprecated)]
#![doc = include_str!("../doc/macros.md")]
#[macro_use]
#[doc(hidden)]
pub mod internal;
mod tests;
#[macro_export]
#[doc = include_str!("../doc/macros/BitArr_type.md")]
macro_rules! BitArr {
(for $len:expr, in $store:ty, $order:ty $(,)?) => {
$crate::array::BitArray::<
[$store; $crate::mem::elts::<$store>($len)], $order
>
};
(for $len:expr, in $store:ty $(,)?) => {
$crate::BitArr!(for $len, in $store, $crate::order::Lsb0)
};
(for $len:expr) => {
$crate::BitArr!(for $len, in usize)
};
}
#[macro_export]
#[doc = include_str!("../doc/macros/bitarr_value.md")]
macro_rules! bitarr {
/* `const`-expression constructors.
*
* These arms expand to expressions which are guaranteed to be valid in
* `const` position: initializing `static` or `const`, or arguments to
* `const fn`.
*
* > Other arms *may* be valid in `const`s, but do not guarantee it.
*
* They are more restricted than the general variants below, because the
* trait system is not yet usable in `const` contexts and thus these
* expansions can only use codepaths defined in this module, and cannot use
* the rest of `bitvec`’s systems.
*
* All valid invocations with a leading `const` will remain valid if the
* `const` is removed, though their expansion may change to no longer be
* valid in `const` contexts.
*/
// Bit-sequencing requires detecting `Cell` separately from other types.
// See below.
(const Cell<$store:ident>, $order:ident; $($val:expr),* $(,)?) => {{
const ELTS: usize = $crate::__count_elts!($store; $($val),*);
type Data = [Cell<$store>; ELTS];
const DATA: Data = $crate::__encode_bits!(Cell<$store>, $order; $($val),*);
type This = $crate::array::BitArray<Data, $order>;
This { data: DATA, ..This::ZERO }
}};
(const $store:ident, $order:ident; $($val:expr),* $(,)?) => {{
const ELTS: usize = $crate::__count_elts!($store; $($val),*);
type Data = [$store; ELTS];
const DATA: Data = $crate::__encode_bits!($store, $order; $($val),*);
type This = $crate::array::BitArray<Data, $order>;
This { data: DATA, ..This::ZERO }
}};
// Bit-repetition is agnostic to types, so it only needs two arms.
(const $store:ty, $order:ty; $val:expr; $len:expr) => {{
use $crate::macros::internal::core;
type Mem = <$store as $crate::store::BitStore>::Mem;
const ELTS: usize = $crate::mem::elts::<$store>($len);
const ELEM: Mem = $crate::__extend_bool!($val, $store);
const DATA: [Mem; ELTS] = [ELEM; ELTS];
type This = $crate::array::BitArray<[$store; ELTS], $order>;
unsafe { core::mem::transmute::<_, This>(DATA) }
}};
(const $val:expr; $len:expr) => {{
$crate::bitarr!(const usize, $crate::order::Lsb0; $val; $len)
}};
(const $($val:expr),* $(,)?) => {{
$crate::bitarr!(const usize, Lsb0; $($val),*)
}};
/* Non-`const` constructors.
*
* These expansions are allowed to produce code that does not run in `const`
* contexts. While it is *likely* that the expansions will be evaluated at
* compile-time, they won’t do so while the `const` engine is active.
*/
/* Bit-sequence encoding.
*
* This requires four arms to the `const` section’s one, because of how both
* the ordering and storage arguments may be provided. As macros operate
* syntactically, before the type system begins, they have to accept any
* syntax that could later be accepted as the name of a satisfying type.
*
* The `$order:ident` matcher uses the fact that `:ident` matches remain
* matchable across deeper macro invocations, so that the bottom of the
* macro stack can detect the magic tokens `LocalBits`, `Lsb0`, and `Msb0`,
* and operate accordingly. The `$order:path` matcher is always opaque, and
* serves as a fallback for complex type-names.
*
* `Cell<$store>` uses literal detection to extract the interior type width.
* This cannot be done by `:ty` or `:path`, as these are opaque, and
* `:ident` does not match `Cell<_>`.
*/
(Cell<$store:ident>, $order:ident; $($val:expr),* $(,)?) => {{
use $crate::macros::internal::core;
type Celled = core::cell::Cell<$store>;
const ELTS: usize = $crate::__count_elts!($store; $($val),*);
type Data = [Celled; ELTS];
type This = $crate::array::BitArray<Data, $order>;
This::new($crate::__encode_bits!(Cell<$store>, $order; $($val),*))
}};
(Cell<$store:ident>, $order:path; $($val:expr),* $(,)?) => {{
use $crate::macros::internal::core;
type Celled = core::cell::Cell<$store>;
const ELTS: usize = $crate::__count_elts!($store; $($val),*);
type This = $crate::array::BitArray<[Celled; ELTS], $order>;
This::new($crate::__encode_bits!(Cell<$store>, $order; $($val),*))
}};
($store:ident, $order:ident; $($val:expr),* $(,)?) => {{
const ELTS: usize = $crate::__count_elts!($store; $($val),*);
type This = $crate::array::BitArray<[$store; ELTS], $order>;
This::new($crate::__encode_bits!($store, $order; $($val),*))
}};
($store:ident, $order:path; $($val:expr),* $(,)?) => {{
const ELTS: usize = $crate::__count_elts!($store; $($val),*);
type This = $crate::array::BitArray<[$store; ELTS], $order>;
This::new($crate::__encode_bits!($store, $order; $($val),*))
}};
($store:ty, $order:ty; $val:expr; $len:expr) => {{
$crate::bitarr!(const $store, $order; $val; $len)
}};
($val:expr; $len:expr) => {{
$crate::bitarr!(const $val; $len)
}};
($($val:expr),* $(,)?) => {
$crate::bitarr!(usize, Lsb0; $($val),*)
};
}
#[macro_export]
#[doc = include_str!("../doc/macros/bits.md")]
macro_rules! bits {
/* `&'static` constructors.
*
* Like the `bitarr!(const …)` arms, these arms must expand to code that is
* valid in `const` contexts. As such, they can only accept `$order`
* arguments that are one of the `LocalBits`, `Lsb0`, or `Msb0` literals.
* Once the underlying `static BitArray` is created,
*/
(static mut Cell<$store:ident>, $order:ty; $val:expr; $len:expr) => {{
use $crate::macros::internal::core;
type Celled = core::cell::Cell<$store>;
static mut DATA: $crate::BitArr!(for $len, in Celled, $order) =
$crate::bitarr!(const Cell<$store>, $order; $val; $len);
&mut DATA[.. $len]
}};
(static mut $store:ident, $order:ident; $val:expr; $len:expr) => {{
static mut DATA: $crate::BitArr!(for $len, in $store, $order) =
$crate::bitarr!(const $store, $order; $val; $len);
DATA.get_unchecked_mut(.. $len)
}};
(static mut Cell<$store:ident>, $order:ident; $($val:expr),* $(,)?) => {{
use $crate::macros::internal::core;
type Celled = core::cell::Cell<$store>;
const BITS: usize = $crate::__count!($($val),*);
static mut DATA: $crate::BitArr!(for BITS, in $store, $order) =
$crate::bitarr!(const $store, $order; $($val),*);
&mut *(
DATA.get_unchecked_mut(.. BITS)
as *mut $crate::slice::BitSlice<$store, $order>
as *mut $crate::slice::BitSlice<Celled, $order>
)
}};
(static mut $store:ident, $order:ident; $($val:expr),* $(,)?) => {{
const BITS: usize = $crate::__count!($($val),*);
static mut DATA: $crate::BitArr!(for BITS, in $store, $order) =
$crate::bitarr!(const $store, $order; $($val),*);
DATA.get_unchecked_mut(.. BITS)
}};
(static mut $val:expr; $len:expr) => {{
static mut DATA: $crate::BitArr!(for $len) =
$crate::bitarr!(const usize, $crate::order::Lsb0; $val; $len);
DATA.get_unchecked_mut(.. $len)
}};
(static mut $($val:expr),* $(,)?) => {{
$crate::bits!(static mut usize, Lsb0; $($val),*)
}};
(static Cell<$store:ident>, $order:ty; $val:expr; $len:expr) => {{
use $crate::macros::internal::core;
type Celled = core::cell::Cell<$store>;
static DATA: $crate::BitArr!(for $len, in $store, $order) =
$crate::bitarr!(const $store, $order; $val; $len);
unsafe {
&*(
DATA.get_unchecked(.. $len)
as *const $crate::slice::BitSlice<$store, $order>
as *const $crate::slice::BitSlice<Celled, $order>
)
}
}};
(static Cell<$store:ident>, $order:ident; $($val:expr),* $(,)?) => {{
use $crate::macros::internal::core;
type Celled = core::cell::Cell<$store>;
const BITS: usize = $crate::__count!($($val),*);
static DATA: $crate::BitArr!(for BITS, in $store, $order) =
$crate::bitarr!(const $store, $order; $($val),*);
unsafe {
&*(
DATA.get_unchecked(.. BITS)
as *const $crate::slice::BitSlice<$store, $order>
as *const $crate::slice::BitSlice<Celled, $order>
)
}
}};
(static $store:ident, $order:ident; $val:expr; $len:expr) => {{
static DATA: $crate::BitArr!(for $len, in $store, $order) =
$crate::bitarr!(const $store, $order; $val; $len);
unsafe { DATA.get_unchecked(.. $len) }
}};
(static $val:expr; $len:expr) => {{
static DATA: $crate::BitArr!(for $len) =
$crate::bitarr!(const usize, $crate::order::Lsb0; $val; $len);
unsafe { DATA.get_unchecked(.. $len) }
}};
(static $store:ident, $order:ident; $($val:expr),* $(,)?) => {{
const BITS: usize = $crate::__count!($($val),*);
static DATA: $crate::BitArr!(for BITS, in $store, $order) =
$crate::bitarr!(const $store, $order; $($val),*);
unsafe { DATA.get_unchecked(.. BITS) }
}};
(static $($val:expr),* $(,)?) => {{
$crate::bits!(static usize, Lsb0; $($val),*)
}};
// Repetition syntax `[bit ; count]`.
// NOTE: `count` must be a `const`, as this is a non-allocating macro.
// Sequence syntax `[bit (, bit)*]` or `[(bit ,)*]`.
// Explicit order and store.
(mut Cell<$store:ident>, $order:ident; $($val:expr),* $(,)?) => {{
const BITS: usize = $crate::__count!($($val),*);
&mut $crate::bitarr!(Cell<$store>, $order; $($val),*)[.. BITS]
}};
(mut Cell<$store:ident>, $order:path; $($val:expr),* $(,)?) => {{
const BITS: usize = $crate::__count!($($val),*);
&mut $crate::bitarr!(Cell<$store>, $order; $($val),*)[.. BITS]
}};
(mut $store:ident, $order:ident; $($val:expr),* $(,)?) => {{
const BITS: usize = $crate::__count!($($val),*);
&mut $crate::bitarr!($store, $order; $($val),*)[.. BITS]
}};
(mut $store:ident, $order:path; $($val:expr),* $(,)?) => {{
const BITS: usize = $crate::__count!($($val),*);
&mut $crate::bitarr!($store, $order; $($val),*)[.. BITS]
}};
// Explicit order and store.
(mut $store:ty, $order:ty; $val:expr; $len:expr) => {{
&mut $crate::bitarr!($store, $order; $val; $len)[.. $len]
}};
// Default order and store.
(mut $val:expr; $len:expr) => {
$crate::bits!(mut usize, $crate::order::Lsb0; $val; $len)
};
// Default order and store.
(mut $($val:expr),* $(,)?) => {
$crate::bits!(mut usize, Lsb0; $($val),*)
};
// Repeat everything from above, but now immutable.
($store:ty, $order:ty; $val:expr; $len:expr) => {{
&$crate::bitarr!($store, $order; $val; $len)[.. $len]
}};
(Cell<$store:ident>, $order:ident; $($val:expr),* $(,)?) => {{
const BITS: usize = $crate::__count!($($val),*);
&$crate::bitarr!(Cell<$store>, $order; $($val),*)[.. BITS]
}};
($store:ident, $order:ident; $($val:expr),* $(,)?) => {{
const BITS: usize = $crate::__count!($($val),*);
&$crate::bitarr!($store, $order; $($val),*)[.. BITS]
}};
(Cell<$store:ident>, $order:path; $($val:expr),* $(,)?) => {{
const BITS: usize = $crate::__count!($($val),*);
&$crate::bitarr!(Cell<$store>, $order; $($val),*)[.. BITS]
}};
($store:ident, $order:path; $($val:expr),* $(,)?) => {{
const BITS: usize = $crate::__count!($($val),*);
&$crate::bitarr!($store, $order; $($val),*)[.. BITS]
}};
// Default order and store.
($val:expr; $len:expr) => {
$crate::bits!(usize, $crate::order::Lsb0; $val; $len)
};
($($val:expr),* $(,)?) => {
$crate::bits!(usize, Lsb0; $($val),*)
};
}
#[macro_export]
#[cfg(feature = "alloc")]
#[doc = include_str!("../doc/macros/bitvec.md")]
macro_rules! bitvec {
// First, capture the repetition syntax, as it is permitted to use runtime
// values for the repetition count.
($store:ty, $order:ty; $val:expr; $len:expr) => {
$crate::vec::BitVec::<$store, $order>::repeat($val != 0, $len)
};
// Capture `Cell<T>` patterns and prevent them from being parsed as
// comparisons. Guess we didn't escape Most Vexing Parse after all.
(Cell<$store:ident>, $order:ident $($rest:tt)*) => {
$crate::vec::BitVec::from_bitslice($crate::bits!(Cell<$store>, $order $($rest)*))
};
($val:expr; $len:expr) => {
$crate::bitvec!(usize, $crate::order::Lsb0; $val; $len)
};
// Delegate all others to the `bits!` macro.
($($arg:tt)*) => {
$crate::vec::BitVec::from_bitslice($crate::bits!($($arg)*))
};
}
#[macro_export]
#[cfg(feature = "alloc")]
#[doc = include_str!("../doc/macros/bitbox.md")]
macro_rules! bitbox {
($($arg:tt)*) => {
$crate::bitvec!($($arg)*).into_boxed_bitslice()
};
}