@@ -550,3 +550,95 @@ pub type FixedGFAStore<'a> = GFAStore<'a, FixedFamily>;
550550/// `FlatGFA`. It exposes an API for building up a GFA data structure, so it is
551551/// useful for creating new ones from scratch.
552552pub type HeapGFAStore = GFAStore < ' static , HeapFamily > ;
553+
554+
555+ pub struct StepRef {
556+ path : Id < Path > ,
557+ offset : u32
558+ }
559+
560+ pub struct StepsBySegIndex {
561+ steps : Vec < StepRef > ,
562+ segment_steps : Vec < Span < StepRef > >
563+ }
564+
565+
566+ impl StepsBySegIndex {
567+
568+ pub fn new ( fgfa : & FlatGFA ) -> Self {
569+
570+
571+ /// helper to extract the segment index from the stepref
572+ fn segment_of_step ( fgfa : & FlatGFA , step : & StepRef ) -> usize {
573+ let path = & fgfa. paths [ step. path ] ;
574+ let step_span = path. steps ;
575+ let step_slice = & fgfa. steps [ step_span] ;
576+ step_slice[ step. offset as usize ] . segment ( ) . index ( )
577+ }
578+
579+ // will be our `steps` vector that contains all steprefs
580+ let mut all_steps = Vec :: new ( ) ;
581+
582+ // build the vector of all the steprefs, by iterating over each path, so we can construct using a path id and offset
583+ for ( path_id, path) in fgfa. paths . items ( ) {
584+ for ( offset, _) in fgfa. get_path_steps ( path) . enumerate ( ) {
585+ all_steps. push ( StepRef {
586+ path : path_id,
587+ offset : offset as u32 ,
588+ } ) ;
589+ }
590+ }
591+
592+ // organize by the index of the segment in the segment pool
593+ all_steps. sort_by_key ( |a| {
594+ segment_of_step ( fgfa, a)
595+ } ) ;
596+
597+ // the working segment's index
598+ let mut seg_ind: usize = segment_of_step ( fgfa, & all_steps[ 0 ] ) ;
599+
600+ // the working start of the span of StepRefs
601+ let mut span_start: usize = 0 ;
602+
603+ // the vector of spans of step refs that will act as our index
604+ let mut segment_steps: Vec < Span < StepRef > > = Vec :: new ( ) ;
605+
606+
607+
608+ for ( i, step_ref) in all_steps. iter ( ) . enumerate ( ) {
609+ let curr_seg_ind: usize = segment_of_step ( fgfa, step_ref) ;
610+
611+ // if we have moved onto a new segment add to the segment_steps vec
612+ if curr_seg_ind > seg_ind {
613+ // create and push the new span of step refs for this segment
614+ // it will be left inclusive right exclusive
615+ let new_seg: Span < StepRef > = Span :: new ( Id :: new ( span_start) , Id :: new ( i) ) ;
616+ segment_steps. push ( new_seg) ;
617+
618+ // update the working seg_ind and range_start variables to reflect the new segment/range
619+ seg_ind = curr_seg_ind;
620+ span_start = i;
621+ }
622+
623+ }
624+
625+
626+ Self {
627+ steps : all_steps,
628+ segment_steps : segment_steps
629+ }
630+ }
631+
632+
633+ /// Returns a slice of StepRefs that cross over the given segment
634+ pub fn get_steps_slice ( & self , segment : Id < Segment > ) -> & [ StepRef ] {
635+ let range: Range < usize > = Range :: from ( & self . segment_steps [ segment. index ( ) ] ) ;
636+ & ( self . steps [ range] )
637+ }
638+
639+ /// Returns the number of steps that cross over this segment
640+ pub fn get_num_steps ( & self , segment : Id < Segment > ) -> usize {
641+ self . segment_steps [ segment. index ( ) ] . len ( )
642+ }
643+
644+ }
0 commit comments