Show More
@@ -2,13 +2,17 b' use std::fmt::Debug;' | |||||
2 | use std::ops::Deref; |
|
2 | use std::ops::Deref; | |
3 |
|
3 | |||
4 | use byteorder::{BigEndian, ByteOrder}; |
|
4 | use byteorder::{BigEndian, ByteOrder}; | |
|
5 | use bytes_cast::{unaligned, BytesCast}; | |||
5 |
|
6 | |||
|
7 | use super::REVIDX_KNOWN_FLAGS; | |||
6 | use crate::errors::HgError; |
|
8 | use crate::errors::HgError; | |
|
9 | use crate::node::{NODE_BYTES_LENGTH, STORED_NODE_ID_BYTES}; | |||
7 | use crate::revlog::node::Node; |
|
10 | use crate::revlog::node::Node; | |
8 | use crate::revlog::{Revision, NULL_REVISION}; |
|
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 | pub const INDEX_ENTRY_SIZE: usize = 64; |
|
14 | pub const INDEX_ENTRY_SIZE: usize = 64; | |
|
15 | pub const COMPRESSION_MODE_INLINE: u8 = 2; | |||
12 |
|
16 | |||
13 | pub struct IndexHeader { |
|
17 | pub struct IndexHeader { | |
14 | header_bytes: [u8; 4], |
|
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 | /// A Revlog index |
|
202 | /// A Revlog index | |
124 | pub struct Index { |
|
203 | pub struct Index { | |
125 | bytes: IndexData, |
|
204 | bytes: IndexData, | |
@@ -283,6 +362,20 b' impl Index {' | |||||
283 | offset_override, |
|
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 | impl super::RevlogIndex for Index { |
|
381 | impl super::RevlogIndex for Index { |
@@ -20,6 +20,10 b' use std::fmt;' | |||||
20 | /// the future. |
|
20 | /// the future. | |
21 | pub const NODE_BYTES_LENGTH: usize = 20; |
|
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 | /// Id of the null node. |
|
27 | /// Id of the null node. | |
24 | /// |
|
28 | /// | |
25 | /// Used to indicate the absence of node. |
|
29 | /// Used to indicate the absence of node. |
General Comments 0
You need to be logged in to leave comments.
Login now