Mercurial > hg
comparison rust/hg-core/src/revlog/index.rs @ 51189:b4d152a28742
rust-index: add append method
This is the first time the Rust index has any notion of mutability.
This will be used in a future patch from Python, to start synchronizing the
Rust index and the C index.
author | Raphaël Gomès <rgomes@octobus.net> |
---|---|
date | Tue, 27 Jun 2023 16:32:09 +0200 |
parents | 1ef4a36a934d |
children | 13f58ce70299 |
comparison
equal
deleted
inserted
replaced
51188:1ef4a36a934d | 51189:b4d152a28742 |
---|---|
1 use std::fmt::Debug; | 1 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 | 5 use bytes_cast::{unaligned, BytesCast}; |
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], |
15 } | 19 } |
16 | 20 |
114 panic!("index data cannot span existing and added ranges"); | 118 panic!("index data cannot span existing and added ranges"); |
115 } | 119 } |
116 &self.bytes[index] | 120 &self.bytes[index] |
117 } else { | 121 } else { |
118 &self.added[start - immutable_len..end - immutable_len] | 122 &self.added[start - immutable_len..end - immutable_len] |
123 } | |
124 } | |
125 } | |
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, | |
119 } | 198 } |
120 } | 199 } |
121 } | 200 } |
122 | 201 |
123 /// A Revlog index | 202 /// A Revlog index |
280 | 359 |
281 IndexEntry { | 360 IndexEntry { |
282 bytes, | 361 bytes, |
283 offset_override, | 362 offset_override, |
284 } | 363 } |
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(()) | |
285 } | 378 } |
286 } | 379 } |
287 | 380 |
288 impl super::RevlogIndex for Index { | 381 impl super::RevlogIndex for Index { |
289 fn len(&self) -> usize { | 382 fn len(&self) -> usize { |