(&self, pos: Position<NodeId>)
| 198 | } |
| 199 | |
| 200 | fn find_block_end(&self, pos: Position<NodeId>) -> PristineResult<GraphNode<NodeId>> { |
| 201 | // Handle ROOT position specially |
| 202 | if pos.change.is_root() { |
| 203 | return Ok(GraphNode::ROOT); |
| 204 | } |
| 205 | |
| 206 | let table = self.txn.open_multimap_table(GRAPH)?; |
| 207 | |
| 208 | let change_id = pos.change.get(); |
| 209 | let target_pos = pos.pos.get(); |
| 210 | |
| 211 | // FIRST: Check for empty span at exact position using direct lookup. |
| 212 | // This is important because empty vertices like inode markers (e.g., V[9:9]) |
| 213 | // must be found when predecessors references position 9, even if there's |
| 214 | // another span like V[0:9] that also ends at position 9. |
| 215 | // Without this direct lookup, iteration would return V[0:9] first since |
| 216 | // it has a lower start position. |
| 217 | let empty_key = encode_vertex(change_id, target_pos, target_pos); |
| 218 | if table.get(&empty_key)?.next().is_some() { |
| 219 | return Ok(GraphNode { |
| 220 | change: NodeId::new(change_id), |
| 221 | start: ChangePosition::new(target_pos), |
| 222 | end: ChangePosition::new(target_pos), |
| 223 | }); |
| 224 | } |
| 225 | |
| 226 | // SECOND: Fall back to iteration to find vertices that end at this position |
| 227 | let start_key = encode_vertex(change_id, 0, 0); |
| 228 | let end_key = encode_vertex(change_id, u64::MAX, u64::MAX); |
| 229 | |
| 230 | // Look for a span that ends at this position or contains it |
| 231 | for result in table.range::<&[u8; 24]>(&start_key..=&end_key)? { |
| 232 | let (key, _values) = result?; |
| 233 | let (v_change, v_start, v_end) = decode_vertex(key.value()); |
| 234 | |
| 235 | if v_change != change_id { |
| 236 | continue; |
| 237 | } |
| 238 | |
| 239 | // Check for span that ends at this position |
| 240 | if v_end == target_pos && v_start < v_end { |
| 241 | return Ok(GraphNode { |
| 242 | change: NodeId::new(v_change), |
| 243 | start: ChangePosition::new(v_start), |
| 244 | end: ChangePosition::new(v_end), |
| 245 | }); |
| 246 | } |
| 247 | |
| 248 | // Also check if position falls within [start, end) |
| 249 | if v_start <= target_pos && target_pos < v_end { |
| 250 | return Ok(GraphNode { |
| 251 | change: NodeId::new(v_change), |
| 252 | start: ChangePosition::new(v_start), |
| 253 | end: ChangePosition::new(v_end), |
| 254 | }); |
| 255 | } |
| 256 | } |
| 257 |
nothing calls this directly
no test coverage detected