1#![feature(negative_impls)]
2#![feature(auto_traits)]
3#![feature(maybe_uninit_uninit_array)]
4#![feature(slice_index_methods)]
5#![feature(min_specialization)]
6#![feature(const_copy_from_slice)]
7#![feature(const_trait_impl)]
8#![cfg_attr(feature = "std", feature(new_zeroed_alloc))]
9#![feature(allocator_api)]
10#![cfg_attr(test, feature(test))]
11#![cfg_attr(not(feature = "std"), no_std)]
12#![doc = include_str!("../README.md")]
13
14#[cfg(test)]
15extern crate self as fastbuf;
16#[cfg(test)]
17extern crate test;
18
19#[cfg(not(feature = "std"))]
20extern crate core as std;
21
22mod traits;
23pub use traits::*;
24
25mod buffer;
26pub use buffer::*;
27
28mod chunk;
29
30#[cfg(not(feature = "std"))]
31pub(crate) struct EmptyAlloc;
32
33#[cfg(not(feature = "std"))]
34unsafe impl std::alloc::Allocator for EmptyAlloc {
35 fn allocate(
36 &self,
37 _layout: std::alloc::Layout,
38 ) -> Result<std::ptr::NonNull<[u8]>, std::alloc::AllocError> {
39 unreachable!()
40 }
41
42 unsafe fn deallocate(&self, _ptr: std::ptr::NonNull<u8>, _layout: std::alloc::Layout) {
43 unreachable!()
44 }
45}
46
47pub(crate) mod macros {
48
49 #[macro_export]
50 macro_rules! declare_const_fn {
51 ($(#[$($attrs:tt)*])* $visibility:vis fn $($tokens:tt)*) => {
52 #[cfg(feature = "const-trait")]
53 $(#[$($attrs)*])*
54 $visibility const fn $($tokens)*
55
56 #[cfg(not(feature = "const-trait"))]
57 $visibility fn $($tokens)*
58 };
59 }
60
61 #[macro_export]
62 macro_rules! declare_const_trait {
63 ($visibility:vis trait $name:ident<($($generics:tt)*)>
64 : const ($($const_supertrait:path),*), ($($supertrait:path),*) {$($body:tt)*}) => {
65 #[cfg(not(feature = "const-trait"))]
66 $visibility trait $name<$($generics)*>: $($const_supertrait +)* $($supertrait + )* {
67 $($body)*
68 }
69
70 #[cfg(feature = "const-trait")]
71 #[const_trait]
72 $visibility trait $name<$($generics)*>: $(const $const_supertrait +)* $($supertrait + )* {
73 $($body)*
74 }
75 };
76 }
77
78 #[macro_export]
79 macro_rules! declare_const_impl {
80 (($($impl:tt)*), ($($impl_const:tt)*) {$($body:tt)*}) => {
81 #[cfg(feature = "const-trait")]
82 $($impl_const)* { $($body)* }
83
84 #[cfg(not(feature = "const-trait"))]
85 $($impl)* { $($body)* }
86 };
87 }
88
89 #[cfg(feature = "const-trait")]
90 #[macro_export]
91 macro_rules! const_min {
92 ($a:expr, $b:expr) => {
93 if $a > $b {
94 $b
95 } else {
96 $a
97 }
98 };
99 }
100
101 #[cfg(not(feature = "const-trait"))]
102 #[macro_export]
103 macro_rules! const_min {
104 ($a:expr, $b:expr) => {
105 core::cmp::min($a, $b)
106 };
107 }
108}
109
110macro_rules! unsafe_wild_copy {
117 ([$T:ident; $N:ident], $src:ident, $dst:ident, $n:ident) => {
119 debug_assert!($n != 0 && $n <= $N);
120
121 let page_size = 4096;
122 let read_size = core::mem::size_of::<[$T; $N]>();
123 let within_page = $src as usize & (page_size - 1) < (page_size - read_size) && cfg!(all(
124 not(miri),
126 not(debug_assertions),
129 any(target_arch = "x86", target_arch = "x86_64", target_arch = "aarch64")
132 ));
133
134 if within_page {
135 *($dst as *mut core::mem::MaybeUninit<[$T; $N]>) = core::ptr::read($src as *const core::mem::MaybeUninit<[$T; $N]>);
136 } else {
137 $src.copy_to_nonoverlapping($dst, $n);
138 }
139 }
140}
141pub(crate) use unsafe_wild_copy;