konst_kernel-0.3.15/.cargo_vcs_info.json0000644000000001520000000000100136160ustar { "git": { "sha1": "893074d1400a67d9ef041399dc7fbe3f6dc4e9f9" }, "path_in_vcs": "konst_kernel" }konst_kernel-0.3.15/Cargo.toml0000644000000027510000000000100116230ustar # THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies. # # If you are reading this file be aware that the original Cargo.toml # will likely look very different (and much more reasonable). # See Cargo.toml.orig for the original contents. [package] edition = "2021" rust-version = "1.57.0" name = "konst_kernel" version = "0.3.15" authors = ["rodrimati1992 "] build = false include = [ "Cargo.toml", "src/**/*.rs", "LICENSE-ZLIB.md", ] autolib = false autobins = false autoexamples = false autotests = false autobenches = false description = "Foundational const functionality shared between konst and const_panic" documentation = "https://docs.rs/konst/" readme = false keywords = [ "no-std", "const_fn", ] categories = ["no-std"] license = "Zlib" repository = "https://github.com/rodrimati1992/konst/" resolver = "1" [package.metadata.docs.rs] features = [ "debug", "rust_1_64", ] [lib] name = "konst_kernel" path = "src/lib.rs" [dependencies.typewit] version = "1.5" [dev-dependencies.arrayvec] version = "0.7" default-features = false [features] __for_konst = ["rust_1_64"] alloc = [] debug = [] docsrs = [] iter = [] mut_refs = ["rust_1_83"] nightly_mut_refs = ["mut_refs"] rust_1_64 = ["typewit/rust_1_61"] rust_1_83 = [] konst_kernel-0.3.15/Cargo.toml.orig000064400000000000000000000015161046102023000153020ustar 00000000000000[package] name = "konst_kernel" version = "0.3.15" authors = ["rodrimati1992 "] rust-version = "1.57.0" edition = "2021" license = "Zlib" description = "Foundational const functionality shared between konst and const_panic" documentation = "https://docs.rs/konst/" keywords = ["no-std", "const_fn"] categories = ["no-std"] repository = "https://github.com/rodrimati1992/konst/" include = [ "Cargo.toml", "src/**/*.rs", "LICENSE-ZLIB.md", ] [dependencies.typewit] version = "1.5" [dev-dependencies.arrayvec] default-features = false version = "0.7" [features] debug = [] alloc = [] iter = [] rust_1_64 = ["typewit/rust_1_61"] rust_1_83 = [] docsrs = [] nightly_mut_refs = ["mut_refs"] mut_refs = ["rust_1_83"] __for_konst = ["rust_1_64"] [package.metadata.docs.rs] features = ["debug", "rust_1_64"] konst_kernel-0.3.15/LICENSE-ZLIB.md000064400000000000000000000015271046102023000145570ustar 00000000000000Copyright (c) 2022 Matias Rodriguez. This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution.konst_kernel-0.3.15/src/__unsafe_utils.rs000064400000000000000000000010511046102023000165410ustar 00000000000000use core::mem::ManuallyDrop; #[repr(C)] pub union Transmuter { pub from: ManuallyDrop, pub to: ManuallyDrop, } #[repr(C)] pub union PtrToRef<'a, P: ?Sized> { pub ptr: *const P, pub reff: &'a P, } #[doc(hidden)] #[macro_export] macro_rules! __priv_transmute { ($from:ty, $to:ty, $value:expr) => {{ $crate::__::ManuallyDrop::into_inner( $crate::__unsafe_utils::Transmuter::<$from, $to> { from: $crate::__::ManuallyDrop::new($value), } .to, ) }}; } konst_kernel-0.3.15/src/chr/char_formatting.rs000064400000000000000000000045341046102023000174760ustar 00000000000000pub const fn encode_utf8(char: char) -> Utf8Encoded { let u32 = char as u32; match u32 { 0..=127 => Utf8Encoded { encoded: [u32 as u8, 0, 0, 0], len: 1, }, 0x80..=0x7FF => { let b0 = 0b1100_0000 | (u32 >> 6) as u8; let b1 = 0b1000_0000 | (u32 & 0b0011_1111) as u8; Utf8Encoded { encoded: [b0, b1, 0, 0], len: 2, } } 0x800..=0xFFFF => { let b0 = 0b1110_0000 | (u32 >> 12) as u8; let b1 = 0b1000_0000 | ((u32 >> 6) & 0b0011_1111) as u8; let b2 = 0b1000_0000 | (u32 & 0b0011_1111) as u8; Utf8Encoded { encoded: [b0, b1, b2, 0], len: 3, } } 0x10000..=u32::MAX => { let b0 = 0b1111_0000 | (u32 >> 18) as u8; let b1 = 0b1000_0000 | ((u32 >> 12) & 0b0011_1111) as u8; let b2 = 0b1000_0000 | ((u32 >> 6) & 0b0011_1111) as u8; let b3 = 0b1000_0000 | (u32 & 0b0011_1111) as u8; Utf8Encoded { encoded: [b0, b1, b2, b3], len: 4, } } } } #[derive(Copy, Clone)] pub struct Utf8Encoded { encoded: [u8; 4], len: u8, } impl Utf8Encoded { /// Gets the utf8-encoded char as a `&str` pub const fn as_str(&self) -> &str { unsafe { core::str::from_utf8_unchecked(self.as_bytes()) } } /// Gets the utf8-encoded char as a `&[u8]` pub const fn as_bytes(&self) -> &[u8] { crate::slice::slice_up_to(&self.encoded, self.len as usize) } } #[cfg(all(test, not(miri)))] mod tests { use super::{encode_utf8, Utf8Encoded}; fn as_bytes(fmt: &Utf8Encoded) -> &[u8] { &fmt.encoded[..fmt.len as usize] } #[test] fn char_to_utf8_encoding_test() { for c in '\0'..=core::char::MAX { let mut utf8_std = [0u8; 4]; let utf8_std = c.encode_utf8(&mut utf8_std); let utf8_konst = encode_utf8(c); assert_eq!(utf8_std.as_bytes(), as_bytes(&utf8_konst)); assert_eq!(utf8_std.as_bytes(), utf8_konst.as_bytes()); { assert_eq!( core::str::from_utf8(utf8_std.as_bytes()).unwrap(), utf8_konst.as_str(), ); } } } } konst_kernel-0.3.15/src/chr/tests.rs000064400000000000000000000022611046102023000154640ustar 00000000000000use crate::chr::{self, encode_utf8}; #[test] fn test_chars_as_str() { let mut buffer = [0u8; 10]; for c in "fooñ个人bar\u{100000}baz".chars() { let std_encoded = c.encode_utf8(&mut buffer); assert_eq!(encode_utf8(c).as_str(), std_encoded); } } #[cfg(not(miri))] #[test] fn test_all_chars_as_byets() { let mut buffer = [0u8; 10]; for c in '\0'..=char::MAX { let std_encoded = c.encode_utf8(&mut buffer); assert_eq!(encode_utf8(c).as_bytes(), std_encoded.as_bytes()); } } #[cfg(not(miri))] #[test] fn test_all_chars_from_u32() { for c in 0..(u32::from(char::MAX) + 10) { assert_eq!(chr::from_u32(c), core::char::from_u32(c)); } } #[test] fn test_some_chars_from_u32() { let vals = [ 0x0, 0x1, 0x7F, 0xFF, 0x7FF, 0x1000, 0x8000, 0xD7FF, 0xD800, 0xDFFF, 0xE000, 0xE001, 0x10FFFE, 0x10FFFF, 0x110000, 0x110001, ]; for c in vals { let chr = chr::from_u32(c); assert_eq!(chr, core::char::from_u32(c), "number: {c:x}"); if let Some(chr) = chr { unsafe { assert_eq!(chr, chr::from_u32_unchecked(c), "number: {c:x}"); } } } } konst_kernel-0.3.15/src/chr.rs000064400000000000000000000016331046102023000143240ustar 00000000000000mod char_formatting; #[cfg(test)] mod tests; pub use char_formatting::*; // this isn't documented at all, so this lint seems redundant here <_< #[allow(clippy::missing_safety_doc)] pub const unsafe fn from_u32_unchecked(n: u32) -> char { core::mem::transmute(n) } pub const fn from_u32(n: u32) -> Option { if n < 0xD800 || 0xE000 <= n && n <= 0x10FFFF { unsafe { Some(from_u32_unchecked(n)) } } else { None } } // this isn't really dead though, it's used for the static assertion below #[allow(dead_code)] #[track_caller] const fn assert_char_repr_as_u32(c: char) { let num = unsafe { core::mem::transmute::(c) }; assert!(c as u32 == num); } const _: () = { assert_char_repr_as_u32('\0'); assert_char_repr_as_u32('\u{D7FF}'); assert_char_repr_as_u32('\u{E000}'); assert_char_repr_as_u32('\u{10FFFF}'); assert_char_repr_as_u32(char::MAX); }; konst_kernel-0.3.15/src/collect_const.rs000064400000000000000000000065041046102023000164050ustar 00000000000000use crate::type_eq::{MakeTypeWitness, TypeEq, TypeWitnessTypeArg}; pub enum CollectorCmd { ComputeLength(TypeEq), BuildArray(TypeEq<[T; CAP], Ret>), } impl TypeWitnessTypeArg for CollectorCmd { type Arg = Ret; } impl MakeTypeWitness for CollectorCmd { const MAKE: Self = Self::ComputeLength(TypeEq::NEW); } impl MakeTypeWitness for CollectorCmd<[T; CAP], T, CAP> { const MAKE: Self = Self::BuildArray(TypeEq::NEW); } #[macro_export] macro_rules! iter_collect_const { ( $Item:ty => $($rem:tt)* ) => {{ $crate::__collect_const_iter_with!{ $Item , {let item = $crate::__::MaybeUninit::new(item);}, |array, length, item| array[length] = item, elem_length = 1, => $($rem)* } __ARR81608BFNA5 }} } #[doc(hidden)] #[macro_export] macro_rules! __collect_const_iter_with { ( $Item:ty, $reassign_item:tt, |$array:ident, $length:ident, $item:ident| $elem_initer:expr, elem_length = $elem_length:expr, => $($rem:tt)* ) => { const fn __func_zxe7hgbnjs( cmd: $crate::__::CollectorCmd ) -> Ret_KO9Y329U2U { let mut $array = $crate::maybe_uninit::uninit_array::<_, CAP_KO9Y329U2U>(); let mut $length = 0usize; $crate::__process_iter_args!{ ($crate::__iter_collect_const) (cmd, $length, $elem_length, $reassign_item, $elem_initer;) ( $item, 'zxe7hgbnjs, adapter, ) $($rem)* } match cmd { $crate::__::CollectorCmd::ComputeLength(teq) => { $crate::__::forget($array); teq.to_right($length) } $crate::__::CollectorCmd::BuildArray(teq) => { $crate::__::assert!{ $length == CAP_KO9Y329U2U, "initialization was skipped somehow", } // SAFETY: The above assert ensures that // all of the array is initialized let $array = unsafe{ $crate::maybe_uninit::array_assume_init($array) }; teq.to_right($array) } } } const __COUNT81608BFNA5: $crate::__::usize = __func_zxe7hgbnjs($crate::__::MakeTypeWitness::MAKE); const __ARR81608BFNA5: [$Item; __COUNT81608BFNA5] = __func_zxe7hgbnjs($crate::__::MakeTypeWitness::MAKE); }; } #[doc(hidden)] #[macro_export] macro_rules! __iter_collect_const { ( @each $cmd:ident, $length:ident, $elem_length:expr, {$($reassign_item:tt)*}, $elem_initer:expr; ($item:ident adapter), $(,)* ) => ({ $($reassign_item)* if let $crate::__::CollectorCmd::BuildArray(teq) = $cmd { teq.reachability_hint(()); $elem_initer } $length += $elem_length; }); (@end $($tt:tt)*) => {}; } konst_kernel-0.3.15/src/into_iter/range_into_iter.rs000064400000000000000000000152021046102023000207110ustar 00000000000000use core::{ mem::ManuallyDrop, ops::{Range, RangeFrom, RangeInclusive}, }; use crate::{ into_iter::{ConstIntoIter, IntoIterWrapper, IsIteratorKind, IsStdKind}, step_kk::{self, decrement, increment, Step, StepRet}, }; macro_rules! impl_std_kinds { ($($ty:ident => $iter:ident,)*) => ( $( impl ConstIntoIter for $ty { type Kind = IsStdKind; type IntoIter = $iter; type Item = T; } impl ConstIntoIter for &$ty { type Kind = IsStdKind; type IntoIter = $iter; type Item = T; } )* ) } impl_std_kinds! { Range => RangeIter, RangeInclusive => RangeInclusiveIter, RangeFrom => RangeFromIter, } pub struct RangeIter { start: T, end: T, } impl ConstIntoIter for RangeIter { type Kind = IsIteratorKind; type IntoIter = Self; type Item = T; } pub struct RangeIterRev { start: T, end: T, } impl ConstIntoIter for RangeIterRev { type Kind = IsIteratorKind; type IntoIter = Self; type Item = T; } pub struct RangeInclusiveIter { start: T, end: T, } impl ConstIntoIter for RangeInclusiveIter { type Kind = IsIteratorKind; type IntoIter = Self; type Item = T; } pub struct RangeInclusiveIterRev { start: T, end: T, } impl ConstIntoIter for RangeInclusiveIterRev { type Kind = IsIteratorKind; type IntoIter = Self; type Item = T; } pub struct RangeFromIter { start: T, } impl ConstIntoIter for RangeFromIter { type Kind = IsIteratorKind; type IntoIter = Self; type Item = T; } macro_rules! int_range_shared { (is_forward = $is_forward:ident, ty = $Int:ty) => { iterator_shared! { is_forward = $is_forward, item = $Int, iter_forward = RangeIter<$Int>, iter_reversed = RangeIterRev<$Int>, next(self){ let StepRet{finished_exclusive, next, ..} = increment(self.start, self.end); if finished_exclusive { None } else { // this assert can never fail, // because start >= end goes to the other branch // debug_assert!(!overflowed); let ret = self.start; self.start = next; Some((ret, self)) } }, next_back { let StepRet{finished_exclusive, next, overflowed, ..} = decrement(self.start, self.end); if finished_exclusive { None } else { debug_assert!(!overflowed); self.end = next; Some((self.end, self)) } }, fields = {start, end}, } }; } impl RangeIter { int_range_shared! {is_forward = true, ty = T} } impl RangeIterRev { int_range_shared! {is_forward = false, ty = T} } ////////////////////////////////////////////////// macro_rules! int_range_inc_shared { (is_forward = $is_forward:ident, ty = $Int:ty) => { iterator_shared! { is_forward = $is_forward, item = $Int, iter_forward = RangeInclusiveIter<$Int>, iter_reversed = RangeInclusiveIterRev<$Int>, next(self){ let StepRet{finished_inclusive, next, overflowed, ..} = increment(self.start, self.end); if finished_inclusive { None } else { let ret = self.start; if overflowed { self.start = T::MAX_VAL; self.end = T::MIN_VAL; } else { self.start = next; } Some((ret, self)) } }, next_back { let StepRet{finished_inclusive, next, overflowed, ..} = decrement(self.start, self.end); if finished_inclusive { None } else { let ret = self.end; if overflowed { self.start = T::MAX_VAL; self.end = T::MIN_VAL; } else { self.end = next; } Some((ret, self)) } }, fields = {start, end}, } }; } impl RangeInclusiveIter { int_range_inc_shared! {is_forward = true, ty = T} } impl RangeInclusiveIterRev { int_range_inc_shared! {is_forward = false, ty = T} } //////////////////////////////////////////////////////////////////////////////////////////////////// impl RangeFromIter { iterator_shared! { is_forward = true, item = T, iter_forward = RangeFromIter, next(self){ let StepRet{next, overflowed, ..} = increment(self.start, T::MAX_VAL); debug_assert!(!overflowed); let ret = self.start; self.start = next; Some((ret, self)) }, fields = {start}, } } ////////////////////////////////////////////////// macro_rules! ii_wrapper_range_impls { ($range_inc_ii:expr, $($reff:tt)?) => { impl IntoIterWrapper<$($reff)? Range, IsStdKind> { pub const fn const_into_iter(self) -> RangeIter { let range = ManuallyDrop::into_inner(self.iter); RangeIter { start: range.start, end: range.end, } } } impl IntoIterWrapper<$($reff)? RangeInclusive, IsStdKind> { pub const fn const_into_iter(self) -> RangeInclusiveIter { let range = ManuallyDrop::into_inner(self.iter); let (start, end) = $range_inc_ii(range); RangeInclusiveIter {start, end} } } impl IntoIterWrapper<$($reff)? RangeFrom, IsStdKind> { pub const fn const_into_iter(self) -> RangeFromIter { let range = ManuallyDrop::into_inner(self.iter); RangeFromIter { start: range.start, } } } } } ii_wrapper_range_impls! {step_kk::range_inclusive_into_inner, } ii_wrapper_range_impls! {step_kk::range_inclusive_ref_into_inner, &} konst_kernel-0.3.15/src/into_iter/slice_into_iter.rs000064400000000000000000000115101046102023000207120ustar 00000000000000use crate::into_iter::{ConstIntoIter, IntoIterWrapper, IsIteratorKind, IsStdKind}; use core::mem::ManuallyDrop; impl<'a, T, const N: usize> ConstIntoIter for &'a [T; N] { type Kind = IsStdKind; type IntoIter = Iter<'a, T>; type Item = &'a T; } impl<'a, T, const N: usize> ConstIntoIter for &&'a [T; N] { type Kind = IsStdKind; type IntoIter = Iter<'a, T>; type Item = &'a T; } impl<'a, T, const N: usize> IntoIterWrapper<&'a [T; N], IsStdKind> { pub const fn const_into_iter(self) -> Iter<'a, T> { Iter { slice: ManuallyDrop::into_inner(self.iter) as &[T], } } } impl<'a, T, const N: usize> IntoIterWrapper<&&'a [T; N], IsStdKind> { pub const fn const_into_iter(self) -> Iter<'a, T> { Iter { slice: (*ManuallyDrop::into_inner(self.iter)) as &[T], } } } impl<'a, T> ConstIntoIter for &'a [T] { type Kind = IsStdKind; type IntoIter = Iter<'a, T>; type Item = &'a T; } impl<'a, T> IntoIterWrapper<&'a [T], IsStdKind> { pub const fn const_into_iter(self) -> Iter<'a, T> { Iter { slice: ManuallyDrop::into_inner(self.iter), } } } impl<'a, T> ConstIntoIter for &&'a [T] { type Kind = IsStdKind; type IntoIter = Iter<'a, T>; type Item = &'a T; } impl<'a, T> IntoIterWrapper<&&'a [T], IsStdKind> { // clippy suggests a change that doesn't compile #[allow(clippy::explicit_auto_deref)] pub const fn const_into_iter(self) -> Iter<'a, T> { Iter { slice: *ManuallyDrop::into_inner(self.iter), } } } pub const fn iter(slice: &[T]) -> Iter<'_, T> { Iter { slice } } macro_rules! iter_shared { (is_forward = $is_forward:ident) => { iterator_shared! { is_forward = $is_forward, item = &'a T, iter_forward = Iter<'a, T>, iter_reversed = IterRev<'a, T>, next(self) { if let [elem, rem @ ..] = self.slice { self.slice = rem; Some((elem, self)) } else { None } }, next_back { if let [rem @ .., elem] = self.slice { self.slice = rem; Some((elem, self)) } else { None } }, fields = {slice}, } /// Accesses the remaining slice. pub const fn as_slice(&self) -> &'a [T] { self.slice } }; } pub struct Iter<'a, T> { slice: &'a [T], } impl<'a, T> ConstIntoIter for Iter<'a, T> { type Kind = IsIteratorKind; type IntoIter = Self; type Item = &'a T; } pub struct IterRev<'a, T> { slice: &'a [T], } impl<'a, T> ConstIntoIter for IterRev<'a, T> { type Kind = IsIteratorKind; type IntoIter = Self; type Item = &'a T; } impl<'a, T> Iter<'a, T> { iter_shared! {is_forward = true} } impl<'a, T> IterRev<'a, T> { iter_shared! {is_forward = false} } pub use copied::{iter_copied, IterCopied, IterCopiedRev}; mod copied { use super::*; pub const fn iter_copied(slice: &[T]) -> IterCopied<'_, T> { IterCopied { slice } } macro_rules! iter_copied_shared { (is_forward = $is_forward:ident) => { iterator_shared! { is_forward = $is_forward, item = T, iter_forward = IterCopied<'a, T>, iter_reversed = IterCopiedRev<'a, T>, next(self) { if let [elem, rem @ ..] = self.slice { self.slice = rem; Some((*elem, self)) } else { None } }, next_back { if let [rem @ .., elem] = self.slice { self.slice = rem; Some((*elem, self)) } else { None } }, fields = {slice}, } /// Accesses the remaining slice. pub const fn as_slice(&self) -> &'a [T] { self.slice } }; } pub struct IterCopied<'a, T> { slice: &'a [T], } impl<'a, T> ConstIntoIter for IterCopied<'a, T> { type Kind = IsIteratorKind; type IntoIter = Self; type Item = T; } pub struct IterCopiedRev<'a, T> { slice: &'a [T], } impl<'a, T> ConstIntoIter for IterCopiedRev<'a, T> { type Kind = IsIteratorKind; type IntoIter = Self; type Item = T; } impl<'a, T: Copy> IterCopied<'a, T> { iter_copied_shared! {is_forward = true} } impl<'a, T: Copy> IterCopiedRev<'a, T> { iter_copied_shared! {is_forward = false} } } konst_kernel-0.3.15/src/into_iter.rs000064400000000000000000000040401046102023000155370ustar 00000000000000use core::{marker::PhantomData, mem::ManuallyDrop}; #[doc(no_inline)] pub use crate::polymorphism::kinds::{IsIntoIterKind, IsIteratorKind, IsStdKind}; pub mod range_into_iter; pub mod slice_into_iter; pub trait ConstIntoIter { /// What kind of type this is: /// - [`IsIntoIterKind`]: user-defined types that are convertible to const iterators /// - [`IsIteratorKind`]: const iterators /// - [`IsStdKind`]: standard library types that are convertible to const iterators type Kind; /// The item that `Self::IntoIter` yields on `.next()` type Item; /// The iterator that this can be converted into. type IntoIter: ConstIntoIter; } #[repr(transparent)] pub struct IntoIterWrapper { pub iter: ManuallyDrop, pub marker: IsConstIntoIter, } mod is_into_iter_kind { use super::*; pub struct IsConstIntoIter(PhantomData<(fn() -> PhantomData, fn() -> K)>); impl IsConstIntoIter where T: ConstIntoIter, { pub const NEW: Self = Self(PhantomData); } } pub use is_into_iter_kind::IsConstIntoIter; impl IntoIterWrapper { #[inline(always)] pub const fn coerce(self) -> Self { self } } impl IntoIterWrapper { #[inline(always)] pub const fn coerce(self) -> T { ManuallyDrop::into_inner(self.iter) } } impl IntoIterWrapper { #[inline(always)] pub const fn coerce(self) -> Self { self } #[inline(always)] pub const fn const_into_iter(self) -> T where T: ConstIntoIter, { ManuallyDrop::into_inner(self.iter) } } //////////////////////////////////////////////////////////////////////////////// #[macro_export] macro_rules! into_iter_macro { ($iter:expr) => { $crate::__::IntoIterWrapper { iter: $crate::__::ManuallyDrop::new($iter), marker: $crate::__::IsConstIntoIter::NEW, } .coerce() .const_into_iter() }; } konst_kernel-0.3.15/src/iter/combinator_methods.rs000064400000000000000000000336551046102023000204040ustar 00000000000000#[doc(hidden)] #[macro_export] macro_rules! __process_iter_args { ( $callback_macro:tt $fixed_arguments:tt $other_args:tt ) => ( $crate::__::compile_error!{"expected iterator argument"} ); ( $callback_macro:tt $fixed_arguments:tt $other_args:tt $iter:expr $(, $method:ident $(($($args:tt)*))? )* $(,)* $( => $($rem:tt)*)? ) => ({ $( $crate::__cim_assert_has_args!{ $method $(($($args)*))? } )* $crate::iter::__cim_preprocess_methods !{ ( ((iter = $crate::into_iter_macro!($iter));) $callback_macro $fixed_arguments $other_args ( $($method($($($args)*)?),)* $( => $($rem)* )? ) ) [next] $($method $method ($($($args)*)?),)* } }); ( $callback_macro:tt $fixed_arguments:tt $other_args:tt $iter:expr, $method0:ident $(($($args0:tt)*))? .$method1:ident $($rem:tt)* ) => ({ $crate::__::compile_error!{"\ iterator methods in this macro are comma-separated\ "} }) } #[doc(hidden)] #[macro_export] macro_rules! __call_iter_methods { ( $fixed:tt ($vars:tt $macro:tt $prev_args:tt $label:tt next_back $allowed_methods:tt) $item:ident $iters:tt rev($($args:tt)*), $($rem:tt)* ) => ({ $crate::__cim_error_on_args!{rev($($args)*)} $crate::__call_iter_methods!{ ($vars $macro $prev_args $label next $allowed_methods) ($vars $macro $prev_args $label next $allowed_methods) $item $iters $($rem)* } }); ( $fixed:tt ($vars:tt $macro:tt $prev_args:tt $label:tt next $allowed_methods:tt) $item:ident $iters:tt rev($($args:tt)*), $($rem:tt)* ) => ({ $crate::__cim_error_on_args!{rev($($args)*)} $crate::__call_iter_methods!{ ($vars $macro $prev_args $label next_back $allowed_methods) ($vars $macro $prev_args $label next_back $allowed_methods) $item $iters $($rem)* } }); ( ( $vars:tt $macro:tt $prev_args:tt $label:tt $next_fn:tt $allowed_methods:ident ) (($iter_var:ident $($rem_vars:ident)*) $($rem_fixed:tt)*) $item:ident ($($iters:tt)*) zip($($args:tt)*), $($rem:tt)* ) => ( $crate::__call_iter_methods!{ (($($rem_vars)*) $($rem_fixed)*) (($($rem_vars)*) $($rem_fixed)*) $item ( $($iters)* ( {} let $item = if let $crate::__::Some((elem_, next_)) = $iter_var.$next_fn() { $iter_var = next_; ($item, elem_) } else { $crate::__cim_break!{(($($rem_vars)*) $($rem_fixed)*)} }; )) $($rem)* } ); ( $fixed:tt (($iter_var:ident $($rem_vars:ident)*) $($rem_fixed:tt)*) $item:ident ($($iters:tt)*) enumerate($($args:tt)*), $($rem:tt)* ) => ({ $crate::__cim_error_on_args!{enumerate($($args)*)} $crate::__call_iter_methods!{ (($($rem_vars)*) $($rem_fixed)*) (($($rem_vars)*) $($rem_fixed)*) $item ( $($iters)* ( {} let $item = ($iter_var, $item); $iter_var+=1; )) $($rem)* } }); ( $fixed:tt (($var:ident $($rem_vars:ident)*) $($rem_fixed:tt)*) $item:ident ($($iters:tt)*) //``__cim_preprocess_methods` ensures that only one argument is passed take($($args:tt)*), $($rem:tt)* ) => ( $crate::__call_iter_methods!{ (($($rem_vars)*) $($rem_fixed)*) (($($rem_vars)*) $($rem_fixed)*) $item ( $($iters)* ( {} if $var == 0 { $crate::__cim_break!{$fixed} } else { $var -= 1; } )) $($rem)* } ); ( $fixed:tt $fixedb:tt $item:ident ($($iters:tt)*) take_while($($pred:tt)*), $($rem:tt)* ) => ( $crate::__call_iter_methods!{ $fixed $fixedb $item ( $($iters)* ( {} let cond: $crate::__::bool = $crate::utils::__parse_closure_1!( ($crate::__cim_filter) ($item,) (take_while), $($pred)* ); if !cond { $crate::__cim_break!{$fixed} } )) $($rem)* } ); ( $fixed:tt (($var:ident $($rem_vars:ident)*) $($rem_fixed:tt)*) $item:ident ($($iters:tt)*) //``__cim_preprocess_methods` ensures that only one argument is passed skip($($args:tt)*), $($rem:tt)* ) => ( $crate::__call_iter_methods!{ (($($rem_vars)*) $($rem_fixed)*) (($($rem_vars)*) $($rem_fixed)*) $item ( $($iters)* ( {} if $var != 0 { $var -= 1; continue; } )) $($rem)* } ); ( $fixed:tt (($still_skipping:ident $($rem_vars:ident)*) $($rem_fixed:tt)*) $item:ident ($($iters:tt)*) skip_while($($pred:tt)*), $($rem:tt)* ) => ( $crate::__call_iter_methods!{ (($($rem_vars)*) $($rem_fixed)*) (($($rem_vars)*) $($rem_fixed)*) $item ( $($iters)* ( {} $still_skipping = $still_skipping && $crate::utils::__parse_closure_1!( ($crate::__cim_filter) ($item,) (skip_while), $($pred)* ); if $still_skipping { continue; } )) $($rem)* } ); ( $fixed:tt $fixedb:tt $item:ident ($($iters:tt)*) filter($($pred:tt)*), $($rem:tt)* ) => ( $crate::__call_iter_methods!{ $fixed $fixedb $item ( $($iters)* ( {} let cond = $crate::utils::__parse_closure_1!( ($crate::__cim_filter) ($item,) (filter), $($pred)* ); if !cond { continue; } )) $($rem)* } ); ( $fixed:tt $fixedb:tt $item:ident ($($iters:tt)*) filter_map($($args:tt)*), $($rem:tt)* ) => ( $crate::__call_iter_methods!{ $fixed $fixedb $item ( $($iters)* ( {} let val: $crate::__::Option<_> = $crate::utils::__parse_closure_1!( ($crate::__cim_map) ($item,) (filter_map), $($args)* ); let $item = match val { $crate::__::Some(x) => x, $crate::__::None => continue, }; )) $($rem)* } ); ( $fixed:tt $fixedb:tt $item:ident ($($iters:tt)*) map($($args:tt)*), $($rem:tt)* ) => ( $crate::__call_iter_methods!{ $fixed $fixedb $item ( $($iters)* ( {} let $item = $crate::utils::__parse_closure_1!( ($crate::__cim_map) ($item,) (map), $($args)* ); )) $($rem)* } ); ( $fixed:tt $fixedb:tt $item:ident ($($iters:tt)*) copied($($args:tt)*), $($rem:tt)* ) => ({ $crate::__cim_error_on_args!{copied($($args)*)} $crate::__call_iter_methods!{ $fixed $fixedb $item ( $($iters)* ( {} let $item = *$item; )) $($rem)* } }); ( $fixed:tt $fixedb:tt $item:ident $iters:tt flat_map($($args:tt)*), $($rem:tt)* ) => { $crate::__cim_output_layer!{ $fixed $item $iters {} { $crate::utils::__parse_closure_1!{ ($crate::__cim_flat_map) ($fixed $item ($($rem)*)) (flat_map), $($args)* } } {} } }; ( $fixed:tt $fixedb:tt $item:ident $iters:tt flatten($($args:tt)*), $($rem:tt)* ) => ({ $crate::__cim_error_on_args!{flatten($($args)*)} $crate::__cim_output_layer!{ $fixed $item $iters {} { $crate::__cim_flat_map! { $fixed $item ($($rem)*) (elem) {elem} } } {} } }); ( $fixed:tt ($vars:tt $macro:tt $prev_args:tt $label:tt $next_fn:tt adapter) $item:tt $iters:tt $comb:ident ($($args:tt)*), $($rem:tt)* ) => { $crate::iter::__cim_method_not_found_err!{$comb $comb} }; ( $fixed:tt ( $vars:tt ($($macro:tt)*) ($($prev_args:tt)*) $label:tt $next_fn:tt consumer ) $item:ident $iters:tt $($rem:tt)* ) => { $($macro)* ! { $($prev_args)* ($label $item $iters) $vars $item $($rem)* } }; ( $fixed:tt ($vars:tt ($($macro:tt)*) ($($prev_args:tt)*) $label:tt $next_fn:tt $allowed_methods:ident) $item:ident $iters:tt $($rem:tt)* ) => { $crate::__cim_output_layer!{ $fixed $item $iters { } { $($macro)* ! {@each $($prev_args)* ($item $allowed_methods), $($rem)*} } { $($macro)* ! {@end $($prev_args)* ($item $allowed_methods), $($rem)*} } } }; ($($tt:tt)*) => { $crate::__::compile_error!{$crate::__::concat!( "Unsupported arguments: ", $crate::__::stringify!($($tt)*), )} }; } #[doc(hidden)] #[macro_export] macro_rules! __cim_output_layer { ( ( $vars:tt $macro:tt $prev_args:tt ($break_label:lifetime $($label:lifetime)?) $next_fn:tt $allowed_methods:ident ) $item:ident ( $(( { $($var:ident = $var_expr:expr),* $(,)? } $($code:tt)* ))* ) {$($extra_init:tt)*} $each:tt $finish:tt ) => ({ match ($(($($var_expr,)*),)*) { ($(($(mut $var,)*),)*) => { $($extra_init)* $($label:)? loop { $($($code)*)* $each } $finish }, } }); } #[doc(hidden)] #[macro_export] macro_rules! __cim_filter { ($item:ident, ($($elem:tt)*) $(-> $ret_ty:ty)? $v:block) => {{ let $($elem)* = &$item; // avoiding lifetime extension let v: $crate::__::bool = $crate::__annotate_type!{$($ret_ty)? => $v}; v }}; } #[doc(hidden)] #[macro_export] macro_rules! __cim_map { ($item:ident, ($($elem:tt)*) $(-> $ret_ty:ty)? $v:block) => {{ let $($elem)* = $item; // allowing for lifetime extension of temporaries $crate::__annotate_type!{$($ret_ty)? => $v} }}; } #[doc(hidden)] #[macro_export] macro_rules! __cim_break { (( $vars:tt $macro:tt $prev_args:tt ($break_label:tt $($label:tt)?) $next_fn:tt $allowed_methods:ident )) => { break $break_label; }; } #[doc(hidden)] #[macro_export] macro_rules! __cim_flat_map { ( ( $vars:tt $macro:tt $prev_args:tt ($break_label:tt $($label:tt)?) $next_fn:tt $allowed_methods:ident ) $item:ident ($($rem:tt)*) ($($elem:tt)*) $(-> $ret_ty:ty)? $v:block ) => ({ let $($elem)* = $item; $crate::__call_iter_methods!{ ($vars $macro $prev_args ($break_label) $next_fn $allowed_methods) ($vars $macro $prev_args ($break_label) $next_fn $allowed_methods) $item ( ( { iter = $crate::into_iter_macro!( $crate::__annotate_type!{$($ret_ty)? => $v} ) } let $item = if let $crate::__::Some((elem_, next_)) = iter.$next_fn() { iter = next_; elem_ } else { break; }; ) ) $($rem)* } }); } #[doc(hidden)] #[macro_export] macro_rules! __cim_error_on_args { ($func:ident()) => (); ($func:ident ($($args:tt)*)) => { $crate::__::compile_error!{$crate::__::concat!{ "`", $crate::__::stringify!($func), "` does not take arguments, passed: ", $crate::__::stringify!($($args)*), }} }; } #[doc(hidden)] #[macro_export] macro_rules! __cim_assert_has_args { ($func:ident ($($args:tt)*)) => {}; ($func:ident) => { $crate::__::compile_error! {$crate::__::concat!{ "method call expected arguments: ", $crate::__::stringify!($func), }} }; } konst_kernel-0.3.15/src/iter/iter_adaptors.rs000064400000000000000000000013541046102023000173530ustar 00000000000000use crate::into_iter::{ConstIntoIter, IsIteratorKind}; pub const fn repeat(val: T) -> Repeat { Repeat(val) } pub struct Repeat(T); impl ConstIntoIter for Repeat { type Kind = IsIteratorKind; type IntoIter = Self; type Item = T; } impl Repeat { /// Gets the next element in the iterator pub const fn next(self) -> Option<(T, Self)> { Some((self.0, self)) } /// Gets the next element in the iterator pub const fn next_back(self) -> Option<(T, Self)> { Some((self.0, self)) } /// Reverses the iterator pub const fn rev(self) -> Self { self } /// Clones the iterator pub const fn copy(&self) -> Self { Self(self.0) } } konst_kernel-0.3.15/src/iter/iter_eval_macro.rs000064400000000000000000000215671046102023000176560ustar 00000000000000#[macro_export] macro_rules! iter_eval { () => { $crate::__::compile_error!{ "`eval` expects an iterator argument" } }; ($iter:expr $(, $($rem:tt)*)?) => { $crate::__process_iter_args!{ ($crate::__iter_eval) () (item, 'zxe7hgbnjs, consumer,) $iter, $($($rem)*)? } }; } #[doc(hidden)] #[macro_export] macro_rules! __iter_eval { ($fixed:tt () $item:ident for_each($($closure:tt)*), $(,)* ) => { $crate::utils::__parse_closure_1!{ ($crate::__ie_for_each) ($fixed $item,) (for_each), $($closure)* } }; ($fixed:tt $vars:tt $item:ident any($($closure:tt)*), $(,)* ) => { $crate::utils::__parse_closure_1!{ ($crate::__ie_any) ($fixed $vars $item,) (any), $($closure)* } }; ($fixed:tt $vars:tt $item:ident all($($closure:tt)*), $(,)* ) => { $crate::utils::__parse_closure_1!{ ($crate::__ie_all) ($fixed $vars $item,) (all), $($closure)* } }; ($fixed:tt ($var:ident) $item:ident count($($args:tt)*), $(,)* ) => ({ $crate::__cim_error_on_args!{count ($($args)*)} $crate::__ie_output!{ $fixed { $var += 1; } } }); // there's guaranteed to be an identifier for the method name, // so it is required to be either position or rposition. // // `rposition` reverses the iterator in `__cim_preprocess_methods` ( $fixed:tt $vars:tt $item:ident $(position $(@$position:tt)?)? $(rposition $(@$rposition:tt)?)? ($($closure:tt)*), $(,)* ) => { $crate::utils::__parse_closure_1!{ ($crate::__ie_position) ($fixed $vars $item,) ($(position $(@$position)?)? $(rposition $(@$rposition)?)?), $($closure)* } }; ($fixed:tt $vars:tt $item:ident find_map ($($closure:tt)*), $(,)* ) => { $crate::utils::__parse_closure_1!{ ($crate::__ie_find_map) ($fixed $vars $item,) (find_map), $($closure)* } }; ( $fixed:tt $vars:tt $item:ident $(find $(@$find:tt)?)? $(rfind $(@$rfind:tt)?)? ($($closure:tt)*), $(,)* ) => { $crate::utils::__parse_closure_1!{ ($crate::__ie_find) ($fixed $vars $item,) ($(find $(@$find)?)? $(rfind $(@$rfind)?)?), $($closure)* } }; ($fixed:tt $vars:tt $item:ident fold (), $(,)* ) => { $crate::__::compile_error! {"fold method expects accumulator and closure arguments"} }; ($fixed:tt $vars:tt $item:ident rfold (), $(,)* ) => { $crate::__::compile_error! {"rfold method expects accumulator and closure arguments"} }; ( $fixed:tt $vars:tt $item:ident $(fold $(@$fold:tt)?)? $(rfold $(@$rfold:tt)?)? ($accum:expr $(, $($closure:tt)*)?), $(,)* ) => { $crate::utils::__parse_closure_2!{ ($crate::__ie_fold) ($fixed $vars $item,) ($(fold $(@$fold)?)? $(rfold $(@$rfold)?)?), $($($closure)*)? } }; ($fixed:tt $vars:tt $item:ident fold $args:tt, $(,)* ) => { $crate::__::compile_error! {"fold method expects accumulator and closure arguments"} }; ($fixed:tt $vars:tt $item:ident rfold $args:tt, $(,)* ) => { $crate::__::compile_error! {"rfold method expects accumulator and closure arguments"} }; ($fixed:tt ($var:ident) $item:ident next($($args:tt)*), $(,)* ) => ({ $crate::__cim_error_on_args!{next ($($args)*)} $crate::__ie_output!{ $fixed { $var = $crate::__::Some($item); $crate::__ie_break!{$fixed} } } }); ($fixed:tt ($nth:ident $ret:ident) $item:ident nth($($args:tt)*), $(,)* ) => ({ $crate::__ie_output!{ $fixed { let _: $crate::__::usize = $nth; if $nth == 0 { $ret = $crate::__::Some($item); $crate::__ie_break!{$fixed} } else { $nth -= 1; } } } }); ($fixed:tt () $item:ident $comb:ident $($rem:tt)*) => { $crate::__::compile_error! {$crate::__::concat!( "Unsupported iterator method: `", $crate::__::stringify!($comb), "`", )} }; ($fixed:tt () $item:ident $(,)*) => { $crate::__ie_output!{$fixed {}} }; ($fixed:tt () $item:ident $($rem:tt)*) => { $crate::__::compile_error! {$crate::__::concat!( "Unsupported trailing syntax: `", $crate::__::stringify!($($rem)*), "`", )} }; } #[doc(hidden)] #[macro_export] macro_rules! __ie_for_each { ($fixed:tt $item:ident, ($($elem:tt)*) $(-> $ret_ty:ty)? $value:block) => { $crate::__ie_output! { $fixed {let $($elem)* = $item; $crate::__annotate_type!($($ret_ty)? => $value);} } }; } #[doc(hidden)] #[macro_export] macro_rules! __ie_any { ($fixed:tt ($cond:ident) $item:ident, ($($elem:tt)*) $(-> $ret_ty:ty)? $v:block) => { $crate::__ie_output! { $fixed { let $($elem)* = $item; let cond: $crate::__::bool = $crate::__annotate_type!($($ret_ty)? => $v); if cond { $cond = true; $crate::__ie_break!{$fixed} } } } }; } #[doc(hidden)] #[macro_export] macro_rules! __ie_all { ($fixed:tt ($cond:ident) $item:ident, ($($elem:tt)*) $(-> $ret_ty:ty)? $v:block) => { $crate::__ie_output! { $fixed { let $($elem)* = $item; let cond: $crate::__::bool = $crate::__annotate_type!($($ret_ty)? => $v); if !cond { $cond = false; $crate::__ie_break!{$fixed} } } } }; } #[doc(hidden)] #[macro_export] macro_rules! __ie_position { ( $fixed:tt ($i:ident $position:ident) $item:ident, ($($elem:tt)*) $(-> $ret_ty:ty)? $v:block ) => { $crate::__ie_output! { $fixed { let $($elem)* = $item; let cond: $crate::__::bool = $crate::__annotate_type!($($ret_ty)? => $v); if cond { $position = $crate::__::Some($i); $crate::__ie_break!{$fixed} } else { $i += 1; } } } }; } #[doc(hidden)] #[macro_export] macro_rules! __ie_find_map { ($fixed:tt ($ret:ident) $item:ident, ($($elem:tt)*) $(-> $ret_ty:ty)? $v:block) => { $crate::__ie_output! { $fixed { let $($elem)* = $item; $ret = $crate::__annotate_type!($($ret_ty)? => $v); if let $crate::__::Some(_) = $ret { $crate::__ie_break!{$fixed} } } } }; } #[doc(hidden)] #[macro_export] macro_rules! __ie_find { ($fixed:tt ($ret:ident) $item:ident, ($($elem:tt)*) $(-> $ret_ty:ty)? $v:block) => { $crate::__ie_output! { $fixed { let $($elem)* = &$item; let cond: $crate::__::bool = $crate::__annotate_type!($($ret_ty)? => $v); if cond { $ret = $crate::__::Some($item); $crate::__ie_break!{$fixed} } } } }; } #[doc(hidden)] #[macro_export] macro_rules! __ie_fold { ( $fixed:tt ($accum:ident) $item:ident, ($($closure_params:tt)*) $(-> $ret_ty:ty)? $v:block ) => { $crate::__ie_output! { $fixed { let $($closure_params)* = ($accum, $item); $accum = $crate::__annotate_type!($($ret_ty)? => $v); } } }; } #[doc(hidden)] #[macro_export] macro_rules! __ie_output { ( ( ($break_label:tt $($label:tt)?) $item:ident ( $(( {$($var_a:ident = $var_a_expr:expr),* $(,)?} $($code:tt)* ))* ) ) $each:tt ) => ({ match ($($( $var_a_expr,)?)*) { ($($(mut $var_a,)?)*) => { $($label:)? loop { $($($code)*)* $each } }, } }); } #[doc(hidden)] #[macro_export] macro_rules! __ie_break { ( ( ($break_label:tt $($label:tt)?) $item:ident $iter:tt ) $($break_with:expr)? ) => { break $break_label $($break_with)?; }; } konst_kernel-0.3.15/src/iter.rs000064400000000000000000000241371046102023000145170ustar 00000000000000use crate::into_iter::ConstIntoIter; use core::marker::PhantomData; mod combinator_methods; pub mod iter_adaptors; mod iter_eval_macro; #[macro_export] macro_rules! for_each { ($pattern:pat_param in $($rem:tt)*) => ({ $crate::__process_iter_args!{ ($crate::__for_each) (($pattern),) ( item, 'zxe7hgbnjs, adapter, ) $($rem)* } }); } #[doc(hidden)] #[macro_export] macro_rules! __for_each { ( @each ($pattern:pat_param), ($item:ident adapter), $(,)? => $($code:tt)* ) => ({ let $pattern = $item; $($code)* }); (@$other:ident $($tt:tt)*) =>{}; } #[macro_export] macro_rules! iter_count { ($iter:expr $(,)*) => {{ let mut count = 0; $crate::for_each! {_ in $iter => {count+=1;}} count }}; } macro_rules! make__cim_preprocess_methods__macro { ( $_:tt [$( $fn:ident [$($next_fn:ident)?] $args:tt $(return $ret_var:tt)? $(var $new_var:tt)?, )*] [$( ($($st_func:ident)* ($($func_args:tt)*)) => { $var:ident = $var_expr:tt } )*] $($finished_arm:tt)* ) => { #[doc(hidden)] #[macro_export] macro_rules! __cim_method_not_found_err { ($func:ident $($_($fn)?)* $($($_($st_func)?)*)*) => { $crate::__::compile_error! {$crate::__::concat!{ "the `", $crate::__::stringify!($func), "` method cannot be called in this macro", }} }; ($func:ident $func2:ident) => { $crate::__::compile_error!{$crate::__::concat!( "Unsupported iterator method: `", $crate::__::stringify!($func), "`", )} }; } #[doc(hidden)] #[macro_export] macro_rules! __cim_preprocess_methods { $($finished_arm)* $( ( (($_($vars_after:tt)*) $_($fixed:tt)*) [$prev_next_fn:ident $_($ignored:tt)*] $func_:ident $_($fn)? $args, $_($rest:tt)* ) => ({ $( $crate::__assert_first_rev!{$func_ $prev_next_fn $next_fn} )? $crate::iter::__cim_preprocess_methods!{ ( ( $(return(rets = $ret_var))? $_($vars_after)* $((var = $new_var))? ) $_($fixed)* ) [$($next_fn)? $prev_next_fn] $_($rest)* } }); )* $( ( (($_($vars_before:tt)*) $_($fixed:tt)*) [$prev_next_fn:ident $_($ignored:tt)*] $func_:ident $($_($st_func)?)* ($($func_args)*), $_($rest:tt)* ) => ({ $crate::iter::__cim_preprocess_methods!{ (($_($vars_before)* ($var = $var_expr)) $_($fixed)*) [$prev_next_fn] $_($rest)* } }); )* ( $fixed:tt $prev_next_fn:tt $func:ident $func2:ident ($_($args_:tt)*), $_($rest:tt)* ) => { $crate::__::compile_error!{$crate::__::concat!( "unsupported iterator method: ", $crate::__::stringify!($func), )} } } #[doc(hidden)] pub use __cim_preprocess_methods; #[doc(hidden)] pub use __cim_method_not_found_err; }; } make__cim_preprocess_methods__macro! { $ [ copied[] ($($args:tt)*), filter[] ($($args:tt)*), filter_map[] ($($args:tt)*), flat_map[] ($($args:tt)*), flatten[] ($($args:tt)*), map[] ($($args:tt)*), take_while[] ($($args:tt)*), rev[next_back] ($($args:tt)*), rfind[next_back] ($($args:tt)*) return($crate::__::None), all[] ($($args:tt)*) return(true), any[] ($($args:tt)*) return(false), count[] ($($args:tt)*) return(0usize), find[] ($($args:tt)*) return($crate::__::None), find_map[] ($($args:tt)*) return($crate::__::None), rfold[next_back] ($($args:tt)*) return($crate::__assert_fold_accum!(rfold, $($args)*)), fold[] ($($args:tt)*) return($crate::__assert_fold_accum!(fold, $($args)*)), for_each[] ($($args:tt)*), nth[] ($($args:tt)*) return($crate::__::None) var({ let x: $crate::__::usize = $crate::__cim_assert_expr!{nth($($args)*), 0usize}; x }), next[] ($($args:tt)*) return($crate::__::None), position[] ($($args:tt)*) return($crate::__::None) var(0usize), rposition[next_back] ($($args:tt)*) return($crate::__::None) var(0usize), ] [ ( zip($($args:tt)*) ) => { iter = ( $crate::into_iter_macro!( $crate::__cim_assert_expr!{zip($($args)*), 0usize..0} ) ) } ( enumerate($($args:tt)*) ) => { i = { 0usize } } ( take skip ($($args:tt)*) ) => { rem = { let x: $crate::__::usize = $crate::__cim_assert_expr!{take($($args)*), 0}; x } } ( skip_while ($($args:tt)*) ) => { still_skipping = true } ] ( ( ( $(return($ret_var:ident = $ret_val:tt))? ($iter_var:ident = $iter_expr:expr); $(($var:ident = $var_value:expr))* ) ($($callback_macro:tt)*) ($($fixed_arguments:tt)*) ( $item:ident, $label:lifetime, // adapter: analogous to iterator adapter, which return iterators // consumer: methods which consume the iterator without (necessarily) // returning an iterator. $allowed_methods:ident, ) ($($args:tt)*) ) [$next_fn:ident $($ignored:tt)*] ) => ({ $(let mut $ret_var = $ret_val;)? $crate::__call_iter_methods!{ ( ($($var)* $($ret_var)?) ($($callback_macro)*) ($($fixed_arguments)*) ($label $label) $next_fn $allowed_methods ) ( ($($var)* $($ret_var)?) ($($callback_macro)*) ($($fixed_arguments)*) ($label $label) $next_fn $allowed_methods ) $item ( ( { $iter_var = $iter_expr, $($var = $var_value,)* } let elem_phantom_ty = $crate::iter::__get_item_ty(&$iter_var); let $item = if let $crate::__::Some((elem_, next_)) = $iter_var.$next_fn() { $crate::iter::__assert_item_ty(&elem_, elem_phantom_ty); $iter_var = next_; elem_ } else { break $label; }; ) ) $($args)* } $($ret_var)? }); } #[doc(hidden)] #[macro_export] macro_rules! __assert_first_rev { ($func:ident next_back next_back) => { $crate::__::compile_error! {$crate::__::concat!( "cannot call two iterator-reversing methods in `konst::iter` macros,", " called: ", $crate::__::stringify!($func), )} }; ($func:ident $prev_next_fn:ident $($next_fn:ident)?) => {}; } #[doc(hidden)] #[macro_export] macro_rules! __cim_assert_expr { ($func:ident (), $def:expr) => {{ $crate::__cim_no_expr_arg_error! {$func ()} $def }}; ($func:ident ( $expr:expr $(,)?), $def:expr) => { $expr }; ($func:ident ($expr:expr ,$($args:tt)+), $def:expr) => {{ $crate::__::compile_error! {$crate::__::concat!{ "`", $crate::__::stringify!($func), "` only takes one argument" }} $def }}; ($func:ident $args:tt, $def:expr) => {{ $crate::__cim_no_expr_arg_error! {$func $args} $def }}; } #[doc(hidden)] #[macro_export] macro_rules! __cim_no_expr_arg_error { ($func:ident $args:tt) => { $crate::__::compile_error! {$crate::__::concat!{ "`", $crate::__::stringify!($func), "` expected an expression to be passed, passed: ", $crate::__cim_if_empty!{ $args { "``" } else { $crate::__::stringify! $args } }, }} }; } #[doc(hidden)] #[macro_export] macro_rules! __cim_if_empty { (() {$($then:tt)*} else $else:tt) => { $($then)* }; (($($non_empty:tt)+) $then:tt else {$($else:tt)*}) => { $($else)* }; } #[doc(hidden)] #[macro_export] macro_rules! __assert_fold_accum { ($func:ident, $e:expr $(, $($__:tt)*)?) => { $e }; // dummy default value, this'll error in __iter_eval ($func:ident, $($args:tt)*) => { () }; } #[doc(hidden)] #[inline(always)] pub const fn __get_item_ty(_: &Iter) -> PhantomData<(Iter, Iter::Item)> where Iter: ConstIntoIter, { PhantomData } #[doc(hidden)] #[inline(always)] pub const fn __assert_item_ty(_: &Iter::Item, _: PhantomData<(Iter, Iter::Item)>) where Iter: ConstIntoIter, { } konst_kernel-0.3.15/src/lib.rs000064400000000000000000000041651046102023000143210ustar 00000000000000//! This crate has a few items reexported by `konst`, and used by `const_panic`. //! //! None of the items in this crate are documented, //! because they are documented in the 0.3 `konst` crate. //! //! #![no_std] #![cfg_attr(feature = "docsrs", feature(doc_cfg))] #![deny(unused_results)] #![allow(clippy::type_complexity)] #![forbid(clippy::missing_const_for_fn)] #[cfg(feature = "alloc")] extern crate alloc; #[macro_use] mod macros; #[doc(hidden)] #[cfg(feature = "__for_konst")] #[cfg(feature = "iter")] pub mod collect_const; #[cfg(feature = "__for_konst")] pub mod chr; #[doc(hidden)] #[cfg(feature = "__for_konst")] #[cfg(feature = "iter")] pub mod into_iter; #[doc(hidden)] #[cfg(feature = "__for_konst")] #[cfg(feature = "iter")] pub mod iter; pub mod type_eq; #[doc(hidden)] #[cfg(feature = "__for_konst")] pub mod maybe_uninit; #[cfg(feature = "rust_1_64")] #[cfg_attr(feature = "docsrs", doc(cfg(feature = "rust_1_64")))] pub mod slice; #[cfg(feature = "rust_1_64")] #[cfg_attr(feature = "docsrs", doc(cfg(feature = "rust_1_64")))] pub mod string; #[cfg(feature = "iter")] pub mod step_kk; #[cfg(feature = "__for_konst")] pub mod polymorphism; #[doc(hidden)] pub mod __unsafe_utils; #[cfg(feature = "rust_1_64")] #[doc(hidden)] pub mod utils; #[doc(hidden)] pub mod __ { pub use typewit::{ HasTypeWitness, Identity, MakeTypeWitness, TypeEq, TypeFn, TypeWitnessTypeArg, }; #[cfg(feature = "__for_konst")] pub use crate::{ macros::array_macros::{assert_array, uninit_array_of_len, unit_array}, maybe_uninit::{array_assume_init, uninit_array}, type_eq::make_project_fn::__make_projection_parse_generics, }; #[cfg(feature = "iter")] pub use crate::{ collect_const::CollectorCmd, into_iter::{IntoIterWrapper, IsConstIntoIter}, }; pub use core::{ assert, compile_error, concat, marker::PhantomData, mem::{forget, ManuallyDrop, MaybeUninit}, ops::Range, option::Option::{self, None, Some}, panic, primitive::{bool, str, u8, usize}, result::Result::{self, Err, Ok}, stringify, }; } konst_kernel-0.3.15/src/macros/array_macros.rs000064400000000000000000000054231046102023000175170ustar 00000000000000use core::mem::MaybeUninit; #[macro_export] macro_rules! array_map { ($array:expr, $($closure:tt)* ) => ( match $array { ref array => { let array = $crate::__::assert_array(array); $crate::utils::__parse_closure_1!{ ($crate::__array_map) (array, |i| array[i],) (array_map), $($closure)* } } } ); } #[doc(hidden)] #[macro_export] macro_rules! __array_map { ( $array:ident, |$i:ident| $get_input:expr, ($($pattern:tt)*) $(-> $ret:ty)? $mapper:block $(,)? ) => ({ let len = $array.len(); let mut out = $crate::__::uninit_array_of_len(&$array); let mut $i = 0usize; while $i < len { let $($pattern)* = $get_input; out[$i] = $crate::__::MaybeUninit $(::<$ret>)? ::new($mapper); $i += 1; } // protecting against malicious `$mapper`s that break out of the `while` loop $crate::__::assert!($i == len); unsafe{ $crate::__::array_assume_init(out) } }) } //////////////////////////////////////////////////////////////////////////////// #[macro_export] macro_rules! array_from_fn { ($($args:tt)*) => ({ $crate::__split_array_type_and_closure!{ (($crate::__array_from_fn_inner) ()) () ($($args)*) } }); } #[macro_export] macro_rules! __array_from_fn_inner { (($($($type:tt)+)?) $($closure_unparsed:tt)*) => ({ let input = $crate::__::unit_array(); let arr $(: $crate::__unparenthesize_ty!($($type)*))? = $crate::utils::__parse_closure_1!{ ($crate::__array_map) (input, |i| i,) (array_from_fn), $($closure_unparsed)* }; arr }); } #[doc(hidden)] #[macro_export] macro_rules! __split_array_type_and_closure { ((($($callback:tt)*) ($($args:tt)*)) $before:tt (=> $($rem:tt)*)) => { $($callback)* ! {$($args)* $before $($rem)*} }; ((($($callback:tt)*) ($($args:tt)*)) ($($before:tt)*) ($(| $($rem:tt)*)?)) => { $($callback)* ! {$($args)* () $($before)* $(| $($rem)*)?} }; ($callback:tt ($($before:tt)*) ($token:tt $($rem:tt)*)) => { $crate::__split_array_type_and_closure! {$callback ($($before)* $token) ($($rem)*)} }; } //////////////////////////////////////////////////////////////////////////////// #[inline(always)] pub const fn assert_array(array: &[T; N]) -> &[T; N] { array } #[inline(always)] pub const fn uninit_array_of_len(_input: &[T; N]) -> [MaybeUninit; N] { crate::maybe_uninit::uninit_array() } #[inline(always)] pub const fn unit_array() -> [(); N] { [(); N] } konst_kernel-0.3.15/src/macros/control_flow.rs000064400000000000000000000004261046102023000175420ustar 00000000000000#[macro_export] macro_rules! for_range { ($pat:pat_param in $range:expr => $($code:tt)*) => { let $crate::__::Range{mut start, end} = $range; while start < end { let $pat = start; start+=1; $($code)* } }; } konst_kernel-0.3.15/src/macros/internal_macros.rs000064400000000000000000000015361046102023000202160ustar 00000000000000#[doc(hidden)] #[macro_export] macro_rules! __unparenthesize_ty { (($type:ty)) => { $type }; ($type:ty) => { $type }; } #[doc(hidden)] #[macro_export] macro_rules! __unparen_pat { (($(|)? $($pat:pat_param)|+)) => { ($($pat)|+) }; (($($stuff:tt)*)) => { $($stuff)* }; ($($stuff:tt)*) => { $($stuff)* }; } #[doc(hidden)] #[macro_export] macro_rules! __ty_or_und { () => { _ }; ($ty:ty) => { $ty }; } #[doc(hidden)] #[macro_export] macro_rules! __annotate_type { (=> $expr:expr) => { $expr }; ($type:ty => $expr:expr) => { $crate::utils::TypeAnnot::<$type> { val: $expr }.val }; } #[doc(hidden)] #[macro_export] macro_rules! __choose { (true $then:tt $($else:tt)*) => { $then }; (false $then:tt $else:tt) => { $else }; } konst_kernel-0.3.15/src/macros/into_iter_macros.rs000064400000000000000000000027101046102023000203710ustar 00000000000000#[doc(hidden)] #[macro_export] macro_rules! iterator_shared { ( is_forward = $is_forward:ident, item = $Item:ty, iter_forward = $Self:ty, $(iter_reversed = $Rev:path,)? next($self:ident) $next_block:block, $(next_back $next_back_block:block,)? fields = $fields:tt, ) => { /// Creates a clone of this iterator pub const fn copy(&self) -> Self { let Self $fields = *self; Self $fields } $( /// Reverses the iterator pub const fn rev(self) -> $crate::__choose!($is_forward $Rev $Self) { let Self $fields = self; type Type = T; Type::<$crate::__choose!($is_forward $Rev $Self)> $fields } )? /// Advances the iterator and returns the next value. #[track_caller] pub const fn next(mut $self) -> Option<($Item, Self)> { $crate::__choose!{ $is_forward $next_block $($next_back_block)? } } $( /// Removes and returns an element from the end of the iterator. #[track_caller] pub const fn next_back(mut $self) -> Option<($Item, Self)> { $crate::__choose!{ $is_forward $next_back_block $next_block } } )? }; } konst_kernel-0.3.15/src/macros/option_macros_.rs000064400000000000000000000102071046102023000200440ustar 00000000000000#[macro_export] macro_rules! opt_unwrap { ($e:expr $(,)?) => { match $e { $crate::__::Some(x) => x, $crate::__::None => $crate::__::panic!("invoked `unwrap` macro on a `None` value"), } }; } #[macro_export] macro_rules! opt_unwrap_or { ($e:expr, $v:expr $(,)?) => { match ($e, $v) { ($crate::__::Some(x), _) => x, ($crate::__::None, value) => value, } }; } #[macro_export] macro_rules! opt_unwrap_or_else { ($e:expr, || $v:expr $(,)?) => { match $e { $crate::__::Some(x) => x, $crate::__::None => $v, } }; ($opt:expr, | $($anything:tt)* ) => { compile_error!("expected the closure to take no arguments") }; ($e:expr, $v:expr $(,)?) => { match $e { $crate::__::Some(x) => x, $crate::__::None => $v(), } }; } #[macro_export] macro_rules! opt_ok_or { ($e:expr, $v:expr $(,)?) => { match ($e, $v) { ($crate::__::Some(x), _) => $crate::__::Ok(x), ($crate::__::None, value) => $crate::__::Err(value), } }; } #[macro_export] macro_rules! opt_ok_or_else { ($e:expr, || $v:expr $(,)?) => { match $e { $crate::__::Some(x) => $crate::__::Ok(x), $crate::__::None => $crate::__::Err($v), } }; ($opt:expr, | $($anything:tt)* ) => { compile_error!("expected the closure to take no arguments") }; ($e:expr, $v:expr $(,)?) => { match $e { $crate::__::Some(x) => $crate::__::Ok(x), $crate::__::None => $crate::__::Err($v()), } }; } #[macro_export] macro_rules! opt_map { ($opt:expr, |$param:pat_param| $mapper:expr $(,)? ) => { match $opt { $crate::__::Some($param) => $crate::__::Some($mapper), $crate::__::None => $crate::__::None, } }; ($opt:expr, | $($anything:tt)* ) => { compile_error!("expected the closure to take a pattern as an argument") }; ($opt:expr, $function:path $(,)?) => { match $opt { $crate::__::Some(x) => $crate::__::Some($function(x)), $crate::__::None => $crate::__::None, } }; } #[macro_export] macro_rules! opt_and_then { ($opt:expr, |$param:pat_param| $mapper:expr $(,)? ) => { match $opt { $crate::__::Some($param) => $mapper, $crate::__::None => $crate::__::None, } }; ($opt:expr, | $($anything:tt)* ) => { compile_error!("expected the closure to take a pattern as an argument") }; ($opt:expr, $function:path $(,)?) => { match $opt { $crate::__::Some(x) => $function(x), $crate::__::None => $crate::__::None, } }; } #[macro_export] macro_rules! opt_flatten { ($opt:expr $(,)? ) => { match $opt { $crate::__::Some(x) => x, $crate::__::None => $crate::__::None, } }; } #[macro_export] macro_rules! opt_or_else { ($opt:expr, || $mapper:expr $(,)? ) => { match $opt { $crate::__::Some(x) => $crate::__::Some(x), $crate::__::None => $mapper, } }; ($opt:expr, | $($anything:tt)* ) => { compile_error!("expected the closure to take no arguments") }; ($opt:expr, $function:path $(,)?) => { match $opt { $crate::__::Some(x) => $crate::__::Some(x), $crate::__::None => $function(), } }; } #[macro_export] macro_rules! opt_filter { ($e:expr, |$param:pat_param| $v:expr $(,)?) => { match $e { $crate::__::Some(x) if { let $param = &x; $v } => { $crate::__::Some(x) } _ => $crate::__::None, } }; ($opt:expr, | $($anything:tt)* ) => { compile_error!("expected the closure to take a pattern as an argument") }; ($e:expr, $function:path $(,)?) => { match $e { $crate::__::Some(x) if $function(&x) => $crate::__::Some(x), _ => $crate::__::None, } }; } konst_kernel-0.3.15/src/macros/result_macros_.rs000064400000000000000000000101071046102023000200510ustar 00000000000000#[macro_export] macro_rules! unwrap_ctx { ($e:expr $(,)?) => { match $e { $crate::__::Ok(x) => x, $crate::__::Err(e) => e.panic(), } }; } #[macro_export] macro_rules! res_unwrap_or { ($res:expr, $v:expr $(,)?) => { match ($res, $v) { ($crate::__::Ok(x), _) => x, ($crate::__::Err(_), value) => value, } }; } #[macro_export] macro_rules! res_unwrap_or_else { ($res:expr, |$param:pat_param| $expr:expr $(,)?) => { match $res { $crate::__::Ok(x) => x, $crate::__::Err($param) => $expr, } }; ($opt:expr, | $($anything:tt)* ) => { compile_error!("expected the closure to take a pattern as an argument") }; ($res:expr, $function:expr $(,)?) => { match $res { $crate::__::Ok(x) => x, $crate::__::Err(x) => $function(x), } }; } #[macro_export] macro_rules! res_unwrap_err_or_else { ($res:expr, |$param:pat_param| $expr:expr $(,)?) => { match $res { $crate::__::Ok($param) => $expr, $crate::__::Err(x) => x, } }; ($opt:expr, | $($anything:tt)* ) => { compile_error!("expected the closure to take a pattern as an argument") }; ($res:expr, $function:expr $(,)?) => { match $res { $crate::__::Ok(x) => $function(x), $crate::__::Err(x) => x, } }; } #[macro_export] macro_rules! res_ok { ($res:expr $(,)?) => { match $res { $crate::__::Ok(x) => $crate::__::Some(x), $crate::__::Err(_) => $crate::__::None, } }; } #[macro_export] macro_rules! res_err { ($res:expr $(,)?) => { match $res { $crate::__::Ok(_) => $crate::__::None, $crate::__::Err(x) => $crate::__::Some(x), } }; } #[macro_export] macro_rules! res_and_then { ($res:expr, |$param:pat_param| $expr:expr $(,)?) => { match $res { $crate::__::Ok($param) => $expr, $crate::__::Err(x) => $crate::__::Err(x), } }; ($opt:expr, | $($anything:tt)* ) => { compile_error!("expected the closure to take a pattern as an argument") }; ($res:expr, $function:expr $(,)?) => { match $res { $crate::__::Ok(param) => $function(param), $crate::__::Err(x) => $crate::__::Err(x), } }; } #[macro_export] macro_rules! res_map { ($res:expr, |$param:pat_param| $expr:expr $(,)?) => { match $res { $crate::__::Ok($param) => $crate::__::Ok($expr), $crate::__::Err(x) => $crate::__::Err(x), } }; ($opt:expr, | $($anything:tt)* ) => { compile_error!("expected the closure to take a pattern as an argument") }; ($res:expr, $function:expr $(,)?) => { match $res { $crate::__::Ok(param) => $crate::__::Ok($function(param)), $crate::__::Err(x) => $crate::__::Err(x), } }; } #[macro_export] macro_rules! res_map_err { ($res:expr, |$param:pat_param| $expr:expr $(,)?) => { match $res { $crate::__::Ok(x) => $crate::__::Ok(x), $crate::__::Err($param) => $crate::__::Err($expr), } }; ($opt:expr, | $($anything:tt)* ) => { compile_error!("expected the closure to take a pattern as an argument") }; ($res:expr, $function:expr $(,)?) => { match $res { $crate::__::Ok(x) => $crate::__::Ok(x), $crate::__::Err(x) => $crate::__::Err($function(x)), } }; } #[macro_export] macro_rules! res_or_else { ($res:expr, |$param:pat_param| $expr:expr $(,)?) => { match $res { $crate::__::Ok(x) => $crate::__::Ok(x), $crate::__::Err($param) => $expr, } }; ($opt:expr, | $($anything:tt)* ) => { compile_error!("expected the closure to take a pattern as an argument") }; ($res:expr, $function:expr $(,)?) => { match $res { $crate::__::Ok(x) => $crate::__::Ok(x), $crate::__::Err(x) => $function(x), } }; } konst_kernel-0.3.15/src/macros.rs000064400000000000000000000005071046102023000150330ustar 00000000000000#[macro_use] mod control_flow; #[cfg(feature = "iter")] #[macro_use] mod into_iter_macros; #[cfg(feature = "__for_konst")] #[macro_use] mod internal_macros; #[cfg(feature = "__for_konst")] pub(crate) mod array_macros; #[cfg(feature = "__for_konst")] mod option_macros_; #[cfg(feature = "__for_konst")] mod result_macros_; konst_kernel-0.3.15/src/maybe_uninit.rs000064400000000000000000000010011046102023000162200ustar 00000000000000use core::mem::{ManuallyDrop, MaybeUninit}; #[inline(always)] pub const fn uninit_array() -> [MaybeUninit; LEN] { union MakeMUArray { unit: (), array: ManuallyDrop<[MaybeUninit; LEN]>, } unsafe { ManuallyDrop::into_inner(MakeMUArray { unit: () }.array) } } #[inline(always)] pub const unsafe fn array_assume_init(md: [MaybeUninit; N]) -> [T; N] { crate::__priv_transmute! {[MaybeUninit; N], [T; N], md} } konst_kernel-0.3.15/src/polymorphism.rs000064400000000000000000000006231046102023000163100ustar 00000000000000pub mod kinds { /// Marker for user-defined types that can be converted into const iterators pub enum IsIntoIterKind {} /// Marker for const iterators pub enum IsIteratorKind {} /// Marker for references. pub enum IsRefKind {} /// Marker for non-standard library types. pub enum IsNotStdKind {} /// Marker for standard library types. pub enum IsStdKind {} } konst_kernel-0.3.15/src/slice/slice_for_konst.rs000064400000000000000000000060661046102023000200370ustar 00000000000000#![allow(non_camel_case_types)] use core::fmt::{self, Display}; #[inline] pub const fn try_into_array_func( slice: &[T], ) -> Result<&[T; N], TryIntoArrayError> { if slice.len() == N { let ptr = slice.as_ptr() as *const [T; N]; unsafe { Ok(crate::utils::Dereference { ptr }.reff) } } else { Err(TryIntoArrayError { slice_len: slice.len(), array_len: N, }) } } //////////////////////////////////////////////////////////////////////////////// #[cfg(feature = "rust_1_83")] #[inline] pub const fn try_into_array_mut_func( slice: &mut [T], ) -> Result<&mut [T; N], TryIntoArrayError> { if slice.len() == N { unsafe { Ok(&mut *(slice as *mut [T] as *mut [T; N])) } } else { Err(TryIntoArrayError { slice_len: slice.len(), array_len: N, }) } } //////////////////////////////////////////////////////////////////////////////// #[derive(Debug, PartialEq, Eq, Copy, Clone)] pub struct TryIntoArrayError { slice_len: usize, array_len: usize, } impl TryIntoArrayError { /// For panicking with an error message. pub const fn panic(&self) -> ! { use crate::utils::PanikVal; crate::utils::basic_panic(&[ PanikVal::Str("could not convert slice of length `"), PanikVal::Usize(self.slice_len), PanikVal::Str("` to array of length`"), PanikVal::Usize(self.array_len), PanikVal::Str("`"), ]) } } impl Display for TryIntoArrayError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.write_str("Could not cast slice to array reference") } } //////////////////////////////////////////////////////////////////////////////// #[macro_export] macro_rules! slice_concat { ($elem_ty:ty, $slice:expr $(,)*) => {{ const __ARGS_81608BFNA5: &[&[$elem_ty]] = $slice; { const LEN: $crate::__::usize = $crate::slice::concat_sum_lengths(__ARGS_81608BFNA5); const CONC: [$elem_ty; LEN] = $crate::slice::concat_slices(__ARGS_81608BFNA5); CONC } }}; } pub const fn concat_sum_lengths(slice: &[&[T]]) -> usize { let mut sum = 0usize; crate::for_range! {i in 0..slice.len() => sum += slice[i].len(); } sum } pub const fn concat_slices(slices: &[&[T]]) -> [T; N] where T: Copy, { if let Ok(x) = try_into_array_func::(&[]) { return *x; } let mut out = [*first_elem(slices); N]; let mut out_i = 0usize; crate::for_range! {si in 0..slices.len() => let slice = slices[si]; crate::for_range! {i in 0..slice.len() => out[out_i] = slice[i]; out_i += 1; } } out } // returns the first T in a `&[&[T]]` const fn first_elem<'a, T>(slices: &[&'a [T]]) -> &'a T { crate::for_range! {si in 0..slices.len() => if let [first, ..] = slices[si] { return first; } } panic!("there was no element in any slice"); } konst_kernel-0.3.15/src/slice.rs000064400000000000000000000030461046102023000146470ustar 00000000000000#[cfg(feature = "__for_konst")] pub mod slice_for_konst; #[cfg(feature = "__for_konst")] pub use self::slice_for_konst::*; #[doc(hidden)] #[macro_export] macro_rules! __slice_from_impl { ($slice:ident, $start:ident, $as_ptr:ident, $from_raw_parts:ident, $on_overflow:expr) => {{ #[allow(unused_variables, clippy::ptr_offset_with_cast)] let (rem, overflowed) = $slice.len().overflowing_sub($start); if overflowed { return $on_overflow; } #[allow(clippy::ptr_offset_with_cast)] unsafe { core::slice::$from_raw_parts($slice.$as_ptr().offset($start as _), rem) } }}; } #[doc(hidden)] #[macro_export] macro_rules! __slice_up_to_impl { ($slice:ident, $len:ident, $as_ptr:ident, $from_raw_parts:ident, $on_overflow:expr) => {{ #[allow(unused_variables)] let (rem, overflowed) = $slice.len().overflowing_sub($len); if overflowed { return $on_overflow; } // Doing this to get a slice up to length at compile-time unsafe { core::slice::$from_raw_parts($slice.$as_ptr(), $len) } }}; } #[inline] pub const fn slice_from(slice: &[T], start: usize) -> &[T] { crate::__slice_from_impl!(slice, start, as_ptr, from_raw_parts, &[]) } #[inline] pub const fn slice_up_to(slice: &[T], len: usize) -> &[T] { crate::__slice_up_to_impl!(slice, len, as_ptr, from_raw_parts, slice) } #[inline] pub const fn slice_range(slice: &[T], start: usize, end: usize) -> &[T] { slice_from(slice_up_to(slice, end), start) } konst_kernel-0.3.15/src/step_kk.rs000064400000000000000000000134741046102023000152160ustar 00000000000000use crate::{ chr, type_eq::{HasTypeWitness, MakeTypeWitness, TypeEq, TypeWitnessTypeArg}, }; use core::{marker::PhantomData, ops::RangeInclusive}; pub trait Step: HasTypeWitness> + Copy { /// The minimum value of the type. const MIN_VAL: Self; /// The maximum value of the type. const MAX_VAL: Self; // hack to emulate sealed traits #[doc(hidden)] const __PRIV_KO9Y329U2U: __Priv; } #[doc(hidden)] pub struct __Priv(PhantomData T>); pub(crate) struct StepRet { pub(crate) finished_inclusive: bool, pub(crate) finished_exclusive: bool, pub(crate) overflowed: bool, pub(crate) next: T, } type Pair = (T, T); crate::type_eq_projection_fn! { const fn teq_pair(T) -> Pair } crate::type_eq_projection_fn! { const fn teq_range_inclusive(T) -> RangeInclusive } macro_rules! declare_step_witness { ( $(($variant:ident, $type:ty, $kind:ident))* ) => { #[non_exhaustive] #[doc(hidden)] pub enum StepWitness { $( #[non_exhaustive] $variant { teq: TypeEq, }, )* } impl TypeWitnessTypeArg for StepWitness { type Arg = T; } $( impl Step for $type { const MIN_VAL: Self = get_min!($kind, $type); const MAX_VAL: Self = ::MAX; #[doc(hidden)] const __PRIV_KO9Y329U2U: __Priv = __Priv(PhantomData); } impl MakeTypeWitness for StepWitness<$type> { const MAKE: Self = Self::$variant { teq: TypeEq::NEW, }; } )* pub(crate) const fn increment(start: T, end: T) -> StepRet { match HasTypeWitness::WITNESS { $( StepWitness::$variant{teq, ..} => { let start = teq.to_right(start); let end = teq.to_right(end); code_for_step!($kind, increment, start, end, teq, to_left) } )* } } pub(crate) const fn decrement(start: T, end: T) -> StepRet { match HasTypeWitness::WITNESS { $( StepWitness::$variant{teq, ..} => { let start = teq.to_right(start); let end = teq.to_right(end); code_for_step!($kind, decrement, start, end, teq, to_left) } )* } } // needed to work around the fact that copying RangeInclusive's fields // requires that it's passed by reference, // it's not possible to call `.start()` or `.end()` on a `RangeInclusive` value. // // // To do it would require the `Frozen` trait (the "no internal mutability" trait) // is stabilized, then this function can be removed. pub(crate) const fn range_inclusive_into_inner( range: RangeInclusive, ) -> (T, T) { match HasTypeWitness::WITNESS { $( StepWitness::$variant{teq, ..} => { let range = teq_range_inclusive(teq).to_right(range); teq_pair(teq).to_left((*range.start(),*range.end())) } )* } } pub(crate) const fn range_inclusive_ref_into_inner( range: &RangeInclusive, ) -> (T, T) { (*range.start(), *range.end()) } }; } declare_step_witness! { (Usize, usize, int) (I32, i32, int) (U8, u8, int) (U32, u32, int) (I8, i8, int) (U16, u16, int) (U64, u64, int) (U128, u128, int) (I16, i16, int) (I64, i64, int) (I128, i128, int) (Isize, isize, int) (Char, char, char) } macro_rules! code_for_step { (char, increment, $start:ident, $end:ident, $teq:expr, $to_dir:ident) => {{ let (next_num, overflowed) = match $start as u32 { 0xD7FF => (0xE000, false), 0x10FFFF => (0, true), num => (num + 1, false), }; let next = crate::opt_unwrap!(chr::from_u32(next_num)); StepRet { finished_inclusive: $start > $end, finished_exclusive: $start >= $end, overflowed, next: $teq.$to_dir(next), } }}; (char, decrement, $start:ident, $end:ident, $teq:expr, $to_dir:ident) => {{ let (next_num, overflowed) = match $end as u32 { 0 => (0x10FFFF, true), 0xE000 => (0xD7FF, false), num => (num - 1, false), }; let next = crate::opt_unwrap!(chr::from_u32(next_num)); StepRet { finished_inclusive: $end < $start, finished_exclusive: $end <= $start, overflowed, next: $teq.$to_dir(next), } }}; (int, increment, $start:ident, $end:ident, $teq:expr, $to_dir:ident) => {{ let (next, overflowed) = $start.overflowing_add(1); StepRet { finished_inclusive: $start > $end, finished_exclusive: $start >= $end, overflowed, next: $teq.$to_dir(next), } }}; (int, decrement, $start:ident, $end:ident, $teq:expr, $to_dir:ident) => {{ let (next, overflowed) = $end.overflowing_sub(1); StepRet { finished_inclusive: $end < $start, finished_exclusive: $end <= $start, overflowed, next: $teq.$to_dir(next), } }}; } use code_for_step; macro_rules! get_min { (int, $ty:ty) => { <$ty>::MIN }; (char, $ty:ty) => { '\0' }; } use get_min; konst_kernel-0.3.15/src/string/string_for_konst.rs000064400000000000000000000157771046102023000204660ustar 00000000000000#![allow(clippy::len_without_is_empty)] use crate::chr::{encode_utf8, Utf8Encoded}; #[doc(hidden)] pub struct __NormalizeConcatArg(pub &'static [T]); impl __NormalizeConcatArg { pub const fn conv(self) -> __StrConcatArg { __StrConcatArg::Char(self.0) } } impl __NormalizeConcatArg<&'static str> { pub const fn conv(self) -> __StrConcatArg { __StrConcatArg::Str(self.0) } } #[doc(hidden)] #[derive(Copy, Clone)] pub enum __StrConcatArg { Char(&'static [char]), Str(&'static [&'static str]), } #[doc(hidden)] pub struct __MakeSepArg(pub T); #[doc(hidden)] #[derive(Copy, Clone)] pub enum __SepArg { Char(char), Str(&'static str), } impl __SepArg { const fn len(self) -> usize { match self { Self::Char(x) => x.len_utf8(), Self::Str(x) => x.len(), } } } #[doc(hidden)] pub struct __ElemDispatch(pub T); macro_rules! __ref_unref_impls { ($($ref_token:tt $deref_token:tt)?) => { impl __MakeSepArg<$($ref_token)? char> { pub const fn conv(self) -> __SepArg { __SepArg::Char($($deref_token)? self.0) } } impl __MakeSepArg<$($ref_token)? &'static str> { pub const fn conv(self) -> __SepArg { __SepArg::Str(self.0) } } impl __ElemDispatch<$($ref_token)? char> { pub const fn as_bytesable(self) -> Utf8Encoded { encode_utf8($($deref_token)? self.0) } pub const fn len(self) -> usize { self.0.len_utf8() } } impl __ElemDispatch<$($ref_token)? &'static str> { pub const fn as_bytesable(self) -> &'static str { self.0 } pub const fn len(self) -> usize { self.0.len() } } }; } __ref_unref_impls! {} __ref_unref_impls! {& *} #[doc(hidden)] #[macro_export] macro_rules! __with_str_concat_slices { ($arg:expr, |$slices:ident| $with_slices:expr) => { match $arg { $crate::string::__StrConcatArg::Char($slices) => $with_slices, $crate::string::__StrConcatArg::Str($slices) => $with_slices, } }; } //////////////////////////////////////////////////////////////////////////////// #[macro_export] macro_rules! string_concat { ($(&)? []) => { "" }; ($slice:expr $(,)*) => {{ const __ARGS_81608BFNA5: $crate::string::__StrConcatArg = $crate::string::__NormalizeConcatArg($slice).conv(); { const LEN: $crate::__::usize = $crate::string::concat_sum_lengths(__ARGS_81608BFNA5); const CONC: &$crate::string::ArrayStr = &$crate::string::concat_strs(__ARGS_81608BFNA5); const STR: &$crate::__::str = CONC.as_str(); STR } }}; } pub const fn concat_sum_lengths(arg: __StrConcatArg) -> usize { let mut sum = 0usize; __with_str_concat_slices! {arg, |slices| { crate::for_range! {i in 0..slices.len() => sum += __ElemDispatch(slices[i]).len(); } }} sum } pub const fn concat_strs(arg: __StrConcatArg) -> ArrayStr { let mut out = [0u8; N]; let mut out_i = 0usize; __with_str_concat_slices! {arg, |slices| { crate::for_range! {si in 0..slices.len() => let byteser = __ElemDispatch(slices[si]).as_bytesable(); let slice = byteser.as_bytes(); crate::for_range! {i in 0..slice.len() => out[out_i] = slice[i]; out_i += 1; } } }} ArrayStr(out) } //////////////////////////////////////////////////////////////////////////////// #[macro_export] macro_rules! string_join { ($sep:expr, $(&)? []) => { "" }; ($sep:expr, $slice:expr $(,)*) => {{ const __ARGS_81608BFNA5: $crate::string::StrJoinArgs = $crate::string::StrJoinArgs { sep: $crate::string::__MakeSepArg($sep).conv(), slice: $slice, }; { const LEN: $crate::__::usize = $crate::string::join_sum_lengths(__ARGS_81608BFNA5); const CONC: &$crate::string::ArrayStr = &$crate::string::join_strs(__ARGS_81608BFNA5); const STR: &$crate::__::str = CONC.as_str(); STR } }}; } #[derive(Copy, Clone)] pub struct StrJoinArgs { pub sep: __SepArg, pub slice: &'static [&'static str], } pub const fn join_sum_lengths(StrJoinArgs { sep, slice }: StrJoinArgs) -> usize { if slice.is_empty() { 0 } else { concat_sum_lengths(__StrConcatArg::Str(slice)) + sep.len() * (slice.len() - 1) } } pub const fn join_strs( StrJoinArgs { sep, slice: slices }: StrJoinArgs, ) -> ArrayStr { let mut out = [0u8; N]; let mut out_i = 0usize; let utf8e: Utf8Encoded; let sep = match sep { __SepArg::Char(c) => { utf8e = encode_utf8(c); utf8e.as_str() } __SepArg::Str(s) => s, }; macro_rules! write_str { ($str:expr) => {{ let slice = $str.as_bytes(); crate::for_range! {i in 0..slice.len() => out[out_i] = slice[i]; out_i += 1; } }}; } if let [first, rem_slices @ ..] = slices { write_str! {first} crate::for_range! {si in 0..rem_slices.len() => write_str!{sep} write_str!{rem_slices[si]} } } ArrayStr(out) } //////////////////////////////////////////////////////////////////////////////// #[macro_export] macro_rules! str_from_iter { ($($rem:tt)*) => {{ $crate::__collect_const_iter_with!{ $crate::__::u8, {}, |array, written_length, item| { let byteser = $crate::string::__ElemDispatch(item).as_bytesable(); let bytes = byteser.as_bytes(); let item_len = bytes.len(); let mut i = written_length; let mut j = 0; while j < item_len { array[i] = $crate::__::MaybeUninit::new(bytes[j]); i += 1; j += 1; } }, elem_length = { $crate::string::__ElemDispatch(item).len() }, => $($rem)* } const __STR81608BFNA5: &$crate::__::str = match core::str::from_utf8(&__ARR81608BFNA5) { $crate::__::Ok(x) => x, $crate::__::Err(_) => $crate::__::panic!("created string isn't UTF8"), }; __STR81608BFNA5 }} } //////////////////////////////////////////////////////////////////////////////// pub struct ArrayStr([u8; N]); impl ArrayStr { pub const fn as_str(&self) -> &str { match core::str::from_utf8(&self.0) { Ok(s) => s, Err(_) => panic!("bug: konst made an invalid string"), } } } konst_kernel-0.3.15/src/string.rs000064400000000000000000000066501046102023000150620ustar 00000000000000#[cfg(feature = "__for_konst")] pub mod string_for_konst; #[cfg(feature = "__for_konst")] pub use self::string_for_konst::*; #[inline] pub const fn str_up_to(string: &str, len: usize) -> &str { let bytes = string.as_bytes(); if __is_char_boundary_forgiving(bytes, len) { // Safety: __is_char_boundary_forgiving checks that `len` falls on a char boundary. unsafe { __from_u8_subslice_of_str(crate::slice::slice_up_to(bytes, len)) } } else { non_char_boundary_panic("index", len) } } #[inline] pub const fn str_from(string: &str, start: usize) -> &str { let bytes = string.as_bytes(); if __is_char_boundary_forgiving(bytes, start) { // Safety: __is_char_boundary_forgiving checks that `start` falls on a char boundary. unsafe { __from_u8_subslice_of_str(crate::slice::slice_from(bytes, start)) } } else { non_char_boundary_panic("start", start) } } #[inline] pub const fn str_range(string: &str, start: usize, end: usize) -> &str { let bytes = string.as_bytes(); let start_inbounds = __is_char_boundary_forgiving(bytes, start); if start_inbounds && __is_char_boundary_forgiving(bytes, end) { // Safety: __is_char_boundary_forgiving checks that // `start` and `end` fall on a char boundaries. unsafe { __from_u8_subslice_of_str(crate::slice::slice_range(bytes, start, end)) } } else if start_inbounds { non_char_boundary_panic("end", end) } else { non_char_boundary_panic("start", start) } } #[inline] pub const fn is_char_boundary(string: &str, position: usize) -> bool { __is_char_boundary_bytes(string.as_bytes(), position) } macro_rules! byte_is_char_boundary { ($b:expr) => { ($b as i8) >= -0x40 }; } #[doc(hidden)] #[inline] pub const fn __is_char_boundary_bytes(bytes: &[u8], position: usize) -> bool { position == bytes.len() || position < bytes.len() && byte_is_char_boundary!(bytes[position]) } #[inline] const fn __is_char_boundary_forgiving(bytes: &[u8], position: usize) -> bool { position >= bytes.len() || byte_is_char_boundary!(bytes[position]) } #[doc(hidden)] pub const fn __find_next_char_boundary(bytes: &[u8], mut position: usize) -> usize { loop { position += 1; if __is_char_boundary_forgiving(bytes, position) { break position; } } } #[doc(hidden)] pub const fn __find_prev_char_boundary(bytes: &[u8], mut position: usize) -> usize { position = position.saturating_sub(1); while !__is_char_boundary_forgiving(bytes, position) { position -= 1; } position } #[doc(hidden)] #[track_caller] pub const unsafe fn __from_u8_subslice_of_str(s: &[u8]) -> &str { #[cfg(any(feature = "debug", test))] if !s.is_empty() { if !byte_is_char_boundary!(s[0]) { panic!("string doesn't start at a byte boundary") } let cb = __find_prev_char_boundary(s, s.len() - 1); if let Err(_) = core::str::from_utf8(crate::slice::slice_from(s, cb)) { panic!("string doesn't end at a byte boundary") } } core::str::from_utf8_unchecked(s) } #[cold] #[track_caller] #[doc(hidden)] const fn non_char_boundary_panic(extreme: &str, index: usize) -> ! { use crate::utils::PanikVal; crate::utils::basic_panic(&[ PanikVal::Str(extreme), PanikVal::Str(" `"), PanikVal::Usize(index), PanikVal::Str("` is not on a char boundary"), ]) } konst_kernel-0.3.15/src/type_eq/make_project_fn.rs000064400000000000000000000225051046102023000203450ustar 00000000000000#[macro_export] macro_rules! type_eq_projection_fn { ( $(#[$attr:meta])* $vis:vis $(const $(@$is_const:ident@)?)? fn $function:ident ( $($type_param:ident)? $(, $param:ident $(@$L_R_from_ctx:ident@)?: TypeEq<$L:ident, $R:ident>)? ) -> $(:: $(@$c2:ident@)?)? $($type_name:ident)::* < $($gen_params:tt)* ) => { $crate::__mpf_assert_type_param_is_T!{ $($type_param)? } $crate::__::__make_projection_parse_generics!{ ( ( $(($(@$L_R_from_ctx@)?))? (__L, __R,) ) ( $(($param, $L, $R))? (_, __L, __R) ) ( $(#[$attr])* #[inline(always)] $vis $(const $($is_const)?)? fn $function ) ( $(:: $($c2)?)? $($type_name)::* ) ) () // generic parameter () // generic arguments ($($gen_params)*) } }; } macro_rules! __meta__make_projection_parse_generics { ( $_:tt repeat_punct( $(($punct:tt ($($prep:tt)*)))* ) ) => { #[doc(hidden)] #[macro_export] macro_rules! __make_projection_parse_generics { ( $fixed:tt $gen_params:tt $gen_args:tt ( > $_($rem:tt)*) ) => { $crate::__make_projection_fn!{ $fixed $gen_params $gen_args ($_($rem)*) } }; $(( $fixed:tt ($_($prev_gen_params:tt)*) ($_($prev_gen_args:tt)*) ( $lt_param:lifetime $_(: $_( $lt_bound:lifetime $_(+)? )* )? $punct $_($rem:tt)* ) ) => { $crate::__::__make_projection_parse_generics!{ $fixed ( $_($prev_gen_params)* $lt_param $_(: $_( $lt_bound + )* )? , ) ($_($prev_gen_args)* $lt_param,) ( $($prep)* $_($rem)* ) } };)* $(( $fixed:tt ($_($prev_gen_params:tt)*) ($_($prev_gen_args:tt)*) ( const $const_param:ident: $const_ty:ty $punct $_($rem:tt)* ) ) => { $crate::__::__make_projection_parse_generics!{ $fixed ($_($prev_gen_params)* const $const_param: $const_ty,) ($_($prev_gen_args)* $const_param,) ( $($prep)* $_($rem)* ) } };)* $(( ( (($_($declared_replacement_ty_params:tt)*) $_($ignored0:tt)*) $rep_ty_param:tt $prefix:tt $type_name:tt ) ($_($prev_gen_params:tt)*) ($_($prev_gen_args:tt)*) ( T $_(: $_( $lt_bound:lifetime $_(+)? )* $_( ( $_($ty_bounds:tt)* ) )? )? $punct $_($rem:tt)* ) )=>{ $_($_($crate::__mpf_assert_bound!{ $_($ty_bounds)* })?)? $crate::__::__make_projection_parse_generics!{ ( (($_($declared_replacement_ty_params)*) $_($ignored0)*) $rep_ty_param $prefix $type_name ) ( $_($prev_gen_params)* $_($declared_replacement_ty_params)* ) ( @replaced( $_( $_( $lt_bound + )* $_($_( $ty_bounds )*)? )? ); $_($prev_gen_args)* ; ) ( $($prep)* $_($rem)* ) } };)* $(( $fixed:tt ($_($prev_gen_params:tt)*) ($_($prev_gen_args:tt)*) ( $ty_param:ident $_(: $_( $lt_bound:lifetime $_(+)? )* $_( ( $_($ty_bounds:tt)* ) )? )? $punct $_($rem:tt)* ) )=>{ $_($_($crate::__mpf_assert_bound!{ $_($ty_bounds)* })?)? $crate::__::__make_projection_parse_generics!{ $fixed ( $_($prev_gen_params)* $ty_param $_(: $_( $lt_bound + )* $_($_( $ty_bounds )*)? )?, ) ($_($prev_gen_args)* $ty_param,) ( $($prep)* $_($rem)* ) } };)* ( $fixed:tt $prev_gen_params:tt $prev_gen_args:tt ( $ty_param:ident: $_( $lt_bound:lifetime $_(+)? )* $_(::)? $ident:ident $_($rem:tt)* ) )=>{ $crate::__::compile_error!{$crate::__::concat!( "trait bounds in parameter list must be wrapped in parentheses, context: `", stringify!($ty_param: $_( $lt_bound + )* $ident), "`", )} }; } #[doc(hidden)] pub use __make_projection_parse_generics; }; } __meta__make_projection_parse_generics! { $ repeat_punct( (, ()) (> (>)) ) } #[doc(hidden)] #[macro_export] macro_rules! __make_projection_fn { ( ( $ignored0:tt (($param:tt, $L:ident, $R:ident) $($ignored1:tt)*) ($($prefix:tt)*) ($($type_name:tt)*) ) ($($gen_params:tt)*) ( $(@replaced($($rep_ty_bound:tt)*);)* $($lt_arg:lifetime,)* $($gen_arg_before:ident,)* $(;$($gen_arg_after:ident,)*)? ) ( $(where $($where_preds:tt)* )? ) ) => { $crate::__assert_replaced_type_param_and_where_clause!{ ($(@replaced($($rep_ty_bound)*);)*) ($( $($where_preds)* )?) $($prefix)* <$($gen_params)*> ( param: $crate::__::TypeEq<$L, $R> ) -> $crate::__::TypeEq< $($type_name)* <$($lt_arg,)* $($gen_arg_before,)* $L, $($($gen_arg_after,)*)?>, $($type_name)* <$($lt_arg,)* $($gen_arg_before,)* $R, $($($gen_arg_after,)*)?>, > where $L: $($($rep_ty_bound)*)?, $R: $($($rep_ty_bound)*)?, $($($where_preds)*)? { struct __Projector($crate::__::PhantomData); impl<$($gen_params)*> $crate::__::TypeFn<$L> for __Projector< $($type_name)* < $($lt_arg,)* $($gen_arg_before,)* $R, $($($gen_arg_after,)*)? >, > where $L: $($($rep_ty_bound)*)?, $R: $($($rep_ty_bound)*)?, $($($where_preds)*)? { type Output = $($type_name)* < $($lt_arg,)* $($gen_arg_before,)* $L, $($($gen_arg_after,)*)? >; } param.project::< __Projector< $($type_name)* < $($lt_arg,)* $($gen_arg_before,)* $R, $($($gen_arg_after,)*)? > > >() } } }; ($($tt:tt)*) => { $crate::__::compile_error!{ $crate::__::stringify!{$($tt)*} } }; } #[doc(hidden)] #[macro_export] macro_rules! __assert_replaced_type_param_and_where_clause { (() $where:tt $($token:tt)*) => { $crate::__::compile_error!{ "expected a `T` type parameter in the return type" } }; ( (@replaced($($rep_ty_bound:tt)*);) ( $($wc_lt:lifetime: $( $wc_lt_bound:lifetime $(+)? )*),* $(,)? $($wc_ty:ty : $($wc_ty_lt:lifetime $(+)?)* $($wc_ty_bound:path)?),* $(,)? ) $($token:tt)* ) => { $($token)* }; ( $replaced:tt $where:tt $($token:tt)* ) => { $crate::__::compile_error!{"invalid where clause syntax"} } } #[doc(hidden)] #[macro_export] macro_rules! __mpf_assert_bound { ($bound:ty) => {}; } #[doc(hidden)] #[macro_export] macro_rules! __mpf_assert_type_param_is_T { (T) => {}; ($($tt:tt)*) => { $crate::__::compile_error!{$crate::__::concat!( "expected function parameter to be `T`, found: `", $crate::__::stringify!($($tt)*), "`", )} }; } konst_kernel-0.3.15/src/type_eq.rs000064400000000000000000000002211046102023000152060ustar 00000000000000#[cfg(feature = "__for_konst")] pub(crate) mod make_project_fn; pub use typewit::{HasTypeWitness, MakeTypeWitness, TypeEq, TypeWitnessTypeArg}; konst_kernel-0.3.15/src/utils/utils_tests.rs000064400000000000000000000030041046102023000172640ustar 00000000000000use super::{approx_log10, PanikVal, CAP}; type ArrString = arrayvec::ArrayString; fn get_numbers() -> impl Iterator { (0..) .map_while(|pow| 10usize.checked_pow(pow)) .chain((2..).map_while(|pow| 2usize.checked_pow(pow))) .chain([usize::MAX]) .flat_map(|x| x.saturating_sub(2)..=x.saturating_add(2)) } #[test] fn approx_log10_test() { use core::fmt::Write; let mut buff = ArrString::new(); for n in get_numbers() { buff.clear(); write!(buff, "{n}").unwrap(); let log10 = approx_log10(n); let len = buff.len() as u32; assert!(len <= log10, "{len} <= {log10}"); } } #[test] fn fmt_numbers() { for number in get_numbers() { for (prefix, suffix) in [ ("", ""), ("-", ""), ("-", "-"), ("", "-"), ("prefix", "suffix"), ] { let actual = test_fmt_conc(&[ PanikVal::Str(prefix), PanikVal::Usize(number), PanikVal::Str(suffix), ]); let expected = ArrString::try_from(format_args!("{prefix}{number}{suffix}")).unwrap(); assert_eq!(actual, expected) } } } #[cfg(test)] fn test_fmt_conc(slice: &[PanikVal<'_>]) -> ArrString { let arr = super::fmt_conc(slice); let mut ret = ArrString::new(); core::str::from_utf8(&arr) .unwrap() .chars() .filter(|x| *x != '\0') .for_each(|c| ret.push(c)); ret } konst_kernel-0.3.15/src/utils.rs000064400000000000000000000162161046102023000147130ustar 00000000000000#[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 { pub val: T, } //////////////////////////////////////////////////////////////////////////////// #[doc(hidden)] #[repr(C)] pub union Dereference<'a, T: ?Sized> { pub ptr: *const T, pub reff: &'a T, } #[doc(hidden)] #[macro_export] macro_rules! __parse_closure_2 { ( $macro:tt $args:tt $usage_site:tt, || $(,)? ) => { $crate::__parse_closure_no_expr_error!{$usage_site} }; ( $macro:tt $args:tt $usage_site:tt, |$pat1:tt $(: $pat1_ty:ty)?, $pat2:tt $(: $pat2_ty:ty)? $(,)?| $($rem:tt)* ) => ( $crate::__parse_closure_expr! { $usage_site $macro $args ( ($crate::__unparen_pat!($pat1), $crate::__unparen_pat!($pat2)): ($crate::__ty_or_und!($($pat1_ty)?), $crate::__ty_or_und!($($pat2_ty)?)) ), $($rem)* } ); ( $macro:tt $args:tt $usage_site:tt, |$pat1:pat_param, $pat2:pat_param $(,)?| $($rem:tt)* ) => ( $crate::__parse_closure_expr! { $usage_site $macro $args (($pat1, $pat2)), $($rem)* } ); ($macro:tt $args:tt $usage_site:tt, | $($anything:tt)* ) => { $crate::__parse_closure_emit_error!{2 $usage_site} }; ($macro:tt $args:tt $usage_site:tt, || $($anything:tt)* ) => { $crate::__parse_closure_emit_error!{2 $usage_site} }; ( ($($macro:tt)*) ($($args:tt)*) $usage_site:tt, $v:expr $(,)? ) => { match $v {func => { $($macro)* ! { $($args)* ((__x, __y)) -> _ {func(__x, __y)} } }} }; ($macro:tt $args:tt $usage_site:tt $($rem:tt)*) => { $crate::__parse_closure_emit_error!{2 $usage_site} }; ( $($anything:tt)* ) => { $crate::__::compile_error!("expected a closure argument") }; } pub use __parse_closure_2; //////////////////////////////////////////////////////////////////////////////////// #[doc(hidden)] #[macro_export] macro_rules! __parse_closure_1 { ( $macro:tt $args:tt $usage_site:tt, || $(,)? ) => { $crate::__parse_closure_no_expr_error!{$usage_site} }; ( $macro:tt $args:tt $usage_site:tt, |$pat:tt $(: $pat_ty:ty)? $(,)?| $($rem:tt)* ) => ( $crate::__parse_closure_expr! { $usage_site $macro $args ($pat $(: $pat_ty)?), $($rem)* } ); ( $macro:tt $args:tt $usage_site:tt, |$pat:pat_param $(,)?| $($rem:tt)* ) => ( $crate::__parse_closure_expr! { $usage_site $macro $args ($pat), $($rem)* } ); ($macro:tt $args:tt $usage_site:tt, | $($anything:tt)* ) => { $crate::__parse_closure_emit_error!{1 $usage_site} }; ($macro:tt $args:tt $usage_site:tt, || $($anything:tt)* ) => { $crate::__parse_closure_emit_error!{1 $usage_site} }; ( ($($macro:tt)*) ($($args:tt)*) $usage_site:tt, $v:expr $(,)? ) => { match $v {func => { $($macro)* ! { $($args)* (__x) -> _ {func(__x)} } }} }; ($macro:tt $args:tt $usage_site:tt $($rem:tt)*) => { $crate::__parse_closure_emit_error!{1 $usage_site} }; ( $($anything:tt)* ) => { $crate::__::compile_error!("expected a closure argument") }; } pub use __parse_closure_1; #[doc(hidden)] #[macro_export] macro_rules! __parse_closure_expr { ( $usage_site:tt ($($macro:tt)*) ($($args:tt)*) ($($pattern:tt)*), $(,)? ) => { $crate::__parse_closure_no_expr_error!{$usage_site} }; ( $usage_site:tt ($($macro:tt)*) ($($args:tt)*) $pattern:tt, $v:expr $(, $($rem:expr $(, $($rem_tt:tt)*)? )? )? ) => ({ $($( $crate::__parse_closure_trailing_expr_error!{$usage_site $rem} )?)? $($macro)* ! { $($args)* $pattern { $v } } }); ( $usage_site:tt ($($macro:tt)*) ($($args:tt)*) $pattern:tt, -> $ret_ty:ty $v:block $(, $($rem:expr $(, $($rem_tt:tt)*)? )? )? ) => ({ $($( $crate::__parse_closure_trailing_expr_error!{$usage_site $rem} )?)? $($macro)* ! { $($args)* $pattern -> $ret_ty { $v } } }); } //////////////////////////////////////////////////////////////////////////////////// #[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", )} }; }