1macro_rules! unsafe_impl {
23 ($(#[$attr:meta])* $ty:ty: $trait:ident $(; |$candidate:ident| $is_bit_valid:expr)?) => {{
25 crate::util::macros::__unsafe();
26
27 $(#[$attr])*
28 unsafe impl $trait for $ty {
30 unsafe_impl!(@method $trait $(; |$candidate| $is_bit_valid)?);
31 }
32 }};
33
34 ($(#[$attrs:meta])* $ty:ty: $($traits:ident),*) => {
53 unsafe_impl!(@impl_traits_with_packed_attrs { $(#[$attrs])* } $ty: $($traits),*)
54 };
55
56 (@impl_traits_with_packed_attrs $attrs:tt $ty:ty: $($traits:ident),*) => {{
57 $( unsafe_impl!(@unpack_attrs $attrs $ty: $traits); )*
58 }};
59
60 (@unpack_attrs { $(#[$attrs:meta])* } $ty:ty: $traits:ident) => {
61 unsafe_impl!($(#[$attrs])* $ty: $traits);
62 };
63
64 (
90 $(#[$attr:meta])*
91 const $constname:ident : $constty:ident $(,)?
92 $($tyvar:ident $(: $(? $optbound:ident $(+)?)* $($bound:ident $(+)?)* )?),*
93 => $trait:ident for $ty:ty $(; |$candidate:ident| $is_bit_valid:expr)?
94 ) => {
95 unsafe_impl!(
96 @inner
97 $(#[$attr])*
98 @const $constname: $constty,
99 $($tyvar $(: $(? $optbound +)* + $($bound +)*)?,)*
100 => $trait for $ty $(; |$candidate| $is_bit_valid)?
101 );
102 };
103 (
104 $(#[$attr:meta])*
105 $($tyvar:ident $(: $(? $optbound:ident $(+)?)* $($bound:ident $(+)?)* )?),*
106 => $trait:ident for $ty:ty $(; |$candidate:ident| $is_bit_valid:expr)?
107 ) => {{
108 unsafe_impl!(
109 @inner
110 $(#[$attr])*
111 $($tyvar $(: $(? $optbound +)* + $($bound +)*)?,)*
112 => $trait for $ty $(; |$candidate| $is_bit_valid)?
113 );
114 }};
115 (
116 @inner
117 $(#[$attr:meta])*
118 $(@const $constname:ident : $constty:ident,)*
119 $($tyvar:ident $(: $(? $optbound:ident +)* + $($bound:ident +)* )?,)*
120 => $trait:ident for $ty:ty $(; |$candidate:ident| $is_bit_valid:expr)?
121 ) => {{
122 crate::util::macros::__unsafe();
123
124 $(#[$attr])*
125 #[allow(non_local_definitions)]
126 unsafe impl<$($tyvar $(: $(? $optbound +)* $($bound +)*)?),* $(, const $constname: $constty,)*> $trait for $ty {
128 unsafe_impl!(@method $trait $(; |$candidate| $is_bit_valid)?);
129 }
130 }};
131
132 (@method TryFromBytes ; |$candidate:ident| $is_bit_valid:expr) => {
133 #[allow(clippy::missing_inline_in_public_items, dead_code)]
134 #[cfg_attr(all(coverage_nightly, __ZEROCOPY_INTERNAL_USE_ONLY_NIGHTLY_FEATURES_IN_TESTS), coverage(off))]
135 fn only_derive_is_allowed_to_implement_this_trait() {}
136
137 #[inline]
138 fn is_bit_valid<Alignment>($candidate: Maybe<'_, Self, Alignment>) -> bool
139 where
140 Alignment: crate::invariant::Alignment,
141 {
142 $is_bit_valid
143 }
144 };
145 (@method TryFromBytes) => {
146 #[allow(clippy::missing_inline_in_public_items)]
147 #[cfg_attr(all(coverage_nightly, __ZEROCOPY_INTERNAL_USE_ONLY_NIGHTLY_FEATURES_IN_TESTS), coverage(off))]
148 fn only_derive_is_allowed_to_implement_this_trait() {}
149 #[inline(always)]
150 fn is_bit_valid<Alignment>(_candidate: Maybe<'_, Self, Alignment>) -> bool
151 where
152 Alignment: crate::invariant::Alignment,
153 {
154 true
155 }
156 };
157 (@method $trait:ident) => {
158 #[allow(clippy::missing_inline_in_public_items, dead_code)]
159 #[cfg_attr(all(coverage_nightly, __ZEROCOPY_INTERNAL_USE_ONLY_NIGHTLY_FEATURES_IN_TESTS), coverage(off))]
160 fn only_derive_is_allowed_to_implement_this_trait() {}
161 };
162 (@method $trait:ident; |$_candidate:ident| $_is_bit_valid:expr) => {
163 compile_error!("Can't provide `is_bit_valid` impl for trait other than `TryFromBytes`");
164 };
165}
166
167macro_rules! impl_for_transmute_from {
173 (
174 $(#[$attr:meta])*
175 $($tyvar:ident $(: $(? $optbound:ident $(+)?)* $($bound:ident $(+)?)* )?)?
176 => $trait:ident for $ty:ty [$repr:ty]
177 ) => {
178 const _: () = {
179 $(#[$attr])*
180 #[allow(non_local_definitions)]
181
182 unsafe impl<$($tyvar $(: $(? $optbound +)* $($bound +)*)?)?> $trait for $ty {
191 #[allow(dead_code, clippy::missing_inline_in_public_items)]
192 #[cfg_attr(all(coverage_nightly, __ZEROCOPY_INTERNAL_USE_ONLY_NIGHTLY_FEATURES_IN_TESTS), coverage(off))]
193 fn only_derive_is_allowed_to_implement_this_trait() {
194 use crate::pointer::{*, invariant::Valid};
195
196 impl_for_transmute_from!(@assert_is_supported_trait $trait);
197
198 fn is_trait<T, R>()
199 where
200 T: TransmuteFrom<R, Valid, Valid> + ?Sized,
201 R: TransmuteFrom<T, Valid, Valid> + ?Sized,
202 R: $trait,
203 {
204 }
205
206 #[cfg_attr(all(coverage_nightly, __ZEROCOPY_INTERNAL_USE_ONLY_NIGHTLY_FEATURES_IN_TESTS), coverage(off))]
207 fn f<$($tyvar $(: $(? $optbound +)* $($bound +)*)?)?>() {
208 is_trait::<$ty, $repr>();
209 }
210 }
211
212 impl_for_transmute_from!(
213 @is_bit_valid
214 $(<$tyvar $(: $(? $optbound +)* $($bound +)*)?>)?
215 $trait for $ty [$repr]
216 );
217 }
218 };
219 };
220 (@assert_is_supported_trait TryFromBytes) => {};
221 (@assert_is_supported_trait FromZeros) => {};
222 (@assert_is_supported_trait FromBytes) => {};
223 (@assert_is_supported_trait IntoBytes) => {};
224 (
225 @is_bit_valid
226 $(<$tyvar:ident $(: $(? $optbound:ident $(+)?)* $($bound:ident $(+)?)* )?>)?
227 TryFromBytes for $ty:ty [$repr:ty]
228 ) => {
229 #[inline(always)]
230 fn is_bit_valid<Alignment>(candidate: $crate::Maybe<'_, Self, Alignment>) -> bool
231 where
232 Alignment: $crate::invariant::Alignment,
233 {
234 <$repr as TryFromBytes>::is_bit_valid(candidate.transmute::<_, _, BecauseImmutable>())
238 }
239 };
240 (
241 @is_bit_valid
242 $(<$tyvar:ident $(: $(? $optbound:ident $(+)?)* $($bound:ident $(+)?)* )?>)?
243 $trait:ident for $ty:ty [$repr:ty]
244 ) => {
245 };
247}
248
249macro_rules! unsafe_impl_for_power_set {
268 (
269 $first:ident $(, $rest:ident)* $(-> $ret:ident)? => $trait:ident for $macro:ident!(...)
270 $(; |$candidate:ident| $is_bit_valid:expr)?
271 ) => {
272 unsafe_impl_for_power_set!(
273 $($rest),* $(-> $ret)? => $trait for $macro!(...)
274 $(; |$candidate| $is_bit_valid)?
275 );
276 unsafe_impl_for_power_set!(
277 @impl $first $(, $rest)* $(-> $ret)? => $trait for $macro!(...)
278 $(; |$candidate| $is_bit_valid)?
279 );
280 };
281 (
282 $(-> $ret:ident)? => $trait:ident for $macro:ident!(...)
283 $(; |$candidate:ident| $is_bit_valid:expr)?
284 ) => {
285 unsafe_impl_for_power_set!(
286 @impl $(-> $ret)? => $trait for $macro!(...)
287 $(; |$candidate| $is_bit_valid)?
288 );
289 };
290 (
291 @impl $($vars:ident),* $(-> $ret:ident)? => $trait:ident for $macro:ident!(...)
292 $(; |$candidate:ident| $is_bit_valid:expr)?
293 ) => {
294 unsafe_impl!(
295 $($vars,)* $($ret)? => $trait for $macro!($($vars),* $(-> $ret)?)
296 $(; |$candidate| $is_bit_valid)?
297 );
298 };
299}
300
301macro_rules! opt_extern_c_fn {
304 ($($args:ident),* -> $ret:ident) => { Option<extern "C" fn($($args),*) -> $ret> };
305}
306
307macro_rules! opt_unsafe_extern_c_fn {
310 ($($args:ident),* -> $ret:ident) => { Option<unsafe extern "C" fn($($args),*) -> $ret> };
311}
312
313macro_rules! opt_fn {
316 ($($args:ident),* -> $ret:ident) => { Option<fn($($args),*) -> $ret> };
317}
318
319macro_rules! opt_unsafe_fn {
322 ($($args:ident),* -> $ret:ident) => { Option<unsafe fn($($args),*) -> $ret> };
323}
324
325#[allow(rustdoc::private_intra_doc_links)]
328#[cfg_attr(__ZEROCOPY_INTERNAL_USE_ONLY_DEV_MODE, macro_export)] #[doc(hidden)]
379macro_rules! impl_or_verify {
380 (
384 const $constname:ident : $constty:ident $(,)?
385 $($tyvar:ident $(: $(? $optbound:ident $(+)?)* $($bound:ident $(+)?)* )?),*
386 => $trait:ident for $ty:ty
387 ) => {
388 impl_or_verify!(@impl { unsafe_impl!(
389 const $constname: $constty, $($tyvar $(: $(? $optbound +)* $($bound +)*)?),* => $trait for $ty
390 ); });
391 impl_or_verify!(@verify $trait, {
392 impl<const $constname: $constty, $($tyvar $(: $(? $optbound +)* $($bound +)*)?),*> Subtrait for $ty {}
393 });
394 };
395 (
396 $($tyvar:ident $(: $(? $optbound:ident $(+)?)* $($bound:ident $(+)?)* )?),*
397 => $trait:ident for $ty:ty $(; |$candidate:ident| $is_bit_valid:expr)?
398 ) => {
399 impl_or_verify!(@impl { unsafe_impl!(
400 $($tyvar $(: $(? $optbound +)* $($bound +)*)?),* => $trait for $ty
401 $(; |$candidate| $is_bit_valid)?
402 ); });
403 impl_or_verify!(@verify $trait, {
404 impl<$($tyvar $(: $(? $optbound +)* $($bound +)*)?),*> Subtrait for $ty {}
405 });
406 };
407 (@impl $impl_block:tt) => {
408 #[cfg(not(any(feature = "derive", test)))]
409 { $impl_block };
410 };
411 (@verify $trait:ident, $impl_block:tt) => {
412 #[cfg(any(feature = "derive", test))]
413 {
414 #[allow(dead_code)]
417 trait Subtrait: $trait {}
418 $impl_block
419 };
420 };
421}
422
423macro_rules! impl_known_layout {
425 ($(const $constvar:ident : $constty:ty, $tyvar:ident $(: ?$optbound:ident)? => $ty:ty),* $(,)?) => {
426 $(impl_known_layout!(@inner const $constvar: $constty, $tyvar $(: ?$optbound)? => $ty);)*
427 };
428 ($($tyvar:ident $(: ?$optbound:ident)? => $ty:ty),* $(,)?) => {
429 $(impl_known_layout!(@inner , $tyvar $(: ?$optbound)? => $ty);)*
430 };
431 ($($(#[$attrs:meta])* $ty:ty),*) => { $(impl_known_layout!(@inner , => $(#[$attrs])* $ty);)* };
432 (@inner $(const $constvar:ident : $constty:ty)? , $($tyvar:ident $(: ?$optbound:ident)?)? => $(#[$attrs:meta])* $ty:ty) => {
433 const _: () = {
434 use core::ptr::NonNull;
435
436 #[allow(non_local_definitions)]
437 $(#[$attrs])*
438 unsafe impl<$($tyvar $(: ?$optbound)?)? $(, const $constvar : $constty)?> KnownLayout for $ty {
440 #[allow(clippy::missing_inline_in_public_items)]
441 #[cfg_attr(all(coverage_nightly, __ZEROCOPY_INTERNAL_USE_ONLY_NIGHTLY_FEATURES_IN_TESTS), coverage(off))]
442 fn only_derive_is_allowed_to_implement_this_trait() where Self: Sized {}
443
444 type PointerMetadata = ();
445
446 type MaybeUninit = core::mem::MaybeUninit<Self>;
456
457 const LAYOUT: crate::DstLayout = crate::DstLayout::for_type::<$ty>();
458
459 #[inline(always)]
464 fn raw_from_ptr_len(bytes: NonNull<u8>, _meta: ()) -> NonNull<Self> {
465 bytes.cast::<Self>()
466 }
467
468 #[inline(always)]
469 fn pointer_to_metadata(_ptr: *mut Self) -> () {
470 }
471 }
472 };
473 };
474}
475
476macro_rules! unsafe_impl_known_layout {
488 ($($tyvar:ident: ?Sized + KnownLayout =>)? #[repr($repr:ty)] $ty:ty) => {{
489 use core::ptr::NonNull;
490
491 crate::util::macros::__unsafe();
492
493 #[allow(non_local_definitions)]
494 unsafe impl<$($tyvar: ?Sized + KnownLayout)?> KnownLayout for $ty {
496 #[allow(clippy::missing_inline_in_public_items, dead_code)]
497 #[cfg_attr(all(coverage_nightly, __ZEROCOPY_INTERNAL_USE_ONLY_NIGHTLY_FEATURES_IN_TESTS), coverage(off))]
498 fn only_derive_is_allowed_to_implement_this_trait() {}
499
500 type PointerMetadata = <$repr as KnownLayout>::PointerMetadata;
501 type MaybeUninit = <$repr as KnownLayout>::MaybeUninit;
502
503 const LAYOUT: DstLayout = <$repr as KnownLayout>::LAYOUT;
504
505 #[inline(always)]
511 fn raw_from_ptr_len(bytes: NonNull<u8>, meta: <$repr as KnownLayout>::PointerMetadata) -> NonNull<Self> {
512 #[allow(clippy::as_conversions)]
513 let ptr = <$repr>::raw_from_ptr_len(bytes, meta).as_ptr() as *mut Self;
514 unsafe { NonNull::new_unchecked(ptr) }
516 }
517
518 #[inline(always)]
519 fn pointer_to_metadata(ptr: *mut Self) -> Self::PointerMetadata {
520 #[allow(clippy::as_conversions)]
521 let ptr = ptr as *mut $repr;
522 <$repr>::pointer_to_metadata(ptr)
523 }
524 }
525 }};
526}
527
528macro_rules! assert_unaligned {
533 ($($tys:ty),*) => {
534 $(
535 #[cfg(test)]
539 static_assertions::const_assert_eq!(core::mem::align_of::<$tys>(), 1);
540 )*
541 };
542}
543
544macro_rules! maybe_const_trait_bounded_fn {
548 ($(#[$attr:meta])* $vis:vis const fn $name:ident($($args:ident $(: $arg_tys:ty)?),* $(,)?) $(-> $ret_ty:ty)? $body:block) => {
552 #[cfg(not(no_zerocopy_generic_bounds_in_const_fn_1_61_0))]
553 $(#[$attr])* $vis const fn $name($($args $(: $arg_tys)?),*) $(-> $ret_ty)? $body
554
555 #[cfg(no_zerocopy_generic_bounds_in_const_fn_1_61_0)]
556 $(#[$attr])* $vis fn $name($($args $(: $arg_tys)?),*) $(-> $ret_ty)? $body
557 };
558}
559
560macro_rules! const_panic {
567 (@non_panic $($_arg:tt)+) => {{
568 let panic: [_; 0] = [];
571 #[allow(unconditional_panic)]
573 panic[0]
574 }};
575 ($($arg:tt)+) => {{
576 #[cfg(not(no_zerocopy_panic_in_const_and_vec_try_reserve_1_57_0))]
577 panic!($($arg)+);
578 #[cfg(no_zerocopy_panic_in_const_and_vec_try_reserve_1_57_0)]
579 const_panic!(@non_panic $($arg)+)
580 }};
581}
582
583macro_rules! const_assert {
588 ($e:expr) => {{
589 #[cfg(not(no_zerocopy_panic_in_const_and_vec_try_reserve_1_57_0))]
590 assert!($e);
591 #[cfg(no_zerocopy_panic_in_const_and_vec_try_reserve_1_57_0)]
592 {
593 let e = $e;
594 if !e {
595 let _: () = const_panic!(@non_panic concat!("assertion failed: ", stringify!($e)));
596 }
597 }
598 }};
599 ($e:expr, $($args:tt)+) => {{
600 #[cfg(not(no_zerocopy_panic_in_const_and_vec_try_reserve_1_57_0))]
601 assert!($e, $($args)+);
602 #[cfg(no_zerocopy_panic_in_const_and_vec_try_reserve_1_57_0)]
603 {
604 let e = $e;
605 if !e {
606 let _: () = const_panic!(@non_panic concat!("assertion failed: ", stringify!($e), ": ", stringify!($arg)), $($args)*);
607 }
608 }
609 }};
610}
611
612macro_rules! const_debug_assert {
614 ($e:expr $(, $msg:expr)?) => {{
615 #[cfg(not(no_zerocopy_panic_in_const_and_vec_try_reserve_1_57_0))]
616 debug_assert!($e $(, $msg)?);
617 #[cfg(no_zerocopy_panic_in_const_and_vec_try_reserve_1_57_0)]
618 {
619 if cfg!(debug_assertions) {
623 let e = $e;
624 if !e {
625 let _: () = const_panic!(@non_panic concat!("assertion failed: ", stringify!($e) $(, ": ", $msg)?));
626 }
627 }
628 }
629 }}
630}
631
632macro_rules! const_unreachable {
635 () => {{
636 #[cfg(not(no_zerocopy_panic_in_const_and_vec_try_reserve_1_57_0))]
637 unreachable!();
638
639 #[cfg(no_zerocopy_panic_in_const_and_vec_try_reserve_1_57_0)]
640 loop {}
641 }};
642}
643
644macro_rules! static_assert {
649 (Self $(: $(? $optbound:ident $(+)?)* $($bound:ident $(+)?)* )? => $condition:expr $(, $args:tt)*) => {{
650 trait StaticAssert {
651 const ASSERT: bool;
652 }
653
654 impl<T $(: $(? $optbound +)* $($bound +)*)?> StaticAssert for T {
655 const ASSERT: bool = {
656 const_assert!($condition $(, $args)*);
657 $condition
658 };
659 }
660
661 const_assert!(<Self as StaticAssert>::ASSERT);
662 }};
663 ($($tyvar:ident $(: $(? $optbound:ident $(+)?)* $($bound:ident $(+)?)* )?),* => $condition:expr $(, $args:tt)*) => {{
664 trait StaticAssert {
665 const ASSERT: bool;
666 }
667
668 impl<$($tyvar $(: $(? $optbound +)* $($bound +)*)?,)*> StaticAssert for ($(core::marker::PhantomData<$tyvar>,)*) {
670 const ASSERT: bool = {
671 const_assert!($condition $(, $args)*);
672 $condition
673 };
674 }
675
676 const_assert!(<($(core::marker::PhantomData<$tyvar>,)*) as StaticAssert>::ASSERT);
677 }};
678}
679
680macro_rules! static_assert_dst_is_not_zst {
683 ($tyvar:ident) => {{
684 use crate::KnownLayout;
685 static_assert!($tyvar: ?Sized + KnownLayout => {
686 let dst_is_zst = match $tyvar::LAYOUT.size_info {
687 crate::SizeInfo::Sized { .. } => false,
688 crate::SizeInfo::SliceDst(TrailingSliceLayout { elem_size, .. }) => {
689 elem_size == 0
690 }
691 };
692 !dst_is_zst
693 }, "cannot call this method on a dynamically-sized type whose trailing slice element is zero-sized");
694 }}
695}
696
697#[macro_export]
706#[doc(hidden)]
707macro_rules! define_cast {
708 (unsafe { $vis:vis $name:ident $(<$tyvar:ident $(: ?$optbound:ident)?>)? = $src:ty => $dst:ty }) => {
713 #[allow(missing_debug_implementations, missing_copy_implementations, unreachable_pub)]
714 $vis enum $name {}
715
716 unsafe impl $(<$tyvar $(: ?$optbound)?>)? $crate::pointer::cast::Project<$src, $dst> for $name {
720 fn project(src: $crate::pointer::PtrInner<'_, $src>) -> *mut $dst {
721 #[allow(clippy::as_conversions)]
722 return src.as_ptr() as *mut $dst;
723 }
724 }
725
726 unsafe impl $(<$tyvar $(: ?$optbound)?>)? $crate::pointer::cast::Cast<$src, $dst> for $name {}
728 };
729}
730
731macro_rules! unsafe_impl_for_transparent_wrapper {
740 ($vis:vis T $(: ?$optbound:ident)? => $wrapper:ident<T>) => {{
741 crate::util::macros::__unsafe();
742
743 use crate::pointer::{TransmuteFrom, cast::{CastExact, TransitiveProject}, SizeEq, invariant::Valid};
744 use crate::wrappers::ReadOnly;
745
746 unsafe impl<T $(: ?$optbound)?> TransmuteFrom<T, Valid, Valid> for $wrapper<T> {}
749 unsafe impl<T $(: ?$optbound)?> TransmuteFrom<$wrapper<T>, Valid, Valid> for T {}
751 define_cast!(unsafe { $vis CastToWrapper<T $(: ?$optbound)? > = T => $wrapper<T> });
754 unsafe impl<T $(: ?$optbound)?> CastExact<T, $wrapper<T>> for CastToWrapper {}
757 define_cast!(unsafe { $vis CastFromWrapper<T $(: ?$optbound)? > = $wrapper<T> => T });
760 unsafe impl<T $(: ?$optbound)?> CastExact<$wrapper<T>, T> for CastFromWrapper {}
763
764 impl<T $(: ?$optbound)?> SizeEq<T> for $wrapper<T> {
765 type CastFrom = CastToWrapper;
766 }
767 impl<T $(: ?$optbound)?> SizeEq<$wrapper<T>> for T {
768 type CastFrom = CastFromWrapper;
769 }
770
771 impl<T $(: ?$optbound)?> SizeEq<ReadOnly<T>> for $wrapper<T> {
772 type CastFrom = TransitiveProject<
773 T,
774 <T as SizeEq<ReadOnly<T>>>::CastFrom,
775 CastToWrapper,
776 >;
777 }
778 impl<T $(: ?$optbound)?> SizeEq<$wrapper<T>> for ReadOnly<T> {
779 type CastFrom = TransitiveProject<
780 T,
781 CastFromWrapper,
782 <ReadOnly<T> as SizeEq<T>>::CastFrom,
783 >;
784 }
785
786 impl<T $(: ?$optbound)?> SizeEq<ReadOnly<T>> for ReadOnly<$wrapper<T>> {
787 type CastFrom = TransitiveProject<
788 $wrapper<T>,
789 <$wrapper<T> as SizeEq<ReadOnly<T>>>::CastFrom,
790 <ReadOnly<$wrapper<T>> as SizeEq<$wrapper<T>>>::CastFrom,
791 >;
792 }
793 impl<T $(: ?$optbound)?> SizeEq<ReadOnly<$wrapper<T>>> for ReadOnly<T> {
794 type CastFrom = TransitiveProject<
795 $wrapper<T>,
796 <$wrapper<T> as SizeEq<ReadOnly<$wrapper<T>>>>::CastFrom,
797 <ReadOnly<T> as SizeEq<$wrapper<T>>>::CastFrom,
798 >;
799 }
800 }};
801}
802
803macro_rules! impl_transitive_transmute_from {
804 ($($tyvar:ident $(: ?$optbound:ident)?)? => $t:ty => $u:ty => $v:ty) => {
805 const _: () = {
806 use crate::pointer::{TransmuteFrom, SizeEq, invariant::Valid};
807
808 impl<$($tyvar $(: ?$optbound)?)?> SizeEq<$t> for $v
809 where
810 $u: SizeEq<$t>,
811 $v: SizeEq<$u>,
812 {
813 type CastFrom = cast::TransitiveProject<
814 $u,
815 <$u as SizeEq<$t>>::CastFrom,
816 <$v as SizeEq<$u>>::CastFrom
817 >;
818 }
819
820 unsafe impl<$($tyvar $(: ?$optbound)?)?> TransmuteFrom<$t, Valid, Valid> for $v
825 where
826 $u: TransmuteFrom<$t, Valid, Valid>,
827 $v: TransmuteFrom<$u, Valid, Valid>,
828 {}
829 };
830 };
831}
832
833#[inline(always)]
838pub(crate) const unsafe fn __unsafe() {}
839
840#[allow(unused)]
842macro_rules! docstring {
843 ($(#[doc = $content:expr])*) => {
844 concat!($($content, "\n",)*)
845 }
846}
847
848#[allow(unused)]
851macro_rules! codegen_header {
852 ($level:expr, $name:expr) => {
853 concat!(
854 "
855<",
856 $level,
857 " id='method.",
858 $name,
859 ".codegen'>
860 <a class='doc-anchor' href='#method.",
861 $name,
862 ".codegen'>ยง</a>
863 Code Generation
864</",
865 $level,
866 ">
867"
868 )
869 };
870}
871
872#[rustfmt::skip]
874#[allow(unused)]
875macro_rules! tabs {
876 (
877 name = $name:expr,
878 arity = $arity:literal,
879 $([
880 $($open:ident)?
881 @index $n:literal
882 @title $title:literal
883 $(#[doc = $content:expr])*
884 ]),*
885 ) => {
886 concat!("
887<div class='codegen-tabs' style='--arity: ", $arity ,"'>", $(concat!("
888 <details name='tab-", $name,"' style='--n: ", $n ,"'", $(stringify!($open),)*">
889 <summary><h6>", $title, "</h6></summary>
890 <div>
891
892", $($content, "\n",)* "
893\
894 </div>
895 </details>"),)*
896"</div>")
897 }
898}
899
900#[allow(unused)]
902macro_rules! codegen_example {
903 (format = $format:expr, bench = $bench:expr) => {
904 tabs!(
905 name = $bench,
906 arity = 4,
907 [
908 @index 1
909 @title "Format"
910 #[doc = include_str!(concat!("../benches/formats/", $format, ".rs"))]
912 ],
914 [
915 @index 2
916 @title "Benchmark"
917 #[doc = include_str!(concat!("../benches/", $bench, ".rs"))]
919 ],
921 [
922 open
923 @index 3
924 @title "Assembly"
925 #[doc = include_str!(concat!("../benches/", $bench, ".x86-64"))]
927 ],
929 [
930 @index 4
931 @title "Machine Code Analysis"
932 #[doc = include_str!(concat!("../benches/", $bench, ".x86-64.mca"))]
934 ]
936 )
937 }
938}
939
940#[allow(unused)]
942macro_rules! codegen_example_suite {
943 (
944 bench = $bench:expr,
945 format = $format:expr,
946 arity = $arity:literal,
947 $([
948 $($open:ident)?
949 @index $index:literal
950 @title $title:literal
951 @variant $variant:literal
952 ]),*
953 ) => {
954 tabs!(
955 name = $bench,
956 arity = $arity,
957 $([
958 $($open)*
959 @index $index
960 @title $title
961 #[doc = codegen_example!(
962 format = concat!($format, "_", $variant),
963 bench = concat!($bench, "_", $variant)
964 )]
965 ]),*
966 )
967 }
968}
969
970#[allow(unused)]
972macro_rules! codegen_preamble {
973 () => {
974 docstring!(
975 )
982 }
983}
984
985#[allow(unused)]
987macro_rules! codegen_section {
988 (
989 header = $level:expr,
990 bench = $bench:expr,
991 format = $format:expr,
992 arity = $arity:literal,
993 $([
994 $($open:ident)?
995 @index $index:literal
996 @title $title:literal
997 @variant $variant:literal
998 ]),*
999 ) => {
1000 concat!(
1001 codegen_header!($level, $bench),
1002 codegen_preamble!(),
1003 docstring!(
1004 ),
1009 codegen_example_suite!(
1010 bench = $bench,
1011 format = $format,
1012 arity = $arity,
1013 $([
1014 $($open)*
1015 @index $index
1016 @title $title
1017 @variant $variant
1018 ]),*
1019 )
1020 )
1021 };
1022 (
1023 header = $level:expr,
1024 bench = $bench:expr,
1025 format = $format:expr,
1026 ) => {
1027 concat!(
1028 codegen_header!($level, $bench),
1029 codegen_preamble!(),
1030 codegen_example!(
1031 format = $format,
1032 bench = $bench
1033 )
1034 )
1035 }
1036}