rust/hg-core/src/dirstate/parsers.rs
changeset 50536 475c170bb815
parent 49913 c15b415d1bff
equal deleted inserted replaced
50535:a8531bd9210b 50536:475c170bb815
    59         &'a HgPath,
    59         &'a HgPath,
    60         &DirstateEntry,
    60         &DirstateEntry,
    61         Option<&'a HgPath>,
    61         Option<&'a HgPath>,
    62     ) -> Result<(), HgError>,
    62     ) -> Result<(), HgError>,
    63 ) -> Result<&'a DirstateParents, HgError> {
    63 ) -> Result<&'a DirstateParents, HgError> {
    64     let (parents, rest) = DirstateParents::from_bytes(contents)
    64     let mut entry_idx = 0;
    65         .map_err(|_| HgError::corrupted("Too little data for dirstate."))?;
    65     let original_len = contents.len();
       
    66     let (parents, rest) =
       
    67         DirstateParents::from_bytes(contents).map_err(|_| {
       
    68             HgError::corrupted(format!(
       
    69                 "Too little data for dirstate: {} bytes.",
       
    70                 original_len
       
    71             ))
       
    72         })?;
    66     contents = rest;
    73     contents = rest;
    67     while !contents.is_empty() {
    74     while !contents.is_empty() {
    68         let (raw_entry, rest) = RawEntry::from_bytes(contents)
    75         let (raw_entry, rest) = RawEntry::from_bytes(contents)
    69             .map_err(|_| HgError::corrupted("Overflow in dirstate."))?;
    76             .map_err(|_| HgError::corrupted(format!(
       
    77             "dirstate corrupted: ran out of bytes at entry header {}, offset {}.",
       
    78             entry_idx, original_len-contents.len())))?;
    70 
    79 
    71         let entry = DirstateEntry::from_v1_data(
    80         let entry = DirstateEntry::from_v1_data(
    72             EntryState::try_from(raw_entry.state)?,
    81             EntryState::try_from(raw_entry.state)?,
    73             raw_entry.mode.get(),
    82             raw_entry.mode.get(),
    74             raw_entry.size.get(),
    83             raw_entry.size.get(),
    75             raw_entry.mtime.get(),
    84             raw_entry.mtime.get(),
    76         );
    85         );
       
    86         let filename_len = raw_entry.length.get() as usize;
    77         let (paths, rest) =
    87         let (paths, rest) =
    78             u8::slice_from_bytes(rest, raw_entry.length.get() as usize)
    88             u8::slice_from_bytes(rest, filename_len)
    79                 .map_err(|_| HgError::corrupted("Overflow in dirstate."))?;
    89                 .map_err(|_|
       
    90                 HgError::corrupted(format!(
       
    91          "dirstate corrupted: ran out of bytes at entry {}, offset {} (expected {} bytes).",
       
    92               entry_idx, original_len-contents.len(), filename_len))
       
    93                 )?;
    80 
    94 
    81         // `paths` is either a single path, or two paths separated by a NULL
    95         // `paths` is either a single path, or two paths separated by a NULL
    82         // byte
    96         // byte
    83         let mut iter = paths.splitn(2, |&byte| byte == b'\0');
    97         let mut iter = paths.splitn(2, |&byte| byte == b'\0');
    84         let path = HgPath::new(
    98         let path = HgPath::new(
    85             iter.next().expect("splitn always yields at least one item"),
    99             iter.next().expect("splitn always yields at least one item"),
    86         );
   100         );
    87         let copy_source = iter.next().map(HgPath::new);
   101         let copy_source = iter.next().map(HgPath::new);
    88         each_entry(path, &entry, copy_source)?;
   102         each_entry(path, &entry, copy_source)?;
    89 
   103 
       
   104         entry_idx += 1;
    90         contents = rest;
   105         contents = rest;
    91     }
   106     }
    92     Ok(parents)
   107     Ok(parents)
    93 }
   108 }
    94 
   109