Mercurial > hg
comparison rust/hg-core/src/dirstate_tree/dirstate_map.rs @ 47124:cd8ca38fccff
rust: Use `&HgPath` instead of `&HgPathBuf` in may APIs
Getting the former (through `Deref`) is almost the only useful thing one can
do with the latter anyway. With this changes, API become more flexible for the
"provider" of these paths which may store something else that Deref’s to HgPath,
such as `std::borrow::Cow<HgPath>`. Using `Cow` can help reduce memory alloactions
and copying.
Differential Revision: https://phab.mercurial-scm.org/D10558
author | Simon Sapin <simon.sapin@octobus.net> |
---|---|
date | Fri, 30 Apr 2021 19:57:46 +0200 |
parents | d8ac62374943 |
children | 9be618452c3b |
comparison
equal
deleted
inserted
replaced
47123:d8ac62374943 | 47124:cd8ca38fccff |
---|---|
65 } | 65 } |
66 } | 66 } |
67 | 67 |
68 /// `(full_path, entry, copy_source)` | 68 /// `(full_path, entry, copy_source)` |
69 type NodeDataMut<'a> = ( | 69 type NodeDataMut<'a> = ( |
70 &'a WithBasename<HgPathBuf>, | 70 &'a HgPath, |
71 &'a mut Option<DirstateEntry>, | 71 &'a mut Option<DirstateEntry>, |
72 &'a mut Option<HgPathBuf>, | 72 &'a mut Option<HgPathBuf>, |
73 ); | 73 ); |
74 | 74 |
75 impl<'on_disk> DirstateMap<'on_disk> { | 75 impl<'on_disk> DirstateMap<'on_disk> { |
246 node.entry = Some(new_entry) | 246 node.entry = Some(new_entry) |
247 } | 247 } |
248 | 248 |
249 fn iter_nodes<'a>( | 249 fn iter_nodes<'a>( |
250 &'a self, | 250 &'a self, |
251 ) -> impl Iterator<Item = (&'a WithBasename<HgPathBuf>, &'a Node)> + 'a | 251 ) -> impl Iterator<Item = (&'a HgPath, &'a Node)> + 'a { |
252 { | |
253 // Depth first tree traversal. | 252 // Depth first tree traversal. |
254 // | 253 // |
255 // If we could afford internal iteration and recursion, | 254 // If we could afford internal iteration and recursion, |
256 // this would look like: | 255 // this would look like: |
257 // | 256 // |
274 std::iter::from_fn(move || { | 273 std::iter::from_fn(move || { |
275 while let Some((key, child_node)) = iter.next() { | 274 while let Some((key, child_node)) = iter.next() { |
276 // Pseudo-recursion | 275 // Pseudo-recursion |
277 let new_iter = child_node.children.iter(); | 276 let new_iter = child_node.children.iter(); |
278 let old_iter = std::mem::replace(&mut iter, new_iter); | 277 let old_iter = std::mem::replace(&mut iter, new_iter); |
278 let key = &**key.full_path(); | |
279 stack.push((key, child_node, old_iter)); | 279 stack.push((key, child_node, old_iter)); |
280 } | 280 } |
281 // Found the end of a `children.iter()` iterator. | 281 // Found the end of a `children.iter()` iterator. |
282 if let Some((key, child_node, next_iter)) = stack.pop() { | 282 if let Some((key, child_node, next_iter)) = stack.pop() { |
283 // "Return" from pseudo-recursion by restoring state from the | 283 // "Return" from pseudo-recursion by restoring state from the |
305 let mut stack = Vec::new(); | 305 let mut stack = Vec::new(); |
306 let mut iter = self.root.iter_mut(); | 306 let mut iter = self.root.iter_mut(); |
307 std::iter::from_fn(move || { | 307 std::iter::from_fn(move || { |
308 while let Some((key, child_node)) = iter.next() { | 308 while let Some((key, child_node)) = iter.next() { |
309 // Pseudo-recursion | 309 // Pseudo-recursion |
310 let data = | 310 let data = ( |
311 (key, &mut child_node.entry, &mut child_node.copy_source); | 311 &**key.full_path(), |
312 &mut child_node.entry, | |
313 &mut child_node.copy_source, | |
314 ); | |
312 let new_iter = child_node.children.iter_mut(); | 315 let new_iter = child_node.children.iter_mut(); |
313 let old_iter = std::mem::replace(&mut iter, new_iter); | 316 let old_iter = std::mem::replace(&mut iter, new_iter); |
314 stack.push((data, old_iter)); | 317 stack.push((data, old_iter)); |
315 } | 318 } |
316 // Found the end of a `children.values_mut()` iterator. | 319 // Found the end of a `children.values_mut()` iterator. |
419 // entries" set that need to be kept up to date | 422 // entries" set that need to be kept up to date |
420 } | 423 } |
421 | 424 |
422 fn non_normal_or_other_parent_paths( | 425 fn non_normal_or_other_parent_paths( |
423 &mut self, | 426 &mut self, |
424 ) -> Box<dyn Iterator<Item = &HgPathBuf> + '_> { | 427 ) -> Box<dyn Iterator<Item = &HgPath> + '_> { |
425 Box::new(self.iter_nodes().filter_map(|(path, node)| { | 428 Box::new(self.iter_nodes().filter_map(|(path, node)| { |
426 node.entry | 429 node.entry |
427 .as_ref() | 430 .as_ref() |
428 .filter(|entry| { | 431 .filter(|entry| { |
429 entry.is_non_normal() || entry.is_from_other_parent() | 432 entry.is_non_normal() || entry.is_from_other_parent() |
430 }) | 433 }) |
431 .map(|_| path.full_path()) | 434 .map(|_| path) |
432 })) | 435 })) |
433 } | 436 } |
434 | 437 |
435 fn set_non_normal_other_parent_entries(&mut self, _force: bool) { | 438 fn set_non_normal_other_parent_entries(&mut self, _force: bool) { |
436 // Do nothing, this `DirstateMap` does not have a separate "non normal | 439 // Do nothing, this `DirstateMap` does not have a separate "non normal |
437 // entries" and "from other parent" sets that need to be recomputed | 440 // entries" and "from other parent" sets that need to be recomputed |
438 } | 441 } |
439 | 442 |
440 fn iter_non_normal_paths( | 443 fn iter_non_normal_paths( |
441 &mut self, | 444 &mut self, |
442 ) -> Box<dyn Iterator<Item = &HgPathBuf> + Send + '_> { | 445 ) -> Box<dyn Iterator<Item = &HgPath> + Send + '_> { |
443 self.iter_non_normal_paths_panic() | 446 self.iter_non_normal_paths_panic() |
444 } | 447 } |
445 | 448 |
446 fn iter_non_normal_paths_panic( | 449 fn iter_non_normal_paths_panic( |
447 &self, | 450 &self, |
448 ) -> Box<dyn Iterator<Item = &HgPathBuf> + Send + '_> { | 451 ) -> Box<dyn Iterator<Item = &HgPath> + Send + '_> { |
449 Box::new(self.iter_nodes().filter_map(|(path, node)| { | 452 Box::new(self.iter_nodes().filter_map(|(path, node)| { |
450 node.entry | 453 node.entry |
451 .as_ref() | 454 .as_ref() |
452 .filter(|entry| entry.is_non_normal()) | 455 .filter(|entry| entry.is_non_normal()) |
453 .map(|_| path.full_path()) | 456 .map(|_| path) |
454 })) | 457 })) |
455 } | 458 } |
456 | 459 |
457 fn iter_other_parent_paths( | 460 fn iter_other_parent_paths( |
458 &mut self, | 461 &mut self, |
459 ) -> Box<dyn Iterator<Item = &HgPathBuf> + Send + '_> { | 462 ) -> Box<dyn Iterator<Item = &HgPath> + Send + '_> { |
460 Box::new(self.iter_nodes().filter_map(|(path, node)| { | 463 Box::new(self.iter_nodes().filter_map(|(path, node)| { |
461 node.entry | 464 node.entry |
462 .as_ref() | 465 .as_ref() |
463 .filter(|entry| entry.is_from_other_parent()) | 466 .filter(|entry| entry.is_from_other_parent()) |
464 .map(|_| path.full_path()) | 467 .map(|_| path) |
465 })) | 468 })) |
466 } | 469 } |
467 | 470 |
468 fn has_tracked_dir( | 471 fn has_tracked_dir( |
469 &mut self, | 472 &mut self, |
500 // reallocations | 503 // reallocations |
501 let mut size = parents.as_bytes().len(); | 504 let mut size = parents.as_bytes().len(); |
502 for (path, node) in self.iter_nodes() { | 505 for (path, node) in self.iter_nodes() { |
503 if node.entry.is_some() { | 506 if node.entry.is_some() { |
504 size += packed_entry_size( | 507 size += packed_entry_size( |
505 path.full_path(), | 508 path, |
506 node.copy_source.as_ref(), | 509 node.copy_source.as_ref().map(|p| &**p), |
507 ) | 510 ) |
508 } | 511 } |
509 } | 512 } |
510 | 513 |
511 let mut packed = Vec::with_capacity(size); | 514 let mut packed = Vec::with_capacity(size); |
514 let now: i32 = now.0.try_into().expect("time overflow"); | 517 let now: i32 = now.0.try_into().expect("time overflow"); |
515 for (path, opt_entry, copy_source) in self.iter_node_data_mut() { | 518 for (path, opt_entry, copy_source) in self.iter_node_data_mut() { |
516 if let Some(entry) = opt_entry { | 519 if let Some(entry) = opt_entry { |
517 clear_ambiguous_mtime(entry, now); | 520 clear_ambiguous_mtime(entry, now); |
518 pack_entry( | 521 pack_entry( |
519 path.full_path(), | 522 path, |
520 entry, | 523 entry, |
521 copy_source.as_ref(), | 524 copy_source.as_ref().map(|p| &**p), |
522 &mut packed, | 525 &mut packed, |
523 ); | 526 ); |
524 } | 527 } |
525 } | 528 } |
526 Ok(packed) | 529 Ok(packed) |
555 | 558 |
556 fn copy_map_iter(&self) -> CopyMapIter<'_> { | 559 fn copy_map_iter(&self) -> CopyMapIter<'_> { |
557 Box::new(self.iter_nodes().filter_map(|(path, node)| { | 560 Box::new(self.iter_nodes().filter_map(|(path, node)| { |
558 node.copy_source | 561 node.copy_source |
559 .as_ref() | 562 .as_ref() |
560 .map(|copy_source| (path.full_path(), copy_source)) | 563 .map(|copy_source| (path, &**copy_source)) |
561 })) | 564 })) |
562 } | 565 } |
563 | 566 |
564 fn copy_map_contains_key(&self, key: &HgPath) -> bool { | 567 fn copy_map_contains_key(&self, key: &HgPath) -> bool { |
565 if let Some(node) = self.get_node(key) { | 568 if let Some(node) = self.get_node(key) { |
567 } else { | 570 } else { |
568 false | 571 false |
569 } | 572 } |
570 } | 573 } |
571 | 574 |
572 fn copy_map_get(&self, key: &HgPath) -> Option<&HgPathBuf> { | 575 fn copy_map_get(&self, key: &HgPath) -> Option<&HgPath> { |
573 self.get_node(key)?.copy_source.as_ref() | 576 self.get_node(key)?.copy_source.as_ref().map(|p| &**p) |
574 } | 577 } |
575 | 578 |
576 fn copy_map_remove(&mut self, key: &HgPath) -> Option<HgPathBuf> { | 579 fn copy_map_remove(&mut self, key: &HgPath) -> Option<HgPathBuf> { |
577 let count = &mut self.nodes_with_copy_source_count; | 580 let count = &mut self.nodes_with_copy_source_count; |
578 Self::get_node_mut(&mut self.root, key).and_then(|node| { | 581 Self::get_node_mut(&mut self.root, key).and_then(|node| { |
607 self.get_node(key)?.entry.as_ref() | 610 self.get_node(key)?.entry.as_ref() |
608 } | 611 } |
609 | 612 |
610 fn iter(&self) -> StateMapIter<'_> { | 613 fn iter(&self) -> StateMapIter<'_> { |
611 Box::new(self.iter_nodes().filter_map(|(path, node)| { | 614 Box::new(self.iter_nodes().filter_map(|(path, node)| { |
612 node.entry.as_ref().map(|entry| (path.full_path(), entry)) | 615 node.entry.as_ref().map(|entry| (path, entry)) |
613 })) | 616 })) |
614 } | 617 } |
615 } | 618 } |