rust/hg-core/src/revlog/filelog.rs
changeset 48237 027ebad952ac
parent 47969 87e3f878e65f
child 48249 e9faae0f445c
equal deleted inserted replaced
48236:f8dc78716ad2 48237:027ebad952ac
     5 use crate::revlog::NodePrefix;
     5 use crate::revlog::NodePrefix;
     6 use crate::revlog::Revision;
     6 use crate::revlog::Revision;
     7 use crate::utils::files::get_path_from_bytes;
     7 use crate::utils::files::get_path_from_bytes;
     8 use crate::utils::hg_path::HgPath;
     8 use crate::utils::hg_path::HgPath;
     9 use crate::utils::SliceExt;
     9 use crate::utils::SliceExt;
    10 use std::borrow::Cow;
       
    11 use std::path::PathBuf;
    10 use std::path::PathBuf;
    12 
    11 
    13 /// A specialized `Revlog` to work with file data logs.
    12 /// A specialized `Revlog` to work with file data logs.
    14 pub struct Filelog {
    13 pub struct Filelog {
    15     /// The generic `revlog` format.
    14     /// The generic `revlog` format.
    38     /// changeset.
    37     /// changeset.
    39     pub fn data_for_rev(
    38     pub fn data_for_rev(
    40         &self,
    39         &self,
    41         file_rev: Revision,
    40         file_rev: Revision,
    42     ) -> Result<FilelogEntry, RevlogError> {
    41     ) -> Result<FilelogEntry, RevlogError> {
    43         let data = self.revlog.get_rev_data(file_rev)?;
    42         let data: Vec<u8> = self.revlog.get_rev_data(file_rev)?;
    44         Ok(FilelogEntry(data.into()))
    43         Ok(FilelogEntry(data.into()))
    45     }
    44     }
    46 }
    45 }
    47 
    46 
    48 fn store_path(hg_path: &HgPath, suffix: &[u8]) -> PathBuf {
    47 fn store_path(hg_path: &HgPath, suffix: &[u8]) -> PathBuf {
    49     let encoded_bytes =
    48     let encoded_bytes =
    50         path_encode(&[b"data/", hg_path.as_bytes(), suffix].concat());
    49         path_encode(&[b"data/", hg_path.as_bytes(), suffix].concat());
    51     get_path_from_bytes(&encoded_bytes).into()
    50     get_path_from_bytes(&encoded_bytes).into()
    52 }
    51 }
    53 
    52 
    54 pub struct FilelogEntry<'filelog>(Cow<'filelog, [u8]>);
    53 pub struct FilelogEntry(Vec<u8>);
    55 
    54 
    56 impl<'filelog> FilelogEntry<'filelog> {
    55 impl FilelogEntry {
    57     /// Split into metadata and data
    56     /// Split into metadata and data
    58     pub fn split(&self) -> Result<(Option<&[u8]>, &[u8]), HgError> {
    57     /// Returns None if there is no metadata, so the entire entry is data.
       
    58     fn split_metadata(&self) -> Result<Option<(&[u8], &[u8])>, HgError> {
    59         const DELIMITER: &[u8; 2] = &[b'\x01', b'\n'];
    59         const DELIMITER: &[u8; 2] = &[b'\x01', b'\n'];
    60 
    60 
    61         if let Some(rest) = self.0.drop_prefix(DELIMITER) {
    61         if let Some(rest) = self.0.drop_prefix(DELIMITER) {
    62             if let Some((metadata, data)) = rest.split_2_by_slice(DELIMITER) {
    62             if let Some((metadata, data)) = rest.split_2_by_slice(DELIMITER) {
    63                 Ok((Some(metadata), data))
    63                 Ok(Some((metadata, data)))
    64             } else {
    64             } else {
    65                 Err(HgError::corrupted(
    65                 Err(HgError::corrupted(
    66                     "Missing metadata end delimiter in filelog entry",
    66                     "Missing metadata end delimiter in filelog entry",
    67                 ))
    67                 ))
    68             }
    68             }
       
    69         } else {
       
    70             Ok(None)
       
    71         }
       
    72     }
       
    73 
       
    74     /// Split into metadata and data
       
    75     pub fn split(&self) -> Result<(Option<&[u8]>, &[u8]), HgError> {
       
    76         if let Some((metadata, data)) = self.split_metadata()? {
       
    77             Ok((Some(metadata), data))
    69         } else {
    78         } else {
    70             Ok((None, &self.0))
    79             Ok((None, &self.0))
    71         }
    80         }
    72     }
    81     }
    73 
    82 
    74     /// Returns the file contents at this revision, stripped of any metadata
    83     /// Returns the file contents at this revision, stripped of any metadata
    75     pub fn data(&self) -> Result<&[u8], HgError> {
    84     pub fn data(&self) -> Result<&[u8], HgError> {
    76         let (_metadata, data) = self.split()?;
    85         let (_metadata, data) = self.split()?;
    77         Ok(data)
    86         Ok(data)
    78     }
    87     }
       
    88 
       
    89     /// Consume the entry, and convert it into data, discarding any metadata,
       
    90     /// if present.
       
    91     pub fn into_data(self) -> Result<Vec<u8>, HgError> {
       
    92         if let Some((_metadata, data)) = self.split_metadata()? {
       
    93             Ok(data.to_owned())
       
    94         } else {
       
    95             Ok(self.0)
       
    96         }
       
    97     }
    79 }
    98 }