Skip to content

Commit cb1c3e0

Browse files
committed
Compress EnteredDelimiter
1 parent 2c6b706 commit cb1c3e0

File tree

1 file changed

+49
-9
lines changed

1 file changed

+49
-9
lines changed

src/diff/graph.rs

Lines changed: 49 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -141,8 +141,8 @@ impl<'a, 'b> Vertex<'a, 'b> {
141141
}
142142

143143
fn can_pop_either_parent(&self) -> bool {
144-
matches!(self.lhs_parents.peek(), Some(PopEither(_)))
145-
|| matches!(self.rhs_parents.peek(), Some(PopEither(_)))
144+
matches!(self.lhs_parents.peek().map(Into::into), Some(PopEither(_)))
145+
|| matches!(self.rhs_parents.peek().map(Into::into), Some(PopEither(_)))
146146
}
147147
}
148148

@@ -195,7 +195,7 @@ impl Default for Vertex<'_, '_> {
195195

196196
/// Tracks entering syntax List nodes.
197197
#[derive(Debug, Clone, PartialEq, Eq)]
198-
enum EnteredDelimiter<'a> {
198+
enum EnteredDelimiterEnum<'a> {
199199
/// If we've entered the LHS or RHS separately, we can pop either
200200
/// side independently.
201201
///
@@ -211,7 +211,44 @@ enum EnteredDelimiter<'a> {
211211
PopBoth(&'a Syntax<'a>),
212212
}
213213

214-
use EnteredDelimiter::*;
214+
use EnteredDelimiterEnum::*;
215+
216+
/// Compress `EnteredDelimiterEnum` into a usize.
217+
///
218+
/// Utilize the LSB as flag since `Syntax` is aligned.
219+
///
220+
/// ```text
221+
/// LSB = 0 -> PopEither
222+
/// LSB = 1 -> PopBoth
223+
/// ```
224+
#[derive(Debug, Clone, PartialEq, Eq)]
225+
pub struct EnteredDelimiter<'a> {
226+
data: usize,
227+
phantom: PhantomData<&'a Syntax<'a>>,
228+
}
229+
230+
impl<'a> From<&EnteredDelimiter<'a>> for EnteredDelimiterEnum<'a> {
231+
fn from(delim: &EnteredDelimiter<'a>) -> Self {
232+
if delim.data & 1 == 0 {
233+
PopEither(unsafe { transmute_copy(&delim.data) })
234+
} else {
235+
PopBoth(unsafe { transmute_copy(&(delim.data ^ 1)) })
236+
}
237+
}
238+
}
239+
240+
impl<'a> From<&EnteredDelimiterEnum<'a>> for EnteredDelimiter<'a> {
241+
fn from(delim: &EnteredDelimiterEnum<'a>) -> Self {
242+
let data = match *delim {
243+
PopEither(s) => s as *const _ as usize,
244+
PopBoth(s) => s as *const _ as usize | 1,
245+
};
246+
EnteredDelimiter {
247+
data,
248+
phantom: PhantomData,
249+
}
250+
}
251+
}
215252

216253
fn push_both<'a>(
217254
lhs_entered: &Stack<EnteredDelimiter<'a>>,
@@ -220,16 +257,16 @@ fn push_both<'a>(
220257
rhs_delim: &'a Syntax<'a>,
221258
) -> (Stack<EnteredDelimiter<'a>>, Stack<EnteredDelimiter<'a>>) {
222259
(
223-
lhs_entered.push(PopBoth(lhs_delim)),
224-
rhs_entered.push(PopBoth(rhs_delim)),
260+
lhs_entered.push((&PopBoth(lhs_delim)).into()),
261+
rhs_entered.push((&PopBoth(rhs_delim)).into()),
225262
)
226263
}
227264

228265
fn push_either<'a>(
229266
entered: &Stack<EnteredDelimiter<'a>>,
230267
delim: &'a Syntax<'a>,
231268
) -> Stack<EnteredDelimiter<'a>> {
232-
entered.push(PopEither(delim))
269+
entered.push((&PopEither(delim)).into())
233270
}
234271

235272
fn try_pop_both<'a>(
@@ -241,7 +278,10 @@ fn try_pop_both<'a>(
241278
Stack<EnteredDelimiter<'a>>,
242279
Stack<EnteredDelimiter<'a>>,
243280
)> {
244-
match (lhs_entered.peek(), rhs_entered.peek()) {
281+
match (
282+
lhs_entered.peek().map(Into::into),
283+
rhs_entered.peek().map(Into::into),
284+
) {
245285
(Some(PopBoth(lhs_delim)), Some(PopBoth(rhs_delim))) => Some((
246286
lhs_delim,
247287
rhs_delim,
@@ -255,7 +295,7 @@ fn try_pop_both<'a>(
255295
fn try_pop_either<'a>(
256296
entered: &Stack<EnteredDelimiter<'a>>,
257297
) -> Option<(&'a Syntax<'a>, Stack<EnteredDelimiter<'a>>)> {
258-
match entered.peek() {
298+
match entered.peek().map(Into::into) {
259299
Some(PopEither(delim)) => Some((delim, entered.pop().unwrap())),
260300
_ => None,
261301
}

0 commit comments

Comments
 (0)