index: split IndexEntry and related types to "entry" module

Added pub(super) or pub where needed. I won't implement accessor methods on
IndexPositionByGeneration and IndexPosition as they are purely value types,
and protecting the inner values wouldn't make sense.
This commit is contained in:
Yuya Nishihara 2023-12-11 21:03:04 +09:00
parent 90e241cc95
commit 771f447d99
6 changed files with 154 additions and 128 deletions

View file

@ -21,9 +21,10 @@ use std::sync::Arc;
use itertools::Itertools;
use super::entry::{IndexEntry, IndexPosition, IndexPositionByGeneration};
use super::readonly::ReadonlyIndexSegment;
use super::rev_walk::RevWalk;
use super::{IndexEntry, IndexPosition, IndexPositionByGeneration, IndexSegment};
use super::IndexSegment;
use crate::backend::{CommitId, ObjectId};
use crate::index::{HexPrefix, Index, PrefixResolution};
use crate::revset::{ResolvedExpression, Revset, RevsetEvaluationError};

View file

@ -0,0 +1,143 @@
// Copyright 2023 The Jujutsu Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#![allow(missing_docs)]
use std::cmp::Ordering;
use std::fmt::{Debug, Formatter};
use std::hash::{Hash, Hasher};
use smallvec::SmallVec;
use super::composite::CompositeIndex;
use super::IndexSegment;
use crate::backend::{ChangeId, CommitId, ObjectId};
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Hash)]
pub struct IndexPosition(pub(super) u32);
impl IndexPosition {
pub const MAX: Self = IndexPosition(u32::MAX);
}
// SmallVec reuses two pointer-size fields as inline area, which meas we can
// inline up to 16 bytes (on 64-bit platform) for free.
pub(super) type SmallIndexPositionsVec = SmallVec<[IndexPosition; 4]>;
#[derive(Clone)]
pub struct IndexEntry<'a> {
pub(super) source: &'a dyn IndexSegment,
pub(super) pos: IndexPosition,
// Position within the source segment
pub(super) local_pos: u32,
}
impl Debug for IndexEntry<'_> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
f.debug_struct("IndexEntry")
.field("pos", &self.pos)
.field("local_pos", &self.local_pos)
.field("commit_id", &self.commit_id().hex())
.finish()
}
}
impl PartialEq for IndexEntry<'_> {
fn eq(&self, other: &Self) -> bool {
self.pos == other.pos
}
}
impl Eq for IndexEntry<'_> {}
impl Hash for IndexEntry<'_> {
fn hash<H: Hasher>(&self, state: &mut H) {
self.pos.hash(state)
}
}
impl<'a> IndexEntry<'a> {
pub fn position(&self) -> IndexPosition {
self.pos
}
pub fn generation_number(&self) -> u32 {
self.source.segment_generation_number(self.local_pos)
}
pub fn commit_id(&self) -> CommitId {
self.source.segment_commit_id(self.local_pos)
}
pub fn change_id(&self) -> ChangeId {
self.source.segment_change_id(self.local_pos)
}
pub fn num_parents(&self) -> u32 {
self.source.segment_num_parents(self.local_pos)
}
pub fn parent_positions(&self) -> SmallIndexPositionsVec {
self.source.segment_parent_positions(self.local_pos)
}
pub fn parents(&self) -> impl ExactSizeIterator<Item = IndexEntry<'a>> {
let composite = CompositeIndex::new(self.source);
self.parent_positions()
.into_iter()
.map(move |pos| composite.entry_by_pos(pos))
}
}
#[derive(Clone, Eq, PartialEq)]
pub struct IndexEntryByPosition<'a>(pub IndexEntry<'a>);
impl Ord for IndexEntryByPosition<'_> {
fn cmp(&self, other: &Self) -> Ordering {
self.0.pos.cmp(&other.0.pos)
}
}
impl PartialOrd for IndexEntryByPosition<'_> {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
/// Wrapper to sort `IndexPosition` by its generation number.
///
/// This is similar to `IndexEntry` newtypes, but optimized for size and cache
/// locality. The original `IndexEntry` will have to be looked up when needed.
#[derive(Clone, Copy, Debug, Ord, PartialOrd)]
pub(super) struct IndexPositionByGeneration {
pub generation: u32, // order by generation number
pub pos: IndexPosition, // tie breaker
}
impl Eq for IndexPositionByGeneration {}
impl PartialEq for IndexPositionByGeneration {
fn eq(&self, other: &Self) -> bool {
self.pos == other.pos
}
}
impl From<&IndexEntry<'_>> for IndexPositionByGeneration {
fn from(entry: &IndexEntry<'_>) -> Self {
IndexPositionByGeneration {
generation: entry.generation_number(),
pos: entry.position(),
}
}
}

View file

@ -15,19 +15,17 @@
#![allow(missing_docs)]
mod composite;
mod entry;
mod mutable;
mod readonly;
mod rev_walk;
mod store;
use std::cmp::Ordering;
use std::fmt::{Debug, Formatter};
use std::hash::{Hash, Hasher};
use std::sync::Arc;
use smallvec::SmallVec;
pub use self::composite::{CompositeIndex, IndexLevelStats, IndexStats};
use self::entry::SmallIndexPositionsVec;
pub use self::entry::{IndexEntry, IndexEntryByPosition, IndexPosition};
pub use self::mutable::DefaultMutableIndex;
pub use self::readonly::DefaultReadonlyIndex;
use self::readonly::ReadonlyIndexSegment;
@ -35,20 +33,9 @@ pub use self::rev_walk::{
RevWalk, RevWalkDescendants, RevWalkDescendantsGenerationRange, RevWalkGenerationRange,
};
pub use self::store::{DefaultIndexStore, DefaultIndexStoreError, IndexLoadError};
use crate::backend::{ChangeId, CommitId, ObjectId};
use crate::backend::{ChangeId, CommitId};
use crate::index::{HexPrefix, PrefixResolution};
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Hash)]
pub struct IndexPosition(u32);
impl IndexPosition {
pub const MAX: Self = IndexPosition(u32::MAX);
}
// SmallVec reuses two pointer-size fields as inline area, which meas we can
// inline up to 16 bytes (on 64-bit platform) for free.
type SmallIndexPositionsVec = SmallVec<[IndexPosition; 4]>;
trait IndexSegment: Send + Sync {
fn segment_num_parent_commits(&self) -> u32;
@ -82,113 +69,6 @@ trait IndexSegment: Send + Sync {
fn segment_entry_by_pos(&self, pos: IndexPosition, local_pos: u32) -> IndexEntry;
}
#[derive(Clone, Eq, PartialEq)]
pub struct IndexEntryByPosition<'a>(pub IndexEntry<'a>);
impl Ord for IndexEntryByPosition<'_> {
fn cmp(&self, other: &Self) -> Ordering {
self.0.pos.cmp(&other.0.pos)
}
}
impl PartialOrd for IndexEntryByPosition<'_> {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
/// Wrapper to sort `IndexPosition` by its generation number.
///
/// This is similar to `IndexEntry` newtypes, but optimized for size and cache
/// locality. The original `IndexEntry` will have to be looked up when needed.
#[derive(Clone, Copy, Debug, Ord, PartialOrd)]
struct IndexPositionByGeneration {
generation: u32, // order by generation number
pos: IndexPosition, // tie breaker
}
impl Eq for IndexPositionByGeneration {}
impl PartialEq for IndexPositionByGeneration {
fn eq(&self, other: &Self) -> bool {
self.pos == other.pos
}
}
impl From<&IndexEntry<'_>> for IndexPositionByGeneration {
fn from(entry: &IndexEntry<'_>) -> Self {
IndexPositionByGeneration {
generation: entry.generation_number(),
pos: entry.position(),
}
}
}
#[derive(Clone)]
pub struct IndexEntry<'a> {
source: &'a dyn IndexSegment,
pos: IndexPosition,
// Position within the source segment
local_pos: u32,
}
impl Debug for IndexEntry<'_> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
f.debug_struct("IndexEntry")
.field("pos", &self.pos)
.field("local_pos", &self.local_pos)
.field("commit_id", &self.commit_id().hex())
.finish()
}
}
impl PartialEq for IndexEntry<'_> {
fn eq(&self, other: &Self) -> bool {
self.pos == other.pos
}
}
impl Eq for IndexEntry<'_> {}
impl Hash for IndexEntry<'_> {
fn hash<H: Hasher>(&self, state: &mut H) {
self.pos.hash(state)
}
}
impl<'a> IndexEntry<'a> {
pub fn position(&self) -> IndexPosition {
self.pos
}
pub fn generation_number(&self) -> u32 {
self.source.segment_generation_number(self.local_pos)
}
pub fn commit_id(&self) -> CommitId {
self.source.segment_commit_id(self.local_pos)
}
pub fn change_id(&self) -> ChangeId {
self.source.segment_change_id(self.local_pos)
}
pub fn num_parents(&self) -> u32 {
self.source.segment_num_parents(self.local_pos)
}
pub fn parent_positions(&self) -> SmallIndexPositionsVec {
self.source.segment_parent_positions(self.local_pos)
}
pub fn parents(&self) -> impl ExactSizeIterator<Item = IndexEntry<'a>> {
let composite = CompositeIndex::new(self.source);
self.parent_positions()
.into_iter()
.map(move |pos| composite.entry_by_pos(pos))
}
}
#[cfg(test)]
mod tests {
use std::ops::Range;

View file

@ -31,9 +31,10 @@ use smallvec::SmallVec;
use tempfile::NamedTempFile;
use super::composite::CompositeIndex;
use super::entry::{IndexEntry, IndexPosition, SmallIndexPositionsVec};
use super::readonly::{DefaultReadonlyIndex, ReadonlyIndexSegment};
use super::store::IndexLoadError;
use super::{IndexEntry, IndexPosition, IndexSegment, SmallIndexPositionsVec};
use super::IndexSegment;
use crate::backend::{ChangeId, CommitId, ObjectId};
use crate::commit::Commit;
use crate::file_util::persist_content_addressed_temp_file;

View file

@ -26,9 +26,10 @@ use byteorder::{LittleEndian, ReadBytesExt};
use smallvec::SmallVec;
use super::composite::CompositeIndex;
use super::entry::{IndexEntry, IndexPosition, SmallIndexPositionsVec};
use super::mutable::DefaultMutableIndex;
use super::store::IndexLoadError;
use super::{IndexEntry, IndexPosition, IndexSegment, SmallIndexPositionsVec};
use super::IndexSegment;
use crate::backend::{ChangeId, CommitId, ObjectId};
use crate::index::{HexPrefix, Index, MutableIndex, PrefixResolution, ReadonlyIndex};
use crate::revset::{ResolvedExpression, Revset, RevsetEvaluationError};

View file

@ -22,7 +22,7 @@ use std::ops::Range;
use smallvec::SmallVec;
use super::composite::CompositeIndex;
use super::{IndexEntry, IndexPosition, SmallIndexPositionsVec};
use super::entry::{IndexEntry, IndexPosition, SmallIndexPositionsVec};
trait RevWalkIndex<'a> {
type Position: Copy + Ord;