|
1 |
| -use core::{cmp::Ordering, fmt, hash, iter::FromIterator, mem::MaybeUninit, ops, ptr, slice}; |
| 1 | +use core::{ |
| 2 | + cmp::Ordering, |
| 3 | + fmt, hash, |
| 4 | + iter::FromIterator, |
| 5 | + mem, |
| 6 | + mem::{ManuallyDrop, MaybeUninit}, |
| 7 | + ops, ptr, slice, |
| 8 | +}; |
2 | 9 |
|
3 | 10 | /// A fixed capacity [`Vec`](https://doc.rust-lang.org/std/vec/struct.Vec.html).
|
4 | 11 | ///
|
@@ -85,6 +92,45 @@ impl<T, const N: usize> Vec<T, N> {
|
85 | 92 | Ok(v)
|
86 | 93 | }
|
87 | 94 |
|
| 95 | + /// Constructs a new vector with a fixed capacity of `N`, initializing |
| 96 | + /// it with the provided array. |
| 97 | + /// |
| 98 | + /// The length of the provided array, `M` may be equal to _or_ less than |
| 99 | + /// the capacity of the vector, `N`. |
| 100 | + /// |
| 101 | + /// If the length of the provided array is greater than the capacity of the |
| 102 | + /// vector a compile-time error will be produced. |
| 103 | + pub fn from_array<const M: usize>(src: [T; M]) -> Self { |
| 104 | + // Const assert M >= 0 |
| 105 | + crate::sealed::greater_than_eq_0::<M>(); |
| 106 | + // Const assert N >= M |
| 107 | + crate::sealed::greater_than_eq::<N, M>(); |
| 108 | + |
| 109 | + // We've got to copy `src`, but we're functionally moving it. Don't run |
| 110 | + // any Drop code for T. |
| 111 | + let src = ManuallyDrop::new(src); |
| 112 | + |
| 113 | + if N == M { |
| 114 | + Self { |
| 115 | + len: N, |
| 116 | + // NOTE(unsafe) ManuallyDrop<[T; M]> and [MaybeUninit<T>; N] |
| 117 | + // have the same layout when N == M. |
| 118 | + buffer: unsafe { mem::transmute_copy(&src) }, |
| 119 | + } |
| 120 | + } else { |
| 121 | + let mut v = Vec::<T, N>::new(); |
| 122 | + |
| 123 | + for (src_elem, dst_elem) in src.iter().zip(v.buffer.iter_mut()) { |
| 124 | + // NOTE(unsafe) src element is not going to drop as src itself |
| 125 | + // is wrapped in a ManuallyDrop. |
| 126 | + dst_elem.write(unsafe { ptr::read(src_elem) }); |
| 127 | + } |
| 128 | + |
| 129 | + v.len = M; |
| 130 | + v |
| 131 | + } |
| 132 | + } |
| 133 | + |
88 | 134 | /// Clones a vec into a new vec
|
89 | 135 | pub(crate) fn clone(&self) -> Self
|
90 | 136 | where
|
@@ -858,6 +904,12 @@ impl<T, const N: usize> Drop for Vec<T, N> {
|
858 | 904 | }
|
859 | 905 | }
|
860 | 906 |
|
| 907 | +impl<T, const N: usize, const M: usize> From<[T; M]> for Vec<T, N> { |
| 908 | + fn from(array: [T; M]) -> Self { |
| 909 | + Self::from_array(array) |
| 910 | + } |
| 911 | +} |
| 912 | + |
861 | 913 | impl<'a, T: Clone, const N: usize> TryFrom<&'a [T]> for Vec<T, N> {
|
862 | 914 | type Error = ();
|
863 | 915 |
|
@@ -1533,6 +1585,38 @@ mod tests {
|
1533 | 1585 | assert!(Vec::<u8, 2>::from_slice(&[1, 2, 3]).is_err());
|
1534 | 1586 | }
|
1535 | 1587 |
|
| 1588 | + #[test] |
| 1589 | + fn from_array() { |
| 1590 | + // Successful construction, N == M |
| 1591 | + let v: Vec<u8, 3> = Vec::from_array([1, 2, 3]); |
| 1592 | + assert_eq!(v, Vec::<u8, 3>::from([1, 2, 3])); |
| 1593 | + assert_eq!(v.len(), 3); |
| 1594 | + assert_eq!(v.as_slice(), &[1, 2, 3]); |
| 1595 | + |
| 1596 | + // Successful construction, N > M |
| 1597 | + let v: Vec<u8, 4> = Vec::from_array([1, 2, 3]); |
| 1598 | + assert_eq!(v, Vec::<u8, 4>::from([1, 2, 3])); |
| 1599 | + assert_eq!(v.len(), 3); |
| 1600 | + assert_eq!(v.as_slice(), &[1, 2, 3]); |
| 1601 | + } |
| 1602 | + |
| 1603 | + #[test] |
| 1604 | + fn from_array_no_drop() { |
| 1605 | + struct Drops(Option<u8>); |
| 1606 | + |
| 1607 | + impl Drop for Drops { |
| 1608 | + fn drop(&mut self) { |
| 1609 | + self.0 = None; |
| 1610 | + } |
| 1611 | + } |
| 1612 | + |
| 1613 | + let v: Vec<Drops, 3> = Vec::from([Drops(Some(1)), Drops(Some(2)), Drops(Some(3))]); |
| 1614 | + |
| 1615 | + assert_eq!(v[0].0, Some(1)); |
| 1616 | + assert_eq!(v[1].0, Some(2)); |
| 1617 | + assert_eq!(v[2].0, Some(3)); |
| 1618 | + } |
| 1619 | + |
1536 | 1620 | #[test]
|
1537 | 1621 | fn starts_with() {
|
1538 | 1622 | let v: Vec<_, 8> = Vec::from_slice(b"ab").unwrap();
|
|
0 commit comments