1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
use crate::{linked, loose};
use git_hash::ObjectId;
use std::{borrow::Borrow, option::Option::None, sync::Arc};
#[allow(clippy::large_enum_variant)]
enum DbState {
Pack { pack_index: usize, entry_index: u32 },
Loose { iter: loose::db::iter::Type },
}
impl Default for DbState {
fn default() -> Self {
DbState::Pack {
pack_index: 0,
entry_index: 0,
}
}
}
pub struct AllObjects<Db> {
db: Db,
db_index: usize,
db_state: DbState,
}
impl<Db> AllObjects<Db>
where
Db: Borrow<linked::Db>,
{
pub fn new(db: Db) -> Self {
let db_index = 0;
let db_state = {
let db = &db
.borrow()
.dbs
.get(db_index)
.expect("at least one db or no linked::Db at all");
if db.packs.is_empty() {
DbState::Loose { iter: db.loose.iter() }
} else {
DbState::default()
}
};
AllObjects { db, db_index, db_state }
}
}
impl<Db> Iterator for AllObjects<Db>
where
Db: Borrow<linked::Db>,
{
type Item = Result<ObjectId, loose::db::iter::Error>;
fn next(&mut self) -> Option<Self::Item> {
let db = self.db.borrow();
if self.db_index == db.dbs.len() {
return None;
}
match &mut self.db_state {
DbState::Pack {
pack_index,
entry_index,
} => {
let db = &db.dbs[self.db_index];
match db.packs.get(*pack_index) {
Some(bundle) => {
if *entry_index < bundle.index.num_objects() {
let oid = bundle.index.oid_at_index(*entry_index).to_owned();
*entry_index += 1;
Some(Ok(oid))
} else {
*pack_index += 1;
*entry_index = 0;
self.next()
}
}
None => {
self.db_state = DbState::Loose { iter: db.loose.iter() };
self.next()
}
}
}
DbState::Loose { iter } => match iter.next() {
Some(id) => Some(id),
None => {
self.db_index += 1;
self.db_state = Default::default();
self.next()
}
},
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
let packed_objects = self.db.borrow().dbs.iter().fold(0usize, |dbc, db| {
dbc.saturating_add(
db.packs
.iter()
.fold(0, |pc, pack| pc.saturating_add(pack.index.num_objects() as usize)),
)
});
(packed_objects, None)
}
}
impl linked::Db {
pub fn iter(&self) -> AllObjects<&linked::Db> {
AllObjects::new(self)
}
pub fn arc_iter(self: &Arc<linked::Db>) -> AllObjects<Arc<linked::Db>> {
AllObjects::new(Arc::clone(&self))
}
}