Encode field values into a composite sort key. `values` must have the same length as `columns`. Each value is the raw bytes of the field (big-endian for numerics, UTF-8 for strings).
(&self, values: &[&[u8]])
| 59 | /// Each value is the raw bytes of the field (big-endian for numerics, |
| 60 | /// UTF-8 for strings). |
| 61 | pub fn encode(&self, values: &[&[u8]]) -> Vec<u8> { |
| 62 | debug_assert_eq!(values.len(), self.columns.len()); |
| 63 | |
| 64 | let total_len: usize = values.iter().map(|v| 4 + v.len()).sum(); |
| 65 | let mut key = Vec::with_capacity(total_len); |
| 66 | |
| 67 | for (value, col) in values.iter().zip(&self.columns) { |
| 68 | // Length prefix (4 bytes, big-endian) — always ascending so that |
| 69 | // shorter values sort before longer values within the same column. |
| 70 | let len = value.len() as u32; |
| 71 | key.extend_from_slice(&len.to_be_bytes()); |
| 72 | |
| 73 | match col.direction { |
| 74 | SortDirection::Asc => { |
| 75 | key.extend_from_slice(value); |
| 76 | } |
| 77 | SortDirection::Desc => { |
| 78 | // Bitwise complement reverses sort order. |
| 79 | for &b in *value { |
| 80 | key.push(!b); |
| 81 | } |
| 82 | } |
| 83 | } |
| 84 | } |
| 85 | |
| 86 | key |
| 87 | } |
| 88 | |
| 89 | /// Encode an i64 score as big-endian bytes suitable for sorting. |
| 90 | /// |