Show More
@@ -2,13 +2,17 b' use std::fmt::Debug;' | |||
|
2 | 2 | use std::ops::Deref; |
|
3 | 3 | |
|
4 | 4 | use byteorder::{BigEndian, ByteOrder}; |
|
5 | use bytes_cast::{unaligned, BytesCast}; | |
|
5 | 6 | |
|
7 | use super::REVIDX_KNOWN_FLAGS; | |
|
6 | 8 | use crate::errors::HgError; |
|
9 | use crate::node::{NODE_BYTES_LENGTH, STORED_NODE_ID_BYTES}; | |
|
7 | 10 | use crate::revlog::node::Node; |
|
8 | 11 | use crate::revlog::{Revision, NULL_REVISION}; |
|
9 | use crate::{Graph, GraphError, RevlogIndex, UncheckedRevision}; | |
|
12 | use crate::{Graph, GraphError, RevlogError, RevlogIndex, UncheckedRevision}; | |
|
10 | 13 | |
|
11 | 14 | pub const INDEX_ENTRY_SIZE: usize = 64; |
|
15 | pub const COMPRESSION_MODE_INLINE: u8 = 2; | |
|
12 | 16 | |
|
13 | 17 | pub struct IndexHeader { |
|
14 | 18 | header_bytes: [u8; 4], |
@@ -120,6 +124,81 b' impl std::ops::Index<std::ops::Range<usi' | |||
|
120 | 124 | } |
|
121 | 125 | } |
|
122 | 126 | |
|
127 | pub struct RevisionDataParams { | |
|
128 | flags: u16, | |
|
129 | data_offset: u64, | |
|
130 | data_compressed_length: i32, | |
|
131 | data_uncompressed_length: i32, | |
|
132 | data_delta_base: i32, | |
|
133 | link_rev: i32, | |
|
134 | parent_rev_1: i32, | |
|
135 | parent_rev_2: i32, | |
|
136 | node_id: [u8; NODE_BYTES_LENGTH], | |
|
137 | _sidedata_offset: u64, | |
|
138 | _sidedata_compressed_length: i32, | |
|
139 | data_compression_mode: u8, | |
|
140 | _sidedata_compression_mode: u8, | |
|
141 | _rank: i32, | |
|
142 | } | |
|
143 | ||
|
144 | #[derive(BytesCast)] | |
|
145 | #[repr(C)] | |
|
146 | pub struct RevisionDataV1 { | |
|
147 | data_offset_or_flags: unaligned::U64Be, | |
|
148 | data_compressed_length: unaligned::I32Be, | |
|
149 | data_uncompressed_length: unaligned::I32Be, | |
|
150 | data_delta_base: unaligned::I32Be, | |
|
151 | link_rev: unaligned::I32Be, | |
|
152 | parent_rev_1: unaligned::I32Be, | |
|
153 | parent_rev_2: unaligned::I32Be, | |
|
154 | node_id: [u8; STORED_NODE_ID_BYTES], | |
|
155 | } | |
|
156 | ||
|
157 | fn _static_assert_size_of_revision_data_v1() { | |
|
158 | let _ = std::mem::transmute::<RevisionDataV1, [u8; 64]>; | |
|
159 | } | |
|
160 | ||
|
161 | impl RevisionDataParams { | |
|
162 | pub fn validate(&self) -> Result<(), RevlogError> { | |
|
163 | if self.flags & !REVIDX_KNOWN_FLAGS != 0 { | |
|
164 | return Err(RevlogError::corrupted(format!( | |
|
165 | "unknown revlog index flags: {}", | |
|
166 | self.flags | |
|
167 | ))); | |
|
168 | } | |
|
169 | if self.data_compression_mode != COMPRESSION_MODE_INLINE { | |
|
170 | return Err(RevlogError::corrupted(format!( | |
|
171 | "invalid data compression mode: {}", | |
|
172 | self.data_compression_mode | |
|
173 | ))); | |
|
174 | } | |
|
175 | // FIXME isn't this only for v2 or changelog v2? | |
|
176 | if self._sidedata_compression_mode != COMPRESSION_MODE_INLINE { | |
|
177 | return Err(RevlogError::corrupted(format!( | |
|
178 | "invalid sidedata compression mode: {}", | |
|
179 | self._sidedata_compression_mode | |
|
180 | ))); | |
|
181 | } | |
|
182 | Ok(()) | |
|
183 | } | |
|
184 | ||
|
185 | pub fn into_v1(self) -> RevisionDataV1 { | |
|
186 | let data_offset_or_flags = self.data_offset << 16 | self.flags as u64; | |
|
187 | let mut node_id = [0; STORED_NODE_ID_BYTES]; | |
|
188 | node_id[..NODE_BYTES_LENGTH].copy_from_slice(&self.node_id); | |
|
189 | RevisionDataV1 { | |
|
190 | data_offset_or_flags: data_offset_or_flags.into(), | |
|
191 | data_compressed_length: self.data_compressed_length.into(), | |
|
192 | data_uncompressed_length: self.data_uncompressed_length.into(), | |
|
193 | data_delta_base: self.data_delta_base.into(), | |
|
194 | link_rev: self.link_rev.into(), | |
|
195 | parent_rev_1: self.parent_rev_1.into(), | |
|
196 | parent_rev_2: self.parent_rev_2.into(), | |
|
197 | node_id, | |
|
198 | } | |
|
199 | } | |
|
200 | } | |
|
201 | ||
|
123 | 202 | /// A Revlog index |
|
124 | 203 | pub struct Index { |
|
125 | 204 | bytes: IndexData, |
@@ -283,6 +362,20 b' impl Index {' | |||
|
283 | 362 | offset_override, |
|
284 | 363 | } |
|
285 | 364 | } |
|
365 | ||
|
366 | /// TODO move this to the trait probably, along with other things | |
|
367 | pub fn append( | |
|
368 | &mut self, | |
|
369 | revision_data: RevisionDataParams, | |
|
370 | ) -> Result<(), RevlogError> { | |
|
371 | revision_data.validate()?; | |
|
372 | let new_offset = self.bytes.len(); | |
|
373 | if let Some(offsets) = self.offsets.as_mut() { | |
|
374 | offsets.push(new_offset) | |
|
375 | } | |
|
376 | self.bytes.added.extend(revision_data.into_v1().as_bytes()); | |
|
377 | Ok(()) | |
|
378 | } | |
|
286 | 379 | } |
|
287 | 380 | |
|
288 | 381 | impl super::RevlogIndex for Index { |
@@ -20,6 +20,10 b' use std::fmt;' | |||
|
20 | 20 | /// the future. |
|
21 | 21 | pub const NODE_BYTES_LENGTH: usize = 20; |
|
22 | 22 | |
|
23 | /// The length in bytes set aside on disk for a `Node`. Revlog up to v1 only | |
|
24 | /// use 20 out of those 32. | |
|
25 | pub const STORED_NODE_ID_BYTES: usize = 32; | |
|
26 | ||
|
23 | 27 | /// Id of the null node. |
|
24 | 28 | /// |
|
25 | 29 | /// Used to indicate the absence of node. |
General Comments 0
You need to be logged in to leave comments.
Login now