Skip to content

Commit ca7a533

Browse files
committed
Add an iterator over the segment groups
Dealing with the index based group ranges is not ergonomic. Therefore this commits adds an iterator that returns all the groups as views of segment slices. Also segments that are not part of any groups become pseudo-groups of single segments. The splits component should be able to build on top of this.
1 parent 4468ee9 commit ca7a533

File tree

2 files changed

+89
-1
lines changed

2 files changed

+89
-1
lines changed

src/run/mod.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ pub use attempt::Attempt;
3131
pub use editor::{Editor, RenameError};
3232
pub use run_metadata::RunMetadata;
3333
pub use segment::Segment;
34-
pub use segment_groups::{SegmentGroup, SegmentGroups};
34+
pub use segment_groups::{SegmentGroup, SegmentGroupView, SegmentGroups, SegmentGroupsIter};
3535
pub use segment_history::SegmentHistory;
3636

3737
use crate::comparison::{default_generators, personal_best, ComparisonGenerator};
@@ -236,6 +236,11 @@ impl Run {
236236
&mut self.segment_groups
237237
}
238238

239+
#[inline]
240+
pub fn segment_groups_iter(&self) -> SegmentGroupsIter<'_, '_> {
241+
self.segment_groups.iter_with(&self.segments)
242+
}
243+
239244
/// Pushes the segment provided to the end of the list of segments of this Run.
240245
#[inline]
241246
pub fn push_segment(&mut self, segment: Segment) {

src/run/segment_groups.rs

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,11 @@
1+
use {
2+
crate::Segment,
3+
std::{
4+
iter::Peekable,
5+
slice::{self, Iter},
6+
},
7+
};
8+
19
#[derive(Debug, Clone, PartialEq)]
210
pub struct SegmentGroup {
311
start: usize,
@@ -36,4 +44,79 @@ impl SegmentGroups {
3644
Err(group)
3745
}
3846
}
47+
48+
pub fn iter_with<'groups, 'segments>(
49+
&'groups self,
50+
segments: &'segments [Segment],
51+
) -> SegmentGroupsIter<'groups, 'segments> {
52+
SegmentGroupsIter {
53+
iter: self.0.iter().peekable(),
54+
segments,
55+
index: 0,
56+
}
57+
}
58+
}
59+
60+
pub struct SegmentGroupView<'group, 'segments> {
61+
name: Option<&'group str>,
62+
segments: &'segments [Segment],
63+
ending_segment: &'segments Segment,
64+
}
65+
66+
impl<'group, 'segments> SegmentGroupView<'group, 'segments> {
67+
pub fn group_name(&self) -> Option<&'group str> {
68+
self.name
69+
}
70+
71+
pub fn group_name_or_default<'a>(&self) -> &'a str
72+
where
73+
'group: 'a,
74+
'segments: 'a,
75+
{
76+
self.name.unwrap_or_else(|| self.ending_segment.name())
77+
}
78+
79+
pub fn segments(&self) -> &'segments [Segment] {
80+
self.segments
81+
}
82+
83+
pub fn ending_segment(&self) -> &'segments Segment {
84+
self.ending_segment
85+
}
86+
87+
pub fn len(&self) -> usize {
88+
self.segments.len()
89+
}
90+
}
91+
92+
pub struct SegmentGroupsIter<'groups, 'segments> {
93+
iter: Peekable<Iter<'groups, SegmentGroup>>,
94+
segments: &'segments [Segment],
95+
index: usize,
96+
}
97+
98+
impl<'groups, 'segments> Iterator for SegmentGroupsIter<'groups, 'segments> {
99+
type Item = SegmentGroupView<'groups, 'segments>;
100+
101+
fn next(&mut self) -> Option<Self::Item> {
102+
let index = self.index;
103+
if self.iter.peek().map_or(true, |group| group.start > index) {
104+
self.index += 1;
105+
let ending_segment = self.segments.get(index)?;
106+
Some(SegmentGroupView {
107+
name: None,
108+
segments: slice::from_ref(ending_segment),
109+
ending_segment,
110+
})
111+
} else {
112+
let group = self.iter.next()?;
113+
self.index = group.end;
114+
let segments = self.segments.get(group.start..group.end)?;
115+
Some(SegmentGroupView {
116+
name: group.name.as_ref().map(String::as_str),
117+
segments,
118+
ending_segment: segments.last().unwrap(),
119+
})
120+
}
121+
}
39122
}

0 commit comments

Comments
 (0)