authorclover caruso <git@paperclover.net> 2026-10-10 20:23:39-07:00
committerclover caruso <git@paperclover.net> 2026-10-10 22:56:05-07:00
log3bc26d2f339e409b94776447c6d0cd661d5da6ff
tree1f703754fccd4c76e2ebe209e02fb4883bb583ec
parente9d0ff1435aa931d38788bf676968c992e370104
signature Signed by SSH key SHA256:52mNGHRsVFBDED9IAX5pe+LRWUefqTbxEReunq21QvU (~clover)

chore: use array chunks for fixed-size iteration

Replace constant-size chunks_exact iterators with as_chunks, preserving remainder handling and mutable iteration. Keep runtime-size chunking unchanged. Assisted-by: gpt-6.1-sol

39 files changed, 197 insertions(+), 114 deletions(-)

crates/canvas/src/gpu/page/background.rs+15-4
...@@ -599,7 +599,9 @@ pub fn template_picture(name: &str) -> Option<Vec<u8>> {...@@ -599,7 +599,9 @@ pub fn template_picture(name: &str) -> Option<Vec<u8>> {
599 let [width, height] = [view.width(), view.height()].map(|side| side.round() as u32);599 let [width, height] = [view.width(), view.height()].map(|side| side.round() as u32);
600 // Over white paper, as OneNote's pictures are drawn.600 // Over white paper, as OneNote's pictures are drawn.
601 let rgb: Vec<u8> = render(template.svg, [width, height])601 let rgb: Vec<u8> = render(template.svg, [width, height])
602 .chunks_exact(4)602 .as_chunks::<4>()
603 .0
604 .iter()
603 .flat_map(|pixel| {605 .flat_map(|pixel| {
604 let alpha = u16::from(pixel[3]);606 let alpha = u16::from(pixel[3]);
605 [0, 1, 2].map(|channel| {607 [0, 1, 2].map(|channel| {
...@@ -624,12 +626,16 @@ pub fn template_picture(name: &str) -> Option<Vec<u8>> {...@@ -624,12 +626,16 @@ pub fn template_picture(name: &str) -> Option<Vec<u8>> {
624 } else {626 } else {
625 // OneNote's PNG templates hold 256 colours.627 // OneNote's PNG templates hold 256 colours.
626 let rgba: Vec<u8> = rgb628 let rgba: Vec<u8> = rgb
627 .chunks_exact(3)629 .as_chunks::<3>()
630 .0
631 .iter()
628 .flat_map(|pixel| [pixel[0], pixel[1], pixel[2], 255])632 .flat_map(|pixel| [pixel[0], pixel[1], pixel[2], 255])
629 .collect();633 .collect();
630 let quantized = color_quant::NeuQuant::new(10, 256, &rgba);634 let quantized = color_quant::NeuQuant::new(10, 256, &rgba);
631 let indices: Vec<u8> = rgba635 let indices: Vec<u8> = rgba
632 .chunks_exact(4)636 .as_chunks::<4>()
637 .0
638 .iter()
633 .map(|pixel| quantized.index_of(pixel) as u8)639 .map(|pixel| quantized.index_of(pixel) as u8)
634 .collect();640 .collect();
635 let mut encoder = png::Encoder::new(&mut encoded, width, height);641 let mut encoder = png::Encoder::new(&mut encoded, width, height);
...@@ -1044,7 +1050,12 @@ mod tests {...@@ -1044,7 +1050,12 @@ mod tests {
1044 })1050 })
1045 .unwrap();1051 .unwrap();
1046 let pixels = readback.get_mapped_range(..).unwrap().to_vec();1052 let pixels = readback.get_mapped_range(..).unwrap().to_vec();
1047 let pixels: Vec<[u8; 3]> = pixels.chunks_exact(4).map(|p| [p[0], p[1], p[2]]).collect();1053 let pixels: Vec<[u8; 3]> = pixels
1054 .as_chunks::<4>()
1055 .0
1056 .iter()
1057 .map(|p| [p[0], p[1], p[2]])
1058 .collect();
1048 assert!(1059 assert!(
1049 pixels1060 pixels
1050 .iter()1061 .iter()
crates/canvas/src/gpu/tag_art.rs+1-1
...@@ -87,7 +87,7 @@ fn raster(tree: &usvg::Tree) -> Option<Vec<u8>> {...@@ -87,7 +87,7 @@ fn raster(tree: &usvg::Tree) -> Option<Vec<u8>> {
87 [color.red(), color.green(), color.blue(), color.alpha()]87 [color.red(), color.green(), color.blue(), color.alpha()]
88 })88 })
89 .collect();89 .collect();
90 if rgba.chunks_exact(4).all(|pixel| pixel[3] == 0) {90 if rgba.as_chunks::<4>().0.iter().all(|pixel| pixel[3] == 0) {
91 return None;91 return None;
92 }92 }
93 Some(png(&image::RgbaImage::from_raw(width, height, rgba)?))93 Some(png(&image::RgbaImage::from_raw(width, height, rgba)?))
crates/canvas/src/recording.rs+4-2
...@@ -204,7 +204,9 @@ pub fn compress(wav: &[u8]) -> Option<(Vec<u8>, u32)> {...@@ -204,7 +204,9 @@ pub fn compress(wav: &[u8]) -> Option<(Vec<u8>, u32)> {
204 }204 }
205 let samples: Vec<i16> = wave205 let samples: Vec<i16> = wave
206 .data206 .data
207 .chunks_exact(2)207 .as_chunks::<2>()
208 .0
209 .iter()
208 .map(|pair| i16::from_le_bytes([pair[0], pair[1]]))210 .map(|pair| i16::from_le_bytes([pair[0], pair[1]]))
209 .collect();211 .collect();
210 let mut data = Vec::with_capacity(samples.len() / 2 + BLOCK);212 let mut data = Vec::with_capacity(samples.len() / 2 + BLOCK);
...@@ -221,7 +223,7 @@ pub fn compress(wav: &[u8]) -> Option<(Vec<u8>, u32)> {...@@ -221,7 +223,7 @@ pub fn compress(wav: &[u8]) -> Option<(Vec<u8>, u32)> {
221 .chain(std::iter::repeat(last))223 .chain(std::iter::repeat(last))
222 .take(BLOCK_SAMPLES - 1)224 .take(BLOCK_SAMPLES - 1)
223 .collect::<Vec<_>>();225 .collect::<Vec<_>>();
224 for pair in rest.chunks_exact(2) {226 for pair in rest.as_chunks::<2>().0 {
225 let mut byte = 0;227 let mut byte = 0;
226 for (shift, sample) in [0, 4].into_iter().zip(pair) {228 for (shift, sample) in [0, 4].into_iter().zip(pair) {
227 let code = encode(i32::from(*sample), &mut predicted, &mut index);229 let code = encode(i32::from(*sample), &mut predicted, &mut index);
crates/canvas/src/recording/video.rs+3-1
...@@ -359,7 +359,9 @@ impl Pictures {...@@ -359,7 +359,9 @@ impl Pictures {
359 .take(height)359 .take(height)
360 .filter_map(|row| row.get(..width * 4))360 .filter_map(|row| row.get(..width * 4))
361 .flat_map(|row| {361 .flat_map(|row| {
362 row.chunks_exact(4)362 row.as_chunks::<4>()
363 .0
364 .iter()
363 .flat_map(|pixel| [pixel[2], pixel[1], pixel[0]])365 .flat_map(|pixel| [pixel[2], pixel[1], pixel[0]])
364 })366 })
365 .collect();367 .collect();
crates/draw/src/render.rs+4-2
...@@ -107,7 +107,7 @@ fn decoder(encoded: &[u8]) -> Result<impl ImageDecoder + '_, RenderError> {...@@ -107,7 +107,7 @@ fn decoder(encoded: &[u8]) -> Result<impl ImageDecoder + '_, RenderError> {
107/// Premultiplies straight-alpha sRGB RGBA in linear light, so filtering never bleeds the107/// Premultiplies straight-alpha sRGB RGBA in linear light, so filtering never bleeds the
108/// colour of transparent pixels.108/// colour of transparent pixels.
109fn premultiply(pixels: &mut [u8]) {109fn premultiply(pixels: &mut [u8]) {
110 for pixel in pixels.chunks_exact_mut(4) {110 for pixel in pixels.as_chunks_mut::<4>().0 {
111 let alpha = pixel[3];111 let alpha = pixel[3];
112 if alpha == 255 {112 if alpha == 255 {
113 continue;113 continue;
...@@ -2349,7 +2349,9 @@ mod tests {...@@ -2349,7 +2349,9 @@ mod tests {
2349 assert_eq!(renderer.glyphs.len(), count);2349 assert_eq!(renderer.glyphs.len(), count);
2350 assert!(2350 assert!(
2351 captures[0]2351 captures[0]
2352 .chunks_exact(4)2352 .as_chunks::<4>()
2353 .0
2354 .iter()
2353 .filter(|pixel| pixel[0] < 200)2355 .filter(|pixel| pixel[0] < 200)
2354 .count()2356 .count()
2355 > 1002357 > 100
crates/draw/src/render/canvas2d.rs+3-3
...@@ -236,7 +236,7 @@ impl Gpu {...@@ -236,7 +236,7 @@ impl Gpu {
236 .filter(|batch| batch.blend == Blend::Over);236 .filter(|batch| batch.blend == Blend::Over);
237 for batch in batches {237 for batch in batches {
238 let range = batch.vertices.start as usize..batch.vertices.end as usize;238 let range = batch.vertices.start as usize..batch.vertices.end as usize;
239 for quad in frame.vertices[range].chunks_exact(6) {239 for quad in frame.vertices[range].as_chunks::<6>().0 {
240 let Some(color) = tinted(quad) else {240 let Some(color) = tinted(quad) else {
241 continue;241 continue;
242 };242 };
...@@ -320,7 +320,7 @@ impl Gpu {...@@ -320,7 +320,7 @@ impl Gpu {
320 // The canvas takes straight alpha; the picture's colour was premultiplied in linear320 // The canvas takes straight alpha; the picture's colour was premultiplied in linear
321 // light.321 // light.
322 let mut pixels = image.pixels().to_vec();322 let mut pixels = image.pixels().to_vec();
323 for pixel in pixels.chunks_exact_mut(4) {323 for pixel in pixels.as_chunks_mut::<4>().0 {
324 let alpha = f32::from(pixel[3]) / 255.0;324 let alpha = f32::from(pixel[3]) / 255.0;
325 if alpha > 0.0 && alpha < 1.0 {325 if alpha > 0.0 && alpha < 1.0 {
326 for byte in &mut pixel[..3] {326 for byte in &mut pixel[..3] {
...@@ -613,7 +613,7 @@ impl<'a> Painter<'a> {...@@ -613,7 +613,7 @@ impl<'a> Painter<'a> {
613 self.set_clip(None);613 self.set_clip(None);
614 return self.group(index, vertices);614 return self.group(index, vertices);
615 }615 }
616 for quad in vertices.chunks_exact(6) {616 for quad in vertices.as_chunks::<6>().0 {
617 let clip = self.clip_of(batch.scissor, quad);617 let clip = self.clip_of(batch.scissor, quad);
618 self.set_clip(clip);618 self.set_clip(clip);
619 match batch.blend {619 match batch.blend {
crates/draw/src/render/icon.rs+13-4
...@@ -627,18 +627,27 @@ mod tests {...@@ -627,18 +627,27 @@ mod tests {
627 image.data.len(),627 image.data.len(),
628 (image.placement.width * image.placement.height * 4) as usize628 (image.placement.width * image.placement.height * 4) as usize
629 );629 );
630 assert!(image.data.chunks_exact(4).any(|p| p[3] > 0));630 assert!(image.data.as_chunks::<4>().0.iter().any(|p| p[3] > 0));
631 assert!(image.data.chunks_exact(4).any(|p| p[3] < 255));631 assert!(image.data.as_chunks::<4>().0.iter().any(|p| p[3] < 255));
632 assert!(632 assert!(
633 image633 image
634 .data634 .data
635 .chunks_exact(4)635 .as_chunks::<4>()
636 .0
637 .iter()
636 .filter(|p| p[3] == 0)638 .filter(|p| p[3] == 0)
637 .all(|p| p[..3] == [0; 3])639 .all(|p| p[..3] == [0; 3])
638 );640 );
639 }641 }
640 assert_ne!(plain.data, marked.data);642 assert_ne!(plain.data, marked.data);
641 assert!(marked.data.chunks_exact(4).any(|p| p[0] > p[2] && p[3] > 0));643 assert!(
644 marked
645 .data
646 .as_chunks::<4>()
647 .0
648 .iter()
649 .any(|p| p[0] > p[2] && p[3] > 0)
650 );
642 }651 }
643 }652 }
644}653}
crates/draw/src/render/pdf.rs+38-18
...@@ -639,7 +639,9 @@ impl Document {...@@ -639,7 +639,9 @@ impl Document {
639 // Pixels are premultiplied in linear light.639 // Pixels are premultiplied in linear light.
640 let straight: Vec<u8> = image640 let straight: Vec<u8> = image
641 .pixels()641 .pixels()
642 .chunks_exact(4)642 .as_chunks::<4>()
643 .0
644 .iter()
643 .flat_map(|pixel| {645 .flat_map(|pixel| {
644 let alpha = pixel[3];646 let alpha = pixel[3];
645 if alpha == 255 || alpha == 0 {647 if alpha == 255 || alpha == 0 {
...@@ -653,10 +655,16 @@ impl Document {...@@ -653,10 +655,16 @@ impl Document {
653 })655 })
654 .collect();656 .collect();
655 let size = image.size();657 let size = image.size();
656 let opaque = straight.chunks_exact(4).all(|pixel| pixel[3] == 255);658 let opaque = straight
659 .as_chunks::<4>()
660 .0
661 .iter()
662 .all(|pixel| pixel[3] == 255);
657 if opaque && size[0] * size[1] >= 64 * 64 {663 if opaque && size[0] * size[1] >= 64 * 64 {
658 let rgb: Vec<u8> = straight664 let rgb: Vec<u8> = straight
659 .chunks_exact(4)665 .as_chunks::<4>()
666 .0
667 .iter()
660 .flat_map(|pixel| [pixel[0], pixel[1], pixel[2]])668 .flat_map(|pixel| [pixel[0], pixel[1], pixel[2]])
661 .collect();669 .collect();
662 let mut jpeg = Vec::new();670 let mut jpeg = Vec::new();
...@@ -688,23 +696,35 @@ impl Document {...@@ -688,23 +696,35 @@ impl Document {
688 /// Straight sRGB RGBA pixels as a losslessly compressed image XObject.696 /// Straight sRGB RGBA pixels as a losslessly compressed image XObject.
689 fn image(&mut self, [width, height]: [u32; 2], rgba: &[u8], interpolate: bool) -> Ref {697 fn image(&mut self, [width, height]: [u32; 2], rgba: &[u8], interpolate: bool) -> Ref {
690 let rgb: Vec<u8> = rgba698 let rgb: Vec<u8> = rgba
691 .chunks_exact(4)699 .as_chunks::<4>()
700 .0
701 .iter()
692 .flat_map(|pixel| [pixel[0], pixel[1], pixel[2]])702 .flat_map(|pixel| [pixel[0], pixel[1], pixel[2]])
693 .collect();703 .collect();
694 let mask = rgba.chunks_exact(4).any(|pixel| pixel[3] != 255).then(|| {704 let mask = rgba
695 let alpha: Vec<u8> = rgba.chunks_exact(4).map(|pixel| pixel[3]).collect();705 .as_chunks::<4>()
696 let mask = self.reserve();706 .0
697 let data = compress(&alpha);707 .iter()
698 let mut writer = self.pdf.image_xobject(mask, &data);708 .any(|pixel| pixel[3] != 255)
699 writer.filter(Filter::FlateDecode);709 .then(|| {
700 writer710 let alpha: Vec<u8> = rgba
701 .width(width as i32)711 .as_chunks::<4>()
702 .height(height as i32)712 .0
703 .color_space_name(Name(b"DeviceGray"))713 .iter()
704 .bits_per_component(8)714 .map(|pixel| pixel[3])
705 .interpolate(interpolate);715 .collect();
706 mask716 let mask = self.reserve();
707 });717 let data = compress(&alpha);
718 let mut writer = self.pdf.image_xobject(mask, &data);
719 writer.filter(Filter::FlateDecode);
720 writer
721 .width(width as i32)
722 .height(height as i32)
723 .color_space_name(Name(b"DeviceGray"))
724 .bits_per_component(8)
725 .interpolate(interpolate);
726 mask
727 });
708 let reference = self.reserve();728 let reference = self.reserve();
709 let data = compress(&rgb);729 let data = compress(&rgb);
710 let mut writer = self.pdf.image_xobject(reference, &data);730 let mut writer = self.pdf.image_xobject(reference, &data);
crates/mobile/src/tests.rs+4-1
...@@ -968,7 +968,10 @@ fn tag_icons_draw_their_art_and_highlighting_tags_have_none() {...@@ -968,7 +968,10 @@ fn tag_icons_draw_their_art_and_highlighting_tags_have_none() {
968 let drawn = unsafe { sb_tag_icon(tag.shape, true, 32, rgba.as_mut_ptr()) };968 let drawn = unsafe { sb_tag_icon(tag.shape, true, 32, rgba.as_mut_ptr()) };
969 assert_eq!(drawn, tag.shape != 0, "{tag:?}");969 assert_eq!(drawn, tag.shape != 0, "{tag:?}");
970 if drawn {970 if drawn {
971 assert!(rgba.chunks_exact(4).any(|pixel| pixel[3] > 0), "{tag:?}");971 assert!(
972 rgba.as_chunks::<4>().0.iter().any(|pixel| pixel[3] > 0),
973 "{tag:?}"
974 );
972 }975 }
973 }976 }
974}977}
crates/notebook/examples/externalize_fixture.rs+4-2
...@@ -35,8 +35,10 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {...@@ -35,8 +35,10 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
35 u32::from_le_bytes(encoded[offset..offset + 4].try_into()?) as usize;35 u32::from_le_bytes(encoded[offset..offset + 4].try_into()?) as usize;
36 let text = String::from_utf16(36 let text = String::from_utf16(
37 &encoded[offset + 4..offset + 4 + count * 2]37 &encoded[offset + 4..offset + 4 + count * 2]
38 .chunks_exact(2)38 .as_chunks::<2>()
39 .map(|v| u16::from_le_bytes(v.try_into().unwrap()))39 .0
40 .iter()
41 .map(|v| u16::from_le_bytes(*v))
40 .collect::<Vec<_>>(),42 .collect::<Vec<_>>(),
41 )?;43 )?;
42 if let FileDataReference::Internal(guid) = text.parse()? {44 if let FileDataReference::Internal(guid) = text.parse()? {
crates/notebook/src/smb/directory/records.rs+3-1
...@@ -34,7 +34,9 @@ pub(super) fn decode(mut bytes: &[u8]) -> io::Result<Vec<DirectoryEntry>> {...@@ -34,7 +34,9 @@ pub(super) fn decode(mut bytes: &[u8]) -> io::Result<Vec<DirectoryEntry>> {
34 return Err(io::ErrorKind::InvalidData.into());34 return Err(io::ErrorKind::InvalidData.into());
35 }35 }
36 let units: Vec<_> = bytes[64..end]36 let units: Vec<_> = bytes[64..end]
37 .chunks_exact(2)37 .as_chunks::<2>()
38 .0
39 .iter()
38 .map(|unit| u16::from_le_bytes([unit[0], unit[1]]))40 .map(|unit| u16::from_le_bytes([unit[0], unit[1]]))
39 .collect();41 .collect();
40 let name = String::from_utf16(&units).map_err(|_| io::ErrorKind::InvalidData)?;42 let name = String::from_utf16(&units).map_err(|_| io::ErrorKind::InvalidData)?;
crates/notebook/tests/structure.rs+3-1
...@@ -146,7 +146,9 @@ fn sections_and_groups_are_created_renamed_coloured_ordered_and_deleted() {...@@ -146,7 +146,9 @@ fn sections_and_groups_are_created_renamed_coloured_ordered_and_deleted() {
146 let bin = onestore::read_file(root.join("OneNote_RecycleBin/Open Notebook.onetoc2")).unwrap();146 let bin = onestore::read_file(root.join("OneNote_RecycleBin/Open Notebook.onetoc2")).unwrap();
147 assert!(147 assert!(
148 String::from_utf16_lossy(148 String::from_utf16_lossy(
149 &bin.chunks_exact(2)149 &bin.as_chunks::<2>()
150 .0
151 .iter()
150 .map(|c| u16::from_le_bytes([c[0], c[1]]))152 .map(|c| u16::from_le_bytes([c[0], c[1]]))
151 .collect::<Vec<_>>()153 .collect::<Vec<_>>()
152 )154 )
crates/notebook/tests/support/model_schedule.rs+1-1
...@@ -189,7 +189,7 @@ pub fn run(input: &[u8]) {...@@ -189,7 +189,7 @@ pub fn run(input: &[u8]) {
189 let directory = tempfile::tempdir().unwrap();189 let directory = tempfile::tempdir().unwrap();
190 let mut replicas: [Option<Replica>; 12] = std::array::from_fn(|_| None);190 let mut replicas: [Option<Replica>; 12] = std::array::from_fn(|_| None);
191 let mut server = Server::new(source);191 let mut server = Server::new(source);
192 for step in input.chunks_exact(8).take(48) {192 for step in input.as_chunks::<8>().0.iter().take(48) {
193 let actor = usize::from(step[0]) % replicas.len();193 let actor = usize::from(step[0]) % replicas.len();
194 let path = directory.path().join(format!("{actor}.sqlite"));194 let path = directory.path().join(format!("{actor}.sqlite"));
195 let cache = replicas[actor].get_or_insert_with(|| Replica::create(&path, source).unwrap());195 let cache = replicas[actor].get_or_insert_with(|| Replica::create(&path, source).unwrap());
crates/notebook/tests/support/page_schedule.rs+1-1
...@@ -118,7 +118,7 @@ pub fn run(input: &[u8]) {...@@ -118,7 +118,7 @@ pub fn run(input: &[u8]) {
118 write_limit: 4096,118 write_limit: 4096,
119 random: 1,119 random: 1,
120 };120 };
121 for step in input.chunks_exact(8).take(48) {121 for step in input.as_chunks::<8>().0.iter().take(48) {
122 let actor = usize::from(step[0]) % replicas.len();122 let actor = usize::from(step[0]) % replicas.len();
123 let path = directory.path().join(format!("{actor}.sqlite"));123 let path = directory.path().join(format!("{actor}.sqlite"));
124 let cache = replicas[actor].get_or_insert_with(|| Replica::create(&path, &SOURCE).unwrap());124 let cache = replicas[actor].get_or_insert_with(|| Replica::create(&path, &SOURCE).unwrap());
crates/notebook/tests/sync_pages.rs+1-1
...@@ -557,7 +557,7 @@ fn twelve_disjoint_page_batches_merge_with_dependent_bodies_without_review() {...@@ -557,7 +557,7 @@ fn twelve_disjoint_page_batches_merge_with_dependent_bodies_without_review() {
557 let mut expected_text = texts(&source);557 let mut expected_text = texts(&source);
558 let directory = tempfile::tempdir().unwrap();558 let directory = tempfile::tempdir().unwrap();
559 let mut queues = Vec::new();559 let mut queues = Vec::new();
560 for (actor, group) in created.chunks_exact(3).enumerate() {560 for (actor, group) in created.as_chunks::<3>().0.iter().enumerate() {
561 let path = directory.path().join(format!("{actor}.sqlite"));561 let path = directory.path().join(format!("{actor}.sqlite"));
562 let cache = Replica::create(&path, &source).unwrap();562 let cache = Replica::create(&path, &source).unwrap();
563 let edits = [563 let edits = [
crates/onestore/examples/edit_property.rs+4-2
...@@ -18,7 +18,9 @@ fn hex(text: &str) -> Result<Vec<u8>, Box<dyn std::error::Error>> {...@@ -18,7 +18,9 @@ fn hex(text: &str) -> Result<Vec<u8>, Box<dyn std::error::Error>> {
18 return Err("Expected an even number of hexadecimal digits".into());18 return Err("Expected an even number of hexadecimal digits".into());
19 }19 }
20 text.as_bytes()20 text.as_bytes()
21 .chunks_exact(2)21 .as_chunks::<2>()
22 .0
23 .iter()
22 .map(|pair| Ok(u8::from_str_radix(std::str::from_utf8(pair)?, 16)?))24 .map(|pair| Ok(u8::from_str_radix(std::str::from_utf8(pair)?, 16)?))
23 .collect()25 .collect()
24}26}
...@@ -69,7 +71,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {...@@ -69,7 +71,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
69 (0x6000e, 0x1c001c22) => {71 (0x6000e, 0x1c001c22) => {
70 let units = |bytes: &[u8]| -> Vec<u16> {72 let units = |bytes: &[u8]| -> Vec<u16> {
71 let mut units: Vec<u16> = bytes73 let mut units: Vec<u16> = bytes
72 .chunks_exact(2)74 .as_chunks::<2>().0.iter()
73 .map(|pair| u16::from_le_bytes([pair[0], pair[1]]))75 .map(|pair| u16::from_le_bytes([pair[0], pair[1]]))
74 .collect();76 .collect();
75 if units.last() == Some(&0) {77 if units.last() == Some(&0) {
crates/onestore/src/create.rs+2-4
...@@ -456,10 +456,8 @@ fn create(file_name: &str, file_type: FileType, spaces: Vec<NewSpace>) -> Result...@@ -456,10 +456,8 @@ fn create(file_name: &str, file_type: FileType, spaces: Vec<NewSpace>) -> Result
456 for object in &space.objects {456 for object in &space.objects {
457 for (property, value) in &object.properties {457 for (property, value) in &object.properties {
458 if matches!((property >> 26) & 0x1f, 8 | 9) {458 if matches!((property >> 26) & 0x1f, 8 | 9) {
459 for id in value.chunks_exact(4) {459 for id in value.as_chunks::<4>().0 {
460 *counts460 *counts.entry(u32::from_le_bytes(*id)).or_default() += 1;
461 .entry(u32::from_le_bytes(id.try_into().unwrap()))
462 .or_default() += 1;
463 }461 }
464 }462 }
465 }463 }
crates/onestore/src/document.rs+21-14
...@@ -629,8 +629,10 @@ fn unicode(bytes: &[u8]) -> Result<String> {...@@ -629,8 +629,10 @@ fn unicode(bytes: &[u8]) -> Result<String> {
629 return Err(invalid("Odd UTF-16 document string length"));629 return Err(invalid("Odd UTF-16 document string length"));
630 }630 }
631 let units: Vec<_> = bytes631 let units: Vec<_> = bytes
632 .chunks_exact(2)632 .as_chunks::<2>()
633 .map(|x| u16::from_le_bytes(x.try_into().unwrap()))633 .0
634 .iter()
635 .map(|x| u16::from_le_bytes(*x))
634 .collect();636 .collect();
635 String::from_utf16(units.strip_suffix(&[0]).unwrap_or(&units))637 String::from_utf16(units.strip_suffix(&[0]).unwrap_or(&units))
636 .map_err(|_| invalid("Invalid UTF-16 document string"))638 .map_err(|_| invalid("Invalid UTF-16 document string"))
...@@ -690,10 +692,7 @@ impl<'a, 'o> Fields<'a, 'o> {...@@ -690,10 +692,7 @@ impl<'a, 'o> Fields<'a, 'o> {
690 if !bytes.len().is_multiple_of(16) {692 if !bytes.len().is_multiple_of(16) {
691 return Err(invalid("Media identifiers have an invalid length"));693 return Err(invalid("Media identifiers have an invalid length"));
692 }694 }
693 Ok(bytes695 Ok(bytes.as_chunks::<16>().0.to_vec())
694 .chunks_exact(16)
695 .map(|id| id.try_into().unwrap())
696 .collect())
697 }696 }
698 fn u16(&mut self, id: u32) -> Result<Option<u16>> {697 fn u16(&mut self, id: u32) -> Result<Option<u16>> {
699 Ok(self.fixed(id)?.map(u16::from_le_bytes))698 Ok(self.fixed(id)?.map(u16::from_le_bytes))
...@@ -775,10 +774,12 @@ fn references(bytes: &[u8], ids: &BTreeMap<u32, [u8; 16]>) -> Result<Vec<ExGuid>...@@ -775,10 +774,12 @@ fn references(bytes: &[u8], ids: &BTreeMap<u32, [u8; 16]>) -> Result<Vec<ExGuid>
775 {774 {
776 let table: Vec<[u8; 16]> = ids.values().copied().collect();775 let table: Vec<[u8; 16]> = ids.values().copied().collect();
777 return bytes776 return bytes
778 .chunks_exact(4)777 .as_chunks::<4>()
778 .0
779 .iter()
779 .enumerate()780 .enumerate()
780 .map(|(i, bytes)| {781 .map(|(i, bytes)| {
781 let raw = u32::from_le_bytes(bytes.try_into().unwrap());782 let raw = u32::from_le_bytes(*bytes);
782 let guid = table.get((raw >> 8) as usize).ok_or(Error {783 let guid = table.get((raw >> 8) as usize).ok_or(Error {
783 offset: i * 4,784 offset: i * 4,
784 message: "Compact ID refers to a missing global ID",785 message: "Compact ID refers to a missing global ID",
...@@ -814,8 +815,10 @@ fn measurements(bytes: Option<&[u8]>, header: usize) -> Result<Vec<f32>> {...@@ -814,8 +815,10 @@ fn measurements(bytes: Option<&[u8]>, header: usize) -> Result<Vec<f32>> {
814 return Err(invalid("Document measurement array has an invalid length"));815 return Err(invalid("Document measurement array has an invalid length"));
815 }816 }
816 bytes[header..]817 bytes[header..]
817 .chunks_exact(4)818 .as_chunks::<4>()
818 .map(|b| finite(f32::from_le_bytes(b.try_into().unwrap()) * 36.0))819 .0
820 .iter()
821 .map(|b| finite(f32::from_le_bytes(*b) * 36.0))
819 .collect()822 .collect()
820}823}
821824
...@@ -1220,8 +1223,10 @@ impl<'a> Element<'a> {...@@ -1220,8 +1223,10 @@ impl<'a> Element<'a> {
1220 }1223 }
1221 bounds.extend(1224 bounds.extend(
1222 bytes1225 bytes
1223 .chunks_exact(4)1226 .as_chunks::<4>()
1224 .map(|b| u32::from_le_bytes(b.try_into().unwrap())),1227 .0
1228 .iter()
1229 .map(|b| u32::from_le_bytes(*b)),
1225 );1230 );
1226 }1231 }
1227 bounds.push(length);1232 bounds.push(length);
...@@ -1292,8 +1297,10 @@ impl<'a> Element<'a> {...@@ -1292,8 +1297,10 @@ impl<'a> Element<'a> {
1292 return Err(invalid("List format has an invalid length"));1297 return Err(invalid("List format has an invalid length"));
1293 }1298 }
1294 let units = bytes[2..]1299 let units = bytes[2..]
1295 .chunks_exact(2)1300 .as_chunks::<2>()
1296 .map(|b| u16::from_le_bytes(b.try_into().unwrap()))1301 .0
1302 .iter()
1303 .map(|b| u16::from_le_bytes(*b))
1297 .collect::<Vec<_>>();1304 .collect::<Vec<_>>();
1298 String::from_utf16(&units)1305 String::from_utf16(&units)
1299 .map_err(|_| invalid("Invalid UTF-16 list format"))1306 .map_err(|_| invalid("Invalid UTF-16 list format"))
crates/onestore/src/files.rs+3-1
...@@ -41,7 +41,9 @@ impl Object<'_> {...@@ -41,7 +41,9 @@ impl Object<'_> {
41 }41 }
42 let text = String::from_utf16(42 let text = String::from_utf16(
43 &reference43 &reference
44 .chunks_exact(2)44 .as_chunks::<2>()
45 .0
46 .iter()
45 .map(|pair| u16::from_le_bytes([pair[0], pair[1]]))47 .map(|pair| u16::from_le_bytes([pair[0], pair[1]]))
46 .collect::<Vec<_>>(),48 .collect::<Vec<_>>(),
47 )49 )
crates/onestore/src/page/ink.rs+11-4
...@@ -295,7 +295,12 @@ impl InkStroke {...@@ -295,7 +295,12 @@ impl InkStroke {
295 if dimensions.len() % 32 != 0 || dimensions.is_empty() {295 if dimensions.len() % 32 != 0 || dimensions.is_empty() {
296 return Err(invalid("Ink dimension table has an invalid length"));296 return Err(invalid("Ink dimension table has an invalid length"));
297 }297 }
298 let entries: Vec<&[u8]> = dimensions.chunks_exact(32).collect();298 let entries: Vec<&[u8]> = dimensions
299 .as_chunks::<32>()
300 .0
301 .iter()
302 .map(|entry| entry.as_slice())
303 .collect();
299 let axis = |guid: &[u8]| entries.iter().position(|entry| entry[..16] == *guid);304 let axis = |guid: &[u8]| entries.iter().position(|entry| entry[..16] == *guid);
300 let (Some(x), Some(y)) = (axis(&DIMENSION_X), axis(&DIMENSION_Y)) else {305 let (Some(x), Some(y)) = (axis(&DIMENSION_X), axis(&DIMENSION_Y)) else {
301 return Err(invalid("Ink dimension table lacks X and Y"));306 return Err(invalid("Ink dimension table lacks X and Y"));
...@@ -365,8 +370,10 @@ impl InkShape {...@@ -365,8 +370,10 @@ impl InkShape {
365 fn read(kind: Option<u8>, line: Option<&[u8]>, anchors: Option<&[u8]>) -> Option<Self> {370 fn read(kind: Option<u8>, line: Option<&[u8]>, anchors: Option<&[u8]>) -> Option<Self> {
366 let floats = |bytes: &[u8]| -> Vec<f32> {371 let floats = |bytes: &[u8]| -> Vec<f32> {
367 bytes372 bytes
368 .chunks_exact(4)373 .as_chunks::<4>()
369 .map(|b| f32::from_le_bytes(b.try_into().unwrap()))374 .0
375 .iter()
376 .map(|b| f32::from_le_bytes(*b))
370 .collect()377 .collect()
371 };378 };
372 match (kind?, line, anchors) {379 match (kind?, line, anchors) {
...@@ -381,7 +388,7 @@ impl InkShape {...@@ -381,7 +388,7 @@ impl InkShape {
381 let v = floats(bytes);388 let v = floats(bytes);
382 Some(Self::Closed {389 Some(Self::Closed {
383 transform: std::array::from_fn(|i| v[i] * 36.0),390 transform: std::array::from_fn(|i| v[i] * 36.0),
384 anchors: v[6..].chunks_exact(2).map(|p| [p[0], p[1]]).collect(),391 anchors: v[6..].as_chunks::<2>().0.to_vec(),
385 })392 })
386 .filter(Self::finite)393 .filter(Self::finite)
387 }394 }
crates/onestore/src/page/mod.rs+3-1
...@@ -589,7 +589,9 @@ impl Image {...@@ -589,7 +589,9 @@ impl Image {
589 })589 })
590 .map(|bytes| {590 .map(|bytes| {
591 let units: Vec<u16> = bytes591 let units: Vec<u16> = bytes
592 .chunks_exact(2)592 .as_chunks::<2>()
593 .0
594 .iter()
593 .map(|pair| u16::from_le_bytes([pair[0], pair[1]]))595 .map(|pair| u16::from_le_bytes([pair[0], pair[1]]))
594 .collect();596 .collect();
595 String::from_utf16_lossy(&units)597 String::from_utf16_lossy(&units)
crates/onestore/src/paragraph.rs+4-2
...@@ -575,8 +575,10 @@ impl ParagraphJoin {...@@ -575,8 +575,10 @@ impl ParagraphJoin {
575 }575 }
576 ends.truncate(ends.len() - 4);576 ends.truncate(ends.len() - 4);
577 if ends577 if ends
578 .chunks_exact(4)578 .as_chunks::<4>()
579 .map(|bytes| u32::from_le_bytes(bytes.try_into().unwrap()))579 .0
580 .iter()
581 .map(|bytes| u32::from_le_bytes(*bytes))
580 .collect::<Vec<_>>()582 .collect::<Vec<_>>()
581 .windows(2)583 .windows(2)
582 .any(|pair| pair[0] >= pair[1])584 .any(|pair| pair[0] >= pair[1])
crates/onestore/src/store.rs+1-1
...@@ -640,7 +640,7 @@ impl<'a> Store<'a> {...@@ -640,7 +640,7 @@ impl<'a> Store<'a> {
640 max_list: self640 max_list: self
641 .transaction_fragments641 .transaction_fragments
642 .iter()642 .iter()
643 .flat_map(|fragment| fragment.entries.chunks_exact(8))643 .flat_map(|fragment| fragment.entries.as_chunks::<8>().0.iter())
644 .map(|entry| u32::from_le_bytes(entry[..4].try_into().unwrap()))644 .map(|entry| u32::from_le_bytes(entry[..4].try_into().unwrap()))
645 .max()645 .max()
646 .unwrap(),646 .unwrap(),
crates/onestore/src/write.rs+15-13
...@@ -140,8 +140,10 @@ pub(crate) fn table_entries(bytes: &[u8]) -> Result<Vec<u32>> {...@@ -140,8 +140,10 @@ pub(crate) fn table_entries(bytes: &[u8]) -> Result<Vec<u32>> {
140 if let Value::References { compact_ids, .. } = property.value {140 if let Value::References { compact_ids, .. } = property.value {
141 entries.extend(141 entries.extend(
142 compact_ids142 compact_ids
143 .chunks_exact(4)143 .as_chunks::<4>()
144 .map(|id| u32::from_le_bytes(id.try_into().unwrap()) >> 8),144 .0
145 .iter()
146 .map(|id| u32::from_le_bytes(*id) >> 8),
145 );147 );
146 }148 }
147 }149 }
...@@ -394,7 +396,9 @@ pub(crate) fn replacement(id: ExGuid, object: &crate::Object<'_>) -> Result<Prop...@@ -394,7 +396,9 @@ pub(crate) fn replacement(id: ExGuid, object: &crate::Object<'_>) -> Result<Prop
394 let text = |bytes: &[u8]| {396 let text = |bytes: &[u8]| {
395 String::from_utf16(397 String::from_utf16(
396 &bytes398 &bytes
397 .chunks_exact(2)399 .as_chunks::<2>()
400 .0
401 .iter()
398 .map(|pair| u16::from_le_bytes([pair[0], pair[1]]))402 .map(|pair| u16::from_le_bytes([pair[0], pair[1]]))
399 .collect::<Vec<_>>(),403 .collect::<Vec<_>>(),
400 )404 )
...@@ -968,8 +972,8 @@ impl<'a> LiveRevision<'a> {...@@ -968,8 +972,8 @@ impl<'a> LiveRevision<'a> {
968 compact_ids,972 compact_ids,
969 } = property.value973 } = property.value
970 {974 {
971 for bytes in compact_ids.chunks_exact(4) {975 for bytes in compact_ids.as_chunks::<4>().0 {
972 let raw = u32::from_le_bytes(bytes.try_into().unwrap());976 let raw = u32::from_le_bytes(*bytes);
973 if let Some((_, existing)) = targets.iter().find(|(id, _)| *id == raw) {977 if let Some((_, existing)) = targets.iter().find(|(id, _)| *id == raw) {
974 let offset = bytes.as_ptr().addr() - object.bytes.as_ptr().addr();978 let offset = bytes.as_ptr().addr() - object.bytes.as_ptr().addr();
975 remapped.push((offset, *existing));979 remapped.push((offset, *existing));
...@@ -1167,11 +1171,7 @@ fn moved_references(...@@ -1167,11 +1171,7 @@ fn moved_references(
1167 compact_ids,1171 compact_ids,
1168 } = property.value1172 } = property.value
1169 {1173 {
1170 ids.extend(1174 ids.extend(compact_ids.as_chunks::<4>().0.iter().copied());
1171 compact_ids
1172 .chunks_exact(4)
1173 .map(|id| <[u8; 4]>::try_from(id).unwrap()),
1174 );
1175 }1175 }
1176 }1176 }
1177 Ok(ids)1177 Ok(ids)
...@@ -1962,8 +1962,10 @@ impl Appending {...@@ -1962,8 +1962,10 @@ impl Appending {
1962 if let Value::References { compact_ids, .. } = property.value {1962 if let Value::References { compact_ids, .. } = property.value {
1963 let offset =1963 let offset =
1964 compact_ids.as_ptr().addr() - bytes.as_ptr().addr();1964 compact_ids.as_ptr().addr() - bytes.as_ptr().addr();
1965 for (i, value) in compact_ids.chunks_exact(4).enumerate() {1965 for (i, value) in
1966 let value = u32::from_le_bytes(value.try_into().unwrap());1966 compact_ids.as_chunks::<4>().0.iter().enumerate()
1967 {
1968 let value = u32::from_le_bytes(*value);
1967 let target = ExGuid {1969 let target = ExGuid {
1968 guid: object.global_ids[&(value >> 8)],1970 guid: object.global_ids[&(value >> 8)],
1969 n: value & 255,1971 n: value & 255,
...@@ -2196,7 +2198,7 @@ impl Appending {...@@ -2196,7 +2198,7 @@ impl Appending {
2196 crc_used += 8;2198 crc_used += 8;
2197 transaction_crc(checksum, entry, file_type, crc_used == crc_capacity)2199 transaction_crc(checksum, entry, file_type, crc_used == crc_capacity)
2198 };2200 };
2199 for entry in entries.chunks_exact(8) {2201 for entry in entries.as_chunks::<8>().0 {
2200 checksum = advance_crc(checksum, entry);2202 checksum = advance_crc(checksum, entry);
2201 }2203 }
2202 // Past a counter carry, sentinels up to the ceiling follow the one that commits; the2204 // Past a counter carry, sentinels up to the ceiling follow the one that commits; the
crates/onestore/src/write/tests.rs+2-2
...@@ -56,8 +56,8 @@ fn copying_reference_arrays_remaps_every_entry_in_each_stream() {...@@ -56,8 +56,8 @@ fn copying_reference_arrays_remaps_every_entry_in_each_stream() {
56 panic!()56 panic!()
57 };57 };
58 assert_eq!(compact_ids.len(), count as usize * 4);58 assert_eq!(compact_ids.len(), count as usize * 4);
59 for (i, compact) in compact_ids.chunks_exact(4).enumerate() {59 for (i, compact) in compact_ids.as_chunks::<4>().0.iter().enumerate() {
60 let compact = u32::from_le_bytes(compact.try_into().unwrap());60 let compact = u32::from_le_bytes(*compact);
61 assert_eq!(compact & 255, i as u32);61 assert_eq!(compact & 255, i as u32);
62 assert_eq!(target.global_ids[&(compact >> 8)], [(i % 3 + 1) as u8; 16]);62 assert_eq!(target.global_ids[&(compact >> 8)], [(i % 3 + 1) as u8; 16]);
63 }63 }
crates/onestore/tests/page_removal.rs+6-5
...@@ -105,12 +105,13 @@ fn compare_copy(left: &Store<'_>, right: &Store<'_>, source: ExGuid, copied: ExG...@@ -105,12 +105,13 @@ fn compare_copy(left: &Store<'_>, right: &Store<'_>, source: ExGuid, copied: ExG
105 ) => {105 ) => {
106 assert_eq!(stream, other_stream);106 assert_eq!(stream, other_stream);
107 assert_eq!(compact_ids.len(), other_ids.len());107 assert_eq!(compact_ids.len(), other_ids.len());
108 for (a, b) in108 for (a, b) in compact_ids
109 compact_ids.chunks_exact(4).zip(other_ids.chunks_exact(4))109 .as_chunks::<4>()
110 .0
111 .iter()
112 .zip(other_ids.as_chunks::<4>().0.iter())
110 {113 {
111 let ids = [a, b].map(|bytes| {114 let ids = [a, b].map(|bytes| u32::from_le_bytes(*bytes));
112 u32::from_le_bytes(bytes.try_into().unwrap())
113 });
114 let [a, b] = [0, 1].map(|side| ExGuid {115 let [a, b] = [0, 1].map(|side| ExGuid {
115 guid: objects[side].global_ids[&(ids[side] >> 8)],116 guid: objects[side].global_ids[&(ids[side] >> 8)],
116 n: ids[side] & 255,117 n: ids[side] & 255,
crates/onestore/tests/properties.rs+3-1
...@@ -20,7 +20,9 @@ fn native_property_chunks_preserve_unicode_and_ascii_text() {...@@ -20,7 +20,9 @@ fn native_property_chunks_preserve_unicode_and_ascii_text() {
20 if property.id == 0x1c001c22 {20 if property.id == 0x1c001c22 {
21 let text = String::from_utf16(21 let text = String::from_utf16(
22 &data22 &data
23 .chunks_exact(2)23 .as_chunks::<2>()
24 .0
25 .iter()
24 .map(|pair| u16::from_le_bytes([pair[0], pair[1]]))26 .map(|pair| u16::from_le_bytes([pair[0], pair[1]]))
25 .collect::<Vec<_>>(),27 .collect::<Vec<_>>(),
26 )28 )
crates/onestore/tests/revisions.rs+3-1
...@@ -170,7 +170,9 @@ fn active_revision_contains_current_text_and_exact_attachment_bytes() {...@@ -170,7 +170,9 @@ fn active_revision_contains_current_text_and_exact_attachment_bytes() {
170 };170 };
171 let text = String::from_utf16(171 let text = String::from_utf16(
172 &data172 &data
173 .chunks_exact(2)173 .as_chunks::<2>()
174 .0
175 .iter()
174 .map(|pair| u16::from_le_bytes([pair[0], pair[1]]))176 .map(|pair| u16::from_le_bytes([pair[0], pair[1]]))
175 .collect::<Vec<_>>(),177 .collect::<Vec<_>>(),
176 )178 )
crates/onestore/tests/support/metadata.rs+3-3
...@@ -93,10 +93,10 @@ pub fn check(before: &ResolvedRevision<'_>, after: &ResolvedRevision<'_>, name:...@@ -93,10 +93,10 @@ pub fn check(before: &ResolvedRevision<'_>, after: &ResolvedRevision<'_>, name:
93 assert_eq!(old_fields.sets, new.sets);93 assert_eq!(old_fields.sets, new.sets);
94 for field in old_fields.sets.iter().flatten() {94 for field in old_fields.sets.iter().flatten() {
95 if let Value::References { compact_ids, .. } = field.value {95 if let Value::References { compact_ids, .. } = field.value {
96 let ids = compact_ids.chunks_exact(4);96 let (ids, remainder) = compact_ids.as_chunks::<4>();
97 assert!(ids.remainder().is_empty());97 assert!(remainder.is_empty());
98 for compact in ids {98 for compact in ids {
99 let entry = u32::from_le_bytes(compact.try_into().unwrap()) >> 8;99 let entry = u32::from_le_bytes(*compact) >> 8;
100 assert_eq!(100 assert_eq!(
101 metadata.global_ids.get(&entry),101 metadata.global_ids.get(&entry),
102 Some(&old.global_ids[&entry])102 Some(&old.global_ids[&entry])
crates/onestore/tests/support/page_schedule.rs+1-1
...@@ -43,7 +43,7 @@ pub fn run(input: &[u8]) {...@@ -43,7 +43,7 @@ pub fn run(input: &[u8]) {
43 }43 }
44 let mut persisted = source.to_vec();44 let mut persisted = source.to_vec();
45 let mut caches = std::array::from_fn::<_, 12, _>(|_| source.to_vec());45 let mut caches = std::array::from_fn::<_, 12, _>(|_| source.to_vec());
46 for step in input.chunks_exact(8).take(24) {46 for step in input.as_chunks::<8>().0.iter().take(24) {
47 let actor = usize::from(step[0]) % caches.len();47 let actor = usize::from(step[0]) % caches.len();
48 if step[1] % 3 == 0 {48 if step[1] % 3 == 0 {
49 caches[actor].clone_from(&persisted);49 caches[actor].clone_from(&persisted);
crates/onestore/tests/support/tree_model.rs+1-1
...@@ -80,7 +80,7 @@ pub fn run(input: &[u8]) {...@@ -80,7 +80,7 @@ pub fn run(input: &[u8]) {
80 };80 };
81 let mut persisted = source.to_vec();81 let mut persisted = source.to_vec();
82 let mut clients = vec![persisted.clone(); 12];82 let mut clients = vec![persisted.clone(); 12];
83 for step in input.chunks_exact(10).take(36) {83 for step in input.as_chunks::<10>().0.iter().take(36) {
84 let client = usize::from(step[0]) % clients.len();84 let client = usize::from(step[0]) % clients.len();
85 if step[1] & 1 != 0 {85 if step[1] & 1 != 0 {
86 clients[client] = persisted.clone();86 clients[client] = persisted.clone();
crates/relay/src/server.rs+2-5
...@@ -543,11 +543,8 @@ impl Relay {...@@ -543,11 +543,8 @@ impl Relay {
543 else {543 else {
544 return false;544 return false;
545 };545 };
546 let named = named.chunks_exact(SLOT);546 let named = named.as_chunks::<SLOT>().0.iter();
547 (547 (Some(named.map(|slot| u32::from_be_bytes(*slot))), payload)
548 Some(named.map(|slot| u32::from_be_bytes(slot.try_into().unwrap()))),
549 payload,
550 )
551 }548 }
552 _ => (None, rest),549 _ => (None, rest),
553 };550 };
crates/snowbound/src/linux.rs+3-1
...@@ -944,7 +944,9 @@ pub fn symbolize(offsets: impl Iterator<Item = OsString>) -> Result<(), Box<dyn...@@ -944,7 +944,9 @@ pub fn symbolize(offsets: impl Iterator<Item = OsString>) -> Result<(), Box<dyn
944 let strings = sections[field(table, 40, 4)];944 let strings = sections[field(table, 40, 4)];
945 let strings = read(field(strings, 24, 8), field(strings, 32, 8))?;945 let strings = read(field(strings, 24, 8), field(strings, 32, 8))?;
946 let mut ranges: Vec<(usize, usize, &[u8])> = symbols946 let mut ranges: Vec<(usize, usize, &[u8])> = symbols
947 .chunks_exact(24)947 .as_chunks::<24>()
948 .0
949 .iter()
948 .filter(|symbol| symbol[4] & 15 == 2 && field(symbol, 16, 8) > 0)950 .filter(|symbol| symbol[4] & 15 == 2 && field(symbol, 16, 8) > 0)
949 .map(|symbol| {951 .map(|symbol| {
950 let name = &strings[field(symbol, 0, 4)..];952 let name = &strings[field(symbol, 0, 4)..];
crates/snowbound/src/paste.rs+1-1
...@@ -49,7 +49,7 @@ pub(crate) fn pixels(encoded: &[u8]) -> Result<([u32; 2], Vec<u8>), Box<dyn Erro...@@ -49,7 +49,7 @@ pub(crate) fn pixels(encoded: &[u8]) -> Result<([u32; 2], Vec<u8>), Box<dyn Erro
49 let image = draw::RasterImage::decode(encoded, [u32::MAX; 2])49 let image = draw::RasterImage::decode(encoded, [u32::MAX; 2])
50 .map_err(|error| format!("{error:?}"))?;50 .map_err(|error| format!("{error:?}"))?;
51 let mut rgba = image.pixels().to_vec();51 let mut rgba = image.pixels().to_vec();
52 for pixel in rgba.chunks_exact_mut(4) {52 for pixel in rgba.as_chunks_mut::<4>().0 {
53 if pixel[3] != 255 {53 if pixel[3] != 255 {
54 let scale = 255.0 / f32::from(pixel[3].max(1));54 let scale = 255.0 / f32::from(pixel[3].max(1));
55 let linear = draw::srgb(pixel[0], pixel[1], pixel[2]).map(|v| v * scale);55 let linear = draw::srgb(pixel[0], pixel[1], pixel[2]).map(|v| v * scale);
crates/snowbound/src/screenshot.rs+1-1
...@@ -142,7 +142,7 @@ fn window_frame(...@@ -142,7 +142,7 @@ fn window_frame(
142 };142 };
143 let [width, height] = [info.width as f32, info.height as f32];143 let [width, height] = [info.width as f32, info.height as f32];
144 let radius = platform::CORNER_RADIUS * scale;144 let radius = platform::CORNER_RADIUS * scale;
145 for (index, pixel) in pixels.chunks_exact_mut(4).enumerate() {145 for (index, pixel) in pixels.as_chunks_mut::<4>().0.iter_mut().enumerate() {
146 let x = (index as u32 % info.width) as f32 + 0.5;146 let x = (index as u32 % info.width) as f32 + 0.5;
147 let y = (index as u32 / info.width) as f32 + 0.5;147 let y = (index as u32 / info.width) as f32 + 0.5;
148 for ([cx, cy], (fill, rim)) in lights.into_iter().zip(LIGHTS) {148 for ([cx, cy], (fill, rim)) in lights.into_iter().zip(LIGHTS) {
crates/snowbound/src/screenshot/snow_leopard.rs+4-4
...@@ -194,12 +194,12 @@ fn window(...@@ -194,12 +194,12 @@ fn window(
194 })194 })
195 .collect();195 .collect();
196 for (y, row) in content.chunks_exact(width * 4).enumerate() {196 for (y, row) in content.chunks_exact(width * 4).enumerate() {
197 for (x, pixel) in row.chunks_exact(4).enumerate() {197 for (x, pixel) in row.as_chunks::<4>().0.iter().enumerate() {
198 composite(&mut pixels[(y + TITLE_LINE) * width + x], pixel);198 composite(&mut pixels[(y + TITLE_LINE) * width + x], pixel);
199 }199 }
200 }200 }
201 for (y, row) in bar.chunks_exact(width * 4).enumerate() {201 for (y, row) in bar.chunks_exact(width * 4).enumerate() {
202 for (x, pixel) in row.chunks_exact(4).enumerate() {202 for (x, pixel) in row.as_chunks::<4>().0.iter().enumerate() {
203 composite(&mut pixels[y * width + x], pixel);203 composite(&mut pixels[y * width + x], pixel);
204 }204 }
205 }205 }
...@@ -209,9 +209,9 @@ fn window(...@@ -209,9 +209,9 @@ fn window(
209 let mut buttons = vec![0; reader.output_buffer_size().ok_or("Buttons too large")?];209 let mut buttons = vec![0; reader.output_buffer_size().ok_or("Buttons too large")?];
210 let info = reader.next_frame(&mut buttons)?;210 let info = reader.next_frame(&mut buttons)?;
211 for (y, row) in buttons.chunks_exact(info.width as usize * 4).enumerate() {211 for (y, row) in buttons.chunks_exact(info.width as usize * 4).enumerate() {
212 for (x, pixel) in row.chunks_exact(4).enumerate() {212 for (x, pixel) in row.as_chunks::<4>().0.iter().enumerate() {
213 let at = (4 + y) * width + 8 + 21 * (x / 14) + x % 14;213 let at = (4 + y) * width + 8 + 21 * (x / 14) + x % 14;
214 over(&mut pixels[at], pixel.try_into()?);214 over(&mut pixels[at], *pixel);
215 }215 }
216 }216 }
217 // AppKit rounds the top corners by about 4.5 pixels, a textured window's bottom ones by217 // AppKit rounds the top corners by about 4.5 pixels, a textured window's bottom ones by
crates/snowbound/src/surface.rs+1-1
...@@ -299,7 +299,7 @@ impl Surface {...@@ -299,7 +299,7 @@ impl Surface {
299 pixels.extend_from_slice(&line[..size[0] as usize * 4]);299 pixels.extend_from_slice(&line[..size[0] as usize * 4]);
300 }300 }
301 if bgra {301 if bgra {
302 for pixel in pixels.chunks_exact_mut(4) {302 for pixel in pixels.as_chunks_mut::<4>().0 {
303 pixel.swap(0, 2);303 pixel.swap(0, 2);
304 }304 }
305 }305 }
crates/snowbound/src/watch.rs+3-1
...@@ -641,7 +641,9 @@ mod platform {...@@ -641,7 +641,9 @@ mod platform {
641 let start = at + std::mem::offset_of!(FILE_NOTIFY_INFORMATION, FileName);641 let start = at + std::mem::offset_of!(FILE_NOTIFY_INFORMATION, FileName);
642 let end = (start + entry.FileNameLength as usize).min(bytes.len());642 let end = (start + entry.FileNameLength as usize).min(bytes.len());
643 let name: Vec<u16> = bytes[start..end]643 let name: Vec<u16> = bytes[start..end]
644 .chunks_exact(2)644 .as_chunks::<2>()
645 .0
646 .iter()
645 .map(|pair| u16::from_le_bytes([pair[0], pair[1]]))647 .map(|pair| u16::from_le_bytes([pair[0], pair[1]]))
646 .collect();648 .collect();
647 paths.push(root.join(String::from_utf16_lossy(&name)));649 paths.push(root.join(String::from_utf16_lossy(&name)));
crates/snowbound/src/windows.rs+1-1
...@@ -1138,7 +1138,7 @@ impl Clipboard {...@@ -1138,7 +1138,7 @@ impl Clipboard {
1138 let formats = if let Some(picture) = &copied.picture {1138 let formats = if let Some(picture) = &copied.picture {
1139 let (size, mut rgba) =1139 let (size, mut rgba) =
1140 crate::paste::pixels(picture).map_err(|_| "The picture couldn't be decoded")?;1140 crate::paste::pixels(picture).map_err(|_| "The picture couldn't be decoded")?;
1141 for pixel in rgba.chunks_exact_mut(4) {1141 for pixel in rgba.as_chunks_mut::<4>().0 {
1142 pixel.swap(0, 2);1142 pixel.swap(0, 2);
1143 }1143 }
1144 let header = [1144 let header = [