Use <[T]>::as_chunks{_mut} for exact size chunks (#23755)

# Objective

- Reduce `unwrap`s and bounds checks.

## Solution

- Replace usages of `<[T]>::chunks{_mut}` and
`<[T]>::chunks_exact{_mut}` where the size is exact with
`<[T]>::as_chunks{_mut}`.

## Testing

- Ran `cargo run -p ci -- compile`

---------

Co-authored-by: Luo Zhihao <luo_zhihao@outlook.com>
This commit is contained in:
DavidCrossman
2026-05-04 00:56:08 +01:00
committed by GitHub
parent 242f51245e
commit 5d03586dd7
8 changed files with 61 additions and 59 deletions
+2 -2
View File
@@ -133,9 +133,9 @@ where
]
.map(|vec3| config.isometry * vec3);
for chunk in vertices.chunks_exact(3) {
for &[a, b, c] in vertices.as_chunks().0 {
self.gizmos
.short_arc_3d_between(chunk[1], chunk[0], chunk[2], config.color)
.short_arc_3d_between(b, a, c, config.color)
.resolution(config.arc_resolution);
}
+4 -4
View File
@@ -105,10 +105,10 @@ pub fn dds_buffer_to_image(
image.data = if let Some(transcode_format) = transcode_format {
match transcode_format {
TranscodeFormat::Rgb8 => {
let data = dds
.data
.chunks_exact(3)
.flat_map(|pixel| [pixel[0], pixel[1], pixel[2], u8::MAX])
let (chunks, _) = dds.data.as_chunks();
let data = chunks
.iter()
.flat_map(|&[r, g, b]| [r, g, b, u8::MAX])
.collect();
Some(data)
}
@@ -112,12 +112,7 @@ impl Image {
width as usize * height as usize * format.pixel_size().unwrap_or(0),
);
for pixel in image.into_raw().chunks_exact(3) {
// TODO: use the array_chunks method once stabilized
// https://github.com/rust-lang/rust/issues/74985
let r = pixel[0];
let g = pixel[1];
let b = pixel[2];
for [r, g, b] in image.into_raw().as_chunks().0 {
let a = 1f32;
local_data.extend_from_slice(&r.to_le_bytes());
@@ -191,8 +186,8 @@ impl Image {
TextureFormat::Bgra8UnormSrgb | TextureFormat::Bgra8Unorm => {
ImageBuffer::from_raw(width, height, {
let mut data = data;
for bgra in data.chunks_exact_mut(4) {
bgra.swap(0, 2);
for [b, _, r, _] in data.as_chunks_mut().0 {
core::mem::swap(b, r);
}
data
})
+25 -22
View File
@@ -1231,15 +1231,12 @@ impl Mesh {
) -> Result<(), MeshWindingInvertError> {
match topology {
PrimitiveTopology::TriangleList => {
// Early return if the index count doesn't match
if !indices.len().is_multiple_of(3) {
let (chunks, []) = indices.as_chunks_mut() else {
// Early return if the index count doesn't match
return Err(MeshWindingInvertError::AbruptIndicesEnd);
}
for chunk in indices.chunks_mut(3) {
// This currently can only be optimized away with unsafe, rework this when `feature(slice_as_chunks)` gets stable.
let [_, b, c] = chunk else {
return Err(MeshWindingInvertError::AbruptIndicesEnd);
};
};
for [_, b, c] in chunks {
core::mem::swap(b, c);
}
Ok(())
@@ -1353,9 +1350,10 @@ impl Mesh {
.expect("`Mesh::ATTRIBUTE_POSITION` vertex attributes should be of type `float3`");
let normals: Vec<_> = positions
.chunks_exact(3)
.map(|p| triangle_normal(p[0], p[1], p[2]))
.flat_map(|normal| [normal; 3])
.as_chunks()
.0
.iter()
.flat_map(|&[a, b, c]| [triangle_normal(a, b, c); 3])
.collect();
self.try_insert_attribute(Mesh::ATTRIBUTE_NORMAL, normals)
@@ -1608,11 +1606,14 @@ impl Mesh {
let mut normals = vec![Vec3::ZERO; positions.len()];
self.try_indices()?
.iter()
.collect::<Vec<usize>>()
.chunks_exact(3)
.for_each(|face| per_triangle([face[0], face[1], face[2]], positions, &mut normals));
match self.try_indices()? {
Indices::U16(vec) => vec.as_chunks().0.iter().for_each(|&chunk| {
per_triangle(chunk.map(|i| i as usize), positions, &mut normals);
}),
Indices::U32(vec) => vec.as_chunks().0.iter().for_each(|&chunk| {
per_triangle(chunk.map(|i| i as usize), positions, &mut normals);
}),
}
for normal in &mut normals {
*normal = normal.try_normalize().unwrap_or(Vec3::ZERO);
@@ -2218,14 +2219,16 @@ impl Mesh {
// This implicitly truncates the indices to a multiple of 3.
let iterator = match indices {
Indices::U16(vec) => FourIterators::First(
vec.as_slice()
.chunks_exact(3)
.flat_map(move |indices| indices_to_triangle(vertices, indices)),
vec.as_chunks::<3>()
.0
.iter()
.flat_map(|indices| indices_to_triangle(vertices, indices)),
),
Indices::U32(vec) => FourIterators::Second(
vec.as_slice()
.chunks_exact(3)
.flat_map(move |indices| indices_to_triangle(vertices, indices)),
vec.as_chunks::<3>()
.0
.iter()
.flat_map(|indices| indices_to_triangle(vertices, indices)),
),
};
+6 -2
View File
@@ -212,10 +212,14 @@ where
match topology {
PrimitiveTopology::TriangleList => match indices {
Indices::U16(indices) => {
indices.chunks_exact_mut(3).for_each(|arr| arr.swap(1, 0));
for [a, b, _] in indices.as_chunks_mut().0 {
core::mem::swap(a, b);
}
}
Indices::U32(indices) => {
indices.chunks_exact_mut(3).for_each(|arr| arr.swap(1, 0));
for [a, b, _] in indices.as_chunks_mut().0 {
core::mem::swap(a, b);
}
}
},
_ => {
@@ -104,16 +104,14 @@ where
}
indices
.chunks_exact(3)
.as_chunks()
.0
.iter()
.enumerate()
.fold(
(f32::MAX, None),
|(closest_distance, closest_hit), (tri_idx, triangle)| {
let [Ok(a), Ok(b), Ok(c)] = [
triangle[0].try_into(),
triangle[1].try_into(),
triangle[2].try_into(),
] else {
|(closest_distance, closest_hit), (tri_idx, &[a, b, c])| {
let [Ok(a), Ok(b), Ok(c)] = [a.try_into(), b.try_into(), c.try_into()] else {
return (closest_distance, closest_hit);
};
@@ -136,17 +134,14 @@ where
.1
} else {
positions
.chunks_exact(3)
.as_chunks()
.0
.iter()
.map(|&[a, b, c]| [Vec3::from(a), Vec3::from(b), Vec3::from(c)])
.enumerate()
.fold(
(f32::MAX, None),
|(closest_distance, closest_hit), (tri_idx, triangle)| {
let tri_vertices = [
Vec3::from(triangle[0]),
Vec3::from(triangle[1]),
Vec3::from(triangle[2]),
];
|(closest_distance, closest_hit), (tri_idx, tri_vertices)| {
match ray_triangle_intersection(&ray, &tri_vertices, backface_culling) {
Some(hit) if hit.distance >= 0. && hit.distance < closest_distance => {
(hit.distance, Some((tri_idx, hit)))
@@ -581,15 +581,19 @@ impl FrameData {
let data = read_buffer.slice(..).get_mapped_range();
let timestamps = data[..(self.num_timestamps * 8) as usize]
.chunks(8)
.map(|v| u64::from_le_bytes(v.try_into().unwrap()))
.as_chunks()
.0
.iter()
.map(|&v| u64::from_le_bytes(v))
.collect::<Vec<u64>>();
let start = self.pipeline_statistics_buffer_offset as usize;
let len = (self.num_pipeline_statistics as usize) * 40;
let pipeline_statistics = data[start..start + len]
.chunks(8)
.map(|v| u64::from_le_bytes(v.try_into().unwrap()))
.as_chunks()
.0
.iter()
.map(|&v| u64::from_le_bytes(v))
.collect::<Vec<u64>>();
let mut diagnostics = Vec::new();
@@ -90,9 +90,10 @@ pub(crate) fn extract_rgba_pixels(image: &Image) -> Option<Vec<u8>> {
| TextureFormat::Rgba8Uint
| TextureFormat::Rgba8Sint => Some(image.data.clone()?),
TextureFormat::Rgba32Float => image.data.as_ref().map(|data| {
data.chunks(4)
data.as_chunks()
.0
.iter()
.map(|chunk| {
let chunk = chunk.try_into().unwrap();
let num = bytemuck::cast_ref::<[u8; 4], f32>(chunk);
ops::round(num.clamp(0.0, 1.0) * 255.0) as u8
})