Skip to content

Commit 00d88bd

Browse files
authored
Rollup merge of #101672 - idigdoug:array_try_into, r=Mark-Simulacrum
array docs - advertise how to get array from slice On my first Rust project, I spent more time than I care to admit figuring out how to efficiently get an array from a slice. Update the array documentation to explain this a bit more clearly. (As a side note, it's a bit unfortunate that get-array-from-slice is only available via trait since that means it can't be used from const functions yet.)
2 parents 48de123 + 705a766 commit 00d88bd

File tree

3 files changed

+92
-2
lines changed

3 files changed

+92
-2
lines changed

library/core/src/array/mod.rs

+48
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,18 @@ impl<T, const N: usize> const BorrowMut<[T]> for [T; N] {
184184
}
185185
}
186186

187+
/// Tries to create an array `[T; N]` by copying from a slice `&[T]`. Succeeds if
188+
/// `slice.len() == N`.
189+
///
190+
/// ```
191+
/// let bytes: [u8; 3] = [1, 0, 2];
192+
///
193+
/// let bytes_head: [u8; 2] = <[u8; 2]>::try_from(&bytes[0..2]).unwrap();
194+
/// assert_eq!(1, u16::from_le_bytes(bytes_head));
195+
///
196+
/// let bytes_tail: [u8; 2] = bytes[1..3].try_into().unwrap();
197+
/// assert_eq!(512, u16::from_le_bytes(bytes_tail));
198+
/// ```
187199
#[stable(feature = "try_from", since = "1.34.0")]
188200
impl<T, const N: usize> TryFrom<&[T]> for [T; N]
189201
where
@@ -196,6 +208,18 @@ where
196208
}
197209
}
198210

211+
/// Tries to create an array `[T; N]` by copying from a mutable slice `&mut [T]`.
212+
/// Succeeds if `slice.len() == N`.
213+
///
214+
/// ```
215+
/// let mut bytes: [u8; 3] = [1, 0, 2];
216+
///
217+
/// let bytes_head: [u8; 2] = <[u8; 2]>::try_from(&mut bytes[0..2]).unwrap();
218+
/// assert_eq!(1, u16::from_le_bytes(bytes_head));
219+
///
220+
/// let bytes_tail: [u8; 2] = (&mut bytes[1..3]).try_into().unwrap();
221+
/// assert_eq!(512, u16::from_le_bytes(bytes_tail));
222+
/// ```
199223
#[stable(feature = "try_from_mut_slice_to_array", since = "1.59.0")]
200224
impl<T, const N: usize> TryFrom<&mut [T]> for [T; N]
201225
where
@@ -208,6 +232,18 @@ where
208232
}
209233
}
210234

235+
/// Tries to create an array ref `&[T; N]` from a slice ref `&[T]`. Succeeds if
236+
/// `slice.len() == N`.
237+
///
238+
/// ```
239+
/// let bytes: [u8; 3] = [1, 0, 2];
240+
///
241+
/// let bytes_head: &[u8; 2] = <&[u8; 2]>::try_from(&bytes[0..2]).unwrap();
242+
/// assert_eq!(1, u16::from_le_bytes(*bytes_head));
243+
///
244+
/// let bytes_tail: &[u8; 2] = bytes[1..3].try_into().unwrap();
245+
/// assert_eq!(512, u16::from_le_bytes(*bytes_tail));
246+
/// ```
211247
#[stable(feature = "try_from", since = "1.34.0")]
212248
impl<'a, T, const N: usize> TryFrom<&'a [T]> for &'a [T; N] {
213249
type Error = TryFromSliceError;
@@ -223,6 +259,18 @@ impl<'a, T, const N: usize> TryFrom<&'a [T]> for &'a [T; N] {
223259
}
224260
}
225261

262+
/// Tries to create a mutable array ref `&mut [T; N]` from a mutable slice ref
263+
/// `&mut [T]`. Succeeds if `slice.len() == N`.
264+
///
265+
/// ```
266+
/// let mut bytes: [u8; 3] = [1, 0, 2];
267+
///
268+
/// let bytes_head: &mut [u8; 2] = <&mut [u8; 2]>::try_from(&mut bytes[0..2]).unwrap();
269+
/// assert_eq!(1, u16::from_le_bytes(*bytes_head));
270+
///
271+
/// let bytes_tail: &mut [u8; 2] = (&mut bytes[1..3]).try_into().unwrap();
272+
/// assert_eq!(512, u16::from_le_bytes(*bytes_tail));
273+
/// ```
226274
#[stable(feature = "try_from", since = "1.34.0")]
227275
impl<'a, T, const N: usize> TryFrom<&'a mut [T]> for &'a mut [T; N] {
228276
type Error = TryFromSliceError;

library/core/src/primitive_docs.rs

+22-1
Original file line numberDiff line numberDiff line change
@@ -611,7 +611,19 @@ mod prim_pointer {}
611611
///
612612
/// Arrays coerce to [slices (`[T]`)][slice], so a slice method may be called on
613613
/// an array. Indeed, this provides most of the API for working with arrays.
614-
/// Slices have a dynamic size and do not coerce to arrays.
614+
///
615+
/// Slices have a dynamic size and do not coerce to arrays. Instead, use
616+
/// `slice.try_into().unwrap()` or `<ArrayType>::try_from(slice).unwrap()`.
617+
///
618+
/// Array's `try_from(slice)` implementations (and the corresponding `slice.try_into()`
619+
/// array implementations) succeed if the input slice length is the same as the result
620+
/// array length. They optimize especially well when the optimizer can easily determine
621+
/// the slice length, e.g. `<[u8; 4]>::try_from(&slice[4..8]).unwrap()`. Array implements
622+
/// [TryFrom](crate::convert::TryFrom) returning:
623+
///
624+
/// - `[T; N]` copies from the slice's elements
625+
/// - `&[T; N]` references the original slice's elements
626+
/// - `&mut [T; N]` references the original slice's elements
615627
///
616628
/// You can move elements out of an array with a [slice pattern]. If you want
617629
/// one element, see [`mem::replace`].
@@ -640,6 +652,15 @@ mod prim_pointer {}
640652
/// for x in &array { }
641653
/// ```
642654
///
655+
/// You can use `<ArrayType>::try_from(slice)` or `slice.try_into()` to get an array from
656+
/// a slice:
657+
///
658+
/// ```
659+
/// let bytes: [u8; 3] = [1, 0, 2];
660+
/// assert_eq!(1, u16::from_le_bytes(<[u8; 2]>::try_from(&bytes[0..2]).unwrap()));
661+
/// assert_eq!(512, u16::from_le_bytes(bytes[1..3].try_into().unwrap()));
662+
/// ```
663+
///
643664
/// You can use a [slice pattern] to move elements out of an array:
644665
///
645666
/// ```

library/std/src/primitive_docs.rs

+22-1
Original file line numberDiff line numberDiff line change
@@ -611,7 +611,19 @@ mod prim_pointer {}
611611
///
612612
/// Arrays coerce to [slices (`[T]`)][slice], so a slice method may be called on
613613
/// an array. Indeed, this provides most of the API for working with arrays.
614-
/// Slices have a dynamic size and do not coerce to arrays.
614+
///
615+
/// Slices have a dynamic size and do not coerce to arrays. Instead, use
616+
/// `slice.try_into().unwrap()` or `<ArrayType>::try_from(slice).unwrap()`.
617+
///
618+
/// Array's `try_from(slice)` implementations (and the corresponding `slice.try_into()`
619+
/// array implementations) succeed if the input slice length is the same as the result
620+
/// array length. They optimize especially well when the optimizer can easily determine
621+
/// the slice length, e.g. `<[u8; 4]>::try_from(&slice[4..8]).unwrap()`. Array implements
622+
/// [TryFrom](crate::convert::TryFrom) returning:
623+
///
624+
/// - `[T; N]` copies from the slice's elements
625+
/// - `&[T; N]` references the original slice's elements
626+
/// - `&mut [T; N]` references the original slice's elements
615627
///
616628
/// You can move elements out of an array with a [slice pattern]. If you want
617629
/// one element, see [`mem::replace`].
@@ -640,6 +652,15 @@ mod prim_pointer {}
640652
/// for x in &array { }
641653
/// ```
642654
///
655+
/// You can use `<ArrayType>::try_from(slice)` or `slice.try_into()` to get an array from
656+
/// a slice:
657+
///
658+
/// ```
659+
/// let bytes: [u8; 3] = [1, 0, 2];
660+
/// assert_eq!(1, u16::from_le_bytes(<[u8; 2]>::try_from(&bytes[0..2]).unwrap()));
661+
/// assert_eq!(512, u16::from_le_bytes(bytes[1..3].try_into().unwrap()));
662+
/// ```
663+
///
643664
/// You can use a [slice pattern] to move elements out of an array:
644665
///
645666
/// ```

0 commit comments

Comments
 (0)