Patchwork D12548: changelog: avoid copying changeset data into `ChangesetRevisionData`

login
register
mail settings
Submitter phabricator
Date April 13, 2022, 1:11 p.m.
Message ID <differential-rev-PHID-DREV-amkinoz3gp6ivqep6v45-req@mercurial-scm.org>
Download mbox | patch
Permalink /patch/50896/
State New
Headers show

Comments

phabricator - April 13, 2022, 1:11 p.m.
martinvonz created this revision.
Herald added a reviewer: hg-reviewers.
Herald added a subscriber: mercurial-patches.

REPOSITORY
  rHG Mercurial

BRANCH
  default

REVISION DETAIL
  https://phab.mercurial-scm.org/D12548

AFFECTED FILES
  rust/hg-core/src/revlog/changelog.rs

CHANGE DETAILS




To: martinvonz, #hg-reviewers
Cc: mercurial-patches, mercurial-devel

Patch

diff --git a/rust/hg-core/src/revlog/changelog.rs b/rust/hg-core/src/revlog/changelog.rs
--- a/rust/hg-core/src/revlog/changelog.rs
+++ b/rust/hg-core/src/revlog/changelog.rs
@@ -7,6 +7,7 @@ 
 use crate::utils::hg_path::HgPath;
 use itertools::Itertools;
 use std::ascii::escape_default;
+use std::borrow::Cow;
 use std::fmt::{Debug, Formatter};
 
 /// A specialized `Revlog` to work with `changelog` data format.
@@ -52,7 +53,7 @@ 
         &self,
         rev: Revision,
     ) -> Result<ChangelogRevisionData, RevlogError> {
-        let bytes = self.revlog.get_rev_data(rev)?.into_owned();
+        let bytes = self.revlog.get_rev_data(rev)?;
         if bytes.is_empty() {
             Ok(ChangelogRevisionData::null())
         } else {
@@ -79,9 +80,9 @@ 
 
 /// `Changelog` entry which knows how to interpret the `changelog` data bytes.
 #[derive(PartialEq)]
-pub struct ChangelogRevisionData {
+pub struct ChangelogRevisionData<'changelog> {
     /// The data bytes of the `changelog` entry.
-    bytes: Vec<u8>,
+    bytes: Cow<'changelog, [u8]>,
     /// The end offset for the hex manifest (not including the newline)
     manifest_end: usize,
     /// The end offset for the user+email (not including the newline)
@@ -93,8 +94,8 @@ 
     files_end: usize,
 }
 
-impl ChangelogRevisionData {
-    fn new(bytes: Vec<u8>) -> Result<Self, HgError> {
+impl<'changelog> ChangelogRevisionData<'changelog> {
+    fn new(bytes: Cow<'changelog, [u8]>) -> Result<Self, HgError> {
         let mut line_iter = bytes.split(|b| b == &b'\n');
         let manifest_end = line_iter
             .next()
@@ -137,9 +138,9 @@ 
     }
 
     fn null() -> Self {
-        Self::new(
-            b"0000000000000000000000000000000000000000\n\n0 0\n\n".to_vec(),
-        )
+        Self::new(Cow::Borrowed(
+            b"0000000000000000000000000000000000000000\n\n0 0\n\n",
+        ))
         .unwrap()
     }
 
@@ -181,7 +182,7 @@ 
     }
 }
 
-impl Debug for ChangelogRevisionData {
+impl Debug for ChangelogRevisionData<'_> {
     fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
         f.debug_struct("ChangelogRevisionData")
             .field("bytes", &debug_bytes(&self.bytes))
@@ -228,28 +229,30 @@ 
     #[test]
     fn test_create_changelogrevisiondata_invalid() {
         // Completely empty
-        assert!(ChangelogRevisionData::new(b"abcd".to_vec()).is_err());
+        assert!(ChangelogRevisionData::new(Cow::Borrowed(b"abcd")).is_err());
         // No newline after manifest
-        assert!(ChangelogRevisionData::new(b"abcd".to_vec()).is_err());
+        assert!(ChangelogRevisionData::new(Cow::Borrowed(b"abcd")).is_err());
         // No newline after user
-        assert!(ChangelogRevisionData::new(b"abcd\n".to_vec()).is_err());
+        assert!(ChangelogRevisionData::new(Cow::Borrowed(b"abcd\n")).is_err());
         // No newline after timestamp
-        assert!(ChangelogRevisionData::new(b"abcd\n\n0 0".to_vec()).is_err());
+        assert!(
+            ChangelogRevisionData::new(Cow::Borrowed(b"abcd\n\n0 0")).is_err()
+        );
         // Missing newline after files
-        assert!(ChangelogRevisionData::new(
-            b"abcd\n\n0 0\nfile1\nfile2".to_vec()
-        )
+        assert!(ChangelogRevisionData::new(Cow::Borrowed(
+            b"abcd\n\n0 0\nfile1\nfile2"
+        ))
         .is_err(),);
         // Only one newline after files
-        assert!(ChangelogRevisionData::new(
-            b"abcd\n\n0 0\nfile1\nfile2\n".to_vec()
-        )
+        assert!(ChangelogRevisionData::new(Cow::Borrowed(
+            b"abcd\n\n0 0\nfile1\nfile2\n"
+        ))
         .is_err(),);
     }
 
     #[test]
     fn test_create_changelogrevisiondata() {
-        let data = ChangelogRevisionData::new(
+        let data = ChangelogRevisionData::new(Cow::Borrowed(
             b"0123456789abcdef0123456789abcdef01234567
 Some One <someone@example.com>
 0 0
@@ -258,9 +261,8 @@ 
 
 some
 commit
-message"
-                .to_vec(),
-        )
+message",
+        ))
         .unwrap();
         assert_eq!(
             data.manifest_node().unwrap(),