@@ -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
216253fn 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
228265fn 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
235272fn 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>(
255295fn 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