Insert or update a key-value pair. Returns the old value bytes if overwritten. `surrogate` is the row's stable global identity: - On insert of a new row, it is recorded in the reverse map. - On update of an existing row, the entry's existing surrogate is preserved unless `surrogate` is non-zero AND the existing entry is unbound (`Surrogate::ZERO`), in which case the entry is bound. - `Surrogate::
(
&mut self,
key: &[u8],
value: &[u8],
expire_at_ms: u64,
surrogate: Surrogate,
)
| 88 | /// Triggers incremental rehash migration if a rehash is in progress. |
| 89 | /// Triggers a new rehash if the load factor exceeds the threshold. |
| 90 | pub fn put( |
| 91 | &mut self, |
| 92 | key: &[u8], |
| 93 | value: &[u8], |
| 94 | expire_at_ms: u64, |
| 95 | surrogate: Surrogate, |
| 96 | ) -> Option<Vec<u8>> { |
| 97 | // Progress incremental rehash. |
| 98 | self.rehash_step(); |
| 99 | |
| 100 | let h = hash_key(key); |
| 101 | |
| 102 | // Check if key exists in primary — update in place (no key copy needed). |
| 103 | if let Some(idx) = Self::probe_find_index_static(&self.slots, h, key) { |
| 104 | // probe_find_index_static guarantees slots[idx] is Some. |
| 105 | let old_value = { |
| 106 | let slot = self.slots[idx].as_ref()?; |
| 107 | let v = extract_value_from(&slot.value, &self.overflow); |
| 108 | free_value_from(&slot.value, &mut self.overflow); |
| 109 | v |
| 110 | }; |
| 111 | let new_kv_value = store_value_in(&mut self.overflow, value, self.inline_threshold); |
| 112 | if let Some(entry) = self.slots[idx].as_mut() { |
| 113 | entry.value = new_kv_value; |
| 114 | entry.expire_at_ms = expire_at_ms; |
| 115 | // Late-bind a surrogate onto a previously-unbound entry. |
| 116 | if entry.surrogate == Surrogate::ZERO && surrogate != Surrogate::ZERO { |
| 117 | entry.surrogate = surrogate; |
| 118 | self.surrogate_to_key.insert(surrogate.0, key.to_vec()); |
| 119 | } |
| 120 | } |
| 121 | return Some(old_value); |
| 122 | } |
| 123 | |
| 124 | // Check rehash source — if found, remove from old and insert into primary. |
| 125 | if let Some(old_slots) = self.rehash_source.as_mut() |
| 126 | && let Some(idx) = Self::probe_find_index_static(old_slots, h, key) |
| 127 | { |
| 128 | let old_entry = old_slots[idx].take()?; |
| 129 | let old_value = extract_value_from(&old_entry.value, &self.overflow); |
| 130 | free_value_from(&old_entry.value, &mut self.overflow); |
| 131 | let new_kv_value = store_value_in(&mut self.overflow, value, self.inline_threshold); |
| 132 | let preserved = if old_entry.surrogate != Surrogate::ZERO { |
| 133 | old_entry.surrogate |
| 134 | } else { |
| 135 | surrogate |
| 136 | }; |
| 137 | if preserved != Surrogate::ZERO { |
| 138 | self.surrogate_to_key.insert(preserved.0, key.to_vec()); |
| 139 | } |
| 140 | let new_entry = KvEntry { |
| 141 | hash: h, |
| 142 | key: key.to_vec(), // Only copy key when migrating from rehash source. |
| 143 | value: new_kv_value, |
| 144 | expire_at_ms, |
| 145 | surrogate: preserved, |
| 146 | }; |
| 147 | Self::robin_hood_insert(&mut self.slots, new_entry); |