@@ -33,6 +33,7 @@ use enumset::EnumSet;
3333use smallvec:: SmallVec ;
3434use std:: collections:: HashMap ;
3535
36+ use crate :: arena:: Arena ;
3637use crate :: arena:: Handle ;
3738use crate :: arena:: List ;
3839use crate :: arena:: ListArena ;
@@ -128,21 +129,29 @@ where
128129// ----------------------------------------------------------------------------
129130// Cycle detector
130131
131- pub struct Appendables < H > ( pub ( crate ) ListArena < PathOrAppendable < H > > ) ;
132+ pub struct Appendables < H > {
133+ /// List arena for appendable lists
134+ elements : ListArena < InternedPathOrHandle < H > > ,
135+ /// Arena for interned partial paths
136+ interned : Arena < PartialPath > ,
137+ }
132138
133139impl < H > Appendables < H > {
134140 pub fn new ( ) -> Self {
135- Self ( ListArena :: new ( ) )
141+ Self {
142+ elements : ListArena :: new ( ) ,
143+ interned : Arena :: new ( ) ,
144+ }
136145 }
137146}
138147
139148#[ derive( Clone ) ]
140- pub ( crate ) enum PathOrAppendable < H > {
141- Path ( PartialPath ) ,
142- Handle ( H ) ,
149+ pub ( crate ) enum InternedPathOrHandle < H > {
150+ Owned ( Handle < PartialPath > ) ,
151+ Database ( H ) ,
143152}
144153
145- impl < H > PathOrAppendable < H >
154+ impl < H > InternedPathOrHandle < H >
146155where
147156 H : Clone ,
148157{
@@ -151,44 +160,45 @@ where
151160 graph : & StackGraph ,
152161 partials : & mut PartialPaths ,
153162 db : & ' a Db ,
163+ interned : & Arena < PartialPath > ,
154164 path : & mut PartialPath ,
155165 ) -> Result < ( ) , PathResolutionError >
156166 where
157167 A : Appendable + ' a ,
158168 Db : ToAppendable < H , A > ,
159169 {
160170 match self {
161- Self :: Path ( other ) => other . append_to ( graph, partials, path) ,
162- Self :: Handle ( h) => db. get_appendable ( h) . append_to ( graph, partials, path) ,
171+ Self :: Owned ( h ) => interned . get ( * h ) . append_to ( graph, partials, path) ,
172+ Self :: Database ( h) => db. get_appendable ( h) . append_to ( graph, partials, path) ,
163173 }
164174 }
165175
166- fn start_node < ' a , A , Db > ( & self , db : & ' a Db ) -> Handle < Node >
176+ fn start_node < ' a , A , Db > ( & self , db : & ' a Db , interned : & Arena < PartialPath > ) -> Handle < Node >
167177 where
168178 A : Appendable + ' a ,
169179 Db : ToAppendable < H , A > ,
170180 {
171181 match self {
172- Self :: Path ( path ) => path . start_node ,
173- Self :: Handle ( h) => db. get_appendable ( h) . start_node ( ) ,
182+ Self :: Owned ( h ) => interned . get ( * h ) . start_node ,
183+ Self :: Database ( h) => db. get_appendable ( h) . start_node ( ) ,
174184 }
175185 }
176186
177- fn end_node < ' a , A , Db > ( & self , db : & ' a Db ) -> Handle < Node >
187+ fn end_node < ' a , A , Db > ( & self , db : & ' a Db , interned : & Arena < PartialPath > ) -> Handle < Node >
178188 where
179189 A : Appendable + ' a ,
180190 Db : ToAppendable < H , A > ,
181191 {
182192 match self {
183- Self :: Path ( path ) => path . end_node ,
184- Self :: Handle ( h) => db. get_appendable ( h) . end_node ( ) ,
193+ Self :: Owned ( h ) => interned . get ( * h ) . end_node ,
194+ Self :: Database ( h) => db. get_appendable ( h) . end_node ( ) ,
185195 }
186196 }
187197}
188198
189199#[ derive( Clone ) ]
190200pub struct AppendingCycleDetector < H > {
191- appendages : List < PathOrAppendable < H > > ,
201+ appendages : List < InternedPathOrHandle < H > > ,
192202}
193203
194204impl < H > AppendingCycleDetector < H > {
@@ -199,16 +209,19 @@ impl<H> AppendingCycleDetector<H> {
199209 }
200210
201211 pub fn from ( appendables : & mut Appendables < H > , path : PartialPath ) -> Self {
212+ let h = appendables. interned . add ( path) ;
202213 let mut result = Self :: new ( ) ;
203214 result
204215 . appendages
205- . push_front ( & mut appendables. 0 , PathOrAppendable :: Path ( path ) ) ;
216+ . push_front ( & mut appendables. elements , InternedPathOrHandle :: Owned ( h ) ) ;
206217 result
207218 }
208219
209220 pub fn append ( & mut self , appendables : & mut Appendables < H > , appendage : H ) {
210- self . appendages
211- . push_front ( & mut appendables. 0 , PathOrAppendable :: Handle ( appendage) ) ;
221+ self . appendages . push_front (
222+ & mut appendables. elements ,
223+ InternedPathOrHandle :: Database ( appendage) ,
224+ ) ;
212225 }
213226}
214227
@@ -231,8 +244,8 @@ where
231244 {
232245 let mut cycles = EnumSet :: new ( ) ;
233246
234- let end_node = match self . appendages . clone ( ) . pop_front ( & mut appendables. 0 ) {
235- Some ( appendage) => appendage. end_node ( db) ,
247+ let end_node = match self . appendages . clone ( ) . pop_front ( & mut appendables. elements ) {
248+ Some ( appendage) => appendage. end_node ( db, & appendables . interned ) ,
236249 None => return Ok ( cycles) ,
237250 } ;
238251
@@ -242,11 +255,11 @@ where
242255 // get prefix elements
243256 let mut prefix_appendages = List :: empty ( ) ;
244257 loop {
245- let appendable = appendages. pop_front ( & mut appendables. 0 ) . cloned ( ) ;
258+ let appendable = appendages. pop_front ( & mut appendables. elements ) . cloned ( ) ;
246259 match appendable {
247260 Some ( appendage) => {
248- let is_cycle = appendage. start_node ( db) == end_node;
249- prefix_appendages. push_front ( & mut appendables. 0 , appendage) ;
261+ let is_cycle = appendage. start_node ( db, & appendables . interned ) == end_node;
262+ prefix_appendages. push_front ( & mut appendables. elements , appendage) ;
250263 if is_cycle {
251264 break ;
252265 }
@@ -257,8 +270,14 @@ where
257270
258271 // build prefix path -- prefix starts at end_node, because this is a cycle
259272 let mut prefix_path = PartialPath :: from_node ( graph, partials, end_node) ;
260- while let Some ( appendage) = prefix_appendages. pop_front ( & mut appendables. 0 ) {
261- appendage. append_to ( graph, partials, db, & mut prefix_path) ?;
273+ while let Some ( appendage) = prefix_appendages. pop_front ( & mut appendables. elements ) {
274+ appendage. append_to (
275+ graph,
276+ partials,
277+ db,
278+ & appendables. interned ,
279+ & mut prefix_path,
280+ ) ?;
262281 }
263282
264283 // build cyclic path
0 commit comments