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 }