spirv_std/
scalar.rs

1//! Traits related to scalars.
2
3use crate::sealed::Sealed;
4use crate::{ScalarComposite, ScalarOrVector, ScalarOrVectorTransform};
5use core::num::NonZeroUsize;
6
7/// Abstract trait representing a SPIR-V scalar type, which includes:
8/// * Floating-point type: f32, f64
9/// * Integer type: u8, u16, u32, u64, i8, i16, i32, i64
10/// * Boolean type: bool
11///
12/// See the SPIRV spec on [Types](https://registry.khronos.org/SPIR-V/specs/unified1/SPIRV.html#_types).
13///
14/// # Safety
15/// Implementing this trait on non-scalar types breaks assumptions of other unsafe code, and should not be done.
16pub unsafe trait Scalar: ScalarOrVector<Scalar = Self> + crate::sealed::Sealed {}
17
18/// Abstract trait representing a SPIR-V integer or floating-point type. Unlike [`Scalar`], excludes the boolean type.
19///
20/// # Safety
21/// Implementing this trait on non-primitive-integer or non-primitive-float types breaks assumptions of other unsafe
22/// code, and should not be done.
23pub unsafe trait Number: Scalar {}
24
25/// Abstract trait representing any SPIR-V integer type.
26///
27/// # Safety
28/// Implementing this trait on non-primitive-integer types breaks assumptions of other unsafe code,
29/// and should not be done.
30pub unsafe trait Integer: num_traits::PrimInt + Number {
31    /// Width of the integer, in bits.
32    const WIDTH: usize;
33    /// If the integer is signed: true means signed, false means unsigned.
34    const SIGNED: bool;
35}
36
37/// Abstract trait representing any SPIR-V signed integer type.
38///
39/// # Safety
40/// Implementing this trait on non-signed-integer types breaks assumptions of other unsafe code,
41/// and should not be done.
42pub unsafe trait SignedInteger: num_traits::Signed + Integer {}
43
44/// Abstract trait representing any SPIR-V unsigned integer type.
45///
46/// # Safety
47/// Implementing this trait on non-unsigned-integer types breaks assumptions of other unsafe code,
48/// and should not be done.
49pub unsafe trait UnsignedInteger: num_traits::Unsigned + Integer {}
50
51/// Abstract trait representing a SPIR-V floating point type.
52///
53/// # Safety
54/// Implementing this trait on non-primitive-float types breaks assumptions of other unsafe code,
55/// and should not be done.
56pub unsafe trait Float: num_traits::Float + Number {
57    /// Width of the float, in bits.
58    const WIDTH: usize;
59}
60
61macro_rules! impl_scalar {
62    (impl Scalar for $ty:ty;) => {
63        impl Sealed for $ty {}
64        impl ScalarComposite for $ty {
65            #[inline]
66            fn transform<F: ScalarOrVectorTransform>(self, f: &mut F) -> Self {
67                f.transform_scalar(self)
68            }
69        }
70        unsafe impl ScalarOrVector for $ty {
71            type Scalar = Self;
72            const N: NonZeroUsize = NonZeroUsize::new(1).unwrap();
73        }
74        unsafe impl Scalar for $ty {}
75    };
76    (impl Number for $ty:ty;) => {
77        unsafe impl Number for $ty {}
78        impl_scalar!(impl Scalar for $ty;);
79    };
80    (impl UnsignedInteger for $ty:ty;) => {
81        unsafe impl Integer for $ty {
82            const WIDTH: usize = core::mem::size_of::<$ty>() * 8;
83            const SIGNED: bool = false;
84        }
85        unsafe impl UnsignedInteger for $ty {}
86        impl_scalar!(impl Number for $ty;);
87    };
88    (impl SignedInteger for $ty:ty;) => {
89        unsafe impl Integer for $ty {
90            const WIDTH: usize = core::mem::size_of::<$ty>() * 8;
91            const SIGNED: bool = true;
92        }
93        unsafe impl SignedInteger for $ty {}
94        impl_scalar!(impl Number for $ty;);
95    };
96    (impl Float for $ty:ty;) => {
97        unsafe impl Float for $ty {
98            const WIDTH: usize = core::mem::size_of::<$ty>() * 8;
99        }
100        impl_scalar!(impl Number for $ty;);
101    };
102    ($(impl $trait:ident for $ty:ty;)+) => {
103        $(impl_scalar!(impl $trait for $ty;);)+
104    };
105}
106
107impl_scalar! {
108    impl UnsignedInteger for u8;
109    impl UnsignedInteger for u16;
110    impl UnsignedInteger for u32;
111    impl UnsignedInteger for u64;
112    impl SignedInteger for i8;
113    impl SignedInteger for i16;
114    impl SignedInteger for i32;
115    impl SignedInteger for i64;
116    impl Float for f32;
117    impl Float for f64;
118    impl Scalar for bool;
119}
120
121/// used by `ScalarOrVector` derive when working with enums
122#[inline]
123pub fn assert_is_integer<T: Integer>() {}