rust/hg-core/src/revlog/index.rs
changeset 50977 1928b770e3e7
parent 49930 e98fd81bb151
child 50978 27e773aa607d
equal deleted inserted replaced
50976:9929c8a73488 50977:1928b770e3e7
       
     1 use std::fmt::Debug;
     1 use std::ops::Deref;
     2 use std::ops::Deref;
     2 
     3 
     3 use byteorder::{BigEndian, ByteOrder};
     4 use byteorder::{BigEndian, ByteOrder};
     4 
     5 
     5 use crate::errors::HgError;
     6 use crate::errors::HgError;
     6 use crate::revlog::node::Node;
     7 use crate::revlog::node::Node;
     7 use crate::revlog::{Revision, NULL_REVISION};
     8 use crate::revlog::{Revision, NULL_REVISION};
       
     9 use crate::UncheckedRevision;
     8 
    10 
     9 pub const INDEX_ENTRY_SIZE: usize = 64;
    11 pub const INDEX_ENTRY_SIZE: usize = 64;
    10 
    12 
    11 pub struct IndexHeader {
    13 pub struct IndexHeader {
    12     header_bytes: [u8; 4],
    14     header_bytes: [u8; 4],
    82     bytes: Box<dyn Deref<Target = [u8]> + Send>,
    84     bytes: Box<dyn Deref<Target = [u8]> + Send>,
    83     /// Offsets of starts of index blocks.
    85     /// Offsets of starts of index blocks.
    84     /// Only needed when the index is interleaved with data.
    86     /// Only needed when the index is interleaved with data.
    85     offsets: Option<Vec<usize>>,
    87     offsets: Option<Vec<usize>>,
    86     uses_generaldelta: bool,
    88     uses_generaldelta: bool,
       
    89 }
       
    90 
       
    91 impl Debug for Index {
       
    92     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
       
    93         f.debug_struct("Index")
       
    94             .field("offsets", &self.offsets)
       
    95             .field("uses_generaldelta", &self.uses_generaldelta)
       
    96             .finish()
       
    97     }
    87 }
    98 }
    88 
    99 
    89 impl Index {
   100 impl Index {
    90     /// Create an index from bytes.
   101     /// Create an index from bytes.
    91     /// Calculate the start of each entry when is_inline is true.
   102     /// Calculate the start of each entry when is_inline is true.
   173     /// exists.
   184     /// exists.
   174     pub fn get_entry(&self, rev: Revision) -> Option<IndexEntry> {
   185     pub fn get_entry(&self, rev: Revision) -> Option<IndexEntry> {
   175         if rev == NULL_REVISION {
   186         if rev == NULL_REVISION {
   176             return None;
   187             return None;
   177         }
   188         }
   178         if let Some(offsets) = &self.offsets {
   189         Some(if let Some(offsets) = &self.offsets {
   179             self.get_entry_inline(rev, offsets)
   190             self.get_entry_inline(rev, offsets)
   180         } else {
   191         } else {
   181             self.get_entry_separated(rev)
   192             self.get_entry_separated(rev)
   182         }
   193         })
   183     }
   194     }
   184 
   195 
   185     fn get_entry_inline(
   196     fn get_entry_inline(
   186         &self,
   197         &self,
   187         rev: Revision,
   198         rev: Revision,
   188         offsets: &[usize],
   199         offsets: &[usize],
   189     ) -> Option<IndexEntry> {
   200     ) -> IndexEntry {
   190         let start = *offsets.get(rev as usize)?;
   201         let start = offsets[rev as usize];
   191         let end = start.checked_add(INDEX_ENTRY_SIZE)?;
   202         let end = start + INDEX_ENTRY_SIZE;
   192         let bytes = &self.bytes[start..end];
   203         let bytes = &self.bytes[start..end];
   193 
   204 
   194         // See IndexEntry for an explanation of this override.
   205         // See IndexEntry for an explanation of this override.
   195         let offset_override = Some(end);
   206         let offset_override = Some(end);
   196 
   207 
   197         Some(IndexEntry {
   208         IndexEntry {
   198             bytes,
   209             bytes,
   199             offset_override,
   210             offset_override,
   200         })
   211         }
   201     }
   212     }
   202 
   213 
   203     fn get_entry_separated(&self, rev: Revision) -> Option<IndexEntry> {
   214     fn get_entry_separated(&self, rev: Revision) -> IndexEntry {
   204         let max_rev = self.bytes.len() / INDEX_ENTRY_SIZE;
       
   205         if rev as usize >= max_rev {
       
   206             return None;
       
   207         }
       
   208         let start = rev as usize * INDEX_ENTRY_SIZE;
   215         let start = rev as usize * INDEX_ENTRY_SIZE;
   209         let end = start + INDEX_ENTRY_SIZE;
   216         let end = start + INDEX_ENTRY_SIZE;
   210         let bytes = &self.bytes[start..end];
   217         let bytes = &self.bytes[start..end];
   211 
   218 
   212         // Override the offset of the first revision as its bytes are used
   219         // Override the offset of the first revision as its bytes are used
   213         // for the index's metadata (saving space because it is always 0)
   220         // for the index's metadata (saving space because it is always 0)
   214         let offset_override = if rev == 0 { Some(0) } else { None };
   221         let offset_override = if rev == 0 { Some(0) } else { None };
   215 
   222 
   216         Some(IndexEntry {
   223         IndexEntry {
   217             bytes,
   224             bytes,
   218             offset_override,
   225             offset_override,
   219         })
   226         }
   220     }
   227     }
   221 }
   228 }
   222 
   229 
   223 impl super::RevlogIndex for Index {
   230 impl super::RevlogIndex for Index {
   224     fn len(&self) -> usize {
   231     fn len(&self) -> usize {
   271     pub fn uncompressed_len(&self) -> i32 {
   278     pub fn uncompressed_len(&self) -> i32 {
   272         BigEndian::read_i32(&self.bytes[12..=15])
   279         BigEndian::read_i32(&self.bytes[12..=15])
   273     }
   280     }
   274 
   281 
   275     /// Return the revision upon which the data has been derived.
   282     /// Return the revision upon which the data has been derived.
   276     pub fn base_revision_or_base_of_delta_chain(&self) -> Revision {
   283     pub fn base_revision_or_base_of_delta_chain(&self) -> UncheckedRevision {
   277         // TODO Maybe return an Option when base_revision == rev?
   284         // TODO Maybe return an Option when base_revision == rev?
   278         //      Requires to add rev to IndexEntry
   285         //      Requires to add rev to IndexEntry
   279 
   286 
   280         BigEndian::read_i32(&self.bytes[16..])
   287         BigEndian::read_i32(&self.bytes[16..]).into()
   281     }
   288     }
   282 
   289 
   283     pub fn link_revision(&self) -> Revision {
   290     pub fn link_revision(&self) -> UncheckedRevision {
   284         BigEndian::read_i32(&self.bytes[20..])
   291         BigEndian::read_i32(&self.bytes[20..]).into()
   285     }
   292     }
   286 
   293 
   287     pub fn p1(&self) -> Revision {
   294     pub fn p1(&self) -> UncheckedRevision {
   288         BigEndian::read_i32(&self.bytes[24..])
   295         BigEndian::read_i32(&self.bytes[24..]).into()
   289     }
   296     }
   290 
   297 
   291     pub fn p2(&self) -> Revision {
   298     pub fn p2(&self) -> UncheckedRevision {
   292         BigEndian::read_i32(&self.bytes[28..])
   299         BigEndian::read_i32(&self.bytes[28..]).into()
   293     }
   300     }
   294 
   301 
   295     /// Return the hash of revision's full text.
   302     /// Return the hash of revision's full text.
   296     ///
   303     ///
   297     /// Currently, SHA-1 is used and only the first 20 bytes of this field
   304     /// Currently, SHA-1 is used and only the first 20 bytes of this field
   545         let entry = IndexEntry {
   552         let entry = IndexEntry {
   546             bytes: &bytes,
   553             bytes: &bytes,
   547             offset_override: None,
   554             offset_override: None,
   548         };
   555         };
   549 
   556 
   550         assert_eq!(entry.base_revision_or_base_of_delta_chain(), 1)
   557         assert_eq!(entry.base_revision_or_base_of_delta_chain(), 1.into())
   551     }
   558     }
   552 
   559 
   553     #[test]
   560     #[test]
   554     fn link_revision_test() {
   561     fn link_revision_test() {
   555         let bytes = IndexEntryBuilder::new().with_link_revision(123).build();
   562         let bytes = IndexEntryBuilder::new().with_link_revision(123).build();
   557         let entry = IndexEntry {
   564         let entry = IndexEntry {
   558             bytes: &bytes,
   565             bytes: &bytes,
   559             offset_override: None,
   566             offset_override: None,
   560         };
   567         };
   561 
   568 
   562         assert_eq!(entry.link_revision(), 123);
   569         assert_eq!(entry.link_revision(), 123.into());
   563     }
   570     }
   564 
   571 
   565     #[test]
   572     #[test]
   566     fn p1_test() {
   573     fn p1_test() {
   567         let bytes = IndexEntryBuilder::new().with_p1(123).build();
   574         let bytes = IndexEntryBuilder::new().with_p1(123).build();
   569         let entry = IndexEntry {
   576         let entry = IndexEntry {
   570             bytes: &bytes,
   577             bytes: &bytes,
   571             offset_override: None,
   578             offset_override: None,
   572         };
   579         };
   573 
   580 
   574         assert_eq!(entry.p1(), 123);
   581         assert_eq!(entry.p1(), 123.into());
   575     }
   582     }
   576 
   583 
   577     #[test]
   584     #[test]
   578     fn p2_test() {
   585     fn p2_test() {
   579         let bytes = IndexEntryBuilder::new().with_p2(123).build();
   586         let bytes = IndexEntryBuilder::new().with_p2(123).build();
   581         let entry = IndexEntry {
   588         let entry = IndexEntry {
   582             bytes: &bytes,
   589             bytes: &bytes,
   583             offset_override: None,
   590             offset_override: None,
   584         };
   591         };
   585 
   592 
   586         assert_eq!(entry.p2(), 123);
   593         assert_eq!(entry.p2(), 123.into());
   587     }
   594     }
   588 
   595 
   589     #[test]
   596     #[test]
   590     fn node_test() {
   597     fn node_test() {
   591         let node = Node::from_hex("0123456789012345678901234567890123456789")
   598         let node = Node::from_hex("0123456789012345678901234567890123456789")