From c3f70246564cc053f5a8576a51337c20c4484973 Mon Sep 17 00:00:00 2001 From: Tam Nguyen Duc <1218621+tamnd@users.noreply.github.com> Date: Fri, 21 Aug 2026 18:13:10 +0700 Subject: [PATCH 1/2] Take the constant chunk size out of the type (#25) 1.98 adds `clippy::chunks_exact_to_as_chunks`, and it fires four times here. It is a good lint rather than a style note: `chunks_exact(8)` hands back a slice whose length the compiler does not know, so every one of these lines carried a `try_into().expect("eight bytes")` in the middle of it to get an array back out. `as_chunks::<8>()` puts the width in the type and the conversion and its panic go away. Three of them are the widths in `Bytes::extend`, which is the copy out of a column the engine filled into the buffer a typed array is made from. The fourth is the flat edge list, where a pair is now a pair in the type and `edge[0]` and `edge[1]` stop being indexes into something that could be any length. A remainder is the one thing that changes shape: `as_chunks` returns it rather than dropping it. Both call sites want it dropped, and both already do the right thing. `extend` is copying a column of whole elements, so a partial one is a caller handing over something that is not this column at all, which is what `chunks_exact` also ignored. The edge list refuses an odd length by name before it gets here, so the tail is provably empty. The suite is unchanged at 363 tests, 354 passing and 9 skipped, and the typed array round trips are what cover `extend` in both directions. --- src/frame.rs | 27 +++++++++++++++++++++------ src/load.rs | 7 +++++-- 2 files changed, 26 insertions(+), 8 deletions(-) diff --git a/src/frame.rs b/src/frame.rs index 2fe4a1b..adf0120 100644 --- a/src/frame.rs +++ b/src/frame.rs @@ -251,18 +251,33 @@ impl Bytes { /// what the words mean is the layout's business and does not change /// on the way. fn extend(&mut self, raw: &[u8]) { + // `as_chunks` hands back arrays rather than slices, so the width + // is in the type and the conversion that used to sit in the + // middle of each line is gone along with the panic it carried. + // A remainder is bytes that are not a whole element, which is a + // caller handing over something that is not this column, and + // dropping it is what `chunks_exact` did too. match self { Bytes::Eight(v) => v.extend( - raw.chunks_exact(8) - .map(|word| u64::from_ne_bytes(word.try_into().expect("eight bytes"))), + raw.as_chunks::<8>() + .0 + .iter() + .copied() + .map(u64::from_ne_bytes), ), Bytes::Four(v) => v.extend( - raw.chunks_exact(4) - .map(|word| u32::from_ne_bytes(word.try_into().expect("four bytes"))), + raw.as_chunks::<4>() + .0 + .iter() + .copied() + .map(u32::from_ne_bytes), ), Bytes::Two(v) => v.extend( - raw.chunks_exact(2) - .map(|word| u16::from_ne_bytes(word.try_into().expect("two bytes"))), + raw.as_chunks::<2>() + .0 + .iter() + .copied() + .map(u16::from_ne_bytes), ), Bytes::One(v) => v.extend_from_slice(raw), Bytes::Offsets(_) => {} diff --git a/src/load.rs b/src/load.rs index 7b49ab4..ca5e0e6 100644 --- a/src/load.rs +++ b/src/load.rs @@ -495,9 +495,12 @@ fn pairs(env: &Env, options: &Object<'_>, rows: u64) -> Result> flat.len() ))); } + // A pair is a pair in the type, so the two indexes below are not + // indexes any more and the odd tail `as_chunks` would hand back + // is already refused above. let mut pairs = Vec::with_capacity(flat.len() / 2); - for (at, edge) in flat.chunks_exact(2).enumerate() { - pairs.push((within(at, edge[0])?, within(at, edge[1])?)); + for (at, &[from, to]) in flat.as_chunks::<2>().0.iter().enumerate() { + pairs.push((within(at, from)?, within(at, to)?)); } return Ok(pairs); } From 855621c8ebe571ab76eadb4ebd151353c5c756d5 Mon Sep 17 00:00:00 2001 From: Tam Nguyen Duc <1218621+tamnd@users.noreply.github.com> Date: Fri, 21 Aug 2026 18:13:18 +0700 Subject: [PATCH 2/2] Move the pin to Rust 1.98 (#25) The compiler is not chosen here. tamnd/zu's toolchains.toml holds one version for the nine repositories with Rust in them, and the toolchain file here is a copy of that row, so this follows tamnd/zu#515 rather than deciding anything. Two sites, the channel and rust-version. No workflow in this repository names a version: the clippy and test jobs read the toolchain file, which is the arrangement that keeps a bump from having to find every job that hardcoded a number. The libraries need nothing. napi 3.12.1, napi-derive 3.6.3, napi-build 2.4.1 and arrow 59.2.0 were checked against the registry on the same day and are all current. Verified on 1.98.0: `cargo fmt --check`, `cargo clippy --all-features -D warnings` clean now that the chunk sizes moved into the type, and `npm test` at 363 tests with nothing failing. --- Cargo.toml | 2 +- rust-toolchain.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index b1a3191..df53aa3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,7 +2,7 @@ name = "zudb-node" version = "0.0.1" edition = "2024" -rust-version = "1.97" +rust-version = "1.98" license = "Apache-2.0" repository = "https://github.com/tamnd/zu-node" authors = ["Tam Nguyen "] diff --git a/rust-toolchain.toml b/rust-toolchain.toml index 45d0ca1..76cc5f5 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -3,5 +3,5 @@ # a different build of the same code. Held to the version in # tamnd/zu's toolchains.toml. [toolchain] -channel = "1.97.1" +channel = "1.98.0" components = ["rustfmt", "clippy"]