Skip to content

Commit 76aa8a8

Browse files
committed
rust: alloc: vec: Add TryFrom trait
Signed-off-by: Janne Grunau <j@jannau.net>
1 parent 487e4c3 commit 76aa8a8

1 file changed

Lines changed: 48 additions & 0 deletions

File tree

rust/kernel/alloc/kvec.rs

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1399,3 +1399,51 @@ mod tests {
13991399
}
14001400
}
14011401
}
1402+
1403+
// #[stable(feature = "array_try_from_vec", since = "1.48.0")]
1404+
impl<T, A: Allocator, const N: usize> TryFrom<Vec<T, A>> for [T; N] {
1405+
type Error = Vec<T, A>;
1406+
1407+
/// Gets the entire contents of the `Vec<T>` as an array,
1408+
/// if its size exactly matches that of the requested array.
1409+
///
1410+
/// # Examples
1411+
///
1412+
/// ```
1413+
/// assert_eq!(vec![1, 2, 3].try_into(), Ok([1, 2, 3]));
1414+
/// assert_eq!(<Vec<i32>>::new().try_into(), Ok([]));
1415+
/// ```
1416+
///
1417+
/// If the length doesn't match, the input comes back in `Err`:
1418+
/// ```
1419+
/// let r: Result<[i32; 4], _> = (0..10).collect::<Vec<_>>().try_into();
1420+
/// assert_eq!(r, Err(vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9]));
1421+
/// ```
1422+
///
1423+
/// If you're fine with just getting a prefix of the `Vec<T>`,
1424+
/// you can call [`.truncate(N)`](Vec::truncate) first.
1425+
/// ```
1426+
/// let mut v = String::from("hello world").into_bytes();
1427+
/// v.sort();
1428+
/// v.truncate(2);
1429+
/// let [a, b]: [_; 2] = v.try_into().unwrap();
1430+
/// assert_eq!(a, b' ');
1431+
/// assert_eq!(b, b'd');
1432+
/// ```
1433+
fn try_from(mut vec: Vec<T, A>) -> Result<[T; N], Vec<T, A>> {
1434+
if vec.len() != N {
1435+
return Err(vec);
1436+
}
1437+
1438+
// SAFETY: `.set_len(0)` is always sound.
1439+
unsafe { vec.dec_len(vec.len()) };
1440+
1441+
// SAFETY: A `Vec`'s pointer is always aligned properly, and
1442+
// the alignment the array needs is the same as the items.
1443+
// We checked earlier that we have sufficient items.
1444+
// The items will not double-drop as the `set_len`
1445+
// tells the `Vec` not to also drop them.
1446+
let array = unsafe { ptr::read(vec.as_ptr() as *const [T; N]) };
1447+
Ok(array)
1448+
}
1449+
}

0 commit comments

Comments
 (0)