Struct git_pack::data::input::Entry

source ·
pub struct Entry {
    pub header: Header,
    pub header_size: u16,
    pub pack_offset: u64,
    pub compressed: Option<Vec<u8>>,
    pub compressed_size: u64,
    pub crc32: Option<u32>,
    pub decompressed_size: u64,
    pub trailer: Option<ObjectId>,
}
Expand description

An item of the iteration produced by BytesToEntriesIter

Fields§

§header: Header

The header of a pack entry

§header_size: u16

The amount of bytes used to encode the header. pack_offset + header_size is the beginning of the compressed data in the pack.

§pack_offset: u64

The first byte of the entry at which the header can be read.

§compressed: Option<Vec<u8>>

The bytes consumed while producing decompressed These do not contain the header, which makes it possible to easily replace a RefDelta with offset deltas when resolving thin packs. Depends on CompressionMode when the iterator is initialized.

§compressed_size: u64

The amount of bytes the compressed portion of the entry takes, i.e. the portion behind behind the header.

§crc32: Option<u32>

The CRC32 over the complete entry, that is encoded header and compressed object data. Depends on CompressionMode when the iterator is initialized

§decompressed_size: u64

The amount of decompressed bytes of the entry.

§trailer: Option<ObjectId>

Set for the last object in the iteration, providing the hash over all bytes of the iteration for use as trailer in a pack or to verify it matches the trailer.

Implementations§

source§

impl Entry

Create a new input entry from a given data obj set to be placed at the given pack_offset.

This method is useful when arbitrary base entries are created

Examples found in repository?
src/data/input/lookup_ref_delta_objects.rs (line 106)
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
    fn next(&mut self) -> Option<Self::Item> {
        if self.error {
            return None;
        }
        if let Some(delta) = self.next_delta.take() {
            return Some(Ok(delta));
        }
        match self.inner.next() {
            Some(Ok(mut entry)) => match entry.header {
                Header::RefDelta { base_id } => {
                    match self.inserted_entry_length_at_offset.iter().rfind(|e| e.oid == base_id) {
                        None => {
                            let base_entry = match (self.lookup)(base_id, &mut self.buf) {
                                Some(obj) => {
                                    let current_pack_offset = entry.pack_offset;
                                    let mut entry = match input::Entry::from_data_obj(&obj, 0) {
                                        Ok(e) => e,
                                        Err(err) => return Some(Err(err)),
                                    };
                                    entry.pack_offset = self.shifted_pack_offset(current_pack_offset);
                                    self.track_change(
                                        entry.pack_offset,
                                        current_pack_offset,
                                        entry.bytes_in_pack() as i64,
                                        base_id,
                                    );
                                    entry
                                }
                                None => {
                                    self.error = true;
                                    return Some(Err(input::Error::NotFound { object_id: base_id }));
                                }
                            };

                            {
                                self.shift_entry_and_point_to_base_by_offset(&mut entry, base_entry.bytes_in_pack());
                                self.next_delta = Some(entry);
                            }
                            Some(Ok(base_entry))
                        }
                        Some(base_entry) => {
                            let base_distance =
                                self.shifted_pack_offset(entry.pack_offset) - base_entry.shifted_pack_offset;
                            self.shift_entry_and_point_to_base_by_offset(&mut entry, base_distance);
                            Some(Ok(entry))
                        }
                    }
                }
                _ => {
                    if self.inserted_entries_length_in_bytes != 0 {
                        if let Header::OfsDelta { base_distance } = entry.header {
                            // We have to find the new distance based on the previous distance to the base, using the absolute
                            // pack offset computed from it as stored in `base_pack_offset`.
                            let base_pack_offset = entry
                                .pack_offset
                                .checked_sub(base_distance)
                                .expect("distance to be in range of pack");
                            match self
                                .inserted_entry_length_at_offset
                                .binary_search_by_key(&base_pack_offset, |c| c.pack_offset)
                            {
                                Ok(index) => {
                                    let index = {
                                        let maybe_index_of_actual_entry = index + 1;
                                        self.inserted_entry_length_at_offset
                                            .get(maybe_index_of_actual_entry)
                                            .and_then(|c| {
                                                (c.pack_offset == base_pack_offset).then(|| maybe_index_of_actual_entry)
                                            })
                                            .unwrap_or(index)
                                    };
                                    let new_distance = self
                                        .shifted_pack_offset(entry.pack_offset)
                                        .checked_sub(self.inserted_entry_length_at_offset[index].shifted_pack_offset)
                                        .expect("a base that is behind us in the pack");
                                    self.shift_entry_and_point_to_base_by_offset(&mut entry, new_distance);
                                }
                                Err(index) => {
                                    let change_since_offset = self.inserted_entry_length_at_offset[index..]
                                        .iter()
                                        .map(|c| c.size_change_in_bytes)
                                        .sum::<i64>();
                                    let new_distance: u64 = {
                                        (base_distance as i64 + change_since_offset)
                                            .try_into()
                                            .expect("it still points behind us")
                                    };
                                    self.shift_entry_and_point_to_base_by_offset(&mut entry, new_distance);
                                }
                            }
                        } else {
                            // Offset this entry by all changes (positive or negative) that we saw thus far.
                            entry.pack_offset = self.shifted_pack_offset(entry.pack_offset);
                        }
                    }
                    Some(Ok(entry))
                }
            },
            other => other,
        }
    }

The amount of bytes this entry may consume in a pack data file

Examples found in repository?
src/data/input/lookup_ref_delta_objects.rs (line 114)
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
    fn next(&mut self) -> Option<Self::Item> {
        if self.error {
            return None;
        }
        if let Some(delta) = self.next_delta.take() {
            return Some(Ok(delta));
        }
        match self.inner.next() {
            Some(Ok(mut entry)) => match entry.header {
                Header::RefDelta { base_id } => {
                    match self.inserted_entry_length_at_offset.iter().rfind(|e| e.oid == base_id) {
                        None => {
                            let base_entry = match (self.lookup)(base_id, &mut self.buf) {
                                Some(obj) => {
                                    let current_pack_offset = entry.pack_offset;
                                    let mut entry = match input::Entry::from_data_obj(&obj, 0) {
                                        Ok(e) => e,
                                        Err(err) => return Some(Err(err)),
                                    };
                                    entry.pack_offset = self.shifted_pack_offset(current_pack_offset);
                                    self.track_change(
                                        entry.pack_offset,
                                        current_pack_offset,
                                        entry.bytes_in_pack() as i64,
                                        base_id,
                                    );
                                    entry
                                }
                                None => {
                                    self.error = true;
                                    return Some(Err(input::Error::NotFound { object_id: base_id }));
                                }
                            };

                            {
                                self.shift_entry_and_point_to_base_by_offset(&mut entry, base_entry.bytes_in_pack());
                                self.next_delta = Some(entry);
                            }
                            Some(Ok(base_entry))
                        }
                        Some(base_entry) => {
                            let base_distance =
                                self.shifted_pack_offset(entry.pack_offset) - base_entry.shifted_pack_offset;
                            self.shift_entry_and_point_to_base_by_offset(&mut entry, base_distance);
                            Some(Ok(entry))
                        }
                    }
                }
                _ => {
                    if self.inserted_entries_length_in_bytes != 0 {
                        if let Header::OfsDelta { base_distance } = entry.header {
                            // We have to find the new distance based on the previous distance to the base, using the absolute
                            // pack offset computed from it as stored in `base_pack_offset`.
                            let base_pack_offset = entry
                                .pack_offset
                                .checked_sub(base_distance)
                                .expect("distance to be in range of pack");
                            match self
                                .inserted_entry_length_at_offset
                                .binary_search_by_key(&base_pack_offset, |c| c.pack_offset)
                            {
                                Ok(index) => {
                                    let index = {
                                        let maybe_index_of_actual_entry = index + 1;
                                        self.inserted_entry_length_at_offset
                                            .get(maybe_index_of_actual_entry)
                                            .and_then(|c| {
                                                (c.pack_offset == base_pack_offset).then(|| maybe_index_of_actual_entry)
                                            })
                                            .unwrap_or(index)
                                    };
                                    let new_distance = self
                                        .shifted_pack_offset(entry.pack_offset)
                                        .checked_sub(self.inserted_entry_length_at_offset[index].shifted_pack_offset)
                                        .expect("a base that is behind us in the pack");
                                    self.shift_entry_and_point_to_base_by_offset(&mut entry, new_distance);
                                }
                                Err(index) => {
                                    let change_since_offset = self.inserted_entry_length_at_offset[index..]
                                        .iter()
                                        .map(|c| c.size_change_in_bytes)
                                        .sum::<i64>();
                                    let new_distance: u64 = {
                                        (base_distance as i64 + change_since_offset)
                                            .try_into()
                                            .expect("it still points behind us")
                                    };
                                    self.shift_entry_and_point_to_base_by_offset(&mut entry, new_distance);
                                }
                            }
                        } else {
                            // Offset this entry by all changes (positive or negative) that we saw thus far.
                            entry.pack_offset = self.shifted_pack_offset(entry.pack_offset);
                        }
                    }
                    Some(Ok(entry))
                }
            },
            other => other,
        }
    }

Update our CRC value by recalculating it from our header and compressed data.

Examples found in repository?
src/data/input/lookup_ref_delta_objects.rs (line 79)
71
72
73
74
75
76
77
78
79
80
81
    fn shift_entry_and_point_to_base_by_offset(&mut self, entry: &mut input::Entry, base_distance: u64) {
        let pack_offset = entry.pack_offset;
        entry.pack_offset = self.shifted_pack_offset(pack_offset);
        entry.header = Header::OfsDelta { base_distance };
        let previous_header_size = entry.header_size;
        entry.header_size = entry.header.size(entry.decompressed_size) as u16;

        let change = entry.header_size as i64 - previous_header_size as i64;
        entry.crc32 = Some(entry.compute_crc32());
        self.track_change(entry.pack_offset, pack_offset, change, None);
    }
More examples
Hide additional examples
src/data/input/entry.rs (line 23)
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
    pub fn from_data_obj(obj: &git_object::Data<'_>, pack_offset: u64) -> Result<Self, input::Error> {
        let header = to_header(obj.kind);
        let compressed = compress_data(obj)?;
        let compressed_size = compressed.len() as u64;
        let mut entry = input::Entry {
            header,
            header_size: header.size(obj.data.len() as u64) as u16,
            pack_offset,
            compressed: Some(compressed),
            compressed_size,
            crc32: None,
            decompressed_size: obj.data.len() as u64,
            trailer: None,
        };
        entry.crc32 = Some(entry.compute_crc32());
        Ok(entry)
    }

Trait Implementations§

source§

impl Clone for Entry

Returns a copy of the value. Read more
Performs copy-assignment from source. Read more
source§

impl Debug for Entry

Formats the value using the given formatter. Read more
source§

impl<'de> Deserialize<'de> for Entry

Deserialize this value from the given Serde deserializer. Read more
source§

impl Hash for Entry

Feeds this value into the given Hasher. Read more
Feeds a slice of this type into the given Hasher. Read more
source§

impl Ord for Entry

This method returns an Ordering between self and other. Read more
Compares and returns the maximum of two values. Read more
Compares and returns the minimum of two values. Read more
Restrict a value to a certain interval. Read more
source§

impl PartialEq<Entry> for Entry

This method tests for self and other values to be equal, and is used by ==.
This method tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
source§

impl PartialOrd<Entry> for Entry

This method returns an ordering between self and other values if one exists. Read more
This method tests less than (for self and other) and is used by the < operator. Read more
This method tests less than or equal to (for self and other) and is used by the <= operator. Read more
This method tests greater than (for self and other) and is used by the > operator. Read more
This method tests greater than or equal to (for self and other) and is used by the >= operator. Read more
source§

impl Serialize for Entry

Serialize this value into the given Serde serializer. Read more
source§

impl Eq for Entry

source§

impl StructuralEq for Entry

source§

impl StructuralPartialEq for Entry

Auto Trait Implementations§

§

impl RefUnwindSafe for Entry

§

impl Send for Entry

§

impl Sync for Entry

§

impl Unpin for Entry

§

impl UnwindSafe for Entry

Blanket Implementations§

source§

impl<T> Any for Twhere
    T: 'static + ?Sized,

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for Twhere
    T: ?Sized,

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for Twhere
    T: ?Sized,

Mutably borrows from an owned value. Read more
§

impl<Q, K> Equivalent<K> for Qwhere
    Q: Eq + ?Sized,
    K: Borrow<Q> + ?Sized,

Checks if this value is equivalent to the given key. Read more
source§

impl<T> From<T> for T

Returns the argument unchanged.

source§

impl<T, U> Into<U> for Twhere
    U: From<T>,

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

source§

impl<T> ToOwned for Twhere
    T: Clone,

The resulting type after obtaining ownership.
Creates owned data from borrowed data, usually by cloning. Read more
Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T, U> TryFrom<U> for Twhere
    U: Into<T>,

The type returned in the event of a conversion error.
Performs the conversion.
source§

impl<T, U> TryInto<U> for Twhere
    U: TryFrom<T>,

The type returned in the event of a conversion error.
Performs the conversion.
source§

impl<T> DeserializeOwned for Twhere
    T: for<'de> Deserialize<'de>,