mirror of
https://github.com/openharmony/third_party_rust_tinyvec.git
synced 2026-07-21 01:35:22 -04:00
Add TryFrom<&'_ [A::Item]> for ArrayVec<A> (#134)
This commit is contained in:
+34
-1
@@ -1,5 +1,5 @@
|
||||
use super::*;
|
||||
use core::convert::TryInto;
|
||||
use core::convert::{TryInto, TryFrom};
|
||||
|
||||
#[cfg(feature = "serde")]
|
||||
use core::marker::PhantomData;
|
||||
@@ -1190,6 +1190,39 @@ impl<A: Array> From<A> for ArrayVec<A> {
|
||||
}
|
||||
}
|
||||
|
||||
/// The error type returned when a conversion from a slice to an [`ArrayVec`] fails.
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct TryFromSliceError(());
|
||||
|
||||
impl<T, A> TryFrom<&'_ [T]> for ArrayVec<A>
|
||||
where
|
||||
T: Clone + Default,
|
||||
A: Array<Item = T>,
|
||||
{
|
||||
type Error = TryFromSliceError;
|
||||
|
||||
#[inline]
|
||||
#[must_use]
|
||||
/// The output has a length equal to that of the slice, with the same capacity as `A`.
|
||||
fn try_from(slice: &[T]) -> Result<Self, Self::Error> {
|
||||
if slice.len() > A::CAPACITY {
|
||||
Err(TryFromSliceError(()))
|
||||
} else {
|
||||
let mut arr = ArrayVec::new();
|
||||
// We do not use ArrayVec::extend_from_slice, because it looks like LLVM
|
||||
// fails to deduplicate all the length-checking logic between the
|
||||
// above if and the contents of that method, thus producing much
|
||||
// slower code. Unlike many of the other optimizations in this
|
||||
// crate, this one is worth keeping an eye on. I see no reason, for
|
||||
// any element type, that these should produce different code. But
|
||||
// they do. (rustc 1.51.0)
|
||||
arr.set_len(slice.len());
|
||||
arr.as_mut_slice().clone_from_slice(slice);
|
||||
Ok(arr)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<A: Array> FromIterator<A::Item> for ArrayVec<A> {
|
||||
#[inline]
|
||||
#[must_use]
|
||||
|
||||
+4
-13
@@ -3,6 +3,7 @@
|
||||
use super::*;
|
||||
|
||||
use alloc::vec::{self, Vec};
|
||||
use core::convert::TryFrom;
|
||||
use tinyvec_macros::impl_mirrored;
|
||||
|
||||
#[cfg(feature = "serde")]
|
||||
@@ -1114,20 +1115,10 @@ where
|
||||
#[inline]
|
||||
#[must_use]
|
||||
fn from(slice: &[T]) -> Self {
|
||||
if slice.len() > A::CAPACITY {
|
||||
TinyVec::Heap(slice.into())
|
||||
} else {
|
||||
let mut arr = ArrayVec::new();
|
||||
// We do not use ArrayVec::extend_from_slice, because it looks like LLVM
|
||||
// fails to deduplicate all the length-checking logic between the
|
||||
// above if and the contents of that method, thus producing much
|
||||
// slower code. Unlike many of the other optimizations in this
|
||||
// crate, this one is worth keeping an eye on. I see no reason, for
|
||||
// any element type, that these should produce different code. But
|
||||
// they do. (rustc 1.51.0)
|
||||
arr.set_len(slice.len());
|
||||
arr.as_mut_slice().clone_from_slice(slice);
|
||||
if let Ok(arr) = ArrayVec::try_from(slice) {
|
||||
TinyVec::Inline(arr)
|
||||
} else {
|
||||
TinyVec::Heap(slice.into())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -445,3 +445,21 @@ fn ArrayVec_ser_de() {
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ArrayVec_try_from_slice() {
|
||||
use std::convert::TryFrom;
|
||||
|
||||
let nums = [1, 2, 3, 4];
|
||||
|
||||
let empty: Result<ArrayVec<[i32; 2]>, _> = ArrayVec::try_from(&nums[..0]);
|
||||
assert!(empty.is_ok());
|
||||
assert_eq!(empty.unwrap().as_slice(), &[]);
|
||||
|
||||
let fits: Result<ArrayVec<[i32; 2]>, _> = ArrayVec::try_from(&nums[..2]);
|
||||
assert!(fits.is_ok());
|
||||
assert_eq!(fits.unwrap().as_slice(), &[1, 2]);
|
||||
|
||||
let doesnt_fit: Result<ArrayVec<[i32; 2]>, _> = ArrayVec::try_from(&nums[..4]);
|
||||
assert!(doesnt_fit.is_err());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user