You can easily do this with the TryInto trait (which was stabilized in Rust 1.34):
// Before Rust 2021, you need to import the trait:
// use std::convert::TryInto;
fn pop(barry: &[u8]) -> [u8; 3] {
barry.try_into().expect("slice should have length 3")
}
But even better: there is no need to clone/copy your elements! It is actually possible to get a &[u8; 3] from a &[u8]:
fn pop(barry: &[u8]) -> &[u8; 3] {
barry.try_into().expect("slice should have length 3")
}
As mentioned in the other answers, you probably don't want to panic if the length of barry is not 3, but instead handle this error gracefully.
This works thanks to these impls of the related trait TryFrom (before Rust 1.47, these only existed for arrays up to length 32):
impl<'_, T, const N: usize> TryFrom<&'_ [T]> for [T; N]
where
T: Copy,
impl<'a, T, const N: usize> TryFrom<&'a [T]> for &'a [T; N]
impl<'a, T, const N: usize> TryFrom<&'a mut [T]> for &'a mut [T; N]
Answer from Lukas Kalbertodt on Stack OverflowHow to get a slice as an array in Rust? - Stack Overflow
vector - How do I get a slice of a Vec<T> in Rust? - Stack Overflow
Cleanest way to get the index of an element in a slice by pointer/reference?
rust - How to get address of a slice? - Stack Overflow
You can easily do this with the TryInto trait (which was stabilized in Rust 1.34):
// Before Rust 2021, you need to import the trait:
// use std::convert::TryInto;
fn pop(barry: &[u8]) -> [u8; 3] {
barry.try_into().expect("slice should have length 3")
}
But even better: there is no need to clone/copy your elements! It is actually possible to get a &[u8; 3] from a &[u8]:
fn pop(barry: &[u8]) -> &[u8; 3] {
barry.try_into().expect("slice should have length 3")
}
As mentioned in the other answers, you probably don't want to panic if the length of barry is not 3, but instead handle this error gracefully.
This works thanks to these impls of the related trait TryFrom (before Rust 1.47, these only existed for arrays up to length 32):
impl<'_, T, const N: usize> TryFrom<&'_ [T]> for [T; N]
where
T: Copy,
impl<'a, T, const N: usize> TryFrom<&'a [T]> for &'a [T; N]
impl<'a, T, const N: usize> TryFrom<&'a mut [T]> for &'a mut [T; N]
Thanks to @malbarbo we can use this helper function:
use std::convert::AsMut;
fn clone_into_array<A, T>(slice: &[T]) -> A
where
A: Default + AsMut<[T]>,
T: Clone,
{
let mut a = A::default();
<A as AsMut<[T]>>::as_mut(&mut a).clone_from_slice(slice);
a
}
to get a much neater syntax:
fn main() {
let original = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
let e = Example {
a: clone_into_array(&original[0..4]),
b: clone_into_array(&original[4..10]),
};
println!("{:?}", e);
}
as long as T: Default + Clone.
If you know your type implements Copy, you can use this form:
use std::convert::AsMut;
fn copy_into_array<A, T>(slice: &[T]) -> A
where
A: Default + AsMut<[T]>,
T: Copy,
{
let mut a = A::default();
<A as AsMut<[T]>>::as_mut(&mut a).copy_from_slice(slice);
a
}
Both variants will panic! if the target array and the passed-in slice do not have the same length.
The documentation for Vec covers this in the section titled "slicing".
You can create a slice of a Vec or array by indexing it with a Range (or RangeInclusive, RangeFrom, RangeTo, RangeToInclusive, or RangeFull), for example:
fn main() {
let a = vec![1, 2, 3, 4, 5];
// With a start and an end
println!("{:?}", &a[1..4]);
// With a start and an end, inclusive
println!("{:?}", &a[1..=3]);
// With just a start
println!("{:?}", &a[2..]);
// With just an end
println!("{:?}", &a[..3]);
// With just an end, inclusive
println!("{:?}", &a[..=2]);
// All elements
println!("{:?}", &a[..]);
}
If you wish to convert the entire Vec to a slice, you can use deref coercion:
fn main() {
let a = vec![1, 2, 3, 4, 5];
let b: &[i32] = &a;
println!("{:?}", b);
}
This coercion is automatically applied when calling a function:
fn print_it(b: &[i32]) {
println!("{:?}", b);
}
fn main() {
let a = vec![1, 2, 3, 4, 5];
print_it(&a);
}
You can also call Vec::as_slice, but it's a bit less common:
fn main() {
let a = vec![1, 2, 3, 4, 5];
let b = a.as_slice();
println!("{:?}", b);
}
See also:
- Why is it discouraged to accept a reference to a String (&String), Vec (&Vec), or Box (&Box) as a function argument?
Since using raw pointers is not recommended, I assumed the standard library provides a function for seemingly common operation, but I haven't found one yet. Is there a function that takes a slice and a pointer/reference (to an element in that slice) and returns the index of the given element?
I canโt seem to find any such function in the docs. Is there a way to get the range from a slice? eg. s[1..3] creates a slice of s from the range [1..3]. I want an inverse function to get the range [1..3] from the slice of s. The function would have to be the range with respect to the owning structure of course, otherwise the function wouldn't be well defined as you can take a slice of a slice. eg. s[2..9][1..3] (The "inverse" of which should be [3..5]).