3131
3232use enumset:: EnumSet ;
3333use smallvec:: SmallVec ;
34+ use std:: borrow:: Cow ;
3435use std:: collections:: HashMap ;
35- use std:: marker:: PhantomData ;
3636
3737use crate :: arena:: Handle ;
3838use crate :: arena:: List ;
3939use crate :: arena:: ListArena ;
40- use crate :: graph:: Edge ;
4140use crate :: graph:: Node ;
4241use crate :: graph:: StackGraph ;
4342use crate :: partial:: Cyclicity ;
4443use crate :: partial:: PartialPath ;
4544use crate :: partial:: PartialPaths ;
4645use crate :: paths:: PathResolutionError ;
46+ use crate :: stitching:: Appendable ;
4747use crate :: stitching:: Database ;
48- use crate :: stitching:: OwnedOrDatabasePath ;
4948
5049/// Helps detect similar paths in the path-finding algorithm.
5150pub struct SimilarPathDetector < P > {
@@ -130,68 +129,130 @@ where
130129// ----------------------------------------------------------------------------
131130// Cycle detector
132131
133- pub trait Appendable < Ctx > {
134- fn append_to (
132+ pub trait Index < ' a , H , A >
133+ where
134+ A : Appendable + Clone + ' a ,
135+ {
136+ fn get ( & ' a self , handle : & H ) -> Cow < ' a , A > ;
137+ }
138+
139+ impl < ' a > Index < ' a , Handle < PartialPath > , PartialPath > for Database {
140+ fn get ( & ' a self , handle : & Handle < PartialPath > ) -> Cow < ' a , PartialPath > {
141+ Cow :: Borrowed ( & self [ * handle] )
142+ }
143+ }
144+
145+ impl < ' a , A : Appendable + Clone + ' a > Index < ' a , A , A > for ( ) {
146+ fn get ( & self , value : & A ) -> Cow < ' a , A > {
147+ Cow :: Owned ( value. clone ( ) )
148+ }
149+ }
150+
151+ pub struct Appendables < H > ( pub ( crate ) ListArena < PathOrAppendable < H > > ) ;
152+
153+ impl < H > Appendables < H > {
154+ pub fn new ( ) -> Self {
155+ Self ( ListArena :: new ( ) )
156+ }
157+ }
158+
159+ #[ derive( Clone ) ]
160+ pub ( crate ) enum PathOrAppendable < H > {
161+ Path ( PartialPath ) ,
162+ Handle ( H ) ,
163+ }
164+
165+ impl < H > PathOrAppendable < H >
166+ where
167+ H : Clone ,
168+ {
169+ fn append_to < ' a , A , Db > (
135170 & self ,
136171 graph : & StackGraph ,
137172 partials : & mut PartialPaths ,
138- ctx : & mut Ctx ,
173+ db : & ' a Db ,
139174 path : & mut PartialPath ,
140- ) -> Result < ( ) , PathResolutionError > ;
141- fn start_node ( & self , ctx : & mut Ctx ) -> Handle < Node > ;
142- fn end_node ( & self , ctx : & mut Ctx ) -> Handle < Node > ;
143- }
175+ ) -> Result < ( ) , PathResolutionError >
176+ where
177+ A : Appendable + Clone + ' a ,
178+ Db : Index < ' a , H , A > ,
179+ {
180+ match self {
181+ Self :: Path ( other) => other. append_to ( graph, partials, path) ,
182+ Self :: Handle ( h) => db. get ( h) . append_to ( graph, partials, path) ,
183+ }
184+ }
144185
145- pub struct AppendingCycleDetector < Ctx , A >
146- where
147- A : Appendable < Ctx > ,
148- {
149- appendages : List < A > ,
150- ctx : PhantomData < Ctx > ,
151- }
186+ fn start_node < ' a , A , Db > ( & self , db : & ' a Db ) -> Handle < Node >
187+ where
188+ A : Appendable + Clone + ' a ,
189+ Db : Index < ' a , H , A > ,
190+ {
191+ match self {
192+ Self :: Path ( path) => path. start_node ,
193+ Self :: Handle ( h) => db. get ( h) . start_node ( ) ,
194+ }
195+ }
152196
153- impl < Ctx , A : Appendable < Ctx > > Clone for AppendingCycleDetector < Ctx , A > {
154- fn clone ( & self ) -> Self {
155- Self {
156- appendages : self . appendages . clone ( ) ,
157- ctx : PhantomData :: default ( ) ,
197+ fn end_node < ' a , A , Db > ( & self , db : & ' a Db ) -> Handle < Node >
198+ where
199+ A : Appendable + Clone + ' a ,
200+ Db : Index < ' a , H , A > ,
201+ {
202+ match self {
203+ Self :: Path ( path) => path. end_node ,
204+ Self :: Handle ( h) => db. get ( h) . end_node ( ) ,
158205 }
159206 }
160207}
161208
162- pub type Appendables < A > = ListArena < A > ;
209+ #[ derive( Clone ) ]
210+ pub struct AppendingCycleDetector < H > {
211+ appendages : List < PathOrAppendable < H > > ,
212+ }
163213
164- impl < Ctx , A : Appendable < Ctx > + Clone > AppendingCycleDetector < Ctx , A > {
214+ impl < H > AppendingCycleDetector < H > {
165215 pub fn new ( ) -> Self {
166216 Self {
167217 appendages : List :: empty ( ) ,
168- ctx : PhantomData :: default ( ) ,
169218 }
170219 }
171220
172- pub fn from ( appendables : & mut Appendables < A > , appendage : A ) -> Self {
221+ pub fn from ( appendables : & mut Appendables < H > , path : PartialPath ) -> Self {
173222 let mut result = Self :: new ( ) ;
174- result. appendages . push_front ( appendables, appendage) ;
223+ result
224+ . appendages
225+ . push_front ( & mut appendables. 0 , PathOrAppendable :: Path ( path) ) ;
175226 result
176227 }
177228
178- pub fn append ( & mut self , appendables : & mut Appendables < A > , appendage : A ) {
179- self . appendages . push_front ( appendables, appendage) ;
229+ pub fn append ( & mut self , appendables : & mut Appendables < H > , appendage : H ) {
230+ self . appendages
231+ . push_front ( & mut appendables. 0 , PathOrAppendable :: Handle ( appendage) ) ;
180232 }
233+ }
181234
235+ impl < H > AppendingCycleDetector < H >
236+ where
237+ H : Clone ,
238+ {
182239 /// Tests if the path is cyclic. Returns a vector indicating the kind of cycles that were found.
183240 /// If appending or concatenating all fragments succeeds, this function will never raise and error.
184- pub fn is_cyclic (
241+ pub fn is_cyclic < ' a , A , Db > (
185242 & self ,
186243 graph : & StackGraph ,
187244 partials : & mut PartialPaths ,
188- ctx : & mut Ctx ,
189- appendables : & mut Appendables < A > ,
190- ) -> Result < EnumSet < Cyclicity > , PathResolutionError > {
245+ db : & ' a Db ,
246+ appendables : & mut Appendables < H > ,
247+ ) -> Result < EnumSet < Cyclicity > , PathResolutionError >
248+ where
249+ A : Appendable + Clone + ' a ,
250+ Db : Index < ' a , H , A > ,
251+ {
191252 let mut cycles = EnumSet :: new ( ) ;
192253
193- let end_node = match self . appendages . clone ( ) . pop_front ( appendables) {
194- Some ( appendage) => appendage. end_node ( ctx ) ,
254+ let end_node = match self . appendages . clone ( ) . pop_front ( & mut appendables. 0 ) {
255+ Some ( appendage) => appendage. end_node ( db ) ,
195256 None => return Ok ( cycles) ,
196257 } ;
197258
@@ -201,11 +262,11 @@ impl<Ctx, A: Appendable<Ctx> + Clone> AppendingCycleDetector<Ctx, A> {
201262 // get prefix elements
202263 let mut prefix_appendages = List :: empty ( ) ;
203264 loop {
204- let appendable = appendages. pop_front ( appendables) . cloned ( ) ;
265+ let appendable = appendages. pop_front ( & mut appendables. 0 ) . cloned ( ) ;
205266 match appendable {
206267 Some ( appendage) => {
207- let is_cycle = appendage. start_node ( ctx ) == end_node;
208- prefix_appendages. push_front ( appendables, appendage) ;
268+ let is_cycle = appendage. start_node ( db ) == end_node;
269+ prefix_appendages. push_front ( & mut appendables. 0 , appendage) ;
209270 if is_cycle {
210271 break ;
211272 }
@@ -216,62 +277,18 @@ impl<Ctx, A: Appendable<Ctx> + Clone> AppendingCycleDetector<Ctx, A> {
216277
217278 // build prefix path -- prefix starts at end_node, because this is a cycle
218279 let mut prefix_path = PartialPath :: from_node ( graph, partials, end_node) ;
219- while let Some ( appendage) = prefix_appendages. pop_front ( appendables) {
220- prefix_path. resolve_to_node ( graph, partials, appendage. start_node ( ctx) ) ?;
221- appendage. append_to ( graph, partials, ctx, & mut prefix_path) ?;
280+ while let Some ( appendage) = prefix_appendages. pop_front ( & mut appendables. 0 ) {
281+ appendage. append_to ( graph, partials, db, & mut prefix_path) ?;
222282 }
223283
224284 // build cyclic path
225285 let cyclic_path = maybe_cyclic_path
226286 . unwrap_or_else ( || PartialPath :: from_node ( graph, partials, end_node) ) ;
227- prefix_path. resolve_to_node ( graph, partials, cyclic_path. start_node ) ?;
228- prefix_path. ensure_no_overlapping_variables ( partials, & cyclic_path) ;
229- prefix_path. concatenate ( graph, partials, & cyclic_path) ?;
287+ cyclic_path. append_to ( graph, partials, & mut prefix_path) ?;
230288 if let Some ( cyclicity) = prefix_path. is_cyclic ( graph, partials) {
231289 cycles |= cyclicity;
232290 }
233291 maybe_cyclic_path = Some ( prefix_path) ;
234292 }
235293 }
236294}
237-
238- impl Appendable < ( ) > for Edge {
239- fn append_to (
240- & self ,
241- graph : & StackGraph ,
242- partials : & mut PartialPaths ,
243- _: & mut ( ) ,
244- path : & mut PartialPath ,
245- ) -> Result < ( ) , PathResolutionError > {
246- path. append ( graph, partials, * self )
247- }
248-
249- fn start_node ( & self , _: & mut ( ) ) -> Handle < Node > {
250- self . source
251- }
252-
253- fn end_node ( & self , _: & mut ( ) ) -> Handle < Node > {
254- self . sink
255- }
256- }
257-
258- impl Appendable < Database > for OwnedOrDatabasePath {
259- fn append_to (
260- & self ,
261- graph : & StackGraph ,
262- partials : & mut PartialPaths ,
263- db : & mut Database ,
264- path : & mut PartialPath ,
265- ) -> Result < ( ) , PathResolutionError > {
266- path. ensure_no_overlapping_variables ( partials, self . get ( db) ) ;
267- path. concatenate ( graph, partials, self . get ( db) )
268- }
269-
270- fn start_node ( & self , db : & mut Database ) -> Handle < Node > {
271- self . get ( db) . start_node
272- }
273-
274- fn end_node ( & self , db : & mut Database ) -> Handle < Node > {
275- self . get ( db) . end_node
276- }
277- }
0 commit comments