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}