rust/hg-core/src/dirstate_tree/on_disk.rs
changeset 47679 731286dc5321
parent 47678 065e61628980
child 47680 a8b0f29dc0d7
equal deleted inserted replaced
47678:065e61628980 47679:731286dc5321
   588 impl Writer<'_, '_> {
   588 impl Writer<'_, '_> {
   589     fn write_nodes(
   589     fn write_nodes(
   590         &mut self,
   590         &mut self,
   591         nodes: dirstate_map::ChildNodesRef,
   591         nodes: dirstate_map::ChildNodesRef,
   592     ) -> Result<ChildNodes, DirstateError> {
   592     ) -> Result<ChildNodes, DirstateError> {
   593         // `dirstate_map::ChildNodes` is a `HashMap` with undefined iteration
   593         // Reuse already-written nodes if possible
   594         // order. Sort to enable binary search in the written file.
   594         if self.append {
       
   595             if let dirstate_map::ChildNodesRef::OnDisk(nodes_slice) = nodes {
       
   596                 let start = self.offset_of(nodes_slice);
       
   597                 let len = child_nodes_len_from_usize(nodes_slice.len());
       
   598                 return Ok(ChildNodes { start, len });
       
   599             }
       
   600         }
       
   601 
       
   602         // `dirstate_map::ChildNodes::InMemory` contains a `HashMap` which has
       
   603         // undefined iteration order. Sort to enable binary search in the
       
   604         // written file.
   595         let nodes = nodes.sorted();
   605         let nodes = nodes.sorted();
   596         let nodes_len = nodes.len();
   606         let nodes_len = nodes.len();
   597 
   607 
   598         // First accumulate serialized nodes in a `Vec`
   608         // First accumulate serialized nodes in a `Vec`
   599         let mut on_disk_nodes = Vec::with_capacity(nodes_len);
   609         let mut on_disk_nodes = Vec::with_capacity(nodes_len);
   662             })
   672             })
   663         }
   673         }
   664         // … so we can write them contiguously, after writing everything else
   674         // … so we can write them contiguously, after writing everything else
   665         // they refer to.
   675         // they refer to.
   666         let start = self.current_offset();
   676         let start = self.current_offset();
   667         let len = u32::try_from(nodes_len)
   677         let len = child_nodes_len_from_usize(nodes_len);
   668             // Could only panic with over 4 billion nodes
       
   669             .expect("dirstate-v2 path length overflow")
       
   670             .into();
       
   671         self.out.extend(on_disk_nodes.as_bytes());
   678         self.out.extend(on_disk_nodes.as_bytes());
   672         Ok(ChildNodes { start, len })
   679         Ok(ChildNodes { start, len })
       
   680     }
       
   681 
       
   682     /// Takes a slice of items within `on_disk` and returns its offset for the
       
   683     /// start of `on_disk`.
       
   684     ///
       
   685     /// Panics if the given slice is not within `on_disk`.
       
   686     fn offset_of<T>(&self, slice: &[T]) -> Offset
       
   687     where
       
   688         T: BytesCast,
       
   689     {
       
   690         fn address_range(slice: &[u8]) -> std::ops::RangeInclusive<usize> {
       
   691             let start = slice.as_ptr() as usize;
       
   692             let end = start + slice.len();
       
   693             start..=end
       
   694         }
       
   695         let slice_addresses = address_range(slice.as_bytes());
       
   696         let on_disk_addresses = address_range(self.dirstate_map.on_disk);
       
   697         assert!(on_disk_addresses.contains(slice_addresses.start()));
       
   698         assert!(on_disk_addresses.contains(slice_addresses.end()));
       
   699         let offset = slice_addresses.start() - on_disk_addresses.start();
       
   700         offset_from_usize(offset)
   673     }
   701     }
   674 
   702 
   675     fn current_offset(&mut self) -> Offset {
   703     fn current_offset(&mut self) -> Offset {
   676         let mut offset = self.out.len();
   704         let mut offset = self.out.len();
   677         if self.append {
   705         if self.append {
   678             offset += self.dirstate_map.on_disk.len()
   706             offset += self.dirstate_map.on_disk.len()
   679         }
   707         }
   680         u32::try_from(offset)
   708         offset_from_usize(offset)
   681             // Could only panic for a dirstate file larger than 4 GiB
       
   682             .expect("dirstate-v2 offset overflow")
       
   683             .into()
       
   684     }
   709     }
   685 
   710 
   686     fn write_path(&mut self, slice: &[u8]) -> PathSlice {
   711     fn write_path(&mut self, slice: &[u8]) -> PathSlice {
   687         let start = self.current_offset();
   712         let start = self.current_offset();
   688         let len = u16::try_from(slice.len())
   713         let len = path_len_from_usize(slice.len());
   689             // Could only panic for paths over 64 KiB
       
   690             .expect("dirstate-v2 path length overflow")
       
   691             .into();
       
   692         self.out.extend(slice.as_bytes());
   714         self.out.extend(slice.as_bytes());
   693         PathSlice { start, len }
   715         PathSlice { start, len }
   694     }
   716     }
   695 }
   717 }
       
   718 
       
   719 fn offset_from_usize(x: usize) -> Offset {
       
   720     u32::try_from(x)
       
   721         // Could only panic for a dirstate file larger than 4 GiB
       
   722         .expect("dirstate-v2 offset overflow")
       
   723         .into()
       
   724 }
       
   725 
       
   726 fn child_nodes_len_from_usize(x: usize) -> Size {
       
   727     u32::try_from(x)
       
   728         // Could only panic with over 4 billion nodes
       
   729         .expect("dirstate-v2 slice length overflow")
       
   730         .into()
       
   731 }
       
   732 
       
   733 fn path_len_from_usize(x: usize) -> PathSize {
       
   734     u16::try_from(x)
       
   735         // Could only panic for paths over 64 KiB
       
   736         .expect("dirstate-v2 path length overflow")
       
   737         .into()
       
   738 }