spirv_std/scalar.rs
1//! Traits related to scalars.
2
3use crate::ScalarOrVector;
4use crate::sealed::Sealed;
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 unsafe impl ScalarOrVector for $ty {
65 type Scalar = Self;
66 const N: NonZeroUsize = NonZeroUsize::new(1).unwrap();
67 }
68 unsafe impl Scalar for $ty {}
69 };
70 (impl Number for $ty:ty;) => {
71 unsafe impl Number for $ty {}
72 impl_scalar!(impl Scalar for $ty;);
73 };
74 (impl UnsignedInteger for $ty:ty;) => {
75 unsafe impl Integer for $ty {
76 const WIDTH: usize = core::mem::size_of::<$ty>() * 8;
77 const SIGNED: bool = false;
78 }
79 unsafe impl UnsignedInteger for $ty {}
80 impl_scalar!(impl Number for $ty;);
81 };
82 (impl SignedInteger for $ty:ty;) => {
83 unsafe impl Integer for $ty {
84 const WIDTH: usize = core::mem::size_of::<$ty>() * 8;
85 const SIGNED: bool = true;
86 }
87 unsafe impl SignedInteger for $ty {}
88 impl_scalar!(impl Number for $ty;);
89 };
90 (impl Float for $ty:ty;) => {
91 unsafe impl Float for $ty {
92 const WIDTH: usize = core::mem::size_of::<$ty>() * 8;
93 }
94 impl_scalar!(impl Number for $ty;);
95 };
96 ($(impl $trait:ident for $ty:ty;)+) => {
97 $(impl_scalar!(impl $trait for $ty;);)+
98 };
99}
100
101impl_scalar! {
102 impl UnsignedInteger for u8;
103 impl UnsignedInteger for u16;
104 impl UnsignedInteger for u32;
105 impl UnsignedInteger for u64;
106 impl SignedInteger for i8;
107 impl SignedInteger for i16;
108 impl SignedInteger for i32;
109 impl SignedInteger for i64;
110 impl Float for f32;
111 impl Float for f64;
112 impl Scalar for bool;
113}