audio_channel_buffer/
var_buffer_ref.rs

1use core::num::NonZeroUsize;
2use core::ops::{Index, IndexMut, Range};
3
4use arrayvec::ArrayVec;
5
6/// An immutable memory-efficient buffer of samples with a fixed runtime number of
7/// channels each with a fixed runtime number of frames (samples in a single channel
8/// of audio).
9///
10/// This version uses a reference to a slice as its data source.
11#[derive(Debug, Clone)]
12pub struct VarChannelBufferRef<'a, T: Clone + Copy + Default + Sized, const MAX_CHANNELS: usize> {
13    data: &'a [T],
14    offsets: ArrayVec<*const T, MAX_CHANNELS>,
15    frames: usize,
16}
17
18impl<'a, T: Clone + Copy + Default + Sized, const MAX_CHANNELS: usize>
19    VarChannelBufferRef<'a, T, MAX_CHANNELS>
20{
21    const _COMPILE_TIME_ASSERTS: () = {
22        assert!(MAX_CHANNELS > 0);
23    };
24
25    #[inline(always)]
26    pub(crate) unsafe fn from_raw(
27        data: &'a [T],
28        offsets: ArrayVec<*const T, MAX_CHANNELS>,
29        frames: usize,
30    ) -> Self {
31        let _ = Self::_COMPILE_TIME_ASSERTS;
32
33        Self {
34            data,
35            offsets,
36            frames,
37        }
38    }
39
40    /// Create an empty [`VarChannelBufferRef`] with no data.
41    pub fn empty() -> Self {
42        let _ = Self::_COMPILE_TIME_ASSERTS;
43
44        let data = &[];
45        let mut offsets = ArrayVec::new();
46        offsets.push(data.as_ptr());
47
48        Self {
49            data,
50            offsets,
51            frames: 0,
52        }
53    }
54
55    /// Create a new [`VarChannelBufferRef`] using the given slice as the data.
56    ///
57    /// # Panics
58    /// Panics if `channels.get() > MAX_CHANNELS`.
59    pub fn new(data: &'a [T], channels: NonZeroUsize) -> Self {
60        let _ = Self::_COMPILE_TIME_ASSERTS;
61
62        assert!(channels.get() <= MAX_CHANNELS);
63
64        let frames = data.len() / channels.get();
65
66        let mut offsets = ArrayVec::new();
67        // SAFETY:
68        // * All of these pointers point to valid memory in the slice.
69        // * We have constrained `channels` above.
70        // * We have asserted at compile-time that `MAX_CHANNELS` is non-zero.
71        unsafe {
72            for ch_i in 0..channels.get() {
73                offsets.push_unchecked(data.as_ptr().add(ch_i * frames));
74            }
75        }
76
77        Self {
78            data,
79            offsets,
80            frames,
81        }
82    }
83
84    /// Create a new [`VarChannelBufferRef`] using the given slice as the data.
85    ///
86    /// # Safety
87    /// The caller must uphold that:
88    /// * `data.len() >= frames * self.channels().get()`
89    /// * and `channels.get() <= MAX_CHANNELS`
90    pub unsafe fn new_unchecked(data: &'a [T], frames: usize, channels: NonZeroUsize) -> Self {
91        let _ = Self::_COMPILE_TIME_ASSERTS;
92
93        let mut offsets = ArrayVec::new();
94        for ch_i in 0..channels.get() {
95            offsets.push_unchecked(data.as_ptr().add(ch_i * frames));
96        }
97
98        Self {
99            data,
100            offsets,
101            frames,
102        }
103    }
104
105    /// The number of channels in this buffer.
106    pub fn channels(&self) -> NonZeroUsize {
107        // SAFETY: The constructors ensure that there is at least one element in `offsets`.
108        unsafe { NonZeroUsize::new_unchecked(self.offsets.len()) }
109    }
110
111    /// The number of frames (samples in a single channel of audio) that are allocated
112    /// in this buffer.
113    pub fn frames(&self) -> usize {
114        self.frames
115    }
116
117    #[inline(always)]
118    /// Get an immutable reference to the channel at `index`. The slice will have a length
119    /// of `self.frames()`.
120    ///
121    /// Returns `None` if `index` is out of bounds.
122    pub fn channel(&self, index: usize) -> Option<&[T]> {
123        if index < self.offsets.len() {
124            // SAFETY:
125            // We haved checked that `index` is within bounds.
126            unsafe { Some(self.channel_unchecked(index)) }
127        } else {
128            None
129        }
130    }
131
132    #[inline(always)]
133    /// Get an immutable reference to the channel at `index`. The slice will have a length
134    /// of `self.frames()`.
135    ///
136    /// # Safety
137    /// `index` must be less than `self.channels()`
138    pub unsafe fn channel_unchecked(&self, index: usize) -> &[T] {
139        // SAFETY:
140        //
141        // * The constructors ensure that the pointed-to data slice has a length of at
142        // least `frames * self.channels()`.
143        // * The caller upholds that `index` is within bounds.
144        // * The data slice cannot be moved, so the pointers are valid for the lifetime
145        // of the slice.
146        // * We have asserted at compile-time that `MAX_CHANNELS` is non-zero.
147        core::slice::from_raw_parts(*self.offsets.get_unchecked(index), self.frames)
148    }
149
150    /// Get all channels as immutable slices. Each slice will have a length of `self.frames()`.
151    #[inline]
152    pub fn as_slices(&self) -> ArrayVec<&[T], MAX_CHANNELS> {
153        let mut v = ArrayVec::new();
154
155        // SAFETY:
156        //
157        // * The constructors ensure that the pointed-to data slice has a length of at
158        // least `frames * self.channels()`.
159        // * The data slice cannot be moved, so the pointers are valid for the lifetime
160        // of the slice.
161        // * We have asserted at compile-time that `MAX_CHANNELS` is non-zero.
162        unsafe {
163            for ptr in self.offsets.iter() {
164                v.push_unchecked(core::slice::from_raw_parts(*ptr, self.frames));
165            }
166        }
167
168        v
169    }
170
171    /// Get all channels as immutable slices with the given length in frames.
172    ///
173    /// If `frames > self.frames()`, then each slice will have a length of `self.frames()`
174    /// instead.
175    #[inline]
176    pub fn as_slices_with_length(&self, frames: usize) -> ArrayVec<&[T], MAX_CHANNELS> {
177        let frames = frames.min(self.frames);
178
179        let mut v = ArrayVec::new();
180
181        // SAFETY:
182        //
183        // * The constructors ensure that the pointed-to data slice has a length of at
184        // least `frames * self.channels()`.
185        // * The data slice cannot be moved, so the pointers are valid for the lifetime
186        // of the slice.
187        // * We have constrained `frames` above.
188        // * We have asserted at compile-time that `MAX_CHANNELS` is non-zero.
189        unsafe {
190            for ptr in self.offsets.iter() {
191                v.push_unchecked(core::slice::from_raw_parts(*ptr, frames));
192            }
193        }
194
195        v
196    }
197
198    /// Get all channels as immutable slices in the given range.
199    ///
200    /// If all or part of the range falls out of bounds, then only the part that falls
201    /// within range will be returned.
202    #[inline]
203    pub fn as_slices_with_range(&self, range: Range<usize>) -> ArrayVec<&[T], MAX_CHANNELS> {
204        let start_frame = range.start.min(self.frames);
205        let frames = range.end.min(self.frames) - start_frame;
206
207        let mut v = ArrayVec::new();
208
209        // SAFETY:
210        //
211        // * The constructors ensure that the pointed-to data slice has a length of at
212        // least `frames * self.channels()`.
213        // * The data slice cannot be moved, so the pointers are valid for the lifetime
214        // of the slice.
215        // * We have constrained the given range above.
216        // * We have asserted at compile-time that `MAX_CHANNELS` is non-zero.
217        unsafe {
218            for ptr in self.offsets.iter() {
219                v.push_unchecked(core::slice::from_raw_parts(ptr.add(start_frame), frames));
220            }
221        }
222
223        v
224    }
225
226    /// Get the entire contents of the buffer as a single immutable slice.
227    pub fn raw(&self) -> &[T] {
228        self.data
229    }
230}
231
232impl<'a, T: Clone + Copy + Default + Sized, const MAX_CHANNELS: usize> Index<usize>
233    for VarChannelBufferRef<'a, T, MAX_CHANNELS>
234{
235    type Output = [T];
236
237    #[inline(always)]
238    fn index(&self, index: usize) -> &Self::Output {
239        self.channel(index).unwrap()
240    }
241}
242
243impl<'a, T: Clone + Copy + Default + Sized, const MAX_CHANNELS: usize> Default
244    for VarChannelBufferRef<'a, T, MAX_CHANNELS>
245{
246    fn default() -> Self {
247        Self::empty()
248    }
249}
250
251impl<'a, T: Clone + Copy + Default + Sized, const MAX_CHANNELS: usize> Into<&'a [T]>
252    for VarChannelBufferRefMut<'a, T, MAX_CHANNELS>
253{
254    fn into(self) -> &'a [T] {
255        self.data
256    }
257}
258
259// # SAFETY: All the stored pointers are valid for the lifetime of the struct, and
260// the public API prevents misuse of the pointers.
261unsafe impl<'a, T: Clone + Copy + Default + Sized, const CHANNELS: usize> Send
262    for VarChannelBufferRef<'a, T, CHANNELS>
263{
264}
265// # SAFETY: All the stored pointers are valid for the lifetime of the struct, and
266// the public API prevents misuse of the pointers.
267unsafe impl<'a, T: Clone + Copy + Default + Sized, const CHANNELS: usize> Sync
268    for VarChannelBufferRef<'a, T, CHANNELS>
269{
270}
271
272/// A mutable memory-efficient buffer of samples with a fixed runtime number of
273/// channels each with a fixed runtime number of frames (samples in a single channel
274/// of audio).
275///
276/// This version uses a reference to a slice as its data source.
277#[derive(Debug)]
278pub struct VarChannelBufferRefMut<'a, T: Clone + Copy + Default + Sized, const MAX_CHANNELS: usize>
279{
280    data: &'a mut [T],
281    offsets: ArrayVec<*mut T, MAX_CHANNELS>,
282    frames: usize,
283}
284
285impl<'a, T: Clone + Copy + Default + Sized, const MAX_CHANNELS: usize>
286    VarChannelBufferRefMut<'a, T, MAX_CHANNELS>
287{
288    const _COMPILE_TIME_ASSERTS: () = {
289        assert!(MAX_CHANNELS > 0);
290    };
291
292    #[inline(always)]
293    pub(crate) unsafe fn from_raw(
294        data: &'a mut [T],
295        offsets: ArrayVec<*mut T, MAX_CHANNELS>,
296        frames: usize,
297    ) -> Self {
298        let _ = Self::_COMPILE_TIME_ASSERTS;
299
300        Self {
301            data,
302            offsets,
303            frames,
304        }
305    }
306
307    /// Create an empty [`VarChannelBufferRefMut`] with no data.
308    pub fn empty() -> Self {
309        let _ = Self::_COMPILE_TIME_ASSERTS;
310
311        let data = &mut [];
312        let mut offsets = ArrayVec::new();
313        offsets.push(data.as_mut_ptr());
314
315        Self {
316            data,
317            offsets,
318            frames: 0,
319        }
320    }
321
322    /// Create a new [`VarChannelBufferRefMut`] using the given slice as the data.
323    ///
324    /// # Panics
325    /// Panics if `channels.get() > MAX_CHANNELS`.
326    pub fn new(data: &'a mut [T], channels: NonZeroUsize) -> Self {
327        let _ = Self::_COMPILE_TIME_ASSERTS;
328
329        assert!(channels.get() <= MAX_CHANNELS);
330
331        let frames = data.len() / channels.get();
332
333        let mut offsets = ArrayVec::new();
334        // SAFETY:
335        // * All of these pointers point to valid memory in the slice.
336        // * We have constrained `channels` above.
337        // * We have asserted at compile-time that `MAX_CHANNELS` is non-zero.
338        unsafe {
339            for ch_i in 0..channels.get() {
340                offsets.push_unchecked(data.as_mut_ptr().add(ch_i * frames));
341            }
342        }
343
344        Self {
345            data,
346            offsets,
347            frames,
348        }
349    }
350
351    /// Create a new [`VarChannelBufferRefMut`] using the given slice as the data.
352    ///
353    /// # Safety
354    /// The caller must uphold that:
355    /// * `data.len() >= frames * self.channels().get()`
356    /// * and `channels.get() <= MAX_CHANNELS`
357    pub unsafe fn new_unchecked(data: &'a mut [T], frames: usize, channels: NonZeroUsize) -> Self {
358        let _ = Self::_COMPILE_TIME_ASSERTS;
359
360        let mut offsets = ArrayVec::new();
361        for ch_i in 0..channels.get() {
362            offsets.push_unchecked(data.as_mut_ptr().add(ch_i * frames));
363        }
364
365        Self {
366            data,
367            offsets,
368            frames,
369        }
370    }
371
372    /// The number of channels in this buffer.
373    pub fn channels(&self) -> NonZeroUsize {
374        // SAFETY: The constructors ensure that there is at least one element in `offsets`.
375        unsafe { NonZeroUsize::new_unchecked(self.offsets.len()) }
376    }
377
378    /// The number of frames (samples in a single channel of audio) that are allocated
379    /// in this buffer.
380    pub fn frames(&self) -> usize {
381        self.frames
382    }
383
384    #[inline(always)]
385    /// Get an immutable reference to the channel at `index`. The slice will have a length
386    /// of `self.frames()`.
387    ///
388    /// Returns `None` if `index` is out of bounds.
389    pub fn channel(&self, index: usize) -> Option<&[T]> {
390        if index < self.offsets.len() {
391            // SAFETY:
392            // We haved checked that `index` is within bounds.
393            unsafe { Some(self.channel_unchecked(index)) }
394        } else {
395            None
396        }
397    }
398
399    #[inline(always)]
400    /// Get an immutable reference to the channel at `index`. The slice will have a length
401    /// of `self.frames()`.
402    ///
403    /// # Safety
404    /// `index` must be less than `self.channels()`
405    pub unsafe fn channel_unchecked(&self, index: usize) -> &[T] {
406        // SAFETY:
407        //
408        // * The constructors ensure that the pointed-to data slice has a length of at
409        // least `frames * self.channels()`.
410        // * The caller upholds that `index` is within bounds.
411        // * The data slice cannot be moved, so the pointers are valid for the lifetime
412        // of the slice.
413        // * We have asserted at compile-time that `MAX_CHANNELS` is non-zero.
414        core::slice::from_raw_parts(*self.offsets.get_unchecked(index), self.frames)
415    }
416
417    #[inline(always)]
418    /// Get a mutable reference to the channel at `index`. The slice will have a length
419    /// of `self.frames()`.
420    ///
421    /// Returns `None` if `index` is out of bounds.
422    pub fn channel_mut(&mut self, index: usize) -> Option<&mut [T]> {
423        if index < self.offsets.len() {
424            // SAFETY:
425            // We haved checked that `index` is within bounds.
426            unsafe { Some(self.channel_unchecked_mut(index)) }
427        } else {
428            None
429        }
430    }
431
432    #[inline(always)]
433    /// Get a mutable reference to the channel at `index`. The slice will have a length
434    /// of `self.frames()`.
435    ///
436    /// # Safety
437    /// `index` must be less than `self.channels()`
438    pub unsafe fn channel_unchecked_mut(&mut self, index: usize) -> &mut [T] {
439        // SAFETY:
440        //
441        // * The constructors ensure that the pointed-to data slice has a length of at
442        // least `frames * self.channels()`.
443        // * The caller upholds that `index` is within bounds.
444        // * The data slice cannot be moved, so the pointers are valid for the lifetime
445        // of the slice.
446        // * `self` is borrowed as mutable, ensuring that no other references to the
447        // data slice can exist.
448        // * We have asserted at compile-time that `MAX_CHANNELS` is non-zero.
449        core::slice::from_raw_parts_mut(*self.offsets.get_unchecked(index), self.frames)
450    }
451
452    /// Get all channels as immutable slices. Each slice will have a length of `self.frames()`.
453    #[inline]
454    pub fn as_slices(&self) -> ArrayVec<&[T], MAX_CHANNELS> {
455        let mut v = ArrayVec::new();
456
457        // SAFETY:
458        //
459        // * The constructors ensure that the pointed-to data slice has a length of at
460        // least `frames * self.channels()`.
461        // * The data slice cannot be moved, so the pointers are valid for the lifetime
462        // of the slice.
463        // * We have asserted at compile-time that `MAX_CHANNELS` is non-zero.
464        unsafe {
465            for ptr in self.offsets.iter() {
466                v.push_unchecked(core::slice::from_raw_parts(*ptr, self.frames));
467            }
468        }
469
470        v
471    }
472
473    /// Get all channels as mutable slices. Each slice will have a length of `self.frames()`.
474    #[inline]
475    pub fn as_mut_slices(&mut self) -> ArrayVec<&mut [T], MAX_CHANNELS> {
476        let mut v = ArrayVec::new();
477
478        // SAFETY:
479        //
480        // * The constructors ensure that the pointed-to data slice has a length of at
481        // least `frames * self.channels()`.
482        // * The data slice cannot be moved, so the pointers are valid for the lifetime
483        // of the slice.
484        // * `self` is borrowed as mutable, and none of these slices overlap, so all
485        // mutability rules are being upheld.
486        // * We have asserted at compile-time that `MAX_CHANNELS` is non-zero.
487        unsafe {
488            for ptr in self.offsets.iter() {
489                v.push_unchecked(core::slice::from_raw_parts_mut(*ptr, self.frames));
490            }
491        }
492
493        v
494    }
495
496    /// Get all channels as immutable slices with the given length in frames.
497    ///
498    /// If `frames > self.frames()`, then each slice will have a length of `self.frames()`
499    /// instead.
500    #[inline]
501    pub fn as_slices_with_length(&self, frames: usize) -> ArrayVec<&[T], MAX_CHANNELS> {
502        let frames = frames.min(self.frames);
503
504        let mut v = ArrayVec::new();
505
506        // SAFETY:
507        //
508        // * The constructors ensure that the pointed-to data slice has a length of at
509        // least `frames * self.channels()`.
510        // * The data slice cannot be moved, so the pointers are valid for the lifetime
511        // of the slice.
512        // * We have constrained `frames` above.
513        // * We have asserted at compile-time that `MAX_CHANNELS` is non-zero.
514        unsafe {
515            for ptr in self.offsets.iter() {
516                v.push_unchecked(core::slice::from_raw_parts(*ptr, frames));
517            }
518        }
519
520        v
521    }
522
523    /// Get all channels as mutable slices with the given length in frames.
524    ///
525    /// If `frames > self.frames()`, then each slice will have a length of `self.frames()`
526    /// instead.
527    #[inline]
528    pub fn as_mut_slices_with_length(&mut self, frames: usize) -> ArrayVec<&mut [T], MAX_CHANNELS> {
529        let frames = frames.min(self.frames);
530
531        let mut v = ArrayVec::new();
532
533        // SAFETY:
534        //
535        // * The constructors ensure that the pointed-to data slice has a length of at
536        // least `frames * self.channels()`.
537        // * The data slice cannot be moved, so the pointers are valid for the lifetime
538        // of the slice.
539        // * We have constrained `frames` above.
540        // * `self` is borrowed as mutable, and none of these slices overlap, so all
541        // mutability rules are being upheld.
542        // * We have asserted at compile-time that `MAX_CHANNELS` is non-zero.
543        unsafe {
544            for ptr in self.offsets.iter() {
545                v.push_unchecked(core::slice::from_raw_parts_mut(*ptr, frames));
546            }
547        }
548
549        v
550    }
551
552    /// Get all channels as immutable slices in the given range.
553    ///
554    /// If all or part of the range falls out of bounds, then only the part that falls
555    /// within range will be returned.
556    #[inline]
557    pub fn as_slices_with_range(&self, range: Range<usize>) -> ArrayVec<&[T], MAX_CHANNELS> {
558        let start_frame = range.start.min(self.frames);
559        let frames = range.end.min(self.frames) - start_frame;
560
561        let mut v = ArrayVec::new();
562
563        // SAFETY:
564        //
565        // * The constructors ensure that the pointed-to data slice has a length of at
566        // least `frames * self.channels()`.
567        // * The data slice cannot be moved, so the pointers are valid for the lifetime
568        // of the slice.
569        // * We have constrained the given range above.
570        // * We have asserted at compile-time that `MAX_CHANNELS` is non-zero.
571        unsafe {
572            for ptr in self.offsets.iter() {
573                v.push_unchecked(core::slice::from_raw_parts(ptr.add(start_frame), frames));
574            }
575        }
576
577        v
578    }
579
580    /// Get all channels as immutable slices in the given range.
581    ///
582    /// If all or part of the range falls out of bounds, then only the part that falls
583    /// within range will be returned.
584    #[inline]
585    pub fn as_mut_slices_with_range(
586        &mut self,
587        range: Range<usize>,
588    ) -> ArrayVec<&mut [T], MAX_CHANNELS> {
589        let start_frame = range.start.min(self.frames);
590        let frames = range.end.min(self.frames) - start_frame;
591
592        let mut v = ArrayVec::new();
593
594        // SAFETY:
595        //
596        // * The constructors ensure that the pointed-to data slice has a length of at
597        // least `frames * self.channels()`.
598        // * The data slice cannot be moved, so the pointers are valid for the lifetime
599        // of the slice.
600        // * We have constrained the given range above.
601        // * `self` is borrowed as mutable, and none of these slices overlap, so all
602        // mutability rules are being upheld.
603        // * We have asserted at compile-time that `MAX_CHANNELS` is non-zero.
604        unsafe {
605            for ptr in self.offsets.iter_mut() {
606                v.push_unchecked(core::slice::from_raw_parts_mut(
607                    ptr.add(start_frame),
608                    frames,
609                ));
610            }
611        }
612
613        v
614    }
615
616    /// Get the entire contents of the buffer as a single immutable slice.
617    pub fn raw(&self) -> &[T] {
618        self.data
619    }
620
621    /// Get the entire contents of the buffer as a single mutable slice.
622    pub fn raw_mut(&mut self) -> &mut [T] {
623        &mut self.data[..]
624    }
625
626    /// Clear all data with the default value.
627    pub fn clear(&mut self) {
628        self.raw_mut().fill(T::default());
629    }
630
631    /// Clear all data in each channel up to `frames` with the default value.
632    pub fn clear_frames(&mut self, frames: usize) {
633        for ch in self.as_mut_slices_with_length(frames) {
634            ch.fill(T::default());
635        }
636    }
637}
638
639impl<'a, T: Clone + Copy + Default + Sized, const MAX_CHANNELS: usize> Index<usize>
640    for VarChannelBufferRefMut<'a, T, MAX_CHANNELS>
641{
642    type Output = [T];
643
644    #[inline(always)]
645    fn index(&self, index: usize) -> &Self::Output {
646        self.channel(index).unwrap()
647    }
648}
649
650impl<'a, T: Clone + Copy + Default + Sized, const MAX_CHANNELS: usize> IndexMut<usize>
651    for VarChannelBufferRefMut<'a, T, MAX_CHANNELS>
652{
653    #[inline(always)]
654    fn index_mut(&mut self, index: usize) -> &mut Self::Output {
655        self.channel_mut(index).unwrap()
656    }
657}
658
659impl<'a, T: Clone + Copy + Default + Sized, const MAX_CHANNELS: usize> Default
660    for VarChannelBufferRefMut<'a, T, MAX_CHANNELS>
661{
662    fn default() -> Self {
663        Self::empty()
664    }
665}
666
667impl<'a, T: Clone + Copy + Default + Sized, const MAX_CHANNELS: usize>
668    Into<VarChannelBufferRef<'a, T, MAX_CHANNELS>> for VarChannelBufferRefMut<'a, T, MAX_CHANNELS>
669{
670    #[inline(always)]
671    fn into(self) -> VarChannelBufferRef<'a, T, MAX_CHANNELS> {
672        VarChannelBufferRef {
673            data: self.data,
674            // SAFETY: `ArrayVec<*const T; MAX_CHANNELS>` and `ArrayVec<*mut T; MAX_CHANNELS>`
675            // are interchangeable bit-for-bit.
676            offsets: unsafe { core::mem::transmute_copy(&self.offsets) },
677            frames: self.frames,
678        }
679    }
680}
681
682impl<'a, T: Clone + Copy + Default + Sized, const MAX_CHANNELS: usize> Into<&'a mut [T]>
683    for VarChannelBufferRefMut<'a, T, MAX_CHANNELS>
684{
685    fn into(self) -> &'a mut [T] {
686        self.data
687    }
688}
689
690// # SAFETY: All the stored pointers are valid for the lifetime of the struct, and
691// the public API prevents misuse of the pointers.
692unsafe impl<'a, T: Clone + Copy + Default + Sized, const CHANNELS: usize> Send
693    for VarChannelBufferRefMut<'a, T, CHANNELS>
694{
695}
696// # SAFETY: All the stored pointers are valid for the lifetime of the struct, and
697// the public API prevents misuse of the pointers.
698unsafe impl<'a, T: Clone + Copy + Default + Sized, const CHANNELS: usize> Sync
699    for VarChannelBufferRefMut<'a, T, CHANNELS>
700{
701}