Skip to content

Commit 3efa839

Browse files
committed
newtype wrappers for lane index and alias id
1 parent a36c6fb commit 3efa839

5 files changed

Lines changed: 69 additions & 41 deletions

File tree

asyncgit/src/graph/buffer.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use super::chunk::{Chunk, Markers};
2+
use super::AliasId;
23
use std::collections::BTreeMap;
34

45
/// A single mutation of the lane state, recorded while processing one
@@ -39,7 +40,7 @@ pub struct Buffer {
3940

4041
/// Aliases of merge commits whose second parent still needs a new
4142
/// lane.
42-
merge_commits: Vec<usize>,
43+
merge_commits: Vec<AliasId>,
4344

4445
/// Scratch list of the [`DeltaOp`]s recorded for processing commit
4546
pending_delta: Vec<DeltaOp>,
@@ -64,7 +65,7 @@ impl Buffer {
6465

6566
/// Remember `alias` as a merge commit whose second parent must be
6667
/// given its own lane.
67-
pub fn track_merge_commit(&mut self, alias: usize) {
68+
pub fn track_merge_commit(&mut self, alias: AliasId) {
6869
self.merge_commits.push(alias);
6970
}
7071

@@ -104,7 +105,7 @@ impl Buffer {
104105

105106
fn find_lane_awaiting_parent(
106107
&self,
107-
alias: Option<usize>,
108+
alias: Option<AliasId>,
108109
) -> Option<usize> {
109110
let alias = alias?;
110111
self.current.iter().position(|slot| {
@@ -119,7 +120,7 @@ impl Buffer {
119120

120121
fn consume_alias_in_other_chunks(
121122
&mut self,
122-
alias: usize,
123+
alias: AliasId,
123124
skip_index: usize,
124125
) {
125126
for index in 0..self.current.len() {

asyncgit/src/graph/chunk.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use super::AliasId;
2+
13
#[derive(Clone, Debug, PartialEq, Eq)]
24
pub enum Markers {
35
Uncommitted,
@@ -6,8 +8,8 @@ pub enum Markers {
68

79
#[derive(Clone, Debug, PartialEq, Eq)]
810
pub struct Chunk {
9-
pub alias: Option<usize>,
10-
pub parent_a: Option<usize>,
11-
pub parent_b: Option<usize>,
11+
pub alias: Option<AliasId>,
12+
pub parent_a: Option<AliasId>,
13+
pub parent_b: Option<AliasId>,
1214
pub marker: Markers,
1315
}

asyncgit/src/graph/mod.rs

Lines changed: 37 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,39 @@ pub const MAX_LANE_COLORS: usize = 16;
1111
// Yes, there are repositories where this is exceeded
1212
// Are they very rare? Yes.
1313
// On most terminals can more than 256 lanes even be represneted usefully? Not really.
14-
pub type LaneIdx = u8;
14+
#[derive(Clone, Copy, Debug, Default)]
15+
pub struct LaneIndex(u8);
1516

16-
/// Convert a lane position into the compact [`LaneIdx`]
17-
/// representation. This way we can keep full granularity when computing,
18-
/// but not when storing.
19-
pub(crate) fn to_lane_idx(lane: usize) -> LaneIdx {
20-
LaneIdx::try_from(lane).unwrap_or(LaneIdx::MAX)
17+
/// Numeric alias assigned to each commit in the graph.
18+
///
19+
/// The alias is a dense integer index created by [`GraphOids`](super::oids::GraphOids)
20+
/// that avoids storing full [`CommitId`](crate::sync::CommitId)s inside the lane state.
21+
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
22+
pub struct AliasId(usize);
23+
24+
impl std::ops::Deref for AliasId {
25+
type Target = usize;
26+
fn deref(&self) -> &usize {
27+
&self.0
28+
}
29+
}
30+
31+
impl From<usize> for AliasId {
32+
fn from(v: usize) -> Self {
33+
Self(v)
34+
}
35+
}
36+
37+
impl From<usize> for LaneIndex {
38+
fn from(lane: usize) -> Self {
39+
Self(u8::try_from(lane).unwrap_or(u8::MAX))
40+
}
41+
}
42+
43+
impl From<LaneIndex> for usize {
44+
fn from(lane: LaneIndex) -> Self {
45+
lane.0 as usize
46+
}
2147
}
2248

2349
/// The type of connection between nodes in the graph.
@@ -53,10 +79,10 @@ pub enum ConnectionType {
5379
#[derive(Clone, Debug, Default)]
5480
pub struct GraphRow {
5581
/// Number of active lanes at this commit row
56-
pub lane_count: LaneIdx,
82+
pub lane_count: LaneIndex,
5783

5884
/// Which lane index this commit sits on
59-
pub commit_lane: LaneIdx,
85+
pub commit_lane: LaneIndex,
6086

6187
/// Whether this is a merge commit (two parents)
6288
pub is_merge: bool,
@@ -70,13 +96,13 @@ pub struct GraphRow {
7096
/// Connections emitted per lane:
7197
/// None = empty space
7298
/// Some((ConnectionType, `color_index`)) = draw this connector in this color
73-
pub lanes: Vec<Option<(ConnectionType, LaneIdx)>>,
99+
pub lanes: Vec<Option<(ConnectionType, LaneIndex)>>,
74100

75101
/// Horizontal merge bridge: if this commit merges rightward,
76102
/// (`from_lane`, `to_lane`) — the span to draw ─ ╭ ╮ across
77-
pub merge_bridge: Option<(LaneIdx, LaneIdx)>,
103+
pub merge_bridge: Option<(LaneIndex, LaneIndex)>,
78104

79105
/// Horizontal branch bridges: if this commit spawns branches,
80106
/// spans to draw ─ ╭ ╮ across
81-
pub branches: Vec<(LaneIdx, LaneIdx)>,
107+
pub branches: Vec<(LaneIndex, LaneIndex)>,
82108
}

asyncgit/src/graph/oids.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
1+
use super::AliasId;
12
use crate::sync::CommitId;
23
use std::collections::HashMap;
34

45
/// mapping of `CommitId` to a numeric alias
5-
pub struct GraphOids(HashMap<CommitId, usize>);
6+
pub struct GraphOids(HashMap<CommitId, AliasId>);
67

78
impl Default for GraphOids {
89
fn default() -> Self {
@@ -17,18 +18,18 @@ impl GraphOids {
1718
}
1819

1920
/// Get the alias for `id`, assigning a new one if it doesn't exist yet.
20-
pub fn get_or_insert(&mut self, id: &CommitId) -> usize {
21+
pub fn get_or_insert(&mut self, id: &CommitId) -> AliasId {
2122
if let Some(&alias) = self.0.get(id) {
2223
return alias;
2324
}
2425

25-
let alias = self.0.len();
26+
let alias = AliasId::from(self.0.len());
2627
self.0.insert(*id, alias);
2728
alias
2829
}
2930

3031
/// Look up the alias for `id`, returning `None` if not found.
31-
pub fn get(&self, id: &CommitId) -> Option<usize> {
32+
pub fn get(&self, id: &CommitId) -> Option<AliasId> {
3233
self.0.get(id).copied()
3334
}
3435
}

asyncgit/src/graph/walker.rs

Lines changed: 17 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,13 @@
11
use super::buffer::Buffer;
22
use super::chunk::{Chunk, Markers};
33
use super::oids::GraphOids;
4-
use super::{
5-
to_lane_idx, ConnectionType, GraphRow, LaneIdx, MAX_LANE_COLORS,
6-
};
4+
use super::{AliasId, ConnectionType, GraphRow, LaneIndex, MAX_LANE_COLORS};
75
use crate::sync::CommitId;
86
use std::collections::{HashMap, HashSet};
97

108
/// Get the lanes color index, which cycles through the ste palette.
11-
fn lane_color(lane: usize) -> LaneIdx {
12-
to_lane_idx(lane % MAX_LANE_COLORS)
9+
fn lane_color(lane: usize) -> LaneIndex {
10+
LaneIndex::from(lane % MAX_LANE_COLORS)
1311
}
1412

1513
use bitflags::bitflags;
@@ -103,9 +101,9 @@ const fn dirs_conn(dirs: Dirs, dotted: bool) -> ConnectionType {
103101
/// The line with a vertical component is the chosen way with color
104102
/// ensuring lanes stay visually continuous
105103
fn overlay_cell(
106-
cell: &mut Option<(ConnectionType, LaneIdx)>,
104+
cell: &mut Option<(ConnectionType, LaneIndex)>,
107105
add: Dirs,
108-
color: LaneIdx,
106+
color: LaneIndex,
109107
) {
110108
if let Some((conn, existing_color)) = cell {
111109
if let Some(existing) = conn_dirs(*conn) {
@@ -135,7 +133,7 @@ pub struct GraphWalker {
135133
pub branch_lane_map: HashMap<CommitId, usize>,
136134

137135
/// Maps a merge commit's alias to the alias of its second parent.
138-
pub merge_parents: HashMap<usize, usize>,
136+
pub merge_parents: HashMap<AliasId, AliasId>,
139137
}
140138

141139
impl Default for GraphWalker {
@@ -236,7 +234,7 @@ impl GraphWalker {
236234
}
237235

238236
fn draw_merge_bridge(
239-
lanes: &mut [Option<(ConnectionType, LaneIdx)>],
237+
lanes: &mut [Option<(ConnectionType, LaneIndex)>],
240238
merge_bridge: Option<(usize, usize)>,
241239
commit_lane: usize,
242240
current: &[Option<Chunk>],
@@ -287,15 +285,15 @@ impl GraphWalker {
287285
}
288286

289287
fn draw_branching_lanes(
290-
lanes: &mut Vec<Option<(ConnectionType, LaneIdx)>>,
288+
lanes: &mut Vec<Option<(ConnectionType, LaneIndex)>>,
291289
branching_lanes: &[usize],
292290
commit_lane: usize,
293-
) -> Vec<(LaneIdx, LaneIdx)> {
291+
) -> Vec<(LaneIndex, LaneIndex)> {
294292
let mut branches = Vec::new();
295293
for &branch_lane in branching_lanes {
296294
let from = std::cmp::min(branch_lane, commit_lane);
297295
let to = std::cmp::max(branch_lane, commit_lane);
298-
branches.push((to_lane_idx(from), to_lane_idx(to)));
296+
branches.push((LaneIndex::from(from), LaneIndex::from(to)));
299297

300298
if lanes.len() <= to {
301299
lanes.resize(to + 1, None);
@@ -403,24 +401,24 @@ impl GraphWalker {
403401
);
404402

405403
GraphRow {
406-
lane_count: to_lane_idx(current.iter().flatten().count()),
407-
commit_lane: to_lane_idx(commit_lane),
404+
lane_count: LaneIndex::from(current.iter().flatten().count()),
405+
commit_lane: LaneIndex::from(commit_lane),
408406
is_merge,
409407
is_branch_tip,
410408
is_stash,
411409
lanes,
412410
merge_bridge: merge_bridge
413-
.map(|(f, t)| (to_lane_idx(f), to_lane_idx(t))),
411+
.map(|(f, t)| (LaneIndex::from(f), LaneIndex::from(t))),
414412
branches,
415413
}
416414
}
417415

418416
#[allow(clippy::too_many_arguments)]
419417
fn fill_lanes(
420418
&self,
421-
lanes: &mut [Option<(ConnectionType, LaneIdx)>],
419+
lanes: &mut [Option<(ConnectionType, LaneIndex)>],
422420
curr: &[Option<Chunk>],
423-
alias: Option<usize>,
421+
alias: Option<AliasId>,
424422
head_id: Option<&CommitId>,
425423
is_stash: bool,
426424
is_merge: bool,
@@ -473,10 +471,10 @@ impl GraphWalker {
473471
/// between its two ends, merging with whatever each cell already
474472
/// shows.
475473
fn draw_bridge_span(
476-
lanes: &mut [Option<(ConnectionType, LaneIdx)>],
474+
lanes: &mut [Option<(ConnectionType, LaneIndex)>],
477475
from: usize,
478476
to: usize,
479-
color: LaneIdx,
477+
color: LaneIndex,
480478
) {
481479
for lane in lanes.iter_mut().take(to).skip(from + 1) {
482480
overlay_cell(lane, Dirs::LEFT | Dirs::RIGHT, color);

0 commit comments

Comments
 (0)