mirror of
https://github.com/storytold/pdfcraft.git
synced 2026-10-26 19:19:10 -06:00
CI: as_chunks instead of constant-size chunks_exact (clippy 1.99 chunks_exact_to_as_chunks)
Stable clippy 1.99 denies chunks_exact/chunks_exact_mut with a constant size (32 sites), which failed the test job on main and every open PR. Behaviour unchanged; MSRV 1.90 has as_chunks. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
788456a8e7
commit
ab47bf4b9a
@@ -215,7 +215,7 @@ pub fn build(d: &Dict) -> Option<Stream> {
|
||||
_ if markup => {
|
||||
let q = nums(d, b"QuadPoints").filter(|q| !q.is_empty() && q.len() % 8 == 0)?;
|
||||
let col = stroke?;
|
||||
for quad in q.chunks_exact(8) {
|
||||
for quad in q.as_chunks::<8>().0.iter() {
|
||||
let p = |i: usize| (quad[2 * i], quad[2 * i + 1]);
|
||||
let (p1, p2, p3, p4) = (p(0), p(1), p(2), p(3));
|
||||
let h = (p1.0 - p3.0).hypot(p1.1 - p3.1);
|
||||
@@ -268,7 +268,7 @@ pub fn build(d: &Dict) -> Option<Stream> {
|
||||
let q = nums(d, b"QuadPoints").filter(|q| !q.is_empty() && q.len() % 8 == 0)?;
|
||||
let col = stroke.unwrap_or([0.89, 0.13, 0.13]);
|
||||
c.push_str(&format!("{}1 w\n", rg_stroke(col)));
|
||||
for quad in q.chunks_exact(8) {
|
||||
for quad in q.as_chunks::<8>().0.iter() {
|
||||
c.push_str(&format!(
|
||||
"{} {} m {} {} l {} {} l {} {} l h S\n",
|
||||
n(quad[0]),
|
||||
@@ -326,7 +326,7 @@ pub fn build(d: &Dict) -> Option<Stream> {
|
||||
}
|
||||
b"Polygon" | b"PolyLine" => {
|
||||
let v = nums(d, b"Vertices").filter(|v| v.len() >= 4 && v.len() % 2 == 0)?;
|
||||
let pts: Vec<(f64, f64)> = v.chunks_exact(2).map(|p| (p[0], p[1])).collect();
|
||||
let pts: Vec<(f64, f64)> = v.as_chunks::<2>().0.iter().map(|p| (p[0], p[1])).collect();
|
||||
let col = stroke;
|
||||
let closed = subtype == b"Polygon";
|
||||
let fill = if closed { color(d, b"IC")? } else { None };
|
||||
@@ -388,7 +388,7 @@ pub fn build(d: &Dict) -> Option<Stream> {
|
||||
c.push_str(&format!("{}{} w 1 J 1 j\n", rg_stroke(col), n(w)));
|
||||
for s in list {
|
||||
let pts: Vec<f64> = s.as_array()?.iter().map(|o| o.as_f64()).collect::<Option<_>>()?;
|
||||
let pts: Vec<(f64, f64)> = pts.chunks_exact(2).map(|p| (p[0], p[1])).collect();
|
||||
let pts: Vec<(f64, f64)> = pts.as_chunks::<2>().0.iter().map(|p| (p[0], p[1])).collect();
|
||||
let Some(first) = pts.first() else { continue };
|
||||
c.push_str(&format!("{} {} m\n", n(first.0), n(first.1)));
|
||||
if pts.len() == 1 {
|
||||
@@ -408,7 +408,7 @@ pub fn build(d: &Dict) -> Option<Stream> {
|
||||
c.push_str(&rg(stroke.unwrap_or([0.0; 3])));
|
||||
for contour in outline {
|
||||
let v: Vec<f64> = contour.as_array().map(|a| a.iter().filter_map(Object::as_f64).collect()).unwrap_or_default();
|
||||
for (i, p) in v.chunks_exact(2).enumerate() {
|
||||
for (i, p) in v.as_chunks::<2>().0.iter().enumerate() {
|
||||
c.push_str(&format!("{} {} {}\n", n(x0 + p[0] * w), n(y0 + p[1] * h), if i == 0 { "m" } else { "l" }));
|
||||
}
|
||||
if v.len() >= 6 {
|
||||
@@ -515,7 +515,7 @@ pub fn build(d: &Dict) -> Option<Stream> {
|
||||
return None;
|
||||
}
|
||||
let lw = bw.max(0.5);
|
||||
let pts: Vec<(f64, f64)> = cl.chunks_exact(2).map(|p| (p[0], p[1])).collect();
|
||||
let pts: Vec<(f64, f64)> = cl.as_chunks::<2>().0.iter().map(|p| (p[0], p[1])).collect();
|
||||
c.push_str(&format!("{}{}{} w 1 J 1 j\n", rg_stroke(text_color), rg(bg.unwrap_or([1.0; 3])), n(lw)));
|
||||
for (i, p) in pts.iter().enumerate() {
|
||||
c.push_str(&format!("{} {} {}\n", n(p.0), n(p.1), if i == 0 { "m" } else { "l" }));
|
||||
|
||||
@@ -714,7 +714,8 @@ fn rect_for(shape: &Shape, style: &Style) -> Result<[f64; 4], AnnotError> {
|
||||
if quads.is_empty() || !quads.iter().all(|q| finite(q)) {
|
||||
return Err(bad("text area (no quadrilaterals)"));
|
||||
}
|
||||
bounds(quads.iter().flat_map(|q| q.chunks_exact(2).map(|p| [p[0], p[1]]).collect::<Vec<_>>())).ok_or_else(|| bad("text area"))?
|
||||
bounds(quads.iter().flat_map(|q| q.as_chunks::<2>().0.iter().map(|p| [p[0], p[1]]).collect::<Vec<_>>()))
|
||||
.ok_or_else(|| bad("text area"))?
|
||||
}
|
||||
Shape::Rectangle { rect }
|
||||
| Shape::Oval { rect }
|
||||
@@ -1479,7 +1480,7 @@ pub fn summaries(doc: &Document) -> Vec<Summary> {
|
||||
color = Some([f(i - 3), f(i - 2), f(i - 1)]);
|
||||
}
|
||||
}
|
||||
let quads = nums(b"QuadPoints").chunks_exact(8).map(|q| <[f32; 8]>::try_from(q).unwrap_or_default()).collect();
|
||||
let quads = nums(b"QuadPoints").as_chunks::<8>().0.to_vec();
|
||||
let in_reply_to = d.get(b"IRT").map(|o| doc.resolve(o)).and_then(|o| o.as_dict().cloned()).and_then(|p| text_value(doc, &p, b"NM"));
|
||||
out.push(Summary {
|
||||
page,
|
||||
@@ -1653,7 +1654,7 @@ pub fn erase_ink(doc: &mut Document, page: usize, index: usize, path: &[[f64; 2]
|
||||
.iter()
|
||||
.map(|s| {
|
||||
let v: Vec<f64> = doc.resolve(s).as_array().map(|a| a.iter().filter_map(|x| doc.resolve(x).as_f64()).collect()).unwrap_or_default();
|
||||
v.chunks_exact(2).map(|p| [p[0], p[1]]).collect()
|
||||
v.as_chunks::<2>().0.iter().map(|p| [p[0], p[1]]).collect()
|
||||
})
|
||||
.collect();
|
||||
// Distance from a point to the eraser's path (segments, or a single point).
|
||||
|
||||
@@ -1506,7 +1506,7 @@ fn outline(items: &[printcraft_render::OutlineItem]) -> Value {
|
||||
|
||||
fn encode_png(width: u32, height: u32, premultiplied: &[u8]) -> Result<Vec<u8>> {
|
||||
let mut rgba = premultiplied.to_vec();
|
||||
for px in rgba.chunks_exact_mut(4) {
|
||||
for px in rgba.as_chunks_mut::<4>().0 {
|
||||
let a = u32::from(px[3]);
|
||||
if a != 0 && a != 255 {
|
||||
for c in &mut px[..3] {
|
||||
|
||||
@@ -56,7 +56,7 @@ impl PdfString {
|
||||
pub fn to_text(&self) -> String {
|
||||
let b = &self.bytes;
|
||||
if b.len() >= 2 && b[0] == 0xFE && b[1] == 0xFF {
|
||||
let units: Vec<u16> = b[2..].chunks_exact(2).map(|c| u16::from_be_bytes([c[0], c[1]])).collect();
|
||||
let units: Vec<u16> = b[2..].as_chunks::<2>().0.iter().map(|c| u16::from_be_bytes(*c)).collect();
|
||||
return String::from_utf16_lossy(&units);
|
||||
}
|
||||
if b.len() >= 3 && b[..3] == [0xEF, 0xBB, 0xBF] {
|
||||
|
||||
@@ -230,7 +230,7 @@ fn unpack(data: &[u8], w: usize, h: usize, n: usize, bpc: usize) -> Option<Vec<u
|
||||
let r = &data[y * row..(y + 1) * row];
|
||||
match bpc {
|
||||
8 => out.extend_from_slice(&r[..w * n]),
|
||||
16 => out.extend(r.chunks_exact(2).take(w * n).map(|c| c[0])),
|
||||
16 => out.extend(r.as_chunks::<2>().0.iter().take(w * n).map(|c| c[0])),
|
||||
_ => {
|
||||
let per = 8 / bpc;
|
||||
let m = (1u8 << bpc) - 1;
|
||||
@@ -275,7 +275,7 @@ fn png(w: u32, h: u32, rgb: &[u8], alpha: Option<&[u8]>) -> Result<Vec<u8>, Stri
|
||||
let data: Vec<u8> = match alpha {
|
||||
Some(a) => {
|
||||
enc.set_color(png::ColorType::Rgba);
|
||||
rgb.chunks_exact(3).zip(a).flat_map(|(c, a)| [c[0], c[1], c[2], *a]).collect()
|
||||
rgb.as_chunks::<3>().0.iter().zip(a).flat_map(|(c, a)| [c[0], c[1], c[2], *a]).collect()
|
||||
}
|
||||
None => {
|
||||
enc.set_color(png::ColorType::Rgb);
|
||||
|
||||
@@ -266,10 +266,13 @@ fn png_image(name: &str, bytes: &[u8]) -> Result<Embedded, CreateError> {
|
||||
/// 8-bit RGBA pixels → an image (gray when every pixel is, with a soft mask when any pixel is
|
||||
/// not opaque).
|
||||
fn rgba_image(rgba: &[u8], (w, h): (u32, u32), dpi: (f64, f64)) -> Embedded {
|
||||
let gray = rgba.chunks_exact(4).all(|p| p[0] == p[1] && p[1] == p[2]);
|
||||
let opaque = rgba.chunks_exact(4).all(|p| p[3] == 255);
|
||||
let colour: Vec<u8> =
|
||||
if gray { rgba.chunks_exact(4).map(|p| p[0]).collect() } else { rgba.chunks_exact(4).flat_map(|p| [p[0], p[1], p[2]]).collect() };
|
||||
let gray = rgba.as_chunks::<4>().0.iter().all(|p| p[0] == p[1] && p[1] == p[2]);
|
||||
let opaque = rgba.as_chunks::<4>().0.iter().all(|p| p[3] == 255);
|
||||
let colour: Vec<u8> = if gray {
|
||||
rgba.as_chunks::<4>().0.iter().map(|p| p[0]).collect()
|
||||
} else {
|
||||
rgba.as_chunks::<4>().0.iter().flat_map(|p| [p[0], p[1], p[2]]).collect()
|
||||
};
|
||||
let mut d = Dict::new();
|
||||
d.set(b"ColorSpace".to_vec(), Object::name(if gray { "DeviceGray" } else { "DeviceRGB" }));
|
||||
d.set(b"BitsPerComponent".to_vec(), Object::Int(8));
|
||||
@@ -281,7 +284,7 @@ fn rgba_image(rgba: &[u8], (w, h): (u32, u32), dpi: (f64, f64)) -> Embedded {
|
||||
m.set(b"Height".to_vec(), Object::Int(h as i64));
|
||||
m.set(b"ColorSpace".to_vec(), Object::name("DeviceGray"));
|
||||
m.set(b"BitsPerComponent".to_vec(), Object::Int(8));
|
||||
(m, rgba.chunks_exact(4).map(|p| p[3]).collect())
|
||||
(m, rgba.as_chunks::<4>().0.iter().map(|p| p[3]).collect())
|
||||
});
|
||||
Embedded { dict: d, data: colour, filtered: false, smask, px: (w, h), dpi }
|
||||
}
|
||||
@@ -351,7 +354,7 @@ fn tiff_pages(name: &str, bytes: &[u8]) -> Result<Vec<Embedded>, CreateError> {
|
||||
}
|
||||
C::RGBA(8 | 16) => rgba_image(&data, (w, h), dpi),
|
||||
C::GrayA(8 | 16) => {
|
||||
let rgba: Vec<u8> = data.chunks_exact(2).flat_map(|p| [p[0], p[0], p[0], p[1]]).collect();
|
||||
let rgba: Vec<u8> = data.as_chunks::<2>().0.iter().flat_map(|p| [p[0], p[0], p[0], p[1]]).collect();
|
||||
rgba_image(&rgba, (w, h), dpi)
|
||||
}
|
||||
other => return Err(bad(format!("{other:?} TIFF images aren't supported yet"))),
|
||||
|
||||
@@ -105,7 +105,7 @@ impl Exporter {
|
||||
/// Premultiplied RGBA → PNG (straight alpha).
|
||||
pub fn encode_png(width: u32, height: u32, premultiplied: &[u8]) -> Result<Vec<u8>, String> {
|
||||
let mut rgba = premultiplied.to_vec();
|
||||
for px in rgba.chunks_exact_mut(4) {
|
||||
for px in rgba.as_chunks_mut::<4>().0 {
|
||||
let a = u32::from(px[3]);
|
||||
if a != 0 && a != 255 {
|
||||
for c in &mut px[..3] {
|
||||
@@ -155,7 +155,9 @@ impl ImageFormat {
|
||||
/// Premultiplied RGBA composited over white → RGB.
|
||||
fn over_white(premultiplied: &[u8]) -> Vec<u8> {
|
||||
premultiplied
|
||||
.chunks_exact(4)
|
||||
.as_chunks::<4>()
|
||||
.0
|
||||
.iter()
|
||||
.flat_map(|p| {
|
||||
let k = 255 - p[3];
|
||||
[p[0].saturating_add(k), p[1].saturating_add(k), p[2].saturating_add(k)]
|
||||
|
||||
@@ -114,7 +114,7 @@ impl Ocr {
|
||||
}
|
||||
// ocrs wants 1 or 3 channels.
|
||||
let rgb: std::borrow::Cow<[u8]> = if pixels.len() == (width * height * 4) as usize {
|
||||
pixels.chunks_exact(4).flat_map(|p| [p[0], p[1], p[2]]).collect::<Vec<u8>>().into()
|
||||
pixels.as_chunks::<4>().0.iter().flat_map(|p| [p[0], p[1], p[2]]).collect::<Vec<u8>>().into()
|
||||
} else {
|
||||
pixels.into()
|
||||
};
|
||||
|
||||
@@ -131,7 +131,7 @@ pub fn page_label_ranges(doc: &Document) -> Vec<LabelRange> {
|
||||
let node = doc.resolve(&node);
|
||||
let Some(d) = node.as_dict() else { continue };
|
||||
if let Some(nums) = d.get(b"Nums").map(|n| doc.resolve(n)).and_then(|n| n.as_array().cloned()) {
|
||||
for pair in nums.chunks_exact(2) {
|
||||
for pair in nums.as_chunks::<2>().0 {
|
||||
let (Some(start), Some(spec)) = (pair[0].as_int(), doc.resolve(&pair[1]).as_dict().cloned()) else { continue };
|
||||
if start < 0 {
|
||||
continue;
|
||||
|
||||
@@ -227,7 +227,7 @@ pub(crate) fn process(doc: &mut Document, scope: &mut Scope<'_>, streams: &[Vec<
|
||||
let pts: Vec<(f64, f64)> = match o {
|
||||
b"re" => op.nums::<4>().map(|[x, y, w, h]| vec![(x, y), (x + w, y), (x, y + h), (x + w, y + h)]).unwrap_or_default(),
|
||||
b"h" | b"W" | b"W*" => Vec::new(),
|
||||
_ => op.operands.iter().filter_map(Object::as_f64).collect::<Vec<_>>().chunks_exact(2).map(|p| (p[0], p[1])).collect(),
|
||||
_ => op.operands.iter().filter_map(Object::as_f64).collect::<Vec<_>>().as_chunks::<2>().0.iter().map(|p| (p[0], p[1])).collect(),
|
||||
};
|
||||
for (x, y) in pts {
|
||||
let (u, v) = gs.ctm.apply(x, y);
|
||||
|
||||
@@ -141,7 +141,9 @@ pub fn marks(doc: &Document) -> Vec<Mark> {
|
||||
.and_then(|q| doc.resolve(q).as_array().map(|a| a.iter().filter_map(Object::as_f64).collect()))
|
||||
.unwrap_or_default();
|
||||
let mut rects: Vec<[f64; 4]> = quads
|
||||
.chunks_exact(8)
|
||||
.as_chunks::<8>()
|
||||
.0
|
||||
.iter()
|
||||
.map(|q| {
|
||||
let xs = [q[0], q[2], q[4], q[6]];
|
||||
let ys = [q[1], q[3], q[5], q[7]];
|
||||
|
||||
@@ -586,7 +586,7 @@ impl<'a> Inspector<'a> {
|
||||
let quads = match d.get(b"QuadPoints").map(|o| self.resolve(o)) {
|
||||
Ok(Object::Array(q)) => {
|
||||
let v: Vec<f32> = q.iter().map(|o| o.as_float().unwrap_or(0.0)).collect();
|
||||
v.chunks_exact(8).map(|c| <[f32; 8]>::try_from(c).unwrap_or_default()).collect()
|
||||
v.as_chunks::<8>().0.to_vec()
|
||||
}
|
||||
_ => Vec::new(),
|
||||
};
|
||||
|
||||
@@ -742,7 +742,7 @@ trailer << /Root 1 0 R >>
|
||||
assert_eq!((looped.width, looped.height), (40, 40));
|
||||
let plain = render(pdf("1 0 d0 0 0 1 1 re f"));
|
||||
assert!(plain.error.is_none(), "{:?}", plain.error);
|
||||
assert!(plain.rgba.chunks_exact(4).any(|p| p[0] < 128), "a normal Type 3 glyph still paints");
|
||||
assert!(plain.rgba.as_chunks::<4>().0.iter().any(|p| p[0] < 128), "a normal Type 3 glyph still paints");
|
||||
}
|
||||
|
||||
/// From `cargo xtask fuzz`: an inline image claiming /W 4294967295 over four bytes of data
|
||||
|
||||
@@ -140,7 +140,7 @@ impl<'a> Tlv<'a> {
|
||||
tag::UTF8_STRING | tag::PRINTABLE_STRING | tag::IA5_STRING => Some(String::from_utf8_lossy(self.value).into_owned()),
|
||||
tag::T61_STRING => Some(self.value.iter().map(|b| *b as char).collect()),
|
||||
tag::BMP_STRING => {
|
||||
let units: Vec<u16> = self.value.chunks_exact(2).map(|c| u16::from_be_bytes([c[0], c[1]])).collect();
|
||||
let units: Vec<u16> = self.value.as_chunks::<2>().0.iter().map(|c| u16::from_be_bytes([c[0], c[1]])).collect();
|
||||
Some(String::from_utf16_lossy(&units))
|
||||
}
|
||||
_ => None,
|
||||
|
||||
@@ -200,7 +200,7 @@ pub(crate) fn script_preview(text: &str, w: usize, h: usize) -> egui::ColorImage
|
||||
}
|
||||
}
|
||||
xs.sort_by(|a, b| a.total_cmp(b));
|
||||
for pair in xs.chunks_exact(2) {
|
||||
for pair in xs.as_chunks::<2>().0 {
|
||||
let (from, to) = (pair[0].round().max(0.0) as usize, (pair[1].round() as usize).min(w));
|
||||
for x in from..to {
|
||||
img[(x, y)] = Color32::BLACK;
|
||||
|
||||
@@ -149,7 +149,7 @@ pub(crate) fn ink_bounds(w: usize, h: usize, rgba: &[u8]) -> Option<[f32; 4]> {
|
||||
let ink = |p: &[u8]| p[3] > 16 && (p[0] < 240 || p[1] < 240 || p[2] < 240);
|
||||
let (mut x0, mut y0, mut x1, mut y1) = (w, h, 0, 0);
|
||||
for (y, row) in rgba.chunks_exact(w * 4).take(h).enumerate() {
|
||||
for (x, p) in row.chunks_exact(4).enumerate() {
|
||||
for (x, p) in row.as_chunks::<4>().0.iter().enumerate() {
|
||||
if ink(p) {
|
||||
x0 = x0.min(x);
|
||||
x1 = x1.max(x + 1);
|
||||
|
||||
@@ -252,7 +252,7 @@ fn marquee_zoom_and_snapshot() {
|
||||
drag(&mut h, at(15.0, 175.0), at(180.0, 140.0));
|
||||
let (w, hgt, px) = h.state().last_snapshot.clone().expect("a snapshot");
|
||||
assert!(w > 50 && hgt > 10, "{w} × {hgt}");
|
||||
assert!(px.chunks_exact(4).any(|p| p[0] < 100), "the text is in it");
|
||||
assert!(px.as_chunks::<4>().0.iter().any(|p| p[0] < 100), "the text is in it");
|
||||
// Marquee zoom on a small area zooms in, centred on it.
|
||||
let before = h.state().views[i].zoom;
|
||||
h.state_mut().set_option("quick", "marquee-zoom").unwrap();
|
||||
|
||||
@@ -256,7 +256,7 @@ fn xfdf_annots(doc: &Document, out: &mut String) {
|
||||
out.push_str("<inklist>");
|
||||
for g in ink {
|
||||
let v = nums_of(doc, Some(&g));
|
||||
let pts: Vec<String> = v.chunks_exact(2).map(|p| format!("{},{}", n(p[0]), n(p[1]))).collect();
|
||||
let pts: Vec<String> = v.as_chunks::<2>().0.iter().map(|p| format!("{},{}", n(p[0]), n(p[1]))).collect();
|
||||
let _ = write!(out, "<gesture>{}</gesture>", pts.join(";"));
|
||||
}
|
||||
out.push_str("</inklist>");
|
||||
|
||||
@@ -364,7 +364,7 @@ fn collect_outline(doc: &Document, node: ObjectId, out: &mut Vec<ObjectId>) {
|
||||
/// Decode a PDF text string (UTF-16BE with BOM, else treated as Latin-1).
|
||||
fn decode_text(bytes: &[u8]) -> String {
|
||||
if let Some(rest) = bytes.strip_prefix(&[0xfe, 0xff]) {
|
||||
let units: Vec<u16> = rest.chunks_exact(2).map(|c| u16::from_be_bytes([c[0], c[1]])).collect();
|
||||
let units: Vec<u16> = rest.as_chunks::<2>().0.iter().map(|c| u16::from_be_bytes([c[0], c[1]])).collect();
|
||||
String::from_utf16_lossy(&units)
|
||||
} else {
|
||||
bytes.iter().map(|&b| b as char).collect()
|
||||
|
||||
Reference in New Issue
Block a user