encase/core/
rw.rs

1use super::ShaderType;
2use core::mem::MaybeUninit;
3use thiserror::Error;
4
5#[derive(Clone, Copy, Debug, Error)]
6pub enum Error {
7    #[error("could not read/write {expected} bytes from/into {found} byte sized buffer")]
8    BufferTooSmall { expected: u64, found: u64 },
9}
10
11pub type Result<T> = core::result::Result<T, Error>;
12
13pub struct WriteContext {
14    /// length of the contained runtime sized array
15    ///
16    /// used by the derive macro
17    pub rts_array_length: Option<u32>,
18}
19
20pub struct Writer<B: BufferMut> {
21    pub ctx: WriteContext,
22    cursor: Cursor<B>,
23}
24
25impl<B: BufferMut> Writer<B> {
26    #[inline]
27    pub fn new<T: ?Sized + ShaderType>(data: &T, buffer: B, offset: usize) -> Result<Self> {
28        let mut cursor = Cursor::new(buffer, offset);
29        let size = data.size().get();
30        if cursor.try_enlarge(offset + size as usize).is_err() {
31            Err(Error::BufferTooSmall {
32                expected: size,
33                found: cursor.capacity() as u64,
34            })
35        } else {
36            Ok(Self {
37                ctx: WriteContext {
38                    rts_array_length: None,
39                },
40                cursor,
41            })
42        }
43    }
44
45    #[inline]
46    pub fn advance(&mut self, amount: usize) {
47        self.cursor.advance(amount);
48    }
49
50    #[inline]
51    pub fn write<const N: usize>(&mut self, val: &[u8; N]) {
52        self.cursor.write(val);
53    }
54
55    #[inline]
56    pub fn write_slice(&mut self, val: &[u8]) {
57        self.cursor.write_slice(val)
58    }
59}
60
61pub struct ReadContext {
62    /// max elements to read into the contained runtime sized array
63    ///
64    /// used by the derive macro
65    pub rts_array_max_el_to_read: Option<u32>,
66}
67
68pub struct Reader<B: BufferRef> {
69    pub ctx: ReadContext,
70    cursor: Cursor<B>,
71}
72
73impl<B: BufferRef> Reader<B> {
74    #[inline]
75    pub fn new<T: ?Sized + ShaderType>(buffer: B, offset: usize) -> Result<Self> {
76        let cursor = Cursor::new(buffer, offset);
77        if cursor.remaining() < T::min_size().get() as usize {
78            Err(Error::BufferTooSmall {
79                expected: T::min_size().get(),
80                found: cursor.remaining() as u64,
81            })
82        } else {
83            Ok(Self {
84                ctx: ReadContext {
85                    rts_array_max_el_to_read: None,
86                },
87                cursor,
88            })
89        }
90    }
91
92    #[inline]
93    pub fn advance(&mut self, amount: usize) {
94        self.cursor.advance(amount);
95    }
96
97    #[inline]
98    pub fn read<const N: usize>(&mut self) -> &[u8; N] {
99        self.cursor.read()
100    }
101
102    #[inline]
103    pub fn read_slice(&mut self, val: &mut [u8]) {
104        self.cursor.read_slice(val)
105    }
106
107    #[inline]
108    pub fn remaining(&self) -> usize {
109        self.cursor.remaining()
110    }
111}
112
113struct Cursor<B> {
114    buffer: B,
115    pos: usize,
116}
117
118impl<B> Cursor<B> {
119    #[inline]
120    fn new(buffer: B, offset: usize) -> Self {
121        Self {
122            buffer,
123            pos: offset,
124        }
125    }
126    #[inline]
127    fn advance(&mut self, amount: usize) {
128        self.pos += amount;
129    }
130}
131
132impl<B: BufferRef> Cursor<B> {
133    #[inline]
134    fn remaining(&self) -> usize {
135        self.buffer.len().saturating_sub(self.pos)
136    }
137
138    #[inline]
139    fn read<const N: usize>(&mut self) -> &[u8; N] {
140        let res = self.buffer.read(self.pos);
141        self.pos += N;
142        res
143    }
144
145    #[inline]
146    fn read_slice(&mut self, val: &mut [u8]) {
147        self.buffer.read_slice(self.pos, val);
148        self.pos += val.len();
149    }
150}
151
152impl<B: BufferMut> Cursor<B> {
153    #[inline]
154    fn capacity(&self) -> usize {
155        self.buffer.capacity().saturating_sub(self.pos)
156    }
157
158    #[inline]
159    fn write<const N: usize>(&mut self, val: &[u8; N]) {
160        self.buffer.write(self.pos, val);
161        self.pos += N;
162    }
163
164    #[inline]
165    fn write_slice(&mut self, val: &[u8]) {
166        self.buffer.write_slice(self.pos, val);
167        self.pos += val.len();
168    }
169
170    #[inline]
171    fn try_enlarge(&mut self, wanted: usize) -> core::result::Result<(), EnlargeError> {
172        self.buffer.try_enlarge(wanted)
173    }
174}
175
176#[derive(Clone, Copy, Debug, Error)]
177#[error("could not enlarge buffer")]
178pub struct EnlargeError;
179
180impl From<std::collections::TryReserveError> for EnlargeError {
181    fn from(_: std::collections::TryReserveError) -> Self {
182        Self
183    }
184}
185
186#[allow(clippy::len_without_is_empty)]
187pub trait BufferRef {
188    fn len(&self) -> usize;
189
190    fn read<const N: usize>(&self, offset: usize) -> &[u8; N];
191
192    fn read_slice(&self, offset: usize, val: &mut [u8]);
193}
194
195pub trait BufferMut {
196    fn capacity(&self) -> usize;
197
198    fn write<const N: usize>(&mut self, offset: usize, val: &[u8; N]);
199
200    fn write_slice(&mut self, offset: usize, val: &[u8]);
201
202    #[inline]
203    fn try_enlarge(&mut self, wanted: usize) -> core::result::Result<(), EnlargeError> {
204        if wanted > self.capacity() {
205            Err(EnlargeError)
206        } else {
207            Ok(())
208        }
209    }
210}
211
212impl BufferRef for [u8] {
213    fn len(&self) -> usize {
214        self.len()
215    }
216
217    #[inline]
218    fn read<const N: usize>(&self, offset: usize) -> &[u8; N] {
219        use crate::utils::SliceExt;
220        self.array(offset)
221    }
222
223    #[inline]
224    fn read_slice(&self, offset: usize, val: &mut [u8]) {
225        val.copy_from_slice(&self[offset..offset + val.len()])
226    }
227}
228
229impl<const LEN: usize> BufferRef for [u8; LEN] {
230    #[inline]
231    fn len(&self) -> usize {
232        <[u8] as BufferRef>::len(self)
233    }
234
235    #[inline]
236    fn read<const N: usize>(&self, offset: usize) -> &[u8; N] {
237        <[u8] as BufferRef>::read(self, offset)
238    }
239
240    #[inline]
241    fn read_slice(&self, offset: usize, val: &mut [u8]) {
242        <[u8] as BufferRef>::read_slice(self, offset, val)
243    }
244}
245
246impl BufferRef for Vec<u8> {
247    #[inline]
248    fn len(&self) -> usize {
249        <[u8] as BufferRef>::len(self)
250    }
251
252    #[inline]
253    fn read<const N: usize>(&self, offset: usize) -> &[u8; N] {
254        <[u8] as BufferRef>::read(self, offset)
255    }
256
257    #[inline]
258    fn read_slice(&self, offset: usize, val: &mut [u8]) {
259        <[u8] as BufferRef>::read_slice(self, offset, val)
260    }
261}
262
263impl BufferMut for [u8] {
264    #[inline]
265    fn capacity(&self) -> usize {
266        self.len()
267    }
268
269    #[inline]
270    fn write<const N: usize>(&mut self, offset: usize, val: &[u8; N]) {
271        use crate::utils::SliceExt;
272        *self.array_mut(offset) = *val;
273    }
274
275    #[inline]
276    fn write_slice(&mut self, offset: usize, val: &[u8]) {
277        self[offset..offset + val.len()].copy_from_slice(val);
278    }
279}
280
281impl BufferMut for [MaybeUninit<u8>] {
282    #[inline]
283    fn capacity(&self) -> usize {
284        self.len()
285    }
286
287    #[inline]
288    fn write<const N: usize>(&mut self, offset: usize, val: &[u8; N]) {
289        use crate::utils::SliceExt;
290        // SAFETY: &[u8; N] and &[MaybeUninit<u8>; N] have the same layout
291        let val: &[MaybeUninit<u8>; N] = unsafe { core::mem::transmute(val) };
292        *self.array_mut(offset) = *val;
293    }
294
295    #[inline]
296    fn write_slice(&mut self, offset: usize, val: &[u8]) {
297        // SAFETY: &[u8] and &[MaybeUninit<u8>] have the same layout
298        let val: &[MaybeUninit<u8>] = unsafe { core::mem::transmute(val) };
299        self[offset..offset + val.len()].copy_from_slice(val);
300    }
301}
302
303impl<const LEN: usize> BufferMut for [u8; LEN] {
304    #[inline]
305    fn capacity(&self) -> usize {
306        <[u8] as BufferMut>::capacity(self)
307    }
308
309    #[inline]
310    fn write<const N: usize>(&mut self, offset: usize, val: &[u8; N]) {
311        <[u8] as BufferMut>::write(self, offset, val);
312    }
313
314    #[inline]
315    fn write_slice(&mut self, offset: usize, val: &[u8]) {
316        <[u8] as BufferMut>::write_slice(self, offset, val)
317    }
318}
319
320impl<const LEN: usize> BufferMut for [MaybeUninit<u8>; LEN] {
321    #[inline]
322    fn capacity(&self) -> usize {
323        <[MaybeUninit<u8>] as BufferMut>::capacity(self)
324    }
325
326    #[inline]
327    fn write<const N: usize>(&mut self, offset: usize, val: &[u8; N]) {
328        <[MaybeUninit<u8>] as BufferMut>::write(self, offset, val)
329    }
330
331    #[inline]
332    fn write_slice(&mut self, offset: usize, val: &[u8]) {
333        <[MaybeUninit<u8>] as BufferMut>::write_slice(self, offset, val)
334    }
335}
336
337impl BufferMut for Vec<u8> {
338    #[inline]
339    fn capacity(&self) -> usize {
340        self.capacity()
341    }
342
343    #[inline]
344    fn write<const N: usize>(&mut self, offset: usize, val: &[u8; N]) {
345        <[u8] as BufferMut>::write(self, offset, val);
346    }
347
348    #[inline]
349    fn write_slice(&mut self, offset: usize, val: &[u8]) {
350        <[u8] as BufferMut>::write_slice(self, offset, val)
351    }
352
353    #[inline]
354    fn try_enlarge(&mut self, wanted: usize) -> core::result::Result<(), EnlargeError> {
355        use crate::utils::ByteVecExt;
356        self.try_extend(wanted).map_err(EnlargeError::from)
357    }
358}
359
360impl BufferMut for Vec<MaybeUninit<u8>> {
361    #[inline]
362    fn capacity(&self) -> usize {
363        self.capacity()
364    }
365
366    #[inline]
367    fn write<const N: usize>(&mut self, offset: usize, val: &[u8; N]) {
368        <[MaybeUninit<u8>] as BufferMut>::write(self, offset, val)
369    }
370
371    #[inline]
372    fn write_slice(&mut self, offset: usize, val: &[u8]) {
373        <[MaybeUninit<u8>] as BufferMut>::write_slice(self, offset, val)
374    }
375
376    #[inline]
377    fn try_enlarge(&mut self, wanted: usize) -> core::result::Result<(), EnlargeError> {
378        use crate::utils::ByteVecExt;
379        self.try_extend(wanted).map_err(EnlargeError::from)
380    }
381}
382
383macro_rules! impl_buffer_ref_for_wrappers {
384    ($($type:ty),*) => {$(
385        impl<T: ?Sized + BufferRef> BufferRef for $type {
386            #[inline]
387            fn len(&self) -> usize {
388                T::len(self)
389            }
390
391            #[inline]
392            fn read<const N: usize>(&self, offset: usize) -> &[u8; N] {
393                T::read(self, offset)
394            }
395
396            #[inline]
397            fn read_slice(&self, offset: usize, val: &mut [u8]) {
398                T::read_slice(self, offset, val)
399            }
400        }
401    )*};
402}
403
404impl_buffer_ref_for_wrappers!(&T, &mut T, Box<T>, std::rc::Rc<T>, std::sync::Arc<T>);
405
406macro_rules! impl_buffer_mut_for_wrappers {
407    ($($type:ty),*) => {$(
408        impl<T: ?Sized + BufferMut> BufferMut for $type {
409            #[inline]
410            fn capacity(&self) -> usize {
411                T::capacity(self)
412            }
413
414            #[inline]
415            fn write<const N: usize>(&mut self, offset: usize, val: &[u8; N]) {
416                T::write(self, offset, val)
417            }
418
419            #[inline]
420            fn write_slice(&mut self, offset: usize, val: &[u8]) {
421                T::write_slice(self, offset, val)
422            }
423
424            #[inline]
425            fn try_enlarge(&mut self, wanted: usize) -> core::result::Result<(), EnlargeError> {
426                T::try_enlarge(self, wanted)
427            }
428        }
429    )*};
430}
431
432impl_buffer_mut_for_wrappers!(&mut T, Box<T>);
433
434#[cfg(test)]
435mod buffer_ref {
436    use super::BufferRef;
437
438    #[test]
439    fn array() {
440        let arr = [0, 1, 2, 3, 4, 5];
441
442        assert_eq!(BufferRef::len(&arr), 6);
443        assert_eq!(BufferRef::read(&arr, 3), &[3, 4]);
444    }
445
446    #[test]
447    fn vec() {
448        let vec = Vec::from([0, 1, 2, 3, 4, 5]);
449
450        assert_eq!(BufferRef::len(&vec), 6);
451        assert_eq!(BufferRef::read(&vec, 3), &[3, 4]);
452    }
453}
454
455#[cfg(test)]
456mod buffer_mut {
457    use super::BufferMut;
458    use crate::core::EnlargeError;
459
460    #[test]
461    fn array() {
462        let mut arr = [0, 1, 2, 3, 4, 5];
463
464        assert_eq!(BufferMut::capacity(&arr), 6);
465
466        BufferMut::write(&mut arr, 3, &[9, 1]);
467        assert_eq!(arr, [0, 1, 2, 9, 1, 5]);
468
469        assert!(matches!(BufferMut::try_enlarge(&mut arr, 6), Ok(())));
470        assert!(matches!(
471            BufferMut::try_enlarge(&mut arr, 7),
472            Err(EnlargeError)
473        ));
474    }
475
476    #[test]
477    fn vec() {
478        let mut vec = Vec::from([0, 1, 2, 3, 4, 5]);
479
480        assert_eq!(BufferMut::capacity(&vec), vec.capacity());
481
482        BufferMut::write(&mut vec, 3, &[9, 1]);
483        assert_eq!(vec, Vec::from([0, 1, 2, 9, 1, 5]));
484
485        assert!(matches!(BufferMut::try_enlarge(&mut vec, 100), Ok(())));
486        assert!(matches!(
487            BufferMut::try_enlarge(&mut vec, usize::MAX),
488            Err(EnlargeError)
489        ));
490    }
491}
492
493#[cfg(test)]
494mod error {
495    use super::Error;
496
497    #[test]
498    fn derived_traits() {
499        let err = Error::BufferTooSmall {
500            expected: 4,
501            found: 2,
502        };
503
504        {
505            use std::error::Error;
506            assert!(err.source().is_none());
507        }
508
509        assert_eq!(
510            format!("{}", err.clone()),
511            "could not read/write 4 bytes from/into 2 byte sized buffer"
512        );
513
514        assert_eq!(
515            format!("{:?}", err.clone()),
516            "BufferTooSmall { expected: 4, found: 2 }"
517        );
518    }
519}
520
521#[cfg(test)]
522mod enlarge_error {
523    use super::EnlargeError;
524
525    #[test]
526    fn derived_traits() {
527        // can't construct a TryReserveError due to TryReserveErrorKind being unstable
528        let try_reserve_error = {
529            let mut vec = Vec::<u8>::new();
530            vec.try_reserve(usize::MAX).err().unwrap()
531        };
532        let err = EnlargeError::from(try_reserve_error);
533
534        use std::error::Error;
535        assert!(err.source().is_none());
536
537        assert_eq!(format!("{}", err.clone()), "could not enlarge buffer");
538
539        assert_eq!(format!("{:?}", err.clone()), "EnlargeError");
540    }
541}