konst_kernel 0.3.4

Foundational const functionality shared between konst and const_panic
Documentation
#[cfg(test)]
mod utils_tests;

pub(crate) enum PanikVal<'a> {
    Str(&'a str),
    Usize(usize),
}

// an approximate value is acceptable.
// because unwritten '\0' bytes are removed when printing
const fn approx_log10(n: usize) -> u32 {
    (usize::BITS - n.leading_zeros()) / 3 + 1
}

const CAP: usize = 256;
pub(crate) const fn fmt_conc(slice: &[PanikVal<'_>]) -> [u8; CAP] {
    let mut out = [0u8; CAP];
    let mut i = 0usize;

    macro_rules! write_byte {
        ($byte:expr) => {
            out[i] = $byte;
            i += 1;
        };
    }

    crate::for_range! {slice_i in 0..slice.len() =>
        match slice[slice_i] {
            PanikVal::Str(str) => {
                let mut j = 0;
                let str = str.as_bytes();
                while j < str.len() {
                    write_byte!(str[j]);
                    j += 1;
                }
            }
            PanikVal::Usize(mut number) => {
                if number == 0 {
                    write_byte!(b'0');
                } else {
                    let digit_len = approx_log10(number);
                    i += digit_len as usize;
                    let mut j = i;
                    while number != 0 {
                        j -= 1;
                        out[j] = (number % 10) as u8 + b'0';
                        number /= 10;
                    }
                }
            }
        }
    }

    out
}

#[cold]
#[track_caller]
pub(crate) const fn basic_panic(slice: &[PanikVal<'_>]) -> ! {
    let arr = fmt_conc(slice);
    match core::str::from_utf8(&arr) {
        Ok(x) => panic!("{}", x),
        Err(_) => panic!("BUG: formatted string isn't UTF-8"),
    }
}

////////////////////////////////////////////////////////////////////////////////

pub struct TypeAnnot<T> {
    pub val: T,
}

////////////////////////////////////////////////////////////////////////////////

#[doc(hidden)]
#[repr(C)]
pub union Dereference<'a, T: ?Sized> {
    pub ptr: *const T,
    pub reff: &'a T,
}

macro_rules! make_parse_closure_macro {
    (
        $_:tt $macro_name:ident $arg_count:tt
        ($($pat_var:ident)*)
        ($($pat_macro_vars:tt)*)
        ($($pat_params:tt)*)
    ) => {
        #[doc(hidden)]
        #[macro_export]
        macro_rules! $macro_name {
            (
                $macro:tt $args:tt $usage_site:tt,
                |$($pat_macro_vars)*|  $_(,)?
            ) => {
                $crate::__parse_closure_no_expr_error!{$usage_site}
            };
            (
                ($_($macro:tt)*) ($_($args:tt)*)
                $usage_site:tt,
                |$($pat_macro_vars)*| $v:expr
                $_(, $_($rem:expr $_(, $_($rem_tt:tt)*)? )? )?
            ) => ({
                $_($_(
                    $crate::__parse_closure_trailing_expr_error!{$usage_site $rem}
                )?)?

                $_($macro)* ! {
                    $_($args)*
                    |$($pat_params)*| { $v }
                }
            });
            (
                ($_($macro:tt)*) ($_($args:tt)*)
                $usage_site:tt,
                |$($pat_macro_vars)*| -> $ret_ty:ty $v:block
                $_(, $_($rem:expr $_(, $_($rem_tt:tt)*)? )? )?
            ) => ({
                $_($_(
                    $crate::__parse_closure_trailing_expr_error!{$usage_site $rem}
                )?)?

                $_($macro)* ! {
                    $_($args)*
                    |$($pat_params)*| -> $ret_ty $v
                }
            });
            ($macro:tt $args:tt $usage_site:tt, | $_($anything:tt)* ) => {
                $crate::__parse_closure_emit_error!{
                    $arg_count
                    $usage_site
                }
            };
            ($macro:tt $args:tt $usage_site:tt, || $_($anything:tt)* ) => {
                $crate::__parse_closure_emit_error!{
                    $arg_count
                    $usage_site
                }
            };
            (
                ($_($macro:tt)*) ($_($args:tt)*)
                $usage_site:tt, $v:expr $_(,)?
            ) => {
                match $v {func => {
                    $_($macro)* ! {
                        $_($args)*
                        |$($pat_var),*| {func($($pat_var),*)}
                    }
                }}
            };
            ($macro:tt $args:tt $usage_site:tt $_($rem:tt)*) => {
                $crate::__parse_closure_emit_error!{
                    $arg_count
                    $usage_site
                }
            };

            ( $_($anything:tt)* ) => {
                $crate::__::compile_error!("expected a closure argument")
            };
        }

        pub use $macro_name;
    }
}

make_parse_closure_macro! {
    $ __parse_closure_1 1
    (aaa)
    ($aaa:pat_param $(,)?)
    ($aaa)
}
make_parse_closure_macro! {
    $ __parse_closure_2 2
    (aaa bbb)
    ($aaa:pat_param, $bbb:pat_param $(,)?)
    ($aaa, $bbb)
}

make_parse_closure_macro! {
    $ __alt_parse_closure_1 1
    (aaa)
    ($aaa:tt $(: $param_ty:ty)? $(,)?)
    ($aaa $(: $param_ty)?)
}

#[doc(hidden)]
#[macro_export]
macro_rules! __parse_closure_no_expr_error {
    (($($usage_site:tt)*)) => {
        $crate::__::compile_error!{$crate::__::concat!(
            "`",
            $crate::__::stringify!($($usage_site)*),
            "` expects valid closure syntax, passed closure without return value",
        )}
    };
}

#[doc(hidden)]
#[macro_export]
macro_rules! __parse_closure_trailing_expr_error {
    (($($usage_site:tt)*) $($rem:tt)*) => {
        $crate::__::compile_error!{$crate::__::concat!(
            "`",
            $crate::__::stringify!($($usage_site)*),
            "` expects no arguments after closure argument",
        )}
    };
}

#[doc(hidden)]
#[macro_export]
macro_rules! __parse_closure_emit_error {
    ($count:tt ($($usage_site:tt)*)) => {
        $crate::__::compile_error!{$crate::__::concat!(
            "`",
            $crate::__::stringify!($($usage_site)*),
            "` expects to be passed a ",
            $count,
            "-parameter closure",
        )}
    };
}