|
1 | 1 | use crate::ringbuffer_trait::{RingBufferIntoIterator, RingBufferIterator, RingBufferMutIterator}; |
2 | 2 | use crate::RingBuffer; |
3 | 3 | use core::iter::FromIterator; |
4 | | -use core::mem; |
5 | 4 | use core::mem::MaybeUninit; |
| 5 | +use core::mem::{self, ManuallyDrop}; |
6 | 6 | use core::ops::{Index, IndexMut}; |
7 | 7 |
|
8 | 8 | /// The `ConstGenericRingBuffer` struct is a `RingBuffer` implementation which does not require `alloc` but |
@@ -42,11 +42,14 @@ pub struct ConstGenericRingBuffer<T, const CAP: usize> { |
42 | 42 |
|
43 | 43 | impl<T, const CAP: usize> From<[T; CAP]> for ConstGenericRingBuffer<T, CAP> { |
44 | 44 | fn from(value: [T; CAP]) -> Self { |
| 45 | + let v = ManuallyDrop::new(value); |
45 | 46 | Self { |
46 | 47 | // Safety: |
47 | 48 | // T has the same layout as MaybeUninit<T> |
48 | 49 | // [T; N] has the same layout as [MaybeUninit<T>; N] |
49 | | - buf: unsafe { mem::transmute_copy(&value) }, |
| 50 | + // Without ManuallyDrop this would be unsound as |
| 51 | + // transmute_copy doesn't take ownership |
| 52 | + buf: unsafe { mem::transmute_copy(&v) }, |
50 | 53 | readptr: 0, |
51 | 54 | writeptr: CAP, |
52 | 55 | } |
@@ -178,12 +181,8 @@ impl<T, const CAP: usize> ConstGenericRingBuffer<T, CAP> { |
178 | 181 | #[allow(clippy::let_unit_value)] |
179 | 182 | let () = Self::ERROR_CAPACITY_IS_NOT_ALLOWED_TO_BE_ZERO; |
180 | 183 |
|
181 | | - // allow here since we are constructing an array of MaybeUninit<T> |
182 | | - // which explicitly *is* defined behavior |
183 | | - // https://rust-lang.github.io/rust-clippy/master/index.html#uninit_assumed_init |
184 | | - #[allow(clippy::uninit_assumed_init)] |
185 | 184 | Self { |
186 | | - buf: unsafe { MaybeUninit::uninit().assume_init() }, |
| 185 | + buf: [const { MaybeUninit::<T>::uninit() }; CAP], |
187 | 186 | writeptr: 0, |
188 | 187 | readptr: 0, |
189 | 188 | } |
@@ -280,7 +279,6 @@ unsafe impl<T, const CAP: usize> RingBuffer<T> for ConstGenericRingBuffer<T, CAP |
280 | 279 | // make sure we drop whatever is being overwritten |
281 | 280 | // SAFETY: the buffer is full, so this must be initialized |
282 | 281 | // : also, index has been masked |
283 | | - // make sure we drop because it won't happen automatically |
284 | 282 | ret = Some(unsafe { previous_value.assume_init() }); |
285 | 283 | self.readptr += 1; |
286 | 284 | } |
@@ -360,7 +358,10 @@ impl<T, const CAP: usize> IndexMut<usize> for ConstGenericRingBuffer<T, CAP> { |
360 | 358 |
|
361 | 359 | #[cfg(test)] |
362 | 360 | mod tests { |
363 | | - use super::*; |
| 361 | + use crate::{AllocRingBuffer, ConstGenericRingBuffer, GrowableAllocRingBuffer, RingBuffer}; |
| 362 | + use alloc::collections::{LinkedList, VecDeque}; |
| 363 | + use alloc::string::ToString; |
| 364 | + use alloc::vec; |
364 | 365 |
|
365 | 366 | #[test] |
366 | 367 | fn test_not_power_of_two() { |
@@ -428,79 +429,71 @@ mod tests { |
428 | 429 | } |
429 | 430 | } |
430 | 431 |
|
431 | | - #[cfg(test)] |
432 | | - mod tests { |
433 | | - use crate::{AllocRingBuffer, ConstGenericRingBuffer, GrowableAllocRingBuffer, RingBuffer}; |
434 | | - use alloc::collections::{LinkedList, VecDeque}; |
435 | | - use alloc::string::ToString; |
436 | | - use alloc::vec; |
437 | | - |
438 | | - #[test] |
439 | | - fn from() { |
440 | | - assert_eq!( |
441 | | - ConstGenericRingBuffer::<i32, 3>::from([1, 2, 3]).to_vec(), |
442 | | - vec![1, 2, 3] |
443 | | - ); |
444 | | - |
445 | | - let v: &[i32; 3] = &[1, 2, 3]; |
446 | | - assert_eq!( |
447 | | - ConstGenericRingBuffer::<i32, 3>::from(v).to_vec(), |
448 | | - vec![1, 2, 3] |
449 | | - ); |
450 | | - |
451 | | - let v: &[i32] = &[1, 2, 3]; |
452 | | - assert_eq!( |
453 | | - ConstGenericRingBuffer::<i32, 3>::from(v).to_vec(), |
454 | | - vec![1, 2, 3] |
455 | | - ); |
456 | | - |
457 | | - let v: &mut [i32; 3] = &mut [1, 2, 3]; |
458 | | - assert_eq!( |
459 | | - ConstGenericRingBuffer::<i32, 3>::from(v).to_vec(), |
460 | | - vec![1, 2, 3] |
461 | | - ); |
462 | | - |
463 | | - let v: &mut [i32] = &mut [1, 2, 3]; |
464 | | - assert_eq!( |
465 | | - ConstGenericRingBuffer::<i32, 3>::from(v).to_vec(), |
466 | | - vec![1, 2, 3] |
467 | | - ); |
468 | | - |
469 | | - assert_eq!( |
470 | | - ConstGenericRingBuffer::<i32, 3>::from(vec![1, 2, 3]).to_vec(), |
471 | | - vec![1, 2, 3] |
472 | | - ); |
473 | | - assert_eq!( |
474 | | - ConstGenericRingBuffer::<i32, 3>::from( |
475 | | - vec![1, 2, 3].into_iter().collect::<VecDeque<_>>() |
476 | | - ) |
477 | | - .to_vec(), |
478 | | - vec![1, 2, 3] |
479 | | - ); |
480 | | - assert_eq!( |
481 | | - ConstGenericRingBuffer::<i32, 3>::from( |
482 | | - vec![1, 2, 3].into_iter().collect::<LinkedList<_>>() |
483 | | - ) |
| 432 | + #[test] |
| 433 | + fn from() { |
| 434 | + assert_eq!( |
| 435 | + ConstGenericRingBuffer::<i32, 3>::from([1, 2, 3]).to_vec(), |
| 436 | + vec![1, 2, 3] |
| 437 | + ); |
| 438 | + |
| 439 | + let v: &[i32; 3] = &[1, 2, 3]; |
| 440 | + assert_eq!( |
| 441 | + ConstGenericRingBuffer::<i32, 3>::from(v).to_vec(), |
| 442 | + vec![1, 2, 3] |
| 443 | + ); |
| 444 | + |
| 445 | + let v: &[i32] = &[1, 2, 3]; |
| 446 | + assert_eq!( |
| 447 | + ConstGenericRingBuffer::<i32, 3>::from(v).to_vec(), |
| 448 | + vec![1, 2, 3] |
| 449 | + ); |
| 450 | + |
| 451 | + let v: &mut [i32; 3] = &mut [1, 2, 3]; |
| 452 | + assert_eq!( |
| 453 | + ConstGenericRingBuffer::<i32, 3>::from(v).to_vec(), |
| 454 | + vec![1, 2, 3] |
| 455 | + ); |
| 456 | + |
| 457 | + let v: &mut [i32] = &mut [1, 2, 3]; |
| 458 | + assert_eq!( |
| 459 | + ConstGenericRingBuffer::<i32, 3>::from(v).to_vec(), |
| 460 | + vec![1, 2, 3] |
| 461 | + ); |
| 462 | + |
| 463 | + assert_eq!( |
| 464 | + ConstGenericRingBuffer::<i32, 3>::from(vec![1, 2, 3]).to_vec(), |
| 465 | + vec![1, 2, 3] |
| 466 | + ); |
| 467 | + assert_eq!( |
| 468 | + ConstGenericRingBuffer::<i32, 3>::from( |
| 469 | + vec![1, 2, 3].into_iter().collect::<VecDeque<_>>() |
| 470 | + ) |
| 471 | + .to_vec(), |
| 472 | + vec![1, 2, 3] |
| 473 | + ); |
| 474 | + assert_eq!( |
| 475 | + ConstGenericRingBuffer::<i32, 3>::from( |
| 476 | + vec![1, 2, 3].into_iter().collect::<LinkedList<_>>() |
| 477 | + ) |
| 478 | + .to_vec(), |
| 479 | + vec![1, 2, 3] |
| 480 | + ); |
| 481 | + assert_eq!( |
| 482 | + ConstGenericRingBuffer::<_, 3>::from("abc".to_string()).to_vec(), |
| 483 | + vec!['a', 'b', 'c'] |
| 484 | + ); |
| 485 | + assert_eq!( |
| 486 | + ConstGenericRingBuffer::<_, 3>::from("abc").to_vec(), |
| 487 | + vec!['a', 'b', 'c'] |
| 488 | + ); |
| 489 | + assert_eq!( |
| 490 | + ConstGenericRingBuffer::<_, 3>::from(GrowableAllocRingBuffer::from(vec![1, 2, 3])) |
484 | 491 | .to_vec(), |
485 | | - vec![1, 2, 3] |
486 | | - ); |
487 | | - assert_eq!( |
488 | | - ConstGenericRingBuffer::<_, 3>::from("abc".to_string()).to_vec(), |
489 | | - vec!['a', 'b', 'c'] |
490 | | - ); |
491 | | - assert_eq!( |
492 | | - ConstGenericRingBuffer::<_, 3>::from("abc").to_vec(), |
493 | | - vec!['a', 'b', 'c'] |
494 | | - ); |
495 | | - assert_eq!( |
496 | | - ConstGenericRingBuffer::<_, 3>::from(GrowableAllocRingBuffer::from(vec![1, 2, 3])) |
497 | | - .to_vec(), |
498 | | - vec![1, 2, 3] |
499 | | - ); |
500 | | - assert_eq!( |
501 | | - ConstGenericRingBuffer::<_, 3>::from(AllocRingBuffer::from(vec![1, 2, 3])).to_vec(), |
502 | | - vec![1, 2, 3] |
503 | | - ); |
504 | | - } |
| 492 | + vec![1, 2, 3] |
| 493 | + ); |
| 494 | + assert_eq!( |
| 495 | + ConstGenericRingBuffer::<_, 3>::from(AllocRingBuffer::from(vec![1, 2, 3])).to_vec(), |
| 496 | + vec![1, 2, 3] |
| 497 | + ); |
505 | 498 | } |
506 | 499 | } |
0 commit comments