bevy_crevice/std140/
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::std140::Writer;
9
10pub unsafe trait Std140: Copy + Zeroable + Pod {
13 const ALIGNMENT: usize;
20
21 const PAD_AT_END: bool = false;
26 type Padded: Std140Convertible<Self>;
30
31 fn as_bytes(&self) -> &[u8] {
38 bytes_of(self)
39 }
40}
41
42pub trait Std140Convertible<T: Std140>: Copy {
44 fn into_std140(self) -> T;
46 fn from_std140(_: T) -> Self;
48}
49
50impl<T: Std140> Std140Convertible<T> for T {
51 fn into_std140(self) -> T {
52 self
53 }
54 fn from_std140(also_self: T) -> Self {
55 also_self
56 }
57}
58
59#[derive(Copy, Clone)]
62pub enum InvalidPadded {}
63impl<T: Std140> Std140Convertible<T> for InvalidPadded {
64 fn into_std140(self) -> T {
65 unimplemented!()
66 }
67 fn from_std140(_: T) -> Self {
68 unimplemented!()
69 }
70}
71pub trait AsStd140 {
114 type Output: Std140;
116
117 fn as_std140(&self) -> Self::Output;
119
120 fn std140_size_static() -> usize {
123 size_of::<Self::Output>()
124 }
125
126 fn from_std140(val: Self::Output) -> Self;
128}
129
130impl<T> AsStd140 for T
131where
132 T: Std140,
133{
134 type Output = Self;
135
136 fn as_std140(&self) -> Self {
137 *self
138 }
139
140 fn from_std140(x: Self) -> Self {
141 x
142 }
143}
144
145#[doc(hidden)]
146#[derive(Copy, Clone, Debug)]
147pub struct Std140Padded<T: Std140, const PAD: usize> {
148 inner: T,
149 _padding: [u8; PAD],
150}
151
152unsafe impl<T: Std140, const PAD: usize> Zeroable for Std140Padded<T, PAD> {}
153unsafe impl<T: Std140, const PAD: usize> Pod for Std140Padded<T, PAD> {}
154
155impl<T: Std140, const PAD: usize> Std140Convertible<T> for Std140Padded<T, PAD> {
156 fn into_std140(self) -> T {
157 self.inner
158 }
159
160 fn from_std140(inner: T) -> Self {
161 Self {
162 inner,
163 _padding: [0u8; PAD],
164 }
165 }
166}
167
168#[doc(hidden)]
169#[derive(Copy, Clone, Debug)]
170#[repr(transparent)]
171pub struct Std140Array<T: Std140, const N: usize>([T::Padded; N]);
172
173unsafe impl<T: Std140, const N: usize> Zeroable for Std140Array<T, N> where T::Padded: Zeroable {}
174unsafe impl<T: Std140, const N: usize> Pod for Std140Array<T, N> where T::Padded: Pod {}
175unsafe impl<T: Std140, const N: usize> Std140 for Std140Array<T, N>
176where
177 T::Padded: Pod,
178{
179 const ALIGNMENT: usize = crate::internal::max(T::ALIGNMENT, 16);
180 type Padded = Self;
181}
182
183impl<T: Std140, const N: usize> Std140Array<T, N> {
184 fn uninit_array() -> [MaybeUninit<T::Padded>; N] {
185 unsafe { MaybeUninit::uninit().assume_init() }
186 }
187
188 fn from_uninit_array(a: [MaybeUninit<T::Padded>; N]) -> Self {
189 unsafe { core::mem::transmute_copy(&a) }
190 }
191}
192
193impl<T: AsStd140, const N: usize> AsStd140 for [T; N]
194where
195 <T::Output as Std140>::Padded: Pod,
196{
197 type Output = Std140Array<T::Output, N>;
198 fn as_std140(&self) -> Self::Output {
199 let mut res = Self::Output::uninit_array();
200
201 for i in 0..N {
202 res[i] = MaybeUninit::new(Std140Convertible::from_std140(self[i].as_std140()));
203 }
204
205 Self::Output::from_uninit_array(res)
206 }
207
208 fn from_std140(val: Self::Output) -> Self {
209 let mut res: [MaybeUninit<T>; N] = unsafe { MaybeUninit::uninit().assume_init() };
210 for i in 0..N {
211 res[i] = MaybeUninit::new(T::from_std140(Std140Convertible::into_std140(val.0[i])));
212 }
213 unsafe { core::mem::transmute_copy(&res) }
214 }
215}
216
217#[cfg(feature = "std")]
226pub trait WriteStd140 {
227 fn write_std140<W: Write>(&self, writer: &mut Writer<W>) -> io::Result<usize>;
232
233 fn std140_size(&self) -> usize {
237 let mut writer = Writer::new(io::sink());
238 self.write_std140(&mut writer).unwrap();
239 writer.len()
240 }
241}
242
243#[cfg(feature = "std")]
244impl<T> WriteStd140 for T
245where
246 T: AsStd140,
247{
248 fn write_std140<W: Write>(&self, writer: &mut Writer<W>) -> io::Result<usize> {
249 writer.write_std140(&self.as_std140())
250 }
251
252 fn std140_size(&self) -> usize {
253 size_of::<<Self as AsStd140>::Output>()
254 }
255}
256
257#[cfg(feature = "std")]
258impl<T> WriteStd140 for [T]
259where
260 T: WriteStd140,
261{
262 fn write_std140<W: Write>(&self, writer: &mut Writer<W>) -> io::Result<usize> {
263 let mut offset = writer.len();
265
266 let mut iter = self.iter();
267
268 if let Some(item) = iter.next() {
269 offset = item.write_std140(writer)?;
270 }
271
272 for item in iter {
273 item.write_std140(writer)?;
274 }
275
276 Ok(offset)
277 }
278
279 fn std140_size(&self) -> usize {
280 let mut writer = Writer::new(io::sink());
281 self.write_std140(&mut writer).unwrap();
282 writer.len()
283 }
284}