@@ -206,15 +206,46 @@ pub struct GridlakeColumns {
206206 pub counts : MultiLaneColumn ,
207207}
208208
209+ /// Failure rendering a [`GridBatch`] as gridlake [`MultiLaneColumn`]s.
210+ ///
211+ /// A plain enum rather than a `snafu` type on purpose: `onebrc-probe` is a
212+ /// workspace-excluded standalone probe whose lanes A/C are dependency-free by
213+ /// design (see its `Cargo.toml`) — it carries no `snafu`. This surfaces the
214+ /// same alignment failure `MultiLaneColumn::new` reports, but with the
215+ /// offending `grid` for diagnostics instead of a bare `()`.
216+ #[ derive( Debug , Clone , Copy , PartialEq , Eq ) ]
217+ pub enum GridlakeCarrierError {
218+ /// A column buffer was not 64-byte aligned because `grid` is not a
219+ /// multiple of 16 (i32·16 = i64·8 = u64·8 = 64 B), so
220+ /// `MultiLaneColumn::new` rejected it.
221+ UnalignedGrid { grid : usize } ,
222+ }
223+
224+ impl std:: fmt:: Display for GridlakeCarrierError {
225+ fn fmt ( & self , f : & mut std:: fmt:: Formatter < ' _ > ) -> std:: fmt:: Result {
226+ match self {
227+ Self :: UnalignedGrid { grid } => write ! (
228+ f,
229+ "gridlake carrier: grid {grid} is not a multiple of 16, so a \
230+ column buffer is not 64-byte aligned for MultiLaneColumn"
231+ ) ,
232+ }
233+ }
234+ }
235+
236+ impl std:: error:: Error for GridlakeCarrierError { }
237+
209238impl GridBatch {
210239 /// Render the four accumulator columns as [`MultiLaneColumn`] gridlake
211240 /// carriers (little-endian bytes, zero semantic change — a *reading*, not
212241 /// a re-layout). `count` is widened `u32 → u64` to ride the unsigned
213- /// 64-bit accumulator lane. Returns `Err(())` if a column buffer is not
214- /// 64-byte aligned (i.e. `grid % 16 != 0`), mirroring
215- /// `MultiLaneColumn::new`'s own contract.
216- #[ allow( clippy:: result_unit_err) ] // pass-through of MultiLaneColumn::new's Result<_, ()> alignment contract
217- pub fn as_gridlake_columns ( & self ) -> Result < GridlakeColumns , ( ) > {
242+ /// 64-bit accumulator lane. Returns
243+ /// [`GridlakeCarrierError::UnalignedGrid`] if a column buffer is not
244+ /// 64-byte aligned (i.e. `grid % 16 != 0`), surfacing the alignment
245+ /// contract `MultiLaneColumn::new` enforces with the offending grid size.
246+ pub fn as_gridlake_columns ( & self ) -> Result < GridlakeColumns , GridlakeCarrierError > {
247+ let grid = self . mins . len ( ) ;
248+ let unaligned = |_: ( ) | GridlakeCarrierError :: UnalignedGrid { grid } ;
218249 fn col_i32 ( v : & [ i32 ] ) -> Result < MultiLaneColumn , ( ) > {
219250 let mut b = Vec :: with_capacity ( v. len ( ) * 4 ) ;
220251 for & x in v {
@@ -237,10 +268,10 @@ impl GridBatch {
237268 MultiLaneColumn :: new ( Arc :: from ( b) )
238269 }
239270 Ok ( GridlakeColumns {
240- mins : col_i32 ( & self . mins ) ?,
241- maxs : col_i32 ( & self . maxs ) ?,
242- sums : col_i64 ( & self . sums ) ?,
243- counts : col_u64_from_u32 ( & self . counts ) ?,
271+ mins : col_i32 ( & self . mins ) . map_err ( unaligned ) ?,
272+ maxs : col_i32 ( & self . maxs ) . map_err ( unaligned ) ?,
273+ sums : col_i64 ( & self . sums ) . map_err ( unaligned ) ?,
274+ counts : col_u64_from_u32 ( & self . counts ) . map_err ( unaligned ) ?,
244275 } )
245276 }
246277}
@@ -724,7 +755,10 @@ mod tests {
724755 #[ test]
725756 fn gridlake_carrier_rejects_unaligned_grid ( ) {
726757 let batch = GridBatch :: new ( 72 ) ; // 72 % 16 != 0 → i32 col = 288 B, not 64-mult
727- assert ! ( batch. as_gridlake_columns( ) . is_err( ) ) ;
758+ assert ! ( matches!(
759+ batch. as_gridlake_columns( ) ,
760+ Err ( GridlakeCarrierError :: UnalignedGrid { grid: 72 } )
761+ ) ) ;
728762 }
729763
730764 /// Parity across the knob matrix corners: gridlake (4096) and full
0 commit comments