Skip to main content

hyperactor/
value_mesh.rs

1/*
2 * Copyright (c) Meta Platforms, Inc. and affiliates.
3 * All rights reserved.
4 *
5 * This source code is licensed under the BSD-style license found in the
6 * LICENSE file in the root directory of this source tree.
7 */
8
9//! ## Value mesh invariants (VM-*)
10//!
11//! - **VM-1 (completeness):** Every rank in `region` has exactly one
12//!   value. Iteration and indexing follow the region's linearization.
13
14use std::cmp::Ordering;
15use std::collections::HashMap;
16use std::collections::hash_map::Entry;
17use std::hash::Hash;
18use std::marker::PhantomData;
19use std::mem;
20use std::mem::MaybeUninit;
21use std::ops::Range;
22use std::ptr;
23use std::ptr::NonNull;
24
25use futures::Future;
26use ndslice::extent;
27use ndslice::view;
28use ndslice::view::Ranked;
29use ndslice::view::Region;
30use serde::Deserialize;
31use serde::Serialize;
32use typeuri::Named;
33
34use crate::accum::Accumulator;
35use crate::accum::CommReducer;
36use crate::accum::ReducerSpec;
37
38/// Run-length encoding helpers used by [`ValueMesh`] and [`ValueOverlay`].
39pub mod rle;
40mod value_overlay;
41pub use value_overlay::BuildError;
42pub use value_overlay::ValueOverlay;
43
44/// Errors that occur while constructing a [`ValueMesh`].
45#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
46pub enum ValueMeshError {
47    /// The number of supplied values did not match the region's rank count.
48    #[error("invalid value mesh: expected {expected} ranks, but contains {actual} ranks")]
49    InvalidRankCardinality {
50        /// Required number of rank values for the target region.
51        expected: usize,
52        /// Actual number of rank values provided by the caller.
53        actual: usize,
54    },
55}
56
57impl From<view::InvalidCardinality> for ValueMeshError {
58    fn from(value: view::InvalidCardinality) -> Self {
59        Self::InvalidRankCardinality {
60            expected: value.expected,
61            actual: value.actual,
62        }
63    }
64}
65
66/// A mesh of values, one per rank in `region`.
67///
68/// The internal representation (`rep`) may be dense or compressed,
69/// but externally the mesh always behaves as a complete mapping from
70/// rank index → value.
71///
72/// See VM-1 in module doc.
73#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] // only if T implements
74pub struct ValueMesh<T> {
75    /// The logical multidimensional domain of the mesh.
76    ///
77    /// Determines the number of ranks (`region.num_ranks()`) and the
78    /// order in which they are traversed.
79    region: Region,
80
81    /// The underlying storage representation.
82    ///
83    /// - `Rep::Dense` stores a `Vec<T>` with one value per rank.
84    /// - `Rep::Compressed` stores a run-length encoded table of
85    ///   unique values plus `(Range<usize>, u32)` pairs describing
86    ///   contiguous runs of identical values.
87    ///
88    /// The representation is an internal optimization detail; all
89    /// public APIs (e.g. `values()`, `get()`, slicing) behave as if
90    /// the mesh were dense.
91    rep: Rep<T>,
92}
93
94/// A single run-length–encoded (RLE) segment within a [`ValueMesh`].
95///
96/// Each `Run` represents a contiguous range of ranks `[start, end)`
97/// that all share the same value, referenced indirectly via a table
98/// index `id`. This allows compact storage of large regions with
99/// repeated values.
100///
101/// Runs are serialized in a stable, portable format using `u64` for
102/// range bounds (`start`, `end`) to avoid platform‐dependent `usize`
103/// encoding differences.
104#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
105struct Run {
106    /// Inclusive start of the contiguous range of ranks (0-based).
107    start: u64,
108    /// Exclusive end of the contiguous range of ranks (0-based).
109    end: u64,
110    /// Index into the value table for this run's shared value.
111    id: u32,
112}
113
114impl Run {
115    /// Creates a new `Run` covering ranks `[start, end)` that all
116    /// share the same table entry `id`.
117    ///
118    /// Converts `usize` bounds to `u64` for stable serialization.
119    fn new(start: usize, end: usize, id: u32) -> Self {
120        Self {
121            start: start as u64,
122            end: end as u64,
123            id,
124        }
125    }
126}
127
128impl TryFrom<Run> for (Range<usize>, u32) {
129    type Error = &'static str;
130
131    /// Converts a serialized [`Run`] back into its in-memory form
132    /// `(Range<usize>, u32)`.
133    ///
134    /// Performs checked conversion of the 64-bit wire fields back
135    /// into `usize` indices, returning an error if either bound
136    /// exceeds the platform's addressable range. This ensures safe
137    /// round-tripping between the serialized wire format and native
138    /// representation.
139    #[allow(clippy::result_large_err)]
140    fn try_from(r: Run) -> Result<Self, Self::Error> {
141        let start = usize::try_from(r.start).map_err(|_| "run.start too large")?;
142        let end = usize::try_from(r.end).map_err(|_| "run.end too large")?;
143        Ok((start..end, r.id))
144    }
145}
146
147/// Internal storage representation for a [`ValueMesh`].
148///
149/// This enum abstracts how the per-rank values are stored.
150/// Externally, both variants behave identically — the difference is
151/// purely in memory layout and access strategy.
152///
153/// - [`Rep::Dense`] stores one value per rank, directly.
154/// - [`Rep::Compressed`] stores a compact run-length-encoded form,
155///   reusing identical values across contiguous ranks.
156///
157/// Users of [`ValueMesh`] normally never interact with `Rep`
158/// directly; all iteration and slicing APIs present a dense logical
159/// view.
160#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] // only if T implements
161enum Rep<T> {
162    /// Fully expanded representation: one element per rank.
163    ///
164    /// The length of `values` is always equal to
165    /// `region.num_ranks()`. This form is simple and fast for
166    /// iteration and mutation but uses more memory when large runs of
167    /// repeated values are present.
168    Dense {
169        /// Flat list of values, one per rank in the region's
170        /// linearization order.
171        values: Vec<T>,
172    },
173
174    /// Run-length-encoded representation.
175    ///
176    /// Each run `(Range<usize>, id)` indicates that the ranks within
177    /// `Range` (half-open `[start, end)`) share the same value at
178    /// `table[id]`. The `table` stores each distinct value once.
179    ///
180    /// # Invariants (VM-2)
181    /// - **VM-2 (runs-contiguous):** Runs are non-empty and contiguous (`r.start < r.end`).
182    /// - Runs collectively cover `0..region.num_ranks()` with no gaps
183    ///   or overlaps.
184    /// - `id` indexes into `table` (`id < table.len()`).
185    Compressed {
186        /// The deduplicated set of unique values referenced by runs.
187        table: Vec<T>,
188
189        /// List of `(range, table_id)` pairs describing contiguous
190        /// runs of identical values in region order.
191        runs: Vec<Run>,
192    },
193}
194
195// At this time, Default is used primarily to satisfy the mailbox
196// Accumulator bound. It constructs an empty (zero-rank) mesh. Other
197// contexts may also use this as a generic "empty mesh" initializer
198// when a concrete region is not yet known.
199impl<T> Default for ValueMesh<T> {
200    fn default() -> Self {
201        Self::empty()
202    }
203}
204
205impl<T> ValueMesh<T> {
206    /// Returns an *empty* mesh: a 1-dimensional region of length 0.
207    ///
208    /// This differs from a *dimensionless* (0-D) region, which
209    /// represents a single scalar element. A zero-length 1-D region
210    /// has **no elements at all**, making it the natural `Default`
211    /// placeholder for accumulator state initialization.
212    pub fn empty() -> Self {
213        // zero-rank region; no constraints on T
214        let region = extent!(r = 0).into();
215        Self::new_unchecked(region, Vec::<T>::new())
216    }
217
218    /// Creates a new `ValueMesh` for `region` with exactly one value
219    /// per rank.
220    ///
221    /// # Invariants
222    /// This constructor validates that the number of provided values
223    /// (`ranks.len()`) matches the region's cardinality
224    /// (`region.num_ranks()`). A value mesh must be complete: every
225    /// rank in `region` has a corresponding `T`.
226    ///
227    /// # Errors
228    /// Returns [`ValueMeshError::InvalidRankCardinality`] if `ranks.len() !=
229    /// region.num_ranks()`.
230    #[allow(clippy::result_large_err)]
231    pub fn new(region: Region, ranks: Vec<T>) -> std::result::Result<Self, ValueMeshError> {
232        let (actual, expected) = (ranks.len(), region.num_ranks());
233        if actual != expected {
234            return Err(ValueMeshError::InvalidRankCardinality { expected, actual });
235        }
236        Ok(Self {
237            region,
238            rep: Rep::Dense { values: ranks },
239        })
240    }
241
242    /// Constructs a `ValueMesh` without checking cardinality. Caller
243    /// must ensure `ranks.len() == region.num_ranks()`.
244    #[inline]
245    pub(crate) fn new_unchecked(region: Region, ranks: Vec<T>) -> Self {
246        debug_assert_eq!(region.num_ranks(), ranks.len());
247        Self {
248            region,
249            rep: Rep::Dense { values: ranks },
250        }
251    }
252}
253
254impl<T: Clone> ValueMesh<T> {
255    /// Builds a `ValueMesh` that assigns the single value `s` to
256    /// every rank in `region`, without materializing a dense
257    /// `Vec<T>`. The result is stored in compressed (RLE) form as a
258    /// single run `[0..N)`.
259    ///
260    /// If `region.num_ranks() == 0`, the mesh contains no runs (and
261    /// an empty table), regardless of `s`.
262    pub fn from_single(region: Region, s: T) -> Self {
263        let n = region.num_ranks();
264        if n == 0 {
265            return Self {
266                region,
267                rep: Rep::Compressed {
268                    table: Vec::new(),
269                    runs: Vec::new(),
270                },
271            };
272        }
273
274        let table = vec![s];
275        let runs = vec![Run::new(0, n, 0)];
276        Self {
277            region,
278            rep: Rep::Compressed { table, runs },
279        }
280    }
281}
282
283impl<T: Clone + Default> ValueMesh<T> {
284    /// Builds a [`ValueMesh`] covering the region, filled with
285    /// `T::default()`.
286    ///
287    /// Equivalent to [`ValueMesh::from_single(region,
288    /// T::default())`].
289    pub fn from_default(region: Region) -> Self {
290        ValueMesh::<T>::from_single(region, T::default())
291    }
292}
293
294impl<T: Eq + Hash> ValueMesh<T> {
295    /// Builds a compressed mesh from a default value and a set of
296    /// disjoint ranges that override the default.
297    ///
298    /// - `ranges` may be in any order; they must be non-empty,
299    ///   in-bounds, and non-overlapping.
300    /// - Unspecified ranks are filled with `default`.
301    /// - Result is stored in RLE form; no dense `Vec<T>` is
302    ///   materialized.
303    #[allow(clippy::result_large_err)]
304    pub fn from_ranges_with_default(
305        region: Region,
306        default: T,
307        mut ranges: Vec<(Range<usize>, T)>,
308    ) -> std::result::Result<Self, ValueMeshError> {
309        let n = region.num_ranks();
310
311        if n == 0 {
312            return Ok(Self {
313                region,
314                rep: Rep::Compressed {
315                    table: Vec::new(),
316                    runs: Vec::new(),
317                },
318            });
319        }
320
321        // Validate: non-empty, in-bounds; then sort.
322        for (r, _) in &ranges {
323            if r.is_empty() {
324                return Err(ValueMeshError::InvalidRankCardinality {
325                    expected: n,
326                    actual: 0,
327                }); // TODO: this surfaces the error but its not a great fit
328            }
329            if r.end > n {
330                return Err(ValueMeshError::InvalidRankCardinality {
331                    expected: n,
332                    actual: r.end,
333                });
334            }
335        }
336        ranges.sort_by_key(|(r, _)| (r.start, r.end));
337
338        // Validate: non-overlapping.
339        for w in ranges.windows(2) {
340            let (a, _) = &w[0];
341            let (b, _) = &w[1];
342            if a.end > b.start {
343                // Overlap
344                return Err(ValueMeshError::InvalidRankCardinality {
345                    expected: n,
346                    actual: b.start, // TODO: this surfaces the error but is a bad fit
347                });
348            }
349        }
350
351        // Internal index: value -> table id (assigned once).
352        let mut index: HashMap<T, u32> = HashMap::with_capacity(1 + ranges.len());
353        let mut next_id: u32 = 0;
354
355        // Helper: assign or reuse an id by value, taking ownership of
356        // v.
357        let id_of = |v: T, index: &mut HashMap<T, u32>, next_id: &mut u32| -> u32 {
358            match index.entry(v) {
359                Entry::Occupied(o) => *o.get(),
360                Entry::Vacant(vac) => {
361                    let id = *next_id;
362                    *next_id += 1;
363                    vac.insert(id);
364                    id
365                }
366            }
367        };
368
369        let default_id = id_of(default, &mut index, &mut next_id);
370
371        let mut runs: Vec<Run> = Vec::with_capacity(1 + 2 * ranges.len());
372        let mut cursor = 0usize;
373
374        for (r, v) in ranges.into_iter() {
375            // Fill default gap if any.
376            if cursor < r.start {
377                runs.push(Run::new(cursor, r.start, default_id));
378            }
379            // Override block.
380            let id = id_of(v, &mut index, &mut next_id);
381            runs.push(Run::new(r.start, r.end, id));
382            cursor = r.end;
383        }
384
385        // Trailing default tail.
386        if cursor < n {
387            runs.push(Run::new(cursor, n, default_id));
388        }
389
390        // Materialize table in id order without cloning: move keys
391        // out of the map.
392        let mut table_slots: Vec<Option<T>> = Vec::new();
393        table_slots.resize_with(next_id as usize, || None);
394
395        for (t, id) in index.into_iter() {
396            table_slots[id as usize] = Some(t);
397        }
398
399        let table: Vec<T> = table_slots
400            .into_iter()
401            .map(|o| o.expect("every id must be assigned"))
402            .collect();
403
404        Ok(Self {
405            region,
406            rep: Rep::Compressed { table, runs },
407        })
408    }
409
410    /// Builds a [`ValueMesh`] from a fully materialized dense vector
411    /// of per-rank values, then compresses it into run-length–encoded
412    /// form if possible.
413    ///
414    /// This constructor is intended for callers that already have one
415    /// value per rank (e.g. computed or received data) but wish to
416    /// store it efficiently.
417    ///
418    /// # Parameters
419    /// - `region`: The logical region describing the mesh's shape and
420    ///   rank order.
421    /// - `values`: A dense vector of values, one per rank in
422    ///   `region`.
423    ///
424    /// # Returns
425    /// A [`ValueMesh`] whose internal representation is `Compressed`
426    /// if any adjacent elements are equal, or `Dense` if no
427    /// compression was possible.
428    ///
429    /// # Errors
430    /// Returns an error if the number of provided `values` does not
431    /// match the number of ranks in `region`.
432    ///
433    /// # Examples
434    /// ```ignore
435    /// let region: Region = extent!(n = 5).into();
436    /// let mesh = ValueMesh::from_dense(region, vec![1, 1, 2, 2, 3]).unwrap();
437    /// // Internally compressed to three runs: [1, 1], [2, 2], [3]
438    /// ```
439    #[allow(clippy::result_large_err)]
440    pub fn from_dense(region: Region, values: Vec<T>) -> std::result::Result<Self, ValueMeshError> {
441        let mut vm = Self::new(region, values)?;
442        vm.compress_adjacent_in_place();
443        Ok(vm)
444    }
445}
446
447impl<F: Future> ValueMesh<F> {
448    /// Await all futures in the mesh, yielding a `ValueMesh` of their
449    /// outputs.
450    pub async fn join(self) -> ValueMesh<F::Output> {
451        let ValueMesh { region, rep } = self;
452
453        match rep {
454            Rep::Dense { values } => {
455                let results = futures::future::join_all(values).await;
456                ValueMesh::new_unchecked(region, results)
457            }
458            Rep::Compressed { .. } => {
459                unreachable!("join() not implemented for compressed meshes")
460            }
461        }
462    }
463}
464
465impl<T, E> ValueMesh<Result<T, E>> {
466    /// Transposes a `ValueMesh<Result<T, E>>` into a
467    /// `Result<ValueMesh<T>, E>`.
468    pub fn transpose(self) -> Result<ValueMesh<T>, E> {
469        let ValueMesh { region, rep } = self;
470
471        match rep {
472            Rep::Dense { values } => {
473                let values = values.into_iter().collect::<Result<Vec<T>, E>>()?;
474                Ok(ValueMesh::new_unchecked(region, values))
475            }
476            Rep::Compressed { table, runs } => {
477                let table: Vec<T> = table.into_iter().collect::<Result<Vec<T>, E>>()?;
478                Ok(ValueMesh {
479                    region,
480                    rep: Rep::Compressed { table, runs },
481                })
482            }
483        }
484    }
485}
486
487impl<T: 'static> view::Ranked for ValueMesh<T> {
488    type Item = T;
489
490    /// Returns the region that defines this mesh's shape and rank
491    /// order.
492    fn region(&self) -> &Region {
493        &self.region
494    }
495
496    /// Looks up the value at the given linearized rank.
497    ///
498    /// Works transparently for both dense and compressed
499    /// representations:
500    /// - In the dense case, it simply indexes into the `values`
501    ///   vector.
502    /// - In the compressed case, it performs a binary search over run
503    ///   boundaries to find which run contains the given rank, then
504    ///   returns the corresponding entry from `table`.
505    ///
506    /// Returns `None` if the rank is out of bounds.
507    fn get(&self, rank: usize) -> Option<&Self::Item> {
508        if rank >= self.region.num_ranks() {
509            return None;
510        }
511
512        match &self.rep {
513            Rep::Dense { values } => values.get(rank),
514
515            Rep::Compressed { table, runs } => {
516                let rank = rank as u64;
517
518                // Binary search over runs: find the one whose range
519                // contains `rank`.
520                let idx = runs
521                    .binary_search_by(|run| {
522                        if run.end <= rank {
523                            Ordering::Less
524                        } else if run.start > rank {
525                            Ordering::Greater
526                        } else {
527                            Ordering::Equal
528                        }
529                    })
530                    .ok()?;
531
532                // Map the run's table ID to its actual value.
533                let id = runs[idx].id as usize;
534                table.get(id)
535            }
536        }
537    }
538}
539
540impl<T: 'static> ValueMesh<T> {
541    /// Look up the value at `base_rank` — the rank in the **base space**
542    /// of this mesh's region, not the linearized ordinal that
543    /// [`view::Ranked::get`] takes.
544    ///
545    /// For a full region the two coincide; for a sliced sub-region they
546    /// differ — e.g. a row slice over base ranks `{2, 3, 4, 5}` has
547    /// ordinals `{0, 1, 2, 3}`. This resolves `base_rank` through the
548    /// region's geometry (`point_of_base_rank` → ordinal) and then
549    /// indexes, so callers address by the stable base-space rank and
550    /// never touch the ordinal.
551    ///
552    /// Returns `None` if `base_rank` is not contained in this region.
553    pub fn get_by_base_rank(&self, base_rank: usize) -> Option<&T> {
554        if !self.region.slice().contains(base_rank) {
555            return None;
556        }
557        let ordinal = self.region.point_of_base_rank(base_rank).ok()?.rank();
558        self.get(ordinal)
559    }
560}
561
562impl<T: Clone + 'static> view::RankedSliceable for ValueMesh<T> {
563    fn sliced(&self, region: Region) -> Self {
564        debug_assert!(region.is_subset(self.region()), "sliced: not a subset");
565        let ranks: Vec<T> = self
566            .region()
567            .remap(&region)
568            .unwrap()
569            .map(|index| self.get(index).unwrap().clone())
570            .collect();
571        debug_assert_eq!(
572            region.num_ranks(),
573            ranks.len(),
574            "sliced: cardinality mismatch"
575        );
576        Self::new_unchecked(region, ranks)
577    }
578}
579
580impl<T> view::BuildFromRegion<T> for ValueMesh<T> {
581    type Error = ValueMeshError;
582
583    fn build_dense(region: Region, values: Vec<T>) -> Result<Self, Self::Error> {
584        Self::new(region, values)
585    }
586
587    fn build_dense_unchecked(region: Region, values: Vec<T>) -> Self {
588        Self::new_unchecked(region, values)
589    }
590}
591
592impl<T> view::BuildFromRegionIndexed<T> for ValueMesh<T> {
593    type Error = ValueMeshError;
594
595    fn build_indexed(
596        region: Region,
597        pairs: impl IntoIterator<Item = (usize, T)>,
598    ) -> Result<Self, Self::Error> {
599        let n = region.num_ranks();
600
601        // Allocate uninitialized buffer for T.
602        // Note: Vec<MaybeUninit<T>>'s Drop will only free the
603        // allocation; it never runs T's destructor. We must
604        // explicitly drop any initialized elements (DropGuard) or
605        // convert into Vec<T>.
606        let mut buf: Vec<MaybeUninit<T>> = Vec::with_capacity(n);
607        // SAFETY: set `len = n` to treat the buffer as n uninit slots
608        // of `MaybeUninit<T>`. We never read before `ptr::write`,
609        // drop only slots marked initialized (bitset), and convert to
610        // `Vec<T>` only once all 0..n are initialized (guard enforces
611        // this).
612        unsafe {
613            buf.set_len(n);
614        }
615
616        // Compact bitset for occupancy.
617        let words = n.div_ceil(64);
618        let mut bits = vec![0u64; words];
619        let mut filled = 0usize;
620
621        // Drop guard: cleans up initialized elements on early exit.
622        // Stores raw, non-borrowed pointers (`NonNull`), so we don't
623        // hold Rust references for the whole scope. This allows
624        // mutating `buf`/`bits` inside the loop while still letting
625        // the guard access them if dropped early.
626        struct DropGuard<T> {
627            buf: NonNull<MaybeUninit<T>>,
628            bits: NonNull<u64>,
629            n_elems: usize,
630            n_words: usize,
631            disarm: bool,
632        }
633
634        impl<T> DropGuard<T> {
635            /// # Safety
636            /// - `buf` points to `buf.len()` contiguous
637            ///   `MaybeUninit<T>` and outlives the guard.
638            /// - `bits` points to `bits.len()` contiguous `u64` words
639            ///   and outlives the guard.
640            /// - For every set bit `i` in `bits`, `buf[i]` has been
641            ///   initialized with a valid `T` (and on duplicates, the
642            ///   previous `T` at `i` was dropped before overwrite).
643            /// - While the guard is alive, caller may mutate
644            ///   `buf`/`bits` (the guard holds only raw pointers; it
645            ///   does not create Rust borrows).
646            /// - On drop (when not disarmed), the guard will read
647            ///   `bits`, mask tail bits in the final word, and
648            ///   `drop_in_place` each initialized `buf[i]`—never
649            ///   accessing beyond `buf.len()` / `bits.len()`.
650            /// - If a slice is empty, the stored pointer may be
651            ///   `dangling()`; it is never dereferenced when the
652            ///   corresponding length is zero.
653            unsafe fn new(buf: &mut [MaybeUninit<T>], bits: &mut [u64]) -> Self {
654                let n_elems = buf.len();
655                let n_words = bits.len();
656                // Expected: n_words == (n_elems + 63) / 64
657                // but we don't *require* it; tail is masked in Drop.
658                Self {
659                    buf: NonNull::new(buf.as_mut_ptr()).unwrap_or_else(NonNull::dangling),
660                    bits: NonNull::new(bits.as_mut_ptr()).unwrap_or_else(NonNull::dangling),
661                    n_elems,
662                    n_words,
663                    disarm: false,
664                }
665            }
666
667            #[inline]
668            fn disarm(&mut self) {
669                self.disarm = true;
670            }
671        }
672
673        impl<T> Drop for DropGuard<T> {
674            fn drop(&mut self) {
675                if self.disarm {
676                    return;
677                }
678
679                // SAFETY:
680                // - `self.buf` points to `n_elems` contiguous
681                //   `MaybeUninit<T>` slots (or may be dangling if
682                //   `n_elems == 0`); `self.bits` points to `n_words`
683                //   contiguous `u64` words (or may be dangling if
684                //   `n_words == 0`).
685                // - Loop bounds ensure `w < n_words` when reading
686                //   `*bits_base.add(w)`.
687                // - For the final word we mask unused tail bits so
688                //   any computed index `i = w * 64 + tz` always
689                //   satisfies `i < n_elems` before we dereference
690                //   `buf_base.add(i)`.
691                // - Only slots whose bits are set are dropped, so no
692                //   double-drops.
693                // - No aliasing with active Rust borrows: the guard
694                //   holds raw pointers and runs in `Drop` after the
695                //   fill loop.
696                unsafe {
697                    let buf_base = self.buf.as_ptr();
698                    let bits_base = self.bits.as_ptr();
699
700                    for w in 0..self.n_words {
701                        // Load word.
702                        let mut word = *bits_base.add(w);
703
704                        // Mask off bits beyond `n_elems` in the final
705                        // word (if any).
706                        if w == self.n_words.saturating_sub(1) {
707                            let used_bits = self.n_elems.saturating_sub(w * 64);
708                            if used_bits < 64 {
709                                let mask = if used_bits == 0 {
710                                    0
711                                } else {
712                                    (1u64 << used_bits) - 1
713                                };
714                                word &= mask;
715                            }
716                        }
717
718                        // Fast scan set bits.
719                        while word != 0 {
720                            let tz = word.trailing_zeros() as usize;
721                            let i = w * 64 + tz;
722                            debug_assert!(i < self.n_elems);
723
724                            let slot = buf_base.add(i);
725                            // Drop the initialized element.
726                            ptr::drop_in_place((*slot).as_mut_ptr());
727
728                            // clear the bit we just handled
729                            word &= word - 1;
730                        }
731                    }
732                }
733            }
734        }
735
736        // SAFETY:
737        // - `buf` and `bits` are freshly allocated Vecs with
738        //   capacity/len set to cover exactly `n_elems` and `n_words`,
739        //   so their `.as_mut_ptr()` is valid for that many elements.
740        // - Both slices live at least as long as the guard, and are
741        //   not moved until after the guard is disarmed.
742        // - No aliasing occurs: the guard holds only raw pointers and
743        //   the fill loop mutates through those same allocations.
744        let mut guard = unsafe { DropGuard::new(&mut buf, &mut bits) };
745
746        for (rank, value) in pairs {
747            // Single bounds check up front.
748            if rank >= guard.n_elems {
749                return Err(ValueMeshError::InvalidRankCardinality {
750                    expected: guard.n_elems,
751                    actual: rank + 1,
752                });
753            }
754
755            // Compute word index and bit mask once.
756            let w = rank / 64;
757            let b = rank % 64;
758            let mask = 1u64 << b;
759
760            // SAFETY:
761            // - `rank < guard.n_elems` was checked above, so
762            //   `buf_slot = buf.add(rank)` is within the
763            //   `Vec<MaybeUninit<T>>` allocation.
764            // - `w = rank / 64` and `bits.len() == (n + 63) / 64`
765            //   ensure `bits_ptr = bits.add(w)` is in-bounds.
766            // - If `(word & mask) != 0`, then this slot was
767            //   previously initialized;
768            //   `drop_in_place((*buf_slot).as_mut_ptr())` is valid and
769            //   leaves the slot uninitialized.
770            // - If the bit was clear, we set it and count `filled +=
771            //   1`.
772            // - `(*buf_slot).write(value)` is valid in both cases:
773            //   either writing into an uninitialized slot or
774            //   immediately after dropping the prior `T`.
775            // - No aliasing with Rust references: the guard holds raw
776            //   pointers and we have exclusive ownership of
777            //   `buf`/`bits` within this function.
778            unsafe {
779                // Pointers from the guard (no long-lived & borrows).
780                let bits_ptr = guard.bits.as_ptr().add(w);
781                let buf_slot = guard.buf.as_ptr().add(rank);
782
783                // Read the current word.
784                let word = *bits_ptr;
785
786                if (word & mask) != 0 {
787                    // Duplicate: drop old value before overwriting.
788                    core::ptr::drop_in_place((*buf_slot).as_mut_ptr());
789                    // (Bit already set; no need to set again; don't
790                    // bump `filled`.)
791                } else {
792                    // First time we see this rank.
793                    *bits_ptr = word | mask;
794                    filled += 1;
795                }
796
797                // Write new value into the slot.
798                (*buf_slot).write(value);
799            }
800        }
801
802        if filled != n {
803            // Missing ranks: actual = number of distinct ranks seen.
804            return Err(ValueMeshError::InvalidRankCardinality {
805                expected: n,
806                actual: filled,
807            });
808        }
809
810        // Success: prevent cleanup.
811        guard.disarm();
812
813        // SAFETY: all n slots are initialized
814        let ranks = unsafe {
815            let ptr = buf.as_mut_ptr() as *mut T;
816            let len = buf.len();
817            let cap = buf.capacity();
818            // Prevent `buf` (Vec<MaybeUninit<T>>) from freeing the
819            // allocation. Ownership of the buffer is about to be
820            // transferred to `Vec<T>` via `from_raw_parts`.
821            // Forgetting avoids a double free.
822            mem::forget(buf);
823            Vec::from_raw_parts(ptr, len, cap)
824        };
825
826        Ok(Self::new_unchecked(region, ranks))
827    }
828}
829
830impl<T: PartialEq> ValueMesh<T> {
831    /// Compresses the mesh in place using run-length encoding (RLE).
832    ///
833    /// This method scans the mesh's dense values, coalescing adjacent
834    /// runs of identical elements into a compact [`Rep::Compressed`]
835    /// representation. It replaces the internal storage (`rep`) with
836    /// the compressed form.
837    ///
838    /// # Behavior
839    /// - If the mesh is already compressed, this is a **no-op**.
840    /// - If the mesh is dense, it consumes the current `Vec<T>` and
841    ///   rebuilds the representation as a run table plus value table.
842    /// - Only *adjacent* equal values are merged; non-contiguous
843    ///   duplicates remain distinct.
844    ///
845    /// # Requirements
846    /// - `T` must implement [`PartialEq`] (to detect equal values).
847    ///
848    /// This operation is lossless: expanding the compressed mesh back
849    /// into a dense vector yields the same sequence of values.
850    pub fn compress_adjacent_in_place(&mut self) {
851        self.compress_adjacent_in_place_by(|a, b| a == b)
852    }
853}
854
855impl<T: Clone + PartialEq> ValueMesh<T> {
856    /// Materializes this mesh into a vector of `(Range<usize>, T)`
857    /// runs.
858    ///
859    /// For a dense representation, this walks the value vector and
860    /// groups adjacent equal values into contiguous runs. The result
861    /// is equivalent to what would be stored in a compressed
862    /// representation, but the mesh itself is not mutated or
863    /// re-encoded. This is purely a read-only view.
864    ///
865    /// For a compressed representation, the stored runs are simply
866    /// cloned.
867    ///
868    /// This method is intended for inspection, testing, and
869    /// diff/merge operations that need a uniform view of value runs
870    /// without changing the underlying representation.
871    fn materialized_runs(&self) -> Vec<(Range<usize>, T)> {
872        match &self.rep {
873            Rep::Dense { values } => {
874                // Coalesce adjacent equals into runs.
875                let mut out = Vec::new();
876                if values.is_empty() {
877                    return out;
878                }
879                let mut start = 0usize;
880                for i in 1..values.len() {
881                    if values[i] != values[i - 1] {
882                        out.push((start..i, values[i - 1].clone()));
883                        start = i;
884                    }
885                }
886                out.push((start..values.len(), values.last().unwrap().clone()));
887                out
888            }
889            Rep::Compressed { table, runs } => runs
890                .iter()
891                .map(|r| {
892                    let id = r.id as usize;
893                    ((r.start as usize..r.end as usize), table[id].clone())
894                })
895                .collect(),
896        }
897    }
898}
899
900impl<T: Clone + Eq> ValueMesh<T> {
901    /// Merge a sparse overlay into this mesh.
902    ///
903    /// Overlay segments are applied with **last-writer-wins**
904    /// precedence on overlap (identical to `RankedValues::merge_from`
905    /// behavior). The result is stored compressed.
906    pub fn merge_from_overlay(&mut self, overlay: ValueOverlay<T>) -> Result<(), BuildError> {
907        let n = self.region.num_ranks();
908
909        // Bounds validation (structure already validated by
910        // ValueOverlay).
911        for (r, _) in overlay.runs() {
912            if r.end > n {
913                return Err(BuildError::OutOfBounds {
914                    range: r.clone(),
915                    region_len: n,
916                });
917            }
918        }
919
920        // Left: current mesh as normalized value-bearing runs.
921        let left = self.materialized_runs();
922        // Right: overlay runs (already sorted, non-overlapping,
923        // coalesced).
924        let right: Vec<(std::ops::Range<usize>, T)> = overlay.runs().cloned().collect();
925
926        // Merge with overlay precedence, reusing the same splitting
927        // strategy as RankedValues::merge_from.
928        let merged = rle::merge_value_runs(left, right);
929
930        // Re-encode to compressed representation:
931        let (table, raw_runs) = rle::rle_from_value_runs(merged);
932        let runs = raw_runs
933            .into_iter()
934            .map(|(r, id)| Run::new(r.start, r.end, id))
935            .collect();
936        self.rep = Rep::Compressed { table, runs };
937
938        Ok(())
939    }
940}
941
942impl<T> ValueMesh<T> {
943    /// Compresses the mesh in place using a custom equivalence
944    /// predicate.
945    ///
946    /// This is a generalized form of [`compress_adjacent_in_place`]
947    /// that merges adjacent values according to an arbitrary
948    /// predicate `same(a, b)`, rather than relying on `PartialEq`.
949    ///
950    /// # Behavior
951    /// - If the mesh is already compressed, this is a **no-op**.
952    /// - Otherwise, consumes the dense `Vec<T>` and replaces it with
953    ///   a run-length encoded (`Rep::Compressed`) representation,
954    ///   where consecutive elements satisfying `same(a, b)` are
955    ///   coalesced into a single run.
956    ///
957    /// # Requirements
958    /// - The predicate must be reflexive and symmetric for
959    ///   correctness.
960    ///
961    /// This operation is lossless: expanding the compressed mesh
962    /// reproduces the original sequence exactly under the same
963    /// equivalence.
964    pub fn compress_adjacent_in_place_by<F>(&mut self, same: F)
965    where
966        F: FnMut(&T, &T) -> bool,
967    {
968        let values = match &mut self.rep {
969            Rep::Dense { values } => std::mem::take(values),
970            Rep::Compressed { .. } => return,
971        };
972        let (table, raw_runs) = rle::rle_from_dense(values, same);
973        let runs = raw_runs
974            .into_iter()
975            .map(|(r, id)| Run::new(r.start, r.end, id))
976            .collect();
977        self.rep = Rep::Compressed { table, runs };
978    }
979}
980
981/// Accumulates sparse overlay updates into an authoritative mesh.
982///
983/// Lifecycle:
984/// - Mailbox initializes `State` via `Default` (empty mesh).
985/// - On the first update, the accumulator clones `self` (the template
986///   passed to `open_accum_port_opts`) into `state`. Callers pass a
987///   template such as `StatusMesh::from_single(region, NotExist)`.
988/// - Each overlay update is merged with right-wins semantics via
989///   `merge_from_overlay`, and the accumulator emits a *full*
990///   ValueMesh.
991///
992/// The accumulator's state is a [`ValueMesh<T>`] and its updates are
993/// [`ValueOverlay<T>`] instances. On each update, the overlay's
994/// normalized runs are merged into the mesh using
995/// [`ValueMesh::merge_from_overlay`] with right-wins semantics.
996///
997/// This enables incremental reduction of sparse updates across
998/// distributed reducers without materializing dense data.
999impl<T> Accumulator for ValueMesh<T>
1000where
1001    T: Eq + Clone + Named,
1002{
1003    type State = Self;
1004    type Update = ValueOverlay<T>;
1005
1006    fn accumulate(&self, state: &mut Self::State, update: Self::Update) -> anyhow::Result<()> {
1007        // Mailbox starts with A::State::default() (empty). On the
1008        // first update, re-initialize to our template (self), which
1009        // the caller constructed as "full NotExist over the target
1010        // region".
1011        if state.region().num_ranks() == 0 {
1012            *state = self.clone();
1013        }
1014
1015        // Apply sparse delta into the authoritative mesh
1016        // (right-wins).
1017        state.merge_from_overlay(update)?;
1018        Ok(())
1019    }
1020
1021    fn reducer_spec(&self) -> Option<ReducerSpec> {
1022        Some(ReducerSpec {
1023            typehash: <ValueOverlayReducer<T> as Named>::typehash(),
1024            builder_params: None,
1025        })
1026    }
1027}
1028
1029/// Marker reducer type for [`ValueOverlay<T>`].
1030///
1031/// This reducer carries no state; it exists only to bind a concrete
1032/// type parameter `T` to the [`CommReducer`] implementation below.
1033/// Reduction is purely functional and uses right-wins merge semantics
1034/// defined in [`rle::merge_value_runs`].
1035#[derive(Named)]
1036pub struct ValueOverlayReducer<T>(PhantomData<T>);
1037
1038impl<T> ValueOverlayReducer<T> {
1039    /// Create a reducer for sparse [`ValueOverlay<T>`] updates.
1040    pub fn new() -> Self {
1041        Self(PhantomData)
1042    }
1043}
1044
1045/// Reducer for sparse overlay updates.
1046///
1047/// Combines two [`ValueOverlay<T>`] updates using right-wins
1048/// semantics: overlapping runs from `right` overwrite those in
1049/// `left`. The merged runs are then normalized and validated via
1050/// [`ValueOverlay::try_from_runs`].
1051///
1052/// Used by the corresponding [`Accumulator`] to perform distributed
1053/// reduction of incremental mesh updates.
1054impl<T> CommReducer for ValueOverlayReducer<T>
1055where
1056    T: Eq + Clone + Named,
1057{
1058    type Update = ValueOverlay<T>;
1059
1060    // Last-writer-wins merge of two sparse overlays.
1061    fn reduce(&self, left: Self::Update, right: Self::Update) -> anyhow::Result<Self::Update> {
1062        let merged = rle::merge_value_runs(
1063            left.runs().cloned().collect(),
1064            right.runs().cloned().collect(),
1065        );
1066        Ok(ValueOverlay::try_from_runs(merged)?)
1067    }
1068}
1069
1070#[cfg(test)]
1071mod tests {
1072    use std::convert::Infallible;
1073    use std::future::Future;
1074    use std::pin::Pin;
1075    use std::task::Context;
1076    use std::task::Poll;
1077    use std::task::RawWaker;
1078    use std::task::RawWakerVTable;
1079    use std::task::Waker;
1080
1081    use futures::executor::block_on;
1082    use futures::future;
1083    use ndslice::extent;
1084    use ndslice::strategy::gen_region;
1085    use ndslice::view::CollectExactMeshExt;
1086    use ndslice::view::CollectIndexedMeshExt;
1087    use ndslice::view::CollectMeshExt;
1088    use ndslice::view::MapIntoExt;
1089    use ndslice::view::Ranked;
1090    use ndslice::view::RankedSliceable;
1091    use ndslice::view::ViewExt;
1092    use proptest::prelude::*;
1093    use proptest::strategy::ValueTree;
1094    use serde::Deserialize;
1095    use serde::Serialize;
1096    use serde_json;
1097    use typeuri::Named;
1098
1099    use super::*;
1100
1101    #[test]
1102    fn value_mesh_new_ok() {
1103        let region: Region = extent!(replica = 2, gpu = 3).into();
1104        let mesh = ValueMesh::new(region.clone(), (0..6).collect()).expect("new should succeed");
1105        assert_eq!(mesh.region().num_ranks(), 6);
1106        assert_eq!(mesh.values().count(), 6);
1107        assert_eq!(mesh.values().collect::<Vec<_>>(), vec![0, 1, 2, 3, 4, 5]);
1108    }
1109
1110    #[test]
1111    fn get_by_base_rank_resolves_through_region_geometry() {
1112        // Full region: base rank == ordinal, so get_by_base_rank agrees
1113        // with positional get; out-of-region base ranks return None.
1114        let region: Region = extent!(row = 4, col = 2).into();
1115        let mesh: ValueMesh<i32> =
1116            ValueMesh::new(region.clone(), (0..8).map(|i| i * 10).collect()).unwrap();
1117        assert_eq!(mesh.get_by_base_rank(0), Some(&0));
1118        assert_eq!(mesh.get_by_base_rank(5), Some(&50));
1119        assert_eq!(mesh.get_by_base_rank(8), None);
1120
1121        // Slice rows 1..3 -> base ranks {2, 3, 4, 5}, ordinals {0, 1, 2, 3};
1122        // the sub-mesh carries values {20, 30, 40, 50}.
1123        let sub = mesh.sliced(region.range("row", ndslice::Range(1, Some(3), 1)).unwrap());
1124
1125        // Addressed by BASE rank, which is the whole point:
1126        assert_eq!(sub.get_by_base_rank(2), Some(&20)); // base 2 -> ordinal 0
1127        assert_eq!(sub.get_by_base_rank(5), Some(&50)); // base 5 -> ordinal 3
1128        assert_eq!(sub.get_by_base_rank(0), None); // below the slice
1129        assert_eq!(sub.get_by_base_rank(6), None); // in the parent, not the slice
1130
1131        // Contrast: positional get still indexes by ordinal.
1132        assert_eq!(sub.get(0), Some(&20)); // ordinal 0 == base rank 2
1133    }
1134
1135    #[test]
1136    fn value_mesh_new_len_mismatch_is_error() {
1137        let region: Region = extent!(replica = 2, gpu = 3).into();
1138        let err = ValueMesh::new(region, vec![0_i32; 5]).unwrap_err();
1139        let ValueMeshError::InvalidRankCardinality { expected, actual } = err;
1140        assert_eq!(expected, 6);
1141        assert_eq!(actual, 5);
1142    }
1143
1144    #[test]
1145    fn value_mesh_transpose_ok_and_err() {
1146        let region: Region = extent!(x = 2).into();
1147
1148        // ok case
1149        let ok_mesh = ValueMesh::new(region.clone(), vec![Ok::<_, Infallible>(1), Ok(2)]).unwrap();
1150        let ok = ok_mesh.transpose().unwrap();
1151        assert_eq!(ok.values().collect::<Vec<_>>(), vec![1, 2]);
1152
1153        // err case: propagate user E
1154        #[derive(Debug, PartialEq)]
1155        enum E {
1156            Boom,
1157        }
1158        let err_mesh = ValueMesh::new(region, vec![Ok(1), Err(E::Boom)]).unwrap();
1159        let err = err_mesh.transpose().unwrap_err();
1160        assert_eq!(err, E::Boom);
1161    }
1162
1163    #[test]
1164    fn value_mesh_join_preserves_region_and_values() {
1165        let region: Region = extent!(x = 2, y = 2).into();
1166        let futs = vec![
1167            future::ready(10),
1168            future::ready(11),
1169            future::ready(12),
1170            future::ready(13),
1171        ];
1172        let mesh = ValueMesh::new(region.clone(), futs).unwrap();
1173
1174        let joined = block_on(mesh.join());
1175        assert_eq!(joined.region().num_ranks(), 4);
1176        assert_eq!(joined.values().collect::<Vec<_>>(), vec![10, 11, 12, 13]);
1177    }
1178
1179    #[test]
1180    fn collect_mesh_ok() {
1181        let region: Region = extent!(x = 2, y = 3).into();
1182        let mesh = (0..6)
1183            .collect_mesh::<ValueMesh<_>>(region.clone())
1184            .expect("collect_mesh should succeed");
1185
1186        assert_eq!(mesh.region().num_ranks(), 6);
1187        assert_eq!(mesh.values().collect::<Vec<_>>(), vec![0, 1, 2, 3, 4, 5]);
1188    }
1189
1190    #[test]
1191    fn collect_mesh_len_too_short_is_error() {
1192        let region: Region = extent!(x = 2, y = 3).into();
1193        let err = (0..5).collect_mesh::<ValueMesh<_>>(region).unwrap_err();
1194
1195        let ValueMeshError::InvalidRankCardinality { expected, actual } = err;
1196        assert_eq!(expected, 6);
1197        assert_eq!(actual, 5);
1198    }
1199
1200    #[test]
1201    fn collect_mesh_len_too_long_is_error() {
1202        let region: Region = extent!(x = 2, y = 3).into();
1203        let err = (0..7).collect_mesh::<ValueMesh<_>>(region).unwrap_err();
1204        let ValueMeshError::InvalidRankCardinality { expected, actual } = err;
1205        assert_eq!(expected, 6);
1206        assert_eq!(actual, 7);
1207    }
1208
1209    #[test]
1210    fn collect_mesh_from_map_pipeline() {
1211        let region: Region = extent!(x = 2, y = 2).into();
1212        let mesh = (0..4)
1213            .map(|i| i * 10)
1214            .collect_mesh::<ValueMesh<_>>(region.clone())
1215            .unwrap();
1216
1217        assert_eq!(mesh.region().num_ranks(), 4);
1218        assert_eq!(mesh.values().collect::<Vec<_>>(), vec![0, 10, 20, 30]);
1219    }
1220
1221    #[test]
1222    fn collect_exact_mesh_ok() {
1223        let region: Region = extent!(x = 2, y = 3).into();
1224        let mesh = (0..6)
1225            .collect_exact_mesh::<ValueMesh<_>>(region.clone())
1226            .expect("collect_exact_mesh should succeed");
1227
1228        assert_eq!(mesh.region().num_ranks(), 6);
1229        assert_eq!(mesh.values().collect::<Vec<_>>(), vec![0, 1, 2, 3, 4, 5]);
1230    }
1231
1232    #[test]
1233    fn collect_exact_mesh_len_too_short_is_error() {
1234        let region: Region = extent!(x = 2, y = 3).into();
1235        let err = (0..5)
1236            .collect_exact_mesh::<ValueMesh<_>>(region)
1237            .unwrap_err();
1238
1239        let ValueMeshError::InvalidRankCardinality { expected, actual } = err;
1240        assert_eq!(expected, 6);
1241        assert_eq!(actual, 5);
1242    }
1243
1244    #[test]
1245    fn collect_exact_mesh_len_too_long_is_error() {
1246        let region: Region = extent!(x = 2, y = 3).into();
1247        let err = (0..7)
1248            .collect_exact_mesh::<ValueMesh<_>>(region)
1249            .unwrap_err();
1250
1251        let ValueMeshError::InvalidRankCardinality { expected, actual } = err;
1252        assert_eq!(expected, 6);
1253        assert_eq!(actual, 7);
1254    }
1255
1256    #[test]
1257    fn collect_exact_mesh_from_map_pipeline() {
1258        let region: Region = extent!(x = 2, y = 2).into();
1259        let mesh = (0..4)
1260            .map(|i| i * 10)
1261            .collect_exact_mesh::<ValueMesh<_>>(region.clone())
1262            .unwrap();
1263
1264        assert_eq!(mesh.region().num_ranks(), 4);
1265        assert_eq!(mesh.values().collect::<Vec<_>>(), vec![0, 10, 20, 30]);
1266    }
1267
1268    #[test]
1269    fn collect_indexed_ok_shuffled() {
1270        let region: Region = extent!(x = 2, y = 3).into();
1271        // (rank, value) in shuffled order; values = rank * 10
1272        let pairs = vec![(3, 30), (0, 0), (5, 50), (2, 20), (1, 10), (4, 40)];
1273        let mesh = pairs
1274            .into_iter()
1275            .collect_indexed::<ValueMesh<_>>(region.clone())
1276            .unwrap();
1277
1278        assert_eq!(mesh.region().num_ranks(), 6);
1279        assert_eq!(
1280            mesh.values().collect::<Vec<_>>(),
1281            vec![0, 10, 20, 30, 40, 50]
1282        );
1283    }
1284
1285    #[test]
1286    fn collect_indexed_missing_rank_is_error() {
1287        let region: Region = extent!(x = 2, y = 2).into(); // 4
1288        // Missing rank 3
1289        let pairs = vec![(0, 100), (1, 101), (2, 102)];
1290        let err = pairs
1291            .into_iter()
1292            .collect_indexed::<ValueMesh<_>>(region)
1293            .unwrap_err();
1294
1295        let ValueMeshError::InvalidRankCardinality { expected, actual } = err;
1296        assert_eq!(expected, 4);
1297        assert_eq!(actual, 3); // Distinct ranks seen.
1298    }
1299
1300    #[test]
1301    fn collect_indexed_out_of_bounds_is_error() {
1302        let region: Region = extent!(x = 2, y = 2).into(); // 4 (valid ranks 0..=3)
1303        let pairs = vec![(0, 1), (4, 9)]; // 4 is out-of-bounds
1304        let err = pairs
1305            .into_iter()
1306            .collect_indexed::<ValueMesh<_>>(region)
1307            .unwrap_err();
1308
1309        let ValueMeshError::InvalidRankCardinality { expected, actual } = err;
1310        assert_eq!(expected, 4);
1311        assert_eq!(actual, 5); // offending index + 1
1312    }
1313
1314    #[test]
1315    fn collect_indexed_duplicate_last_write_wins() {
1316        let region: Region = extent!(x = 1, y = 3).into(); // 3
1317        // rank 1 appears twice; last value should stick
1318        let pairs = vec![(0, 7), (1, 8), (1, 88), (2, 9)];
1319        let mesh = pairs
1320            .into_iter()
1321            .collect_indexed::<ValueMesh<_>>(region.clone())
1322            .unwrap();
1323
1324        assert_eq!(mesh.values().collect::<Vec<_>>(), vec![7, 88, 9]);
1325    }
1326
1327    // Indexed collector naïve implementation (for reference).
1328    #[allow(clippy::result_large_err)]
1329    fn build_value_mesh_indexed<T>(
1330        region: Region,
1331        pairs: impl IntoIterator<Item = (usize, T)>,
1332    ) -> std::result::Result<ValueMesh<T>, ValueMeshError> {
1333        let n = region.num_ranks();
1334
1335        // Buffer for exactly n slots; fill by rank.
1336        let mut buf: Vec<Option<T>> = std::iter::repeat_with(|| None).take(n).collect();
1337        let mut filled = 0usize;
1338
1339        for (rank, value) in pairs {
1340            if rank >= n {
1341                // Out-of-bounds: report `expected` = n, `actual` =
1342                // offending index + 1; i.e. number of ranks implied
1343                // so far.
1344                return Err(ValueMeshError::InvalidRankCardinality {
1345                    expected: n,
1346                    actual: rank + 1,
1347                });
1348            }
1349            if buf[rank].is_none() {
1350                filled += 1;
1351            }
1352            buf[rank] = Some(value); // Last write wins.
1353        }
1354
1355        if filled != n {
1356            // Missing ranks: actual = number of distinct ranks seen.
1357            return Err(ValueMeshError::InvalidRankCardinality {
1358                expected: n,
1359                actual: filled,
1360            });
1361        }
1362
1363        // All present and in-bounds: unwrap and build unchecked.
1364        let ranks: Vec<T> = buf.into_iter().map(Option::unwrap).collect();
1365        Ok(ValueMesh::new_unchecked(region, ranks))
1366    }
1367
1368    /// This uses the bit-mixing portion of Sebastiano Vigna's
1369    /// [SplitMix64 algorithm](https://prng.di.unimi.it/splitmix64.c)
1370    /// to generate a high-quality 64-bit hash from a usize index.
1371    /// Unlike the full SplitMix64 generator, this is stateless - we
1372    /// accept an arbitrary x as input and apply the mix function to
1373    /// turn `x` deterministically into a "randomized" u64. input
1374    /// always produces the same output.
1375    fn hash_key(x: usize) -> u64 {
1376        let mut z = x as u64 ^ 0x9E3779B97F4A7C15;
1377        z = (z ^ (z >> 30)).wrapping_mul(0xBF58476D1CE4E5B9);
1378        z = (z ^ (z >> 27)).wrapping_mul(0x94D049BB133111EB);
1379        z ^ (z >> 31)
1380    }
1381
1382    /// Shuffle a slice deterministically, using a hash of indices as
1383    /// the key.
1384    ///
1385    /// Each position `i` is assigned a pseudo-random 64-bit key (from
1386    /// `key(i)`), the slice is sorted by those keys, and the
1387    /// resulting permutation is applied in place.
1388    ///
1389    /// The permutation is fully determined by the sequence of indices
1390    /// `0..n` and the chosen `key` function. Running it twice on the
1391    /// same input yields the same "random-looking" arrangement.
1392    ///
1393    /// This is going to be used (below) for property tests: it gives
1394    /// the effect of a shuffle without introducing global RNG state,
1395    /// and ensures that duplicate elements are still ordered
1396    /// consistently (so we can test "last write wins" semantics in
1397    /// collectors).
1398    fn pseudo_shuffle<'a, T: 'a>(v: &'a mut [T], key: impl Fn(usize) -> u64 + Copy) {
1399        // Build perm.
1400        let mut with_keys: Vec<(u64, usize)> = (0..v.len()).map(|i| (key(i), i)).collect();
1401        with_keys.sort_by_key(|&(k, _)| k);
1402        let perm: Vec<usize> = with_keys.into_iter().map(|(_, i)| i).collect();
1403
1404        // In-place permutation using a cycle based approach (e.g.
1405        // https://www.geeksforgeeks.org/dsa/permute-the-elements-of-an-array-following-given-order/).
1406        let mut seen = vec![false; v.len()];
1407        for i in 0..v.len() {
1408            if seen[i] {
1409                continue;
1410            }
1411            let mut a = i;
1412            while !seen[a] {
1413                seen[a] = true;
1414                let b = perm[a];
1415                // Short circuit on the cycle's start index.
1416                if b == i {
1417                    break;
1418                }
1419                v.swap(a, b);
1420                a = b;
1421            }
1422        }
1423    }
1424
1425    // Property: Optimized and reference collectors yield the same
1426    // `ValueMesh` on complete inputs, even with duplicates.
1427    //
1428    // - Begin with a complete set of `(rank, value)` pairs covering
1429    //   all ranks of the region.
1430    // - Add extra pairs at arbitrary ranks (up to `extra_len`), which
1431    //   necessarily duplicate existing entries when `extra_len > 0`.
1432    // - Shuffle the combined pairs deterministically.
1433    // - Collect using both the reference (`try_collect_indexed`) and
1434    //   optimized (`try_collect_indexed_opt`) implementations.
1435    //
1436    // Both collectors must succeed and produce identical results.
1437    // This demonstrates that the optimized version preserves
1438    // last-write-wins semantics and agrees exactly with the reference
1439    // behavior.
1440    proptest! {
1441        #[test]
1442        fn try_collect_opt_equivalence(region in gen_region(1..=4, 6), extra_len in 0usize..=12) {
1443            let n = region.num_ranks();
1444
1445            // Start with one pair per rank (coverage guaranteed).
1446            let mut pairs: Vec<(usize, i64)> = (0..n).map(|r| (r, r as i64)).collect();
1447
1448            // Add some extra duplicates of random in-bounds ranks.
1449            // Their values differ so last-write-wins is observable.
1450            let extras = proptest::collection::vec(0..n, extra_len)
1451                .new_tree(&mut proptest::test_runner::TestRunner::default())
1452                .unwrap()
1453                .current();
1454            for (k, r) in extras.into_iter().enumerate() {
1455                pairs.push((r, (n as i64) + (k as i64)));
1456            }
1457
1458            // Deterministic "shuffle" to fix iteration order across
1459            // both collectors.
1460            pseudo_shuffle(&mut pairs, hash_key);
1461
1462            // Reference vs optimized.
1463            let mesh_ref = build_value_mesh_indexed(region.clone(), pairs.clone()).unwrap();
1464            let mesh_opt = pairs.into_iter().collect_indexed::<ValueMesh<_>>(region.clone()).unwrap();
1465
1466            prop_assert_eq!(mesh_ref.region(), mesh_opt.region());
1467            prop_assert_eq!(mesh_ref.values().collect::<Vec<_>>(), mesh_opt.values().collect::<Vec<_>>());
1468        }
1469    }
1470
1471    // Property: Optimized and reference collectors report identical
1472    // errors when ranks are missing.
1473    //
1474    // - Begin with a complete set of `(rank, value)` pairs.
1475    // - Remove one rank so coverage is incomplete.
1476    // - Shuffle deterministically.
1477    // - Collect with both implementations.
1478    //
1479    // Both must fail with `InvalidRankCardinality` describing the
1480    // same expected vs. actual counts.
1481    proptest! {
1482        #[test]
1483        fn try_collect_opt_missing_rank_errors_match(region in gen_region(1..=4, 6)) {
1484            let n = region.num_ranks();
1485            // Base complete.
1486            let mut pairs: Vec<(usize, i64)> = (0..n).map(|r| (r, r as i64)).collect();
1487            // Drop one distinct rank.
1488            if n > 0 {
1489                let drop_idx = 0usize; // Deterministic, fine for the property.
1490                pairs.remove(drop_idx);
1491            }
1492            // Shuffle deterministically.
1493            pseudo_shuffle(&mut pairs, hash_key);
1494
1495            let ref_err  = build_value_mesh_indexed(region.clone(), pairs.clone()).unwrap_err();
1496            let opt_err  = pairs.into_iter().collect_indexed::<ValueMesh<_>>(region).unwrap_err();
1497            assert_eq!(format!("{ref_err:?}"), format!("{opt_err:?}"));
1498        }
1499    }
1500
1501    // Property: Optimized and reference collectors report identical
1502    // errors when given out-of-bounds ranks.
1503    //
1504    // - Construct a set of `(rank, value)` pairs.
1505    // - Include at least one pair whose rank is ≥
1506    //   `region.num_ranks()`.
1507    // - Shuffle deterministically.
1508    // - Collect with both implementations.
1509    //
1510    // Both must fail with `InvalidRankCardinality`, and the reported
1511    // error values must match exactly.
1512    proptest! {
1513        #[test]
1514        fn try_collect_opt_out_of_bound_errors_match(region in gen_region(1..=4, 6)) {
1515            let n = region.num_ranks();
1516            // One valid, then one out-of-bound.
1517            let mut pairs = vec![(0usize, 0i64), (n, 123i64)];
1518            pseudo_shuffle(&mut pairs, hash_key);
1519
1520            let ref_err = build_value_mesh_indexed(region.clone(), pairs.clone()).unwrap_err();
1521            let opt_err = pairs.into_iter().collect_indexed::<ValueMesh<_>>(region).unwrap_err();
1522            assert_eq!(format!("{ref_err:?}"), format!("{opt_err:?}"));
1523        }
1524    }
1525
1526    #[test]
1527    fn map_into_preserves_region_and_order() {
1528        let region: Region = extent!(rows = 2, cols = 3).into();
1529        let vm = ValueMesh::new_unchecked(region.clone(), vec![0, 1, 2, 3, 4, 5]);
1530
1531        let doubled: ValueMesh<_> = vm.map_into(|x| x * 2);
1532        assert_eq!(doubled.region, region);
1533        assert_eq!(
1534            doubled.values().collect::<Vec<_>>(),
1535            vec![0, 2, 4, 6, 8, 10]
1536        );
1537    }
1538
1539    #[test]
1540    fn map_into_ref_borrows_and_preserves() {
1541        let region: Region = extent!(n = 4).into();
1542        let vm = ValueMesh::new_unchecked(
1543            region.clone(),
1544            vec!["a".to_string(), "b".into(), "c".into(), "d".into()],
1545        );
1546
1547        let lens: ValueMesh<_> = vm.map_into(|s| s.len());
1548        assert_eq!(lens.region, region);
1549        assert_eq!(lens.values().collect::<Vec<_>>(), vec![1, 1, 1, 1]);
1550    }
1551
1552    #[test]
1553    fn try_map_into_short_circuits_on_error() {
1554        let region = extent!(n = 4).into();
1555        let vm = ValueMesh::new_unchecked(region, vec![1, 2, 3, 4]);
1556
1557        let res: Result<ValueMesh<i32>, &'static str> =
1558            vm.try_map_into(|x| if x == &3 { Err("boom") } else { Ok(x + 10) });
1559
1560        assert!(res.is_err());
1561        assert_eq!(res.unwrap_err(), "boom");
1562    }
1563
1564    #[test]
1565    fn try_map_into_ref_short_circuits_on_error() {
1566        let region = extent!(n = 4).into();
1567        let vm = ValueMesh::new_unchecked(region, vec![1, 2, 3, 4]);
1568
1569        let res: Result<ValueMesh<i32>, &'static str> =
1570            vm.try_map_into(|x| if x == &3 { Err("boom") } else { Ok(x + 10) });
1571
1572        assert!(res.is_err());
1573        assert_eq!(res.unwrap_err(), "boom");
1574    }
1575
1576    // -- Helper to poll `core::future::Ready` without a runtime
1577    fn noop_waker() -> Waker {
1578        fn clone(_: *const ()) -> RawWaker {
1579            RawWaker::new(std::ptr::null(), &VTABLE)
1580        }
1581        fn wake(_: *const ()) {}
1582        fn wake_by_ref(_: *const ()) {}
1583        fn drop(_: *const ()) {}
1584        static VTABLE: RawWakerVTable = RawWakerVTable::new(clone, wake, wake_by_ref, drop);
1585        // SAFETY: The raw waker never dereferences its data pointer
1586        // (`null`), and all vtable fns are no-ops. It's only used to
1587        // satisfy `Context` for polling already-ready futures in
1588        // tests.
1589        unsafe { Waker::from_raw(RawWaker::new(std::ptr::null(), &VTABLE)) }
1590    }
1591
1592    fn poll_now<F: Future>(mut fut: F) -> F::Output {
1593        let waker = noop_waker();
1594        let mut cx = Context::from_waker(&waker);
1595        // SAFETY: `fut` is a local stack variable that we never move
1596        // after pinning, and we only use it to poll immediately
1597        // within this scope. This satisfies the invariants of
1598        // `Pin::new_unchecked`.
1599        let mut fut = unsafe { Pin::new_unchecked(&mut fut) };
1600        match fut.as_mut().poll(&mut cx) {
1601            Poll::Ready(v) => v,
1602            Poll::Pending => unreachable!("Ready futures must complete immediately"),
1603        }
1604    }
1605    // --
1606
1607    #[test]
1608    fn map_into_ready_futures() {
1609        let region: Region = extent!(r = 2, c = 2).into();
1610        let vm = ValueMesh::new_unchecked(region.clone(), vec![10, 20, 30, 40]);
1611
1612        // Map to `core::future::Ready` futures.
1613        let pending: ValueMesh<core::future::Ready<_>> =
1614            vm.map_into(|x| core::future::ready(x + 1));
1615        assert_eq!(pending.region, region);
1616
1617        // Drive the ready futures without a runtime and collect results.
1618        let results: Vec<_> = pending.values().map(|f| poll_now(f.clone())).collect();
1619        assert_eq!(results, vec![11, 21, 31, 41]);
1620    }
1621
1622    #[test]
1623    fn map_into_single_element_mesh() {
1624        let region: Region = extent!(n = 1).into();
1625        let vm = ValueMesh::new_unchecked(region.clone(), vec![7]);
1626
1627        let out: ValueMesh<_> = vm.map_into(|x| x * x);
1628        assert_eq!(out.region, region);
1629        assert_eq!(out.values().collect::<Vec<_>>(), vec![49]);
1630    }
1631
1632    #[test]
1633    fn map_into_ref_with_non_clone_field() {
1634        // A type that intentionally does NOT implement Clone.
1635        #[derive(Debug, PartialEq, Eq)]
1636        struct NotClone(i32);
1637
1638        let region: Region = extent!(x = 3).into();
1639        let values = vec![(10, NotClone(1)), (20, NotClone(2)), (30, NotClone(3))];
1640        let mesh: ValueMesh<(i32, NotClone)> =
1641            values.into_iter().collect_mesh(region.clone()).unwrap();
1642
1643        let projected: ValueMesh<i32> = mesh.map_into(|t| t.0);
1644        assert_eq!(projected.values().collect::<Vec<_>>(), vec![10, 20, 30]);
1645        assert_eq!(projected.region(), &region);
1646    }
1647
1648    #[test]
1649    fn rle_roundtrip_all_equal() {
1650        let region: Region = extent!(n = 6).into();
1651        let mut vm = ValueMesh::new_unchecked(region.clone(), vec![42; 6]);
1652
1653        // Compress and ensure logical equality preserved.
1654        vm.compress_adjacent_in_place();
1655        let collected: Vec<_> = vm.values().collect();
1656        assert_eq!(collected, vec![42, 42, 42, 42, 42, 42]);
1657
1658        // Random access still works.
1659        for i in 0..region.num_ranks() {
1660            assert_eq!(vm.get(i), Some(&42));
1661        }
1662        assert_eq!(vm.get(region.num_ranks()), None); // out-of-bounds
1663    }
1664
1665    #[test]
1666    fn rle_roundtrip_alternating() {
1667        let region: Region = extent!(n = 6).into();
1668        let original = vec![1, 2, 1, 2, 1, 2];
1669        let mut vm = ValueMesh::new_unchecked(region.clone(), original.clone());
1670
1671        vm.compress_adjacent_in_place();
1672        let collected: Vec<_> = vm.values().collect();
1673        assert_eq!(collected, original);
1674
1675        // Spot-check random access after compression.
1676        assert_eq!(vm.get(0), Some(&1));
1677        assert_eq!(vm.get(1), Some(&2));
1678        assert_eq!(vm.get(3), Some(&2));
1679        assert_eq!(vm.get(5), Some(&2));
1680    }
1681
1682    #[test]
1683    fn rle_roundtrip_blocky_and_slice() {
1684        // Blocks: 0,0,0 | 1,1 | 2,2,2,2 | 3
1685        let region: Region = extent!(n = 10).into();
1686        let original = vec![0, 0, 0, 1, 1, 2, 2, 2, 2, 3];
1687        let mut vm = ValueMesh::new_unchecked(region.clone(), original.clone());
1688
1689        vm.compress_adjacent_in_place();
1690        let collected: Vec<_> = vm.values().collect();
1691        assert_eq!(collected, original);
1692
1693        // Slice a middle subregion [3..8) → [1,1,2,2,2]
1694        let sub_region = region.range("n", 3..8).unwrap();
1695        let sliced = vm.sliced(sub_region);
1696        let sliced_vec: Vec<_> = sliced.values().collect();
1697        assert_eq!(sliced_vec, vec![1, 1, 2, 2, 2]);
1698    }
1699
1700    #[test]
1701    fn rle_idempotent_noop_on_second_call() {
1702        let region: Region = extent!(n = 7).into();
1703        let original = vec![9, 9, 9, 8, 8, 9, 9];
1704        let mut vm = ValueMesh::new_unchecked(region.clone(), original.clone());
1705
1706        vm.compress_adjacent_in_place();
1707        let once: Vec<_> = vm.values().collect();
1708        assert_eq!(once, original);
1709
1710        // Calling again should be a no-op and still yield identical
1711        // values.
1712        vm.compress_adjacent_in_place();
1713        let twice: Vec<_> = vm.values().collect();
1714        assert_eq!(twice, original);
1715    }
1716
1717    #[test]
1718    fn rle_works_after_build_indexed() {
1719        // Build with shuffled pairs, then compress and verify
1720        // semantics.
1721        let region: Region = extent!(x = 2, y = 3).into(); // 6
1722        let pairs = vec![(3, 30), (0, 0), (5, 50), (2, 20), (1, 10), (4, 40)];
1723        let mut vm = pairs
1724            .into_iter()
1725            .collect_indexed::<ValueMesh<_>>(region.clone())
1726            .unwrap();
1727
1728        // Should compress to 6 runs of length 1; still must
1729        // round-trip.
1730        vm.compress_adjacent_in_place();
1731        let collected: Vec<_> = vm.values().collect();
1732        assert_eq!(collected, vec![0, 10, 20, 30, 40, 50]);
1733        // Spot-check get()
1734        assert_eq!(vm.get(4), Some(&40));
1735    }
1736
1737    #[test]
1738    fn rle_handles_singleton_mesh() {
1739        let region: Region = extent!(n = 1).into();
1740        let mut vm = ValueMesh::new_unchecked(region.clone(), vec![123]);
1741
1742        vm.compress_adjacent_in_place();
1743        let collected: Vec<_> = vm.values().collect();
1744        assert_eq!(collected, vec![123]);
1745        assert_eq!(vm.get(0), Some(&123));
1746        assert_eq!(vm.get(1), None);
1747    }
1748
1749    #[test]
1750    fn test_dense_round_trip_json() {
1751        // Build a simple dense mesh of 5 integers.
1752        let region: Region = extent!(x = 5).into();
1753        let dense = ValueMesh::new(region.clone(), vec![1, 2, 3, 4, 5]).unwrap();
1754
1755        let json = serde_json::to_string_pretty(&dense).unwrap();
1756        let restored: ValueMesh<i32> = serde_json::from_str(&json).unwrap();
1757
1758        assert_eq!(dense, restored);
1759
1760        // Dense meshes should stay dense on the wire: check the
1761        // tagged variant.
1762        let v: serde_json::Value = serde_json::from_str(&json).unwrap();
1763        // enum tag is nested: {"rep": {"Dense":{...}}
1764        let tag = v.get("rep").and_then(|o| o.get("Dense"));
1765        assert!(tag.is_some(), "json is {}", json);
1766    }
1767
1768    #[test]
1769    fn test_dense_round_trip_bincode() {
1770        // Build a simple dense mesh of 5 integers.
1771        let region: Region = extent!(x = 5).into();
1772        let dense = ValueMesh::new(region.clone(), vec![1, 2, 3, 4, 5]).unwrap();
1773
1774        let encoded = bincode::serde::encode_to_vec(&dense, bincode::config::legacy()).unwrap();
1775        let restored: ValueMesh<i32> =
1776            bincode::serde::decode_from_slice(&encoded, bincode::config::legacy())
1777                .map(|(v, _)| v)
1778                .unwrap();
1779
1780        assert_eq!(dense, restored);
1781        // Dense meshes should stay dense on the wire.
1782        assert!(matches!(restored.rep, Rep::Dense { .. }));
1783    }
1784
1785    #[test]
1786    fn test_compressed_round_trip_json() {
1787        // Build a dense mesh, compress it, and verify it stays
1788        // compressed on the wire.
1789        let region: Region = extent!(x = 10).into();
1790        let mut mesh = ValueMesh::new(region.clone(), vec![1, 1, 1, 2, 2, 3, 3, 3, 3, 3]).unwrap();
1791        mesh.compress_adjacent_in_place();
1792
1793        let json = serde_json::to_string_pretty(&mesh).unwrap();
1794        let restored: ValueMesh<i32> = serde_json::from_str(&json).unwrap();
1795
1796        // Logical equality preserved.
1797        assert_eq!(mesh, restored);
1798
1799        // Compressed meshes should stay compressed on the wire.
1800        let v: serde_json::Value = serde_json::from_str(&json).unwrap();
1801        // enum tag is nested: {"rep": {"Compressed": {...}}
1802        let tag = v.get("rep").and_then(|o| o.get("Compressed"));
1803        assert!(tag.is_some(), "json is {}", json);
1804    }
1805
1806    #[test]
1807    fn test_compressed_round_trip_bincode() {
1808        // Build a dense mesh, compress it, and verify it stays
1809        // compressed on the wire.
1810        let region: Region = extent!(x = 10).into();
1811        let mut mesh = ValueMesh::new(region.clone(), vec![1, 1, 1, 2, 2, 3, 3, 3, 3, 3]).unwrap();
1812        mesh.compress_adjacent_in_place();
1813
1814        let encoded = bincode::serde::encode_to_vec(&mesh, bincode::config::legacy()).unwrap();
1815        let restored: ValueMesh<i32> =
1816            bincode::serde::decode_from_slice(&encoded, bincode::config::legacy())
1817                .map(|(v, _)| v)
1818                .unwrap();
1819
1820        // Logical equality preserved.
1821        assert_eq!(mesh, restored);
1822        // Compressed meshes should stay compressed on the wire.
1823        assert!(matches!(restored.rep, Rep::Compressed { .. }));
1824    }
1825
1826    #[test]
1827    fn test_stable_run_encoding() {
1828        let run = Run::new(0, 10, 42);
1829        let json = serde_json::to_string(&run).unwrap();
1830        let decoded: Run = serde_json::from_str(&json).unwrap();
1831
1832        assert_eq!(run, decoded);
1833        assert_eq!(run.start, 0);
1834        assert_eq!(run.end, 10);
1835        assert_eq!(run.id, 42);
1836
1837        // Ensure conversion back to Range<usize> works.
1838        let (range, id): (Range<usize>, u32) = run.try_into().unwrap();
1839        assert_eq!(range, 0..10);
1840        assert_eq!(id, 42);
1841    }
1842
1843    #[test]
1844    fn from_single_builds_single_run() {
1845        let region: Region = extent!(n = 6).into();
1846        let vm = ValueMesh::from_single(region.clone(), 7);
1847
1848        assert_eq!(vm.region(), &region);
1849        assert_eq!(vm.values().collect::<Vec<_>>(), vec![7, 7, 7, 7, 7, 7]);
1850        assert_eq!(vm.get(0), Some(&7));
1851        assert_eq!(vm.get(5), Some(&7));
1852        assert_eq!(vm.get(6), None);
1853    }
1854
1855    #[test]
1856    fn from_default_builds_with_default_value() {
1857        let region: Region = extent!(n = 6).into();
1858        let vm = ValueMesh::<i32>::from_default(region.clone());
1859
1860        assert_eq!(vm.region(), &region);
1861        // i32::default() == 0
1862        assert_eq!(vm.values().collect::<Vec<_>>(), vec![0, 0, 0, 0, 0, 0]);
1863        assert_eq!(vm.get(0), Some(&0));
1864        assert_eq!(vm.get(5), Some(&0));
1865    }
1866
1867    #[test]
1868    fn test_default_vs_single_equivalence() {
1869        let region: Region = extent!(x = 4).into();
1870        let d1 = ValueMesh::<i32>::from_default(region.clone());
1871        let d2 = ValueMesh::from_single(region.clone(), 0);
1872        assert_eq!(d1, d2);
1873    }
1874
1875    #[test]
1876    fn build_from_ranges_with_default_basic() {
1877        let region: Region = extent!(n = 10).into();
1878        let vm = ValueMesh::from_ranges_with_default(
1879            region.clone(),
1880            0, // default
1881            vec![(2..4, 1), (6..9, 2)],
1882        )
1883        .unwrap();
1884
1885        assert_eq!(vm.region(), &region);
1886        assert_eq!(
1887            vm.values().collect::<Vec<_>>(),
1888            vec![0, 0, 1, 1, 0, 0, 2, 2, 2, 0]
1889        );
1890
1891        // Internal shape: [0..2)->0, [2..4)->1, [4..6)->0, [6..9)->2,
1892        // [9..10)->0
1893        if let Rep::Compressed { table, runs } = &vm.rep {
1894            // Table is small and de-duplicated.
1895            assert!(table.len() <= 3);
1896            assert_eq!(runs.len(), 5);
1897        } else {
1898            panic!("expected compressed");
1899        }
1900    }
1901
1902    #[test]
1903    fn build_from_ranges_with_default_edge_cases() {
1904        let region: Region = extent!(n = 5).into();
1905
1906        // Full override covers entire region.
1907        let vm = ValueMesh::from_ranges_with_default(region.clone(), 9, vec![(0..5, 3)]).unwrap();
1908        assert_eq!(vm.values().collect::<Vec<_>>(), vec![3, 3, 3, 3, 3]);
1909
1910        // Adjacent overrides and default gaps.
1911        let vm = ValueMesh::from_ranges_with_default(region.clone(), 0, vec![(1..2, 7), (2..4, 7)])
1912            .unwrap();
1913        assert_eq!(vm.values().collect::<Vec<_>>(), vec![0, 7, 7, 7, 0]);
1914
1915        // Empty region.
1916        let empty_region: Region = extent!(n = 0).into();
1917        let vm = ValueMesh::from_ranges_with_default(empty_region.clone(), 42, vec![]).unwrap();
1918        assert_eq!(vm.values().collect::<Vec<_>>(), Vec::<i32>::new());
1919    }
1920
1921    #[test]
1922    fn from_dense_builds_and_compresses() {
1923        let region: Region = extent!(n = 6).into();
1924        let mesh = ValueMesh::from_dense(region.clone(), vec![1, 1, 2, 2, 3, 3]).unwrap();
1925
1926        assert_eq!(mesh.region(), &region);
1927        assert!(matches!(mesh.rep, Rep::Compressed { .. }));
1928        assert_eq!(mesh.values().collect::<Vec<_>>(), vec![1, 1, 2, 2, 3, 3]);
1929
1930        // Spot-check indexing.
1931        assert_eq!(mesh.get(0), Some(&1));
1932        assert_eq!(mesh.get(3), Some(&2));
1933        assert_eq!(mesh.get(5), Some(&3));
1934    }
1935
1936    #[test]
1937    fn merge_from_overlay_basic() {
1938        // Base mesh with two contiguous runs.
1939        let region: Region = extent!(n = 8).into();
1940        let mut mesh = ValueMesh::from_dense(region.clone(), vec![1, 1, 1, 2, 2, 2, 3, 3]).unwrap();
1941
1942        // Overlay replaces middle segment [2..6) with 9s.
1943        let overlay = ValueOverlay::try_from_runs(vec![(2..6, 9)]).unwrap();
1944
1945        mesh.merge_from_overlay(overlay).unwrap();
1946
1947        // Materialize back into ranges to inspect.
1948        let out = mesh.materialized_runs();
1949
1950        // Expected: left prefix (0..2)=1, replaced middle (2..6)=9, tail (6..8)=3.
1951        assert_eq!(out, vec![(0..2, 1), (2..6, 9), (6..8, 3)]);
1952    }
1953
1954    #[test]
1955    fn merge_from_overlay_multiple_spans() {
1956        // Build mesh with alternating runs.
1957        let region: Region = extent!(m = 12).into();
1958        let mut mesh =
1959            ValueMesh::from_dense(region.clone(), vec![1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4])
1960                .unwrap();
1961
1962        // Overlay has a run that spans across the boundary of two
1963        // left runs and another disjoint run later.
1964        let overlay = ValueOverlay::try_from_runs(vec![(2..6, 9), (9..11, 8)]).unwrap();
1965
1966        mesh.merge_from_overlay(overlay).unwrap();
1967        let out = mesh.materialized_runs();
1968
1969        // Expected after merge and re-compression:
1970        // (0..2,1) untouched
1971        // (2..6,9) overwrite of part of [1,2] runs
1972        // (6..9,3) left tail survives
1973        // (9..11,8) overwrite inside [4] run
1974        // (11..12,4) leftover tail
1975        assert_eq!(
1976            out,
1977            vec![(0..2, 1), (2..6, 9), (6..9, 3), (9..11, 8), (11..12, 4)]
1978        );
1979    }
1980
1981    #[test]
1982    fn merge_from_overlay_crosses_row_boundary() {
1983        // 2 x 5 region -> 10 linear ranks in row-major order.
1984        let region: Region = extent!(rows = 2, cols = 5).into();
1985
1986        // Dense values laid out row-major:
1987        // row 0: [1, 1, 1, 2, 2]
1988        // row 1: [3, 3, 4, 4, 4]
1989        let mut mesh =
1990            ValueMesh::from_dense(region.clone(), vec![1, 1, 1, 2, 2, 3, 3, 4, 4, 4]).unwrap();
1991
1992        // Overlay that crosses the row boundary:
1993        // linear ranks [3..7) -> 9
1994        //   - tail of row 0: indices 3,4 (the two 2s)
1995        //   - head of row 1: indices 5,6 (the two 3s)
1996        let overlay = ValueOverlay::try_from_runs(vec![(3..7, 9)]).unwrap();
1997
1998        mesh.merge_from_overlay(overlay).unwrap();
1999
2000        // After merge, the dense view should be:
2001        // [1,1,1, 9,9, 9,9, 4,4,4]
2002        let flat: Vec<_> = mesh.values().collect();
2003        assert_eq!(flat, vec![1, 1, 1, 9, 9, 9, 9, 4, 4, 4]);
2004
2005        // And the materialized runs should reflect that:
2006        // (0..3,1) | (3..7,9) | (7..10,4)
2007        let runs = mesh.materialized_runs();
2008        assert_eq!(runs, vec![(0..3, 1), (3..7, 9), (7..10, 4)]);
2009    }
2010
2011    #[test]
2012    fn accumulator_initializes_and_merges_overlays() {
2013        /// Simple three-variant enum local to tests, avoiding a
2014        /// cross-module dependency on `crate::resource::Status`.
2015        #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize, Named)]
2016        enum Val {
2017            Init,
2018            Running,
2019            Stopped,
2020        }
2021
2022        let region: Region = extent!(m = 8).into();
2023        let template = ValueMesh::from_single(region.clone(), Val::Init);
2024
2025        // State starts empty (default).
2026        let mut state = ValueMesh::<Val>::default();
2027        assert_eq!(state.region().num_ranks(), 0);
2028
2029        // First accumulate: state should be cloned from template.
2030        let overlay1 = ValueOverlay::try_from_runs(vec![(2..5, Val::Running)]).unwrap();
2031        template.accumulate(&mut state, overlay1).unwrap();
2032
2033        // State now has the full region, with ranks 2..5 set to Running.
2034        assert_eq!(state.region().num_ranks(), 8);
2035        let vals: Vec<_> = state.values().collect();
2036        assert_eq!(
2037            vals,
2038            vec![
2039                Val::Init,
2040                Val::Init,
2041                Val::Running,
2042                Val::Running,
2043                Val::Running,
2044                Val::Init,
2045                Val::Init,
2046                Val::Init,
2047            ]
2048        );
2049
2050        // Second accumulate: overlay a different subrange with Stopped.
2051        let overlay2 = ValueOverlay::try_from_runs(vec![(5..7, Val::Stopped)]).unwrap();
2052        template.accumulate(&mut state, overlay2).unwrap();
2053
2054        let vals: Vec<_> = state.values().collect();
2055        assert_eq!(
2056            vals,
2057            vec![
2058                Val::Init,
2059                Val::Init,
2060                Val::Running,
2061                Val::Running,
2062                Val::Running,
2063                Val::Stopped,
2064                Val::Stopped,
2065                Val::Init,
2066            ]
2067        );
2068
2069        // reducer_spec should return Some with the correct typehash.
2070        let spec = template
2071            .reducer_spec()
2072            .expect("reducer_spec should be Some");
2073        assert_eq!(
2074            spec.typehash,
2075            <ValueOverlayReducer<Val> as Named>::typehash()
2076        );
2077    }
2078
2079    #[test]
2080    fn value_overlay_reducer_merges_with_right_wins() {
2081        /// Simple three-variant enum local to tests, avoiding a
2082        /// cross-module dependency on `crate::resource::Status`.
2083        #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize, Named)]
2084        enum Val {
2085            Init,
2086            Running,
2087            Stopped,
2088        }
2089
2090        let reducer = ValueOverlayReducer::<Val>(PhantomData);
2091
2092        // Left overlay: ranks 0..4 = Running, 6..8 = Stopped
2093        let left =
2094            ValueOverlay::try_from_runs(vec![(0..4, Val::Running), (6..8, Val::Stopped)]).unwrap();
2095
2096        // Right overlay: ranks 2..6 = Init
2097        // Overlaps with left on 2..4 (should overwrite Running).
2098        let right = ValueOverlay::try_from_runs(vec![(2..6, Val::Init)]).unwrap();
2099
2100        let merged = reducer.reduce(left, right).unwrap();
2101        let runs: Vec<_> = merged.runs().cloned().collect();
2102
2103        // Expected (right wins on overlap):
2104        // 0..2 Running (from left, no overlap)
2105        // 2..6 Init (from right, overwrites left 2..4)
2106        // 6..8 Stopped (from left, no overlap)
2107        assert_eq!(
2108            runs,
2109            vec![
2110                (0..2, Val::Running),
2111                (2..6, Val::Init),
2112                (6..8, Val::Stopped),
2113            ]
2114        );
2115    }
2116}