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 {