1
- use std:: collections:: VecDeque ;
2
-
3
1
/// Returned when using various methods on a [`Tree`]
4
2
#[ derive( thiserror:: Error , Debug ) ]
5
3
#[ allow( missing_docs) ]
@@ -32,15 +30,23 @@ pub struct Item<T> {
32
30
/// Indices into our Tree's `items`, one for each pack entry that depends on us.
33
31
children : Vec < usize > ,
34
32
}
33
+
34
+ /// Identify what kind of node we have last seen
35
+ enum NodeKind {
36
+ Root ,
37
+ Child ,
38
+ }
39
+
35
40
/// A tree that allows one-time iteration over all nodes and their children, consuming it in the process,
36
41
/// while being shareable among threads without a lock.
37
42
/// It does this by making the guarantee that iteration only happens once.
38
43
pub struct Tree < T > {
39
- /// Roots are first, then children.
40
- items : VecDeque < Item < T > > ,
41
- roots : usize ,
42
- /// The last child index into the `items` array
43
- last_index : usize ,
44
+ /// The root nodes, i.e. base objects
45
+ root_items : Vec < Item < T > > ,
46
+ /// The child nodes, i.e. those that rely a base object, like ref and ofs delta objets
47
+ child_items : Vec < Item < T > > ,
48
+ /// The last encountered node was either a root or a child.
49
+ last_seen : Option < NodeKind > ,
44
50
/// Future child offsets, associating their offset into the pack with their index in the items array.
45
51
/// (parent_offset, child_index)
46
52
future_child_offsets : Vec < ( crate :: data:: Offset , usize ) > ,
@@ -50,22 +56,27 @@ impl<T> Tree<T> {
50
56
/// Instantiate a empty tree capable of storing `num_objects` amounts of items.
51
57
pub fn with_capacity ( num_objects : usize ) -> Result < Self , Error > {
52
58
Ok ( Tree {
53
- items : VecDeque :: with_capacity ( num_objects) ,
54
- roots : 0 ,
55
- last_index : 0 ,
59
+ root_items : Vec :: with_capacity ( num_objects / 2 ) ,
60
+ child_items : Vec :: with_capacity ( num_objects / 2 ) ,
61
+ last_seen : None ,
56
62
future_child_offsets : Vec :: new ( ) ,
57
63
} )
58
64
}
59
65
66
+ fn num_items ( & self ) -> usize {
67
+ self . root_items . len ( ) + self . child_items . len ( )
68
+ }
69
+
60
70
fn assert_is_incrementing_and_update_next_offset ( & mut self , offset : crate :: data:: Offset ) -> Result < ( ) , Error > {
61
- if self . items . is_empty ( ) {
62
- return Ok ( ( ) ) ;
63
- }
64
- let item = & mut self . items [ self . last_index ] ;
65
- let last_offset = item. offset ;
66
- if offset <= last_offset {
71
+ let items = match & self . last_seen {
72
+ Some ( NodeKind :: Root ) => & mut self . root_items ,
73
+ Some ( NodeKind :: Child ) => & mut self . child_items ,
74
+ None => return Ok ( ( ) ) ,
75
+ } ;
76
+ let item = & mut items. last_mut ( ) . expect ( "last seen won't lie" ) ;
77
+ if offset <= item. offset {
67
78
return Err ( Error :: InvariantIncreasingPackOffset {
68
- last_pack_offset : last_offset ,
79
+ last_pack_offset : item . offset ,
69
80
pack_offset : offset,
70
81
} ) ;
71
82
}
@@ -77,22 +88,12 @@ impl<T> Tree<T> {
77
88
& mut self ,
78
89
pack_entries_end : crate :: data:: Offset ,
79
90
) -> Result < ( ) , traverse:: Error > {
80
- if self . items . is_empty ( ) {
81
- return Ok ( ( ) ) ;
82
- } ;
83
-
84
91
if !self . future_child_offsets . is_empty ( ) {
85
- let ( roots, children) = self . items . as_mut_slices ( ) ;
86
- assert_eq ! (
87
- roots. len( ) ,
88
- self . roots,
89
- "item deque has been resized, maybe we added more nodes than we declared in the constructor?"
90
- ) ;
91
92
for ( parent_offset, child_index) in self . future_child_offsets . drain ( ..) {
92
- if let Ok ( i) = children . binary_search_by_key ( & parent_offset, |i| i. offset ) {
93
- children [ i] . children . push ( child_index) ;
94
- } else if let Ok ( i) = roots . binary_search_by ( |i| parent_offset . cmp ( & i. offset ) ) {
95
- roots [ i] . children . push ( child_index) ;
93
+ if let Ok ( i) = self . child_items . binary_search_by_key ( & parent_offset, |i| i. offset ) {
94
+ self . child_items [ i] . children . push ( child_index) ;
95
+ } else if let Ok ( i) = self . root_items . binary_search_by_key ( & parent_offset , |i| i. offset ) {
96
+ self . root_items [ i] . children . push ( child_index) ;
96
97
} else {
97
98
return Err ( traverse:: Error :: OutOfPackRefDelta {
98
99
base_pack_offset : parent_offset,
@@ -101,22 +102,22 @@ impl<T> Tree<T> {
101
102
}
102
103
}
103
104
104
- self . items [ self . last_index ] . next_offset = pack_entries_end;
105
+ self . assert_is_incrementing_and_update_next_offset ( pack_entries_end)
106
+ . expect ( "BUG: pack now is smaller than all previously seen entries" ) ;
105
107
Ok ( ( ) )
106
108
}
107
109
108
110
/// Add a new root node, one that only has children but is not a child itself, at the given pack `offset` and associate
109
111
/// custom `data` with it.
110
112
pub fn add_root ( & mut self , offset : crate :: data:: Offset , data : T ) -> Result < ( ) , Error > {
111
113
self . assert_is_incrementing_and_update_next_offset ( offset) ?;
112
- self . last_index = 0 ;
113
- self . items . push_front ( Item {
114
+ self . last_seen = NodeKind :: Root . into ( ) ;
115
+ self . root_items . push ( Item {
114
116
offset,
115
117
next_offset : 0 ,
116
118
data,
117
119
children : Vec :: new ( ) ,
118
120
} ) ;
119
- self . roots += 1 ;
120
121
Ok ( ( ) )
121
122
}
122
123
@@ -128,22 +129,18 @@ impl<T> Tree<T> {
128
129
data : T ,
129
130
) -> Result < ( ) , Error > {
130
131
self . assert_is_incrementing_and_update_next_offset ( offset) ?;
131
- let ( roots, children) = self . items . as_mut_slices ( ) ;
132
- assert_eq ! (
133
- roots. len( ) ,
134
- self . roots,
135
- "item deque has been resized, maybe we added more nodes than we declared in the constructor?"
136
- ) ;
137
- let next_child_index = children. len ( ) ;
138
- if let Ok ( i) = children. binary_search_by_key ( & base_offset, |i| i. offset ) {
139
- children[ i] . children . push ( next_child_index) ;
140
- } else if let Ok ( i) = roots. binary_search_by ( |i| base_offset. cmp ( & i. offset ) ) {
141
- roots[ i] . children . push ( next_child_index) ;
132
+
133
+ let next_child_index = self . child_items . len ( ) ;
134
+ if let Ok ( i) = self . child_items . binary_search_by_key ( & base_offset, |i| i. offset ) {
135
+ self . child_items [ i] . children . push ( next_child_index) ;
136
+ } else if let Ok ( i) = self . root_items . binary_search_by_key ( & base_offset, |i| i. offset ) {
137
+ self . root_items [ i] . children . push ( next_child_index) ;
142
138
} else {
143
139
self . future_child_offsets . push ( ( base_offset, next_child_index) ) ;
144
140
}
145
- self . last_index = self . items . len ( ) ;
146
- self . items . push_back ( Item {
141
+
142
+ self . last_seen = NodeKind :: Child . into ( ) ;
143
+ self . child_items . push ( Item {
147
144
offset,
148
145
next_offset : 0 ,
149
146
data,
@@ -153,8 +150,8 @@ impl<T> Tree<T> {
153
150
}
154
151
155
152
/// Transform this `Tree` into its items.
156
- pub fn into_items ( self ) -> VecDeque < Item < T > > {
157
- self . items
153
+ pub fn into_items ( self ) -> ( Vec < Item < T > > , Vec < Item < T > > ) {
154
+ ( self . root_items , self . child_items )
158
155
}
159
156
}
160
157
0 commit comments