gix_commitgraph/file/
access.rs1use std::{
2 fmt::{Debug, Formatter},
3 path::Path,
4};
5
6use crate::{
7 file::{self, commit::Commit, COMMIT_DATA_ENTRY_SIZE_SANS_HASH},
8 File,
9};
10
11impl File {
13 pub fn base_graph_count(&self) -> u8 {
15 self.base_graph_count
16 }
17
18 pub fn commit_at(&self, pos: file::Position) -> Commit<'_> {
26 Commit::new(self, pos)
27 }
28
29 pub fn object_hash(&self) -> gix_hash::Kind {
33 self.object_hash
34 }
35
36 pub fn id_at(&self, pos: file::Position) -> &gix_hash::oid {
40 assert!(
41 pos.0 < self.num_commits(),
42 "expected lexicographical position less than {}, got {}",
43 self.num_commits(),
44 pos.0
45 );
46 let pos: usize = pos
47 .0
48 .try_into()
49 .expect("an architecture able to hold 32 bits of integer");
50 let start = self.oid_lookup_offset + (pos * self.hash_len);
51 gix_hash::oid::from_bytes_unchecked(&self.data[start..][..self.hash_len])
52 }
53
54 pub fn iter_base_graph_ids(&self) -> impl Iterator<Item = &gix_hash::oid> {
56 let start = self.base_graphs_list_offset.unwrap_or(0);
57 let base_graphs_list = &self.data[start..][..self.hash_len * usize::from(self.base_graph_count)];
58 base_graphs_list
59 .chunks_exact(self.hash_len)
60 .map(gix_hash::oid::from_bytes_unchecked)
61 }
62
63 pub fn iter_commits(&self) -> impl Iterator<Item = Commit<'_>> {
65 (0..self.num_commits()).map(move |i| self.commit_at(file::Position(i)))
66 }
67
68 pub fn iter_ids(&self) -> impl Iterator<Item = &gix_hash::oid> {
70 (0..self.num_commits()).map(move |i| self.id_at(file::Position(i)))
71 }
72
73 pub fn lookup(&self, id: impl AsRef<gix_hash::oid>) -> Option<file::Position> {
76 self.lookup_inner(id.as_ref())
77 }
78
79 fn lookup_inner(&self, id: &gix_hash::oid) -> Option<file::Position> {
80 let first_byte = usize::from(id.first_byte());
81 let mut upper_bound = self.fan[first_byte];
82 let mut lower_bound = if first_byte != 0 { self.fan[first_byte - 1] } else { 0 };
83
84 while lower_bound < upper_bound {
85 let mid = (lower_bound + upper_bound) / 2;
86 let mid_sha = self.id_at(file::Position(mid));
87
88 use std::cmp::Ordering::*;
89 match id.cmp(mid_sha) {
90 Less => upper_bound = mid,
91 Equal => return Some(file::Position(mid)),
92 Greater => lower_bound = mid + 1,
93 }
94 }
95 None
96 }
97
98 pub fn num_commits(&self) -> u32 {
103 self.fan[255]
104 }
105
106 pub fn path(&self) -> &Path {
108 &self.path
109 }
110}
111
112impl File {
113 pub(crate) fn commit_data_bytes(&self, pos: file::Position) -> &[u8] {
115 assert!(
116 pos.0 < self.num_commits(),
117 "expected lexicographical position less than {}, got {}",
118 self.num_commits(),
119 pos.0
120 );
121 let pos: usize = pos
122 .0
123 .try_into()
124 .expect("an architecture able to hold 32 bits of integer");
125 let entry_size = self.hash_len + COMMIT_DATA_ENTRY_SIZE_SANS_HASH;
126 let start = self.commit_data_offset + (pos * entry_size);
127 &self.data[start..][..entry_size]
128 }
129
130 pub(crate) fn extra_edges_data(&self) -> Option<&[u8]> {
132 Some(&self.data[self.extra_edges_list_range.clone()?])
133 }
134}
135
136impl Debug for File {
137 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
138 write!(f, r#"File("{:?}")"#, self.path.display())
139 }
140}