diff --git a/crates/canvas/src/gpu/page/background.rs b/crates/canvas/src/gpu/page/background.rs index 5b6bf2da8d108555b4d23a635ab6032cb9f1e1e1..26413fb13ff3e63df8b2f9142ec88d04789492cf 100644 --- a/crates/canvas/src/gpu/page/background.rs +++ b/crates/canvas/src/gpu/page/background.rs @@ -599,7 +599,9 @@ pub fn template_picture(name: &str) -> Option> { let [width, height] = [view.width(), view.height()].map(|side| side.round() as u32); // Over white paper, as OneNote's pictures are drawn. let rgb: Vec = render(template.svg, [width, height]) - .chunks_exact(4) + .as_chunks::<4>() + .0 + .iter() .flat_map(|pixel| { let alpha = u16::from(pixel[3]); [0, 1, 2].map(|channel| { @@ -624,12 +626,16 @@ pub fn template_picture(name: &str) -> Option> { } else { // OneNote's PNG templates hold 256 colours. let rgba: Vec = rgb - .chunks_exact(3) + .as_chunks::<3>() + .0 + .iter() .flat_map(|pixel| [pixel[0], pixel[1], pixel[2], 255]) .collect(); let quantized = color_quant::NeuQuant::new(10, 256, &rgba); let indices: Vec = rgba - .chunks_exact(4) + .as_chunks::<4>() + .0 + .iter() .map(|pixel| quantized.index_of(pixel) as u8) .collect(); let mut encoder = png::Encoder::new(&mut encoded, width, height); @@ -1044,7 +1050,12 @@ mod tests { }) .unwrap(); let pixels = readback.get_mapped_range(..).unwrap().to_vec(); - let pixels: Vec<[u8; 3]> = pixels.chunks_exact(4).map(|p| [p[0], p[1], p[2]]).collect(); + let pixels: Vec<[u8; 3]> = pixels + .as_chunks::<4>() + .0 + .iter() + .map(|p| [p[0], p[1], p[2]]) + .collect(); assert!( pixels .iter() diff --git a/crates/canvas/src/gpu/tag_art.rs b/crates/canvas/src/gpu/tag_art.rs index 295a6278f0e106262de0f669d81ec9be760850bf..a514b9c4b92ade89b53e1fda3998836e7759f7c2 100644 --- a/crates/canvas/src/gpu/tag_art.rs +++ b/crates/canvas/src/gpu/tag_art.rs @@ -87,7 +87,7 @@ fn raster(tree: &usvg::Tree) -> Option> { [color.red(), color.green(), color.blue(), color.alpha()] }) .collect(); - if rgba.chunks_exact(4).all(|pixel| pixel[3] == 0) { + if rgba.as_chunks::<4>().0.iter().all(|pixel| pixel[3] == 0) { return None; } Some(png(&image::RgbaImage::from_raw(width, height, rgba)?)) diff --git a/crates/canvas/src/recording.rs b/crates/canvas/src/recording.rs index 9c271378e5cafc1ea5b3bc3041ced3f9957b4de9..f614d07e1099f00394ce7793137f3460047320b0 100644 --- a/crates/canvas/src/recording.rs +++ b/crates/canvas/src/recording.rs @@ -204,7 +204,9 @@ pub fn compress(wav: &[u8]) -> Option<(Vec, u32)> { } let samples: Vec = wave .data - .chunks_exact(2) + .as_chunks::<2>() + .0 + .iter() .map(|pair| i16::from_le_bytes([pair[0], pair[1]])) .collect(); let mut data = Vec::with_capacity(samples.len() / 2 + BLOCK); @@ -221,7 +223,7 @@ pub fn compress(wav: &[u8]) -> Option<(Vec, u32)> { .chain(std::iter::repeat(last)) .take(BLOCK_SAMPLES - 1) .collect::>(); - for pair in rest.chunks_exact(2) { + for pair in rest.as_chunks::<2>().0 { let mut byte = 0; for (shift, sample) in [0, 4].into_iter().zip(pair) { let code = encode(i32::from(*sample), &mut predicted, &mut index); diff --git a/crates/canvas/src/recording/video.rs b/crates/canvas/src/recording/video.rs index 14621d3d325d380295ffabace61ae09372acc489..9c0bc2e4b94373df9aa478c783ace0dd4f239686 100644 --- a/crates/canvas/src/recording/video.rs +++ b/crates/canvas/src/recording/video.rs @@ -359,7 +359,9 @@ impl Pictures { .take(height) .filter_map(|row| row.get(..width * 4)) .flat_map(|row| { - row.chunks_exact(4) + row.as_chunks::<4>() + .0 + .iter() .flat_map(|pixel| [pixel[2], pixel[1], pixel[0]]) }) .collect(); diff --git a/crates/draw/src/render.rs b/crates/draw/src/render.rs index 93b5d79f5093fa48bfb98e5b4eb29f0b282fcb81..beea59ae80abf3ccab35fd4a44dabbe81ed7155e 100644 --- a/crates/draw/src/render.rs +++ b/crates/draw/src/render.rs @@ -107,7 +107,7 @@ fn decoder(encoded: &[u8]) -> Result { /// Premultiplies straight-alpha sRGB RGBA in linear light, so filtering never bleeds the /// colour of transparent pixels. fn premultiply(pixels: &mut [u8]) { - for pixel in pixels.chunks_exact_mut(4) { + for pixel in pixels.as_chunks_mut::<4>().0 { let alpha = pixel[3]; if alpha == 255 { continue; @@ -2349,7 +2349,9 @@ mod tests { assert_eq!(renderer.glyphs.len(), count); assert!( captures[0] - .chunks_exact(4) + .as_chunks::<4>() + .0 + .iter() .filter(|pixel| pixel[0] < 200) .count() > 100 diff --git a/crates/draw/src/render/canvas2d.rs b/crates/draw/src/render/canvas2d.rs index 6e138ed8d4d1fe43e8a294252cadf28d50b5a77e..4aa113a7a20f301e959bd8d19b7d0d815d51a4c2 100644 --- a/crates/draw/src/render/canvas2d.rs +++ b/crates/draw/src/render/canvas2d.rs @@ -236,7 +236,7 @@ impl Gpu { .filter(|batch| batch.blend == Blend::Over); for batch in batches { let range = batch.vertices.start as usize..batch.vertices.end as usize; - for quad in frame.vertices[range].chunks_exact(6) { + for quad in frame.vertices[range].as_chunks::<6>().0 { let Some(color) = tinted(quad) else { continue; }; @@ -320,7 +320,7 @@ impl Gpu { // The canvas takes straight alpha; the picture's colour was premultiplied in linear // light. let mut pixels = image.pixels().to_vec(); - for pixel in pixels.chunks_exact_mut(4) { + for pixel in pixels.as_chunks_mut::<4>().0 { let alpha = f32::from(pixel[3]) / 255.0; if alpha > 0.0 && alpha < 1.0 { for byte in &mut pixel[..3] { @@ -613,7 +613,7 @@ impl<'a> Painter<'a> { self.set_clip(None); return self.group(index, vertices); } - for quad in vertices.chunks_exact(6) { + for quad in vertices.as_chunks::<6>().0 { let clip = self.clip_of(batch.scissor, quad); self.set_clip(clip); match batch.blend { diff --git a/crates/draw/src/render/icon.rs b/crates/draw/src/render/icon.rs index 0167a1c1b0312e437c653da77fb4a34f3d6c9b08..109da9483d148e085c41ec643f5e9a0ed5aff031 100644 --- a/crates/draw/src/render/icon.rs +++ b/crates/draw/src/render/icon.rs @@ -627,18 +627,27 @@ mod tests { image.data.len(), (image.placement.width * image.placement.height * 4) as usize ); - assert!(image.data.chunks_exact(4).any(|p| p[3] > 0)); - assert!(image.data.chunks_exact(4).any(|p| p[3] < 255)); + assert!(image.data.as_chunks::<4>().0.iter().any(|p| p[3] > 0)); + assert!(image.data.as_chunks::<4>().0.iter().any(|p| p[3] < 255)); assert!( image .data - .chunks_exact(4) + .as_chunks::<4>() + .0 + .iter() .filter(|p| p[3] == 0) .all(|p| p[..3] == [0; 3]) ); } assert_ne!(plain.data, marked.data); - assert!(marked.data.chunks_exact(4).any(|p| p[0] > p[2] && p[3] > 0)); + assert!( + marked + .data + .as_chunks::<4>() + .0 + .iter() + .any(|p| p[0] > p[2] && p[3] > 0) + ); } } } diff --git a/crates/draw/src/render/pdf.rs b/crates/draw/src/render/pdf.rs index 3e4c11e2559f4985cb2b19764079f9696b03bafd..a4b2187ce0a3c1485dd1c58da8ed4bb14d8b0e60 100644 --- a/crates/draw/src/render/pdf.rs +++ b/crates/draw/src/render/pdf.rs @@ -639,7 +639,9 @@ impl Document { // Pixels are premultiplied in linear light. let straight: Vec = image .pixels() - .chunks_exact(4) + .as_chunks::<4>() + .0 + .iter() .flat_map(|pixel| { let alpha = pixel[3]; if alpha == 255 || alpha == 0 { @@ -653,10 +655,16 @@ impl Document { }) .collect(); let size = image.size(); - let opaque = straight.chunks_exact(4).all(|pixel| pixel[3] == 255); + let opaque = straight + .as_chunks::<4>() + .0 + .iter() + .all(|pixel| pixel[3] == 255); if opaque && size[0] * size[1] >= 64 * 64 { let rgb: Vec = straight - .chunks_exact(4) + .as_chunks::<4>() + .0 + .iter() .flat_map(|pixel| [pixel[0], pixel[1], pixel[2]]) .collect(); let mut jpeg = Vec::new(); @@ -688,23 +696,35 @@ impl Document { /// Straight sRGB RGBA pixels as a losslessly compressed image XObject. fn image(&mut self, [width, height]: [u32; 2], rgba: &[u8], interpolate: bool) -> Ref { let rgb: Vec = rgba - .chunks_exact(4) + .as_chunks::<4>() + .0 + .iter() .flat_map(|pixel| [pixel[0], pixel[1], pixel[2]]) .collect(); - let mask = rgba.chunks_exact(4).any(|pixel| pixel[3] != 255).then(|| { - let alpha: Vec = rgba.chunks_exact(4).map(|pixel| pixel[3]).collect(); - let mask = self.reserve(); - let data = compress(&alpha); - let mut writer = self.pdf.image_xobject(mask, &data); - writer.filter(Filter::FlateDecode); - writer - .width(width as i32) - .height(height as i32) - .color_space_name(Name(b"DeviceGray")) - .bits_per_component(8) - .interpolate(interpolate); - mask - }); + let mask = rgba + .as_chunks::<4>() + .0 + .iter() + .any(|pixel| pixel[3] != 255) + .then(|| { + let alpha: Vec = rgba + .as_chunks::<4>() + .0 + .iter() + .map(|pixel| pixel[3]) + .collect(); + let mask = self.reserve(); + let data = compress(&alpha); + let mut writer = self.pdf.image_xobject(mask, &data); + writer.filter(Filter::FlateDecode); + writer + .width(width as i32) + .height(height as i32) + .color_space_name(Name(b"DeviceGray")) + .bits_per_component(8) + .interpolate(interpolate); + mask + }); let reference = self.reserve(); let data = compress(&rgb); let mut writer = self.pdf.image_xobject(reference, &data); diff --git a/crates/mobile/src/tests.rs b/crates/mobile/src/tests.rs index a7c91fb2b9fb50020232d8b3c7594e07b654fcf4..ee37d4e3ec083315af32f37e77da0f3d6334b60f 100644 --- a/crates/mobile/src/tests.rs +++ b/crates/mobile/src/tests.rs @@ -968,7 +968,10 @@ fn tag_icons_draw_their_art_and_highlighting_tags_have_none() { let drawn = unsafe { sb_tag_icon(tag.shape, true, 32, rgba.as_mut_ptr()) }; assert_eq!(drawn, tag.shape != 0, "{tag:?}"); if drawn { - assert!(rgba.chunks_exact(4).any(|pixel| pixel[3] > 0), "{tag:?}"); + assert!( + rgba.as_chunks::<4>().0.iter().any(|pixel| pixel[3] > 0), + "{tag:?}" + ); } } } diff --git a/crates/notebook/examples/externalize_fixture.rs b/crates/notebook/examples/externalize_fixture.rs index 2b82cd3798d8c710e79c14cd3f60a308588661b0..35a79155c31ff9dd326fbe5e823d6528230440b9 100644 --- a/crates/notebook/examples/externalize_fixture.rs +++ b/crates/notebook/examples/externalize_fixture.rs @@ -35,8 +35,10 @@ fn main() -> Result<(), Box> { u32::from_le_bytes(encoded[offset..offset + 4].try_into()?) as usize; let text = String::from_utf16( &encoded[offset + 4..offset + 4 + count * 2] - .chunks_exact(2) - .map(|v| u16::from_le_bytes(v.try_into().unwrap())) + .as_chunks::<2>() + .0 + .iter() + .map(|v| u16::from_le_bytes(*v)) .collect::>(), )?; if let FileDataReference::Internal(guid) = text.parse()? { diff --git a/crates/notebook/src/smb/directory/records.rs b/crates/notebook/src/smb/directory/records.rs index 823dfb48d18d1053ac25ec0f7c169a86a03985be..059ef8aed95569e3de5e76bae63f4688087b513a 100644 --- a/crates/notebook/src/smb/directory/records.rs +++ b/crates/notebook/src/smb/directory/records.rs @@ -34,7 +34,9 @@ pub(super) fn decode(mut bytes: &[u8]) -> io::Result> { return Err(io::ErrorKind::InvalidData.into()); } let units: Vec<_> = bytes[64..end] - .chunks_exact(2) + .as_chunks::<2>() + .0 + .iter() .map(|unit| u16::from_le_bytes([unit[0], unit[1]])) .collect(); let name = String::from_utf16(&units).map_err(|_| io::ErrorKind::InvalidData)?; diff --git a/crates/notebook/tests/structure.rs b/crates/notebook/tests/structure.rs index 70ba792ec49782f4821954bfa80d36515126b948..5e44785c40d78a1630f1363add0248f97a1cb9c0 100644 --- a/crates/notebook/tests/structure.rs +++ b/crates/notebook/tests/structure.rs @@ -146,7 +146,9 @@ fn sections_and_groups_are_created_renamed_coloured_ordered_and_deleted() { let bin = onestore::read_file(root.join("OneNote_RecycleBin/Open Notebook.onetoc2")).unwrap(); assert!( String::from_utf16_lossy( - &bin.chunks_exact(2) + &bin.as_chunks::<2>() + .0 + .iter() .map(|c| u16::from_le_bytes([c[0], c[1]])) .collect::>() ) diff --git a/crates/notebook/tests/support/model_schedule.rs b/crates/notebook/tests/support/model_schedule.rs index 79827a5906f2e012e6900c8744fc5e415a2b0246..ad2066d623a43134e4a84f3bb4b72219d863d530 100644 --- a/crates/notebook/tests/support/model_schedule.rs +++ b/crates/notebook/tests/support/model_schedule.rs @@ -189,7 +189,7 @@ pub fn run(input: &[u8]) { let directory = tempfile::tempdir().unwrap(); let mut replicas: [Option; 12] = std::array::from_fn(|_| None); let mut server = Server::new(source); - for step in input.chunks_exact(8).take(48) { + for step in input.as_chunks::<8>().0.iter().take(48) { let actor = usize::from(step[0]) % replicas.len(); let path = directory.path().join(format!("{actor}.sqlite")); let cache = replicas[actor].get_or_insert_with(|| Replica::create(&path, source).unwrap()); diff --git a/crates/notebook/tests/support/page_schedule.rs b/crates/notebook/tests/support/page_schedule.rs index d5226f90432e71a67bd44eb1382e0d62a7964ccb..90970c09066983f1c6505ad04963a8ee6379b20e 100644 --- a/crates/notebook/tests/support/page_schedule.rs +++ b/crates/notebook/tests/support/page_schedule.rs @@ -118,7 +118,7 @@ pub fn run(input: &[u8]) { write_limit: 4096, random: 1, }; - for step in input.chunks_exact(8).take(48) { + for step in input.as_chunks::<8>().0.iter().take(48) { let actor = usize::from(step[0]) % replicas.len(); let path = directory.path().join(format!("{actor}.sqlite")); let cache = replicas[actor].get_or_insert_with(|| Replica::create(&path, &SOURCE).unwrap()); diff --git a/crates/notebook/tests/sync_pages.rs b/crates/notebook/tests/sync_pages.rs index 3f819fc2110f393c6adda36b2d8c706f5e0f7574..9415c4ff637b29a58c34a04830a5dd5fcdb20034 100644 --- a/crates/notebook/tests/sync_pages.rs +++ b/crates/notebook/tests/sync_pages.rs @@ -557,7 +557,7 @@ fn twelve_disjoint_page_batches_merge_with_dependent_bodies_without_review() { let mut expected_text = texts(&source); let directory = tempfile::tempdir().unwrap(); let mut queues = Vec::new(); - for (actor, group) in created.chunks_exact(3).enumerate() { + for (actor, group) in created.as_chunks::<3>().0.iter().enumerate() { let path = directory.path().join(format!("{actor}.sqlite")); let cache = Replica::create(&path, &source).unwrap(); let edits = [ diff --git a/crates/onestore/examples/edit_property.rs b/crates/onestore/examples/edit_property.rs index 2e9b45113011fd66a39d4428e98269b2f13f5954..0d1a3eff47c754cb979ecde9d481ad4e86036aef 100644 --- a/crates/onestore/examples/edit_property.rs +++ b/crates/onestore/examples/edit_property.rs @@ -18,7 +18,9 @@ fn hex(text: &str) -> Result, Box> { return Err("Expected an even number of hexadecimal digits".into()); } text.as_bytes() - .chunks_exact(2) + .as_chunks::<2>() + .0 + .iter() .map(|pair| Ok(u8::from_str_radix(std::str::from_utf8(pair)?, 16)?)) .collect() } @@ -69,7 +71,7 @@ fn main() -> Result<(), Box> { (0x6000e, 0x1c001c22) => { let units = |bytes: &[u8]| -> Vec { let mut units: Vec = bytes - .chunks_exact(2) + .as_chunks::<2>().0.iter() .map(|pair| u16::from_le_bytes([pair[0], pair[1]])) .collect(); if units.last() == Some(&0) { diff --git a/crates/onestore/src/create.rs b/crates/onestore/src/create.rs index 6df842542b203b9ff26fadd43dc5ff8ed51497db..4d7769745640d2cd1a2f4bd8a8d7994315c1e015 100644 --- a/crates/onestore/src/create.rs +++ b/crates/onestore/src/create.rs @@ -456,10 +456,8 @@ fn create(file_name: &str, file_type: FileType, spaces: Vec) -> Result for object in &space.objects { for (property, value) in &object.properties { if matches!((property >> 26) & 0x1f, 8 | 9) { - for id in value.chunks_exact(4) { - *counts - .entry(u32::from_le_bytes(id.try_into().unwrap())) - .or_default() += 1; + for id in value.as_chunks::<4>().0 { + *counts.entry(u32::from_le_bytes(*id)).or_default() += 1; } } } diff --git a/crates/onestore/src/document.rs b/crates/onestore/src/document.rs index e49c25558d71f3c1663d866cf945caecef75de41..2acf81cba4ff99ed2258e72c72f9d2e96cffde09 100644 --- a/crates/onestore/src/document.rs +++ b/crates/onestore/src/document.rs @@ -629,8 +629,10 @@ fn unicode(bytes: &[u8]) -> Result { return Err(invalid("Odd UTF-16 document string length")); } let units: Vec<_> = bytes - .chunks_exact(2) - .map(|x| u16::from_le_bytes(x.try_into().unwrap())) + .as_chunks::<2>() + .0 + .iter() + .map(|x| u16::from_le_bytes(*x)) .collect(); String::from_utf16(units.strip_suffix(&[0]).unwrap_or(&units)) .map_err(|_| invalid("Invalid UTF-16 document string")) @@ -690,10 +692,7 @@ impl<'a, 'o> Fields<'a, 'o> { if !bytes.len().is_multiple_of(16) { return Err(invalid("Media identifiers have an invalid length")); } - Ok(bytes - .chunks_exact(16) - .map(|id| id.try_into().unwrap()) - .collect()) + Ok(bytes.as_chunks::<16>().0.to_vec()) } fn u16(&mut self, id: u32) -> Result> { Ok(self.fixed(id)?.map(u16::from_le_bytes)) @@ -775,10 +774,12 @@ fn references(bytes: &[u8], ids: &BTreeMap) -> Result { let table: Vec<[u8; 16]> = ids.values().copied().collect(); return bytes - .chunks_exact(4) + .as_chunks::<4>() + .0 + .iter() .enumerate() .map(|(i, bytes)| { - let raw = u32::from_le_bytes(bytes.try_into().unwrap()); + let raw = u32::from_le_bytes(*bytes); let guid = table.get((raw >> 8) as usize).ok_or(Error { offset: i * 4, message: "Compact ID refers to a missing global ID", @@ -814,8 +815,10 @@ fn measurements(bytes: Option<&[u8]>, header: usize) -> Result> { return Err(invalid("Document measurement array has an invalid length")); } bytes[header..] - .chunks_exact(4) - .map(|b| finite(f32::from_le_bytes(b.try_into().unwrap()) * 36.0)) + .as_chunks::<4>() + .0 + .iter() + .map(|b| finite(f32::from_le_bytes(*b) * 36.0)) .collect() } @@ -1220,8 +1223,10 @@ impl<'a> Element<'a> { } bounds.extend( bytes - .chunks_exact(4) - .map(|b| u32::from_le_bytes(b.try_into().unwrap())), + .as_chunks::<4>() + .0 + .iter() + .map(|b| u32::from_le_bytes(*b)), ); } bounds.push(length); @@ -1292,8 +1297,10 @@ impl<'a> Element<'a> { return Err(invalid("List format has an invalid length")); } let units = bytes[2..] - .chunks_exact(2) - .map(|b| u16::from_le_bytes(b.try_into().unwrap())) + .as_chunks::<2>() + .0 + .iter() + .map(|b| u16::from_le_bytes(*b)) .collect::>(); String::from_utf16(&units) .map_err(|_| invalid("Invalid UTF-16 list format")) diff --git a/crates/onestore/src/files.rs b/crates/onestore/src/files.rs index f4d3e1ec08fbe54d09db7c19ca0ecafcd200f737..6842cff23cba83637451f31ab69a4695018033ef 100644 --- a/crates/onestore/src/files.rs +++ b/crates/onestore/src/files.rs @@ -41,7 +41,9 @@ impl Object<'_> { } let text = String::from_utf16( &reference - .chunks_exact(2) + .as_chunks::<2>() + .0 + .iter() .map(|pair| u16::from_le_bytes([pair[0], pair[1]])) .collect::>(), ) diff --git a/crates/onestore/src/page/ink.rs b/crates/onestore/src/page/ink.rs index 5bb5c15b1540513137ac6678f1e1c23125819156..e9e70ce8c74f2405beaa28f628732850a4d66216 100644 --- a/crates/onestore/src/page/ink.rs +++ b/crates/onestore/src/page/ink.rs @@ -295,7 +295,12 @@ impl InkStroke { if dimensions.len() % 32 != 0 || dimensions.is_empty() { return Err(invalid("Ink dimension table has an invalid length")); } - let entries: Vec<&[u8]> = dimensions.chunks_exact(32).collect(); + let entries: Vec<&[u8]> = dimensions + .as_chunks::<32>() + .0 + .iter() + .map(|entry| entry.as_slice()) + .collect(); let axis = |guid: &[u8]| entries.iter().position(|entry| entry[..16] == *guid); let (Some(x), Some(y)) = (axis(&DIMENSION_X), axis(&DIMENSION_Y)) else { return Err(invalid("Ink dimension table lacks X and Y")); @@ -365,8 +370,10 @@ impl InkShape { fn read(kind: Option, line: Option<&[u8]>, anchors: Option<&[u8]>) -> Option { let floats = |bytes: &[u8]| -> Vec { bytes - .chunks_exact(4) - .map(|b| f32::from_le_bytes(b.try_into().unwrap())) + .as_chunks::<4>() + .0 + .iter() + .map(|b| f32::from_le_bytes(*b)) .collect() }; match (kind?, line, anchors) { @@ -381,7 +388,7 @@ impl InkShape { let v = floats(bytes); Some(Self::Closed { transform: std::array::from_fn(|i| v[i] * 36.0), - anchors: v[6..].chunks_exact(2).map(|p| [p[0], p[1]]).collect(), + anchors: v[6..].as_chunks::<2>().0.to_vec(), }) .filter(Self::finite) } diff --git a/crates/onestore/src/page/mod.rs b/crates/onestore/src/page/mod.rs index 4da1984b25821903ab18e4fa7d0e25e7a3e95ae3..89b837110e5445ccba8f9256c7a70dca9c1f0680 100644 --- a/crates/onestore/src/page/mod.rs +++ b/crates/onestore/src/page/mod.rs @@ -589,7 +589,9 @@ impl Image { }) .map(|bytes| { let units: Vec = bytes - .chunks_exact(2) + .as_chunks::<2>() + .0 + .iter() .map(|pair| u16::from_le_bytes([pair[0], pair[1]])) .collect(); String::from_utf16_lossy(&units) diff --git a/crates/onestore/src/paragraph.rs b/crates/onestore/src/paragraph.rs index f78ddc49ef9feef42c3d8d3955c3fdbc9632d067..a35cdb6e2bfcdbf02036a577c152d7bcedb70f6c 100644 --- a/crates/onestore/src/paragraph.rs +++ b/crates/onestore/src/paragraph.rs @@ -575,8 +575,10 @@ impl ParagraphJoin { } ends.truncate(ends.len() - 4); if ends - .chunks_exact(4) - .map(|bytes| u32::from_le_bytes(bytes.try_into().unwrap())) + .as_chunks::<4>() + .0 + .iter() + .map(|bytes| u32::from_le_bytes(*bytes)) .collect::>() .windows(2) .any(|pair| pair[0] >= pair[1]) diff --git a/crates/onestore/src/store.rs b/crates/onestore/src/store.rs index 02681ae78843e321ec1c909fc2be73bdd077fea2..0bb8dab6e786e4aaa878523019e204fd0b9e86e1 100644 --- a/crates/onestore/src/store.rs +++ b/crates/onestore/src/store.rs @@ -640,7 +640,7 @@ impl<'a> Store<'a> { max_list: self .transaction_fragments .iter() - .flat_map(|fragment| fragment.entries.chunks_exact(8)) + .flat_map(|fragment| fragment.entries.as_chunks::<8>().0.iter()) .map(|entry| u32::from_le_bytes(entry[..4].try_into().unwrap())) .max() .unwrap(), diff --git a/crates/onestore/src/write.rs b/crates/onestore/src/write.rs index 6d0e7b337b9269050b2707573f173990cad3fc55..600be7d786bd5b5ab5f5a1cd936b3a523d1a2bf4 100644 --- a/crates/onestore/src/write.rs +++ b/crates/onestore/src/write.rs @@ -140,8 +140,10 @@ pub(crate) fn table_entries(bytes: &[u8]) -> Result> { if let Value::References { compact_ids, .. } = property.value { entries.extend( compact_ids - .chunks_exact(4) - .map(|id| u32::from_le_bytes(id.try_into().unwrap()) >> 8), + .as_chunks::<4>() + .0 + .iter() + .map(|id| u32::from_le_bytes(*id) >> 8), ); } } @@ -394,7 +396,9 @@ pub(crate) fn replacement(id: ExGuid, object: &crate::Object<'_>) -> Result() + .0 + .iter() .map(|pair| u16::from_le_bytes([pair[0], pair[1]])) .collect::>(), ) @@ -968,8 +972,8 @@ impl<'a> LiveRevision<'a> { compact_ids, } = property.value { - for bytes in compact_ids.chunks_exact(4) { - let raw = u32::from_le_bytes(bytes.try_into().unwrap()); + for bytes in compact_ids.as_chunks::<4>().0 { + let raw = u32::from_le_bytes(*bytes); if let Some((_, existing)) = targets.iter().find(|(id, _)| *id == raw) { let offset = bytes.as_ptr().addr() - object.bytes.as_ptr().addr(); remapped.push((offset, *existing)); @@ -1167,11 +1171,7 @@ fn moved_references( compact_ids, } = property.value { - ids.extend( - compact_ids - .chunks_exact(4) - .map(|id| <[u8; 4]>::try_from(id).unwrap()), - ); + ids.extend(compact_ids.as_chunks::<4>().0.iter().copied()); } } Ok(ids) @@ -1962,8 +1962,10 @@ impl Appending { if let Value::References { compact_ids, .. } = property.value { let offset = compact_ids.as_ptr().addr() - bytes.as_ptr().addr(); - for (i, value) in compact_ids.chunks_exact(4).enumerate() { - let value = u32::from_le_bytes(value.try_into().unwrap()); + for (i, value) in + compact_ids.as_chunks::<4>().0.iter().enumerate() + { + let value = u32::from_le_bytes(*value); let target = ExGuid { guid: object.global_ids[&(value >> 8)], n: value & 255, @@ -2196,7 +2198,7 @@ impl Appending { crc_used += 8; transaction_crc(checksum, entry, file_type, crc_used == crc_capacity) }; - for entry in entries.chunks_exact(8) { + for entry in entries.as_chunks::<8>().0 { checksum = advance_crc(checksum, entry); } // Past a counter carry, sentinels up to the ceiling follow the one that commits; the diff --git a/crates/onestore/src/write/tests.rs b/crates/onestore/src/write/tests.rs index 59160afadc2b1ed70459f5c101969ce35cb574f9..d7eac303fab09f140e09abe557166742c6cf1901 100644 --- a/crates/onestore/src/write/tests.rs +++ b/crates/onestore/src/write/tests.rs @@ -56,8 +56,8 @@ fn copying_reference_arrays_remaps_every_entry_in_each_stream() { panic!() }; assert_eq!(compact_ids.len(), count as usize * 4); - for (i, compact) in compact_ids.chunks_exact(4).enumerate() { - let compact = u32::from_le_bytes(compact.try_into().unwrap()); + for (i, compact) in compact_ids.as_chunks::<4>().0.iter().enumerate() { + let compact = u32::from_le_bytes(*compact); assert_eq!(compact & 255, i as u32); assert_eq!(target.global_ids[&(compact >> 8)], [(i % 3 + 1) as u8; 16]); } diff --git a/crates/onestore/tests/page_removal.rs b/crates/onestore/tests/page_removal.rs index 19b9d2101a0f3e3b1c70e4333c056637d711ada4..25e976fd775bcb83264af6effd4306c9686c35cc 100644 --- a/crates/onestore/tests/page_removal.rs +++ b/crates/onestore/tests/page_removal.rs @@ -105,12 +105,13 @@ fn compare_copy(left: &Store<'_>, right: &Store<'_>, source: ExGuid, copied: ExG ) => { assert_eq!(stream, other_stream); assert_eq!(compact_ids.len(), other_ids.len()); - for (a, b) in - compact_ids.chunks_exact(4).zip(other_ids.chunks_exact(4)) + for (a, b) in compact_ids + .as_chunks::<4>() + .0 + .iter() + .zip(other_ids.as_chunks::<4>().0.iter()) { - let ids = [a, b].map(|bytes| { - u32::from_le_bytes(bytes.try_into().unwrap()) - }); + let ids = [a, b].map(|bytes| u32::from_le_bytes(*bytes)); let [a, b] = [0, 1].map(|side| ExGuid { guid: objects[side].global_ids[&(ids[side] >> 8)], n: ids[side] & 255, diff --git a/crates/onestore/tests/properties.rs b/crates/onestore/tests/properties.rs index 426c24003d8d658bb5b3313ff44d9969bcc7b76e..9db46e811103b2a9a95ade5a74c125f6e0c82c74 100644 --- a/crates/onestore/tests/properties.rs +++ b/crates/onestore/tests/properties.rs @@ -20,7 +20,9 @@ fn native_property_chunks_preserve_unicode_and_ascii_text() { if property.id == 0x1c001c22 { let text = String::from_utf16( &data - .chunks_exact(2) + .as_chunks::<2>() + .0 + .iter() .map(|pair| u16::from_le_bytes([pair[0], pair[1]])) .collect::>(), ) diff --git a/crates/onestore/tests/revisions.rs b/crates/onestore/tests/revisions.rs index b282fd6a8a4c9f2fe64af3ee83ccde9563d30aa0..13da6061a7b3584a4ab40c77d4b308f465a5ab9a 100644 --- a/crates/onestore/tests/revisions.rs +++ b/crates/onestore/tests/revisions.rs @@ -170,7 +170,9 @@ fn active_revision_contains_current_text_and_exact_attachment_bytes() { }; let text = String::from_utf16( &data - .chunks_exact(2) + .as_chunks::<2>() + .0 + .iter() .map(|pair| u16::from_le_bytes([pair[0], pair[1]])) .collect::>(), ) diff --git a/crates/onestore/tests/support/metadata.rs b/crates/onestore/tests/support/metadata.rs index df8bd46e1a77f781881ed9cc9b735927292431e1..e76b32393e6e458e1f2d7b33029ba7086f6465f8 100644 --- a/crates/onestore/tests/support/metadata.rs +++ b/crates/onestore/tests/support/metadata.rs @@ -93,10 +93,10 @@ pub fn check(before: &ResolvedRevision<'_>, after: &ResolvedRevision<'_>, name: assert_eq!(old_fields.sets, new.sets); for field in old_fields.sets.iter().flatten() { if let Value::References { compact_ids, .. } = field.value { - let ids = compact_ids.chunks_exact(4); - assert!(ids.remainder().is_empty()); + let (ids, remainder) = compact_ids.as_chunks::<4>(); + assert!(remainder.is_empty()); for compact in ids { - let entry = u32::from_le_bytes(compact.try_into().unwrap()) >> 8; + let entry = u32::from_le_bytes(*compact) >> 8; assert_eq!( metadata.global_ids.get(&entry), Some(&old.global_ids[&entry]) diff --git a/crates/onestore/tests/support/page_schedule.rs b/crates/onestore/tests/support/page_schedule.rs index 459cdd6ca3a6efa21f0c97f4890d91ba50611478..86814fbf28fa33761b0a722cc971a82f2c08a1a0 100644 --- a/crates/onestore/tests/support/page_schedule.rs +++ b/crates/onestore/tests/support/page_schedule.rs @@ -43,7 +43,7 @@ pub fn run(input: &[u8]) { } let mut persisted = source.to_vec(); let mut caches = std::array::from_fn::<_, 12, _>(|_| source.to_vec()); - for step in input.chunks_exact(8).take(24) { + for step in input.as_chunks::<8>().0.iter().take(24) { let actor = usize::from(step[0]) % caches.len(); if step[1] % 3 == 0 { caches[actor].clone_from(&persisted); diff --git a/crates/onestore/tests/support/tree_model.rs b/crates/onestore/tests/support/tree_model.rs index ec39300852f5ed4de9a49caa50e74f6a23edc16f..f1a7754507d0da41a2a63199769043fad3173048 100644 --- a/crates/onestore/tests/support/tree_model.rs +++ b/crates/onestore/tests/support/tree_model.rs @@ -80,7 +80,7 @@ pub fn run(input: &[u8]) { }; let mut persisted = source.to_vec(); let mut clients = vec![persisted.clone(); 12]; - for step in input.chunks_exact(10).take(36) { + for step in input.as_chunks::<10>().0.iter().take(36) { let client = usize::from(step[0]) % clients.len(); if step[1] & 1 != 0 { clients[client] = persisted.clone(); diff --git a/crates/relay/src/server.rs b/crates/relay/src/server.rs index 1a5fd458a394ae48a4a361933444cd57f07b84cf..2ce8cb466d80aeca68e791d61f6ea4e495bd59c7 100644 --- a/crates/relay/src/server.rs +++ b/crates/relay/src/server.rs @@ -543,11 +543,8 @@ impl Relay { else { return false; }; - let named = named.chunks_exact(SLOT); - ( - Some(named.map(|slot| u32::from_be_bytes(slot.try_into().unwrap()))), - payload, - ) + let named = named.as_chunks::().0.iter(); + (Some(named.map(|slot| u32::from_be_bytes(*slot))), payload) } _ => (None, rest), }; diff --git a/crates/snowbound/src/linux.rs b/crates/snowbound/src/linux.rs index 64b44fdad06e977929cbca9d6398d5a3688609db..b1eae47372b8a7dc5b8183f0e2e3976dd47c7dbb 100644 --- a/crates/snowbound/src/linux.rs +++ b/crates/snowbound/src/linux.rs @@ -944,7 +944,9 @@ pub fn symbolize(offsets: impl Iterator) -> Result<(), Box = symbols - .chunks_exact(24) + .as_chunks::<24>() + .0 + .iter() .filter(|symbol| symbol[4] & 15 == 2 && field(symbol, 16, 8) > 0) .map(|symbol| { let name = &strings[field(symbol, 0, 4)..]; diff --git a/crates/snowbound/src/paste.rs b/crates/snowbound/src/paste.rs index c6768f1151f12bc97db0fa63e4727dc5da304b17..9466635cd383ea0011050630e6088891a0438bd7 100644 --- a/crates/snowbound/src/paste.rs +++ b/crates/snowbound/src/paste.rs @@ -49,7 +49,7 @@ pub(crate) fn pixels(encoded: &[u8]) -> Result<([u32; 2], Vec), Box().0 { if pixel[3] != 255 { let scale = 255.0 / f32::from(pixel[3].max(1)); let linear = draw::srgb(pixel[0], pixel[1], pixel[2]).map(|v| v * scale); diff --git a/crates/snowbound/src/screenshot.rs b/crates/snowbound/src/screenshot.rs index 2ffe981c7e654bafa0ed303f28460fa817de502a..f9306c49919a939066b1d5ec619d94727063211c 100644 --- a/crates/snowbound/src/screenshot.rs +++ b/crates/snowbound/src/screenshot.rs @@ -142,7 +142,7 @@ fn window_frame( }; let [width, height] = [info.width as f32, info.height as f32]; let radius = platform::CORNER_RADIUS * scale; - for (index, pixel) in pixels.chunks_exact_mut(4).enumerate() { + for (index, pixel) in pixels.as_chunks_mut::<4>().0.iter_mut().enumerate() { let x = (index as u32 % info.width) as f32 + 0.5; let y = (index as u32 / info.width) as f32 + 0.5; for ([cx, cy], (fill, rim)) in lights.into_iter().zip(LIGHTS) { diff --git a/crates/snowbound/src/screenshot/snow_leopard.rs b/crates/snowbound/src/screenshot/snow_leopard.rs index aad5fcb5d37b7fb0ccadf6c073d5ce2bb33ad448..ba5bd5c265ae8d8bef5709927583373aae6866d5 100644 --- a/crates/snowbound/src/screenshot/snow_leopard.rs +++ b/crates/snowbound/src/screenshot/snow_leopard.rs @@ -194,12 +194,12 @@ fn window( }) .collect(); for (y, row) in content.chunks_exact(width * 4).enumerate() { - for (x, pixel) in row.chunks_exact(4).enumerate() { + for (x, pixel) in row.as_chunks::<4>().0.iter().enumerate() { composite(&mut pixels[(y + TITLE_LINE) * width + x], pixel); } } for (y, row) in bar.chunks_exact(width * 4).enumerate() { - for (x, pixel) in row.chunks_exact(4).enumerate() { + for (x, pixel) in row.as_chunks::<4>().0.iter().enumerate() { composite(&mut pixels[y * width + x], pixel); } } @@ -209,9 +209,9 @@ fn window( let mut buttons = vec![0; reader.output_buffer_size().ok_or("Buttons too large")?]; let info = reader.next_frame(&mut buttons)?; for (y, row) in buttons.chunks_exact(info.width as usize * 4).enumerate() { - for (x, pixel) in row.chunks_exact(4).enumerate() { + for (x, pixel) in row.as_chunks::<4>().0.iter().enumerate() { let at = (4 + y) * width + 8 + 21 * (x / 14) + x % 14; - over(&mut pixels[at], pixel.try_into()?); + over(&mut pixels[at], *pixel); } } // AppKit rounds the top corners by about 4.5 pixels, a textured window's bottom ones by diff --git a/crates/snowbound/src/surface.rs b/crates/snowbound/src/surface.rs index 05f664334df192e98968595e2dceae4f804c93df..86f7a5e153708d3b5ce8990ef95e54bbc098d9ab 100644 --- a/crates/snowbound/src/surface.rs +++ b/crates/snowbound/src/surface.rs @@ -299,7 +299,7 @@ impl Surface { pixels.extend_from_slice(&line[..size[0] as usize * 4]); } if bgra { - for pixel in pixels.chunks_exact_mut(4) { + for pixel in pixels.as_chunks_mut::<4>().0 { pixel.swap(0, 2); } } diff --git a/crates/snowbound/src/watch.rs b/crates/snowbound/src/watch.rs index 9632bc156064afbc8e59e1a5a2b1f1380b6922c4..01b5eefcbd13dba24aa166072232740902eff5b4 100644 --- a/crates/snowbound/src/watch.rs +++ b/crates/snowbound/src/watch.rs @@ -641,7 +641,9 @@ mod platform { let start = at + std::mem::offset_of!(FILE_NOTIFY_INFORMATION, FileName); let end = (start + entry.FileNameLength as usize).min(bytes.len()); let name: Vec = bytes[start..end] - .chunks_exact(2) + .as_chunks::<2>() + .0 + .iter() .map(|pair| u16::from_le_bytes([pair[0], pair[1]])) .collect(); paths.push(root.join(String::from_utf16_lossy(&name))); diff --git a/crates/snowbound/src/windows.rs b/crates/snowbound/src/windows.rs index 195a1c4ffb31dd877bb0292c6bf0383e5a684518..f82d2da6b6ca640fac307da38da3590772e315d6 100644 --- a/crates/snowbound/src/windows.rs +++ b/crates/snowbound/src/windows.rs @@ -1138,7 +1138,7 @@ impl Clipboard { let formats = if let Some(picture) = &copied.picture { let (size, mut rgba) = crate::paste::pixels(picture).map_err(|_| "The picture couldn't be decoded")?; - for pixel in rgba.chunks_exact_mut(4) { + for pixel in rgba.as_chunks_mut::<4>().0 { pixel.swap(0, 2); } let header = [