bevy_crevice/std430/
traits.rs1use core::mem::{size_of, MaybeUninit};
2#[cfg(feature = "std")]
3use std::io::{self, Write};
4
5use bytemuck::{bytes_of, Pod, Zeroable};
6
7#[cfg(feature = "std")]
8use crate::std430::Writer;
9
10pub unsafe trait Std430: Copy + Zeroable + Pod {
13 const ALIGNMENT: usize;
20
21 const PAD_AT_END: bool = false;
26 type Padded: Std430Convertible<Self>;
30
31 fn as_bytes(&self) -> &[u8] {
38 bytes_of(self)
39 }
40}
41
42unsafe impl Std430 for () {
43 const ALIGNMENT: usize = 0;
44
45 const PAD_AT_END: bool = false;
46
47 type Padded = ();
48}
49
50pub trait Std430Convertible<T: Std430>: Copy {
52 fn into_std430(self) -> T;
54 fn from_std430(_: T) -> Self;
56}
57
58impl<T: Std430> Std430Convertible<T> for T {
59 fn into_std430(self) -> T {
60 self
61 }
62 fn from_std430(also_self: T) -> Self {
63 also_self
64 }
65}
66
67#[derive(Copy, Clone)]
70pub enum InvalidPadded {}
71impl<T: Std430> Std430Convertible<T> for InvalidPadded {
72 fn into_std430(self) -> T {
73 unimplemented!()
74 }
75 fn from_std430(_: T) -> Self {
76 unimplemented!()
77 }
78}
79pub trait AsStd430 {
122 type Output: Std430;
124
125 fn as_std430(&self) -> Self::Output;
127
128 fn std430_size_static() -> usize {
131 size_of::<Self::Output>()
132 }
133
134 fn from_std430(value: Self::Output) -> Self;
136}
137
138impl<T> AsStd430 for T
139where
140 T: Std430,
141{
142 type Output = Self;
143
144 fn as_std430(&self) -> Self {
145 *self
146 }
147
148 fn from_std430(value: Self) -> Self {
149 value
150 }
151}
152
153#[doc(hidden)]
154#[derive(Copy, Clone, Debug)]
155pub struct Std430Padded<T: Std430, const PAD: usize> {
156 inner: T,
157 _padding: [u8; PAD],
158}
159
160unsafe impl<T: Std430, const PAD: usize> Zeroable for Std430Padded<T, PAD> {}
161unsafe impl<T: Std430, const PAD: usize> Pod for Std430Padded<T, PAD> {}
162
163impl<T: Std430, const PAD: usize> Std430Convertible<T> for Std430Padded<T, PAD> {
164 fn into_std430(self) -> T {
165 self.inner
166 }
167
168 fn from_std430(inner: T) -> Self {
169 Self {
170 inner,
171 _padding: [0u8; PAD],
172 }
173 }
174}
175
176#[doc(hidden)]
177#[derive(Copy, Clone, Debug)]
178#[repr(transparent)]
179pub struct Std430Array<T: Std430, const N: usize>([T::Padded; N]);
180
181unsafe impl<T: Std430, const N: usize> Zeroable for Std430Array<T, N> where T::Padded: Zeroable {}
182unsafe impl<T: Std430, const N: usize> Pod for Std430Array<T, N> where T::Padded: Pod {}
183unsafe impl<T: Std430, const N: usize> Std430 for Std430Array<T, N>
184where
185 T::Padded: Pod,
186{
187 const ALIGNMENT: usize = T::ALIGNMENT;
188 type Padded = Self;
189}
190
191impl<T: Std430, const N: usize> Std430Array<T, N> {
192 fn uninit_array() -> [MaybeUninit<T::Padded>; N] {
193 unsafe { MaybeUninit::uninit().assume_init() }
194 }
195
196 fn from_uninit_array(a: [MaybeUninit<T::Padded>; N]) -> Self {
197 unsafe { core::mem::transmute_copy(&a) }
198 }
199}
200
201impl<T: AsStd430, const N: usize> AsStd430 for [T; N]
202where
203 <T::Output as Std430>::Padded: Pod,
204{
205 type Output = Std430Array<T::Output, N>;
206 fn as_std430(&self) -> Self::Output {
207 let mut res = Self::Output::uninit_array();
208
209 for i in 0..N {
210 res[i] = MaybeUninit::new(Std430Convertible::from_std430(self[i].as_std430()));
211 }
212
213 Self::Output::from_uninit_array(res)
214 }
215
216 fn from_std430(val: Self::Output) -> Self {
217 let mut res: [MaybeUninit<T>; N] = unsafe { MaybeUninit::uninit().assume_init() };
218 for i in 0..N {
219 res[i] = MaybeUninit::new(T::from_std430(val.0[i].into_std430()));
220 }
221 unsafe { core::mem::transmute_copy(&res) }
222 }
223}
224
225#[cfg(feature = "std")]
234pub trait WriteStd430 {
235 fn write_std430<W: Write>(&self, writer: &mut Writer<W>) -> io::Result<usize>;
240
241 fn std430_size(&self) -> usize {
245 let mut writer = Writer::new(io::sink());
246 self.write_std430(&mut writer).unwrap();
247 writer.len()
248 }
249}
250
251#[cfg(feature = "std")]
252impl<T> WriteStd430 for T
253where
254 T: AsStd430,
255{
256 fn write_std430<W: Write>(&self, writer: &mut Writer<W>) -> io::Result<usize> {
257 writer.write_std430(&self.as_std430())
258 }
259
260 fn std430_size(&self) -> usize {
261 size_of::<<Self as AsStd430>::Output>()
262 }
263}
264
265#[cfg(feature = "std")]
266impl<T> WriteStd430 for [T]
267where
268 T: WriteStd430,
269{
270 fn write_std430<W: Write>(&self, writer: &mut Writer<W>) -> io::Result<usize> {
271 let mut offset = writer.len();
272
273 let mut iter = self.iter();
274
275 if let Some(item) = iter.next() {
276 offset = item.write_std430(writer)?;
277 }
278
279 for item in iter {
280 item.write_std430(writer)?;
281 }
282
283 Ok(offset)
284 }
285
286 fn std430_size(&self) -> usize {
287 let mut writer = Writer::new(io::sink());
288 self.write_std430(&mut writer).unwrap();
289 writer.len()
290 }
291}