diff --git a/src/lib.rs b/src/lib.rs index af12044..5018c7b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1668,6 +1668,10 @@ impl SmallVec { } #[inline] + #[deprecated( + since = "2.0.0-alpha.13", + note = "use `TryInto::<[T; N]>::into` instead" + )] pub fn into_inner(self) -> Result<[T; N], Self> { if self.len() != N { Err(self) @@ -2689,6 +2693,25 @@ impl From<[T; M]> for SmallVec { } } +impl TryFrom> for [T; M] { + type Error = SmallVec; + + #[inline] + fn try_from(mut this: SmallVec) -> Result<[T; M], SmallVec> { + if this.len() != M { + Err(this) + } else { + // SAFETY: we release ownership of the elements we hold + unsafe { + this.set_len(0); + } + let ptr = this.as_ptr() as *const [T; M]; + // SAFETY: these elements are initialized since the length was `M` + unsafe { Ok(ptr.read()) } + } + } +} + impl From> for SmallVec { fn from(array: Vec) -> Self { Self::from_vec(array) diff --git a/src/tests.rs b/src/tests.rs index e05f24d..803dc4f 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -712,6 +712,26 @@ fn test_into_inner() { assert_eq!(vec.clone().into_inner(), Err(vec)); } +fn test_try_into_array() { + // Inline < capacity + let vec = SmallVec::::from_iter(0..1); + assert_eq!(<[u8; 0]>::try_from(vec.clone()), Err(vec.clone())); + assert_eq!(<[u8; 1]>::try_from(vec.clone()), Ok([0])); + assert_eq!(<[u8; 2]>::try_from(vec.clone()), Err(vec)); + + // Inline == capacity + let vec = SmallVec::::from_iter(0..2); + assert_eq!(<[u8; 1]>::try_from(vec.clone()), Err(vec.clone())); + assert_eq!(<[u8; 2]>::try_from(vec.clone()), Ok([0, 1])); + assert_eq!(<[u8; 3]>::try_from(vec.clone()), Err(vec)); + + // Heap + let vec = SmallVec::::from_iter(0..3); + assert_eq!(<[u8; 2]>::try_from(vec.clone()), Err(vec.clone())); + assert_eq!(<[u8; 3]>::try_from(vec.clone()), Ok([0, 1, 2])); + assert_eq!(<[u8; 4]>::try_from(vec.clone()), Err(vec)); +} + #[test] fn test_from_vec() { let vec = vec![];