Group `(hilbert_prefix, cell_msgpack)` pairs by tile bucket. `cells` — each element is `(hilbert_prefix, zerompk-encoded single cell)`. `prefix_bits` — routing granularity (1–16). Returns one `PutBucket` per unique owning vShard. The order of buckets in the output is unspecified but deterministic within a call.
(cells: &[(u64, Vec<u8>)], prefix_bits: u8)
| 58 | /// Returns one `PutBucket` per unique owning vShard. The order of buckets |
| 59 | /// in the output is unspecified but deterministic within a call. |
| 60 | pub fn partition_put_cells(cells: &[(u64, Vec<u8>)], prefix_bits: u8) -> Result<Vec<PutBucket>> { |
| 61 | if cells.is_empty() { |
| 62 | return Ok(Vec::new()); |
| 63 | } |
| 64 | |
| 65 | // vshard_id → (representative_hilbert_prefix, per-cell byte blobs) |
| 66 | let mut buckets: HashMap<u32, (u64, Vec<Vec<u8>>)> = HashMap::new(); |
| 67 | |
| 68 | for (hilbert_prefix, cell_bytes) in cells { |
| 69 | let vshard_id = array_vshard_for_tile(*hilbert_prefix, prefix_bits)?; |
| 70 | let entry = buckets |
| 71 | .entry(vshard_id) |
| 72 | .or_insert((*hilbert_prefix, Vec::new())); |
| 73 | entry.1.push(cell_bytes.clone()); |
| 74 | } |
| 75 | |
| 76 | buckets |
| 77 | .into_iter() |
| 78 | .map(|(vshard_id, (representative, cell_blobs))| { |
| 79 | let cells_msgpack = encode_blob_vec(&cell_blobs)?; |
| 80 | Ok(PutBucket { |
| 81 | vshard_id, |
| 82 | representative_hilbert_prefix: representative, |
| 83 | cells_msgpack, |
| 84 | }) |
| 85 | }) |
| 86 | .collect() |
| 87 | } |
| 88 | |
| 89 | /// Group `(hilbert_prefix, coord_msgpack)` pairs by tile bucket. |
| 90 | /// |