11use std:: {
22 cmp:: { Ordering , max} ,
3- collections:: VecDeque ,
3+ collections:: { HashSet , VecDeque } ,
44 fmt:: Debug ,
55 iter:: Rev ,
66 mem,
@@ -37,44 +37,71 @@ pub struct SequenceSet(pub Vec1<Sequence>);
3737
3838impl SequenceSet {
3939 pub fn normalize ( & mut self ) -> & mut Self {
40+ let mut singles = HashSet :: with_capacity ( self . 0 . 0 . len ( ) ) ;
41+ let mut ranges = Vec :: with_capacity ( self . 0 . 0 . len ( ) ) ;
42+
43+ // First, normalize all sequences
4044 for seq in & mut self . 0 . 0 {
41- seq. normalize ( ) ;
45+ match seq. normalize ( ) {
46+ Sequence :: Single ( id) => {
47+ singles. insert ( id. to_non_zero_u32 ( ) ) ;
48+ // Push a 1-lenth range so they can merge nicely
49+ // later on
50+ ranges. push ( id. to_non_zero_u32 ( ) ..id. to_non_zero_u32 ( ) . saturating_add ( 1 ) ) ;
51+ }
52+ Sequence :: Range ( a, b) => {
53+ ranges. push ( a. to_non_zero_u32 ( ) ..b. to_non_zero_u32 ( ) . saturating_add ( 1 ) ) ;
54+ }
55+ }
4256 }
4357
44- let set = & mut self . 0 . 0 ;
45-
46- if set. len ( ) == 1 {
47- return self ;
58+ // TODO: Improve this loop, for eg. with a .retain().
59+ for single in singles. clone ( ) {
60+ for range in & mut ranges {
61+ if single. get ( ) == range. start . get ( ) . max ( 2 ) - 1 {
62+ singles. remove ( & single) ;
63+ range. start = single;
64+ } else if single. get ( ) == range. end . get ( ) {
65+ singles. remove ( & single) ;
66+ range. end = single;
67+ } else if range. contains ( & single) {
68+ singles. remove ( & single) ;
69+ }
70+ }
4871 }
4972
50- set. sort_by ( |a, b| a. partial_cmp ( b) . unwrap_or ( Ordering :: Equal ) ) ;
51-
52- let mut a = 0 ;
53- let mut b = 1 ;
54-
55- while b < set. len ( ) {
56- if set[ a] . partial_cmp ( & set[ b] ) . is_some ( ) {
57- a += 1 ;
58- b += 1 ;
59- continue ;
60- }
73+ // Rebuild the inner sequence set with merged ranges
74+ self . 0 . 0 . clear ( ) ;
75+ for range in merge_ranges ( ranges) {
76+ singles. retain ( |single| !range. contains ( single) ) ;
6177
62- match ( & set[ a] , & set[ b] ) {
63- ( Sequence :: Single ( _) , _) => {
64- set. remove ( a) ;
78+ match ( range. start , range. end ) {
79+ ( a, b) if a == b || a. saturating_add ( 1 ) == b => {
80+ let a = NonZeroU32 :: new ( a. get ( ) ) . unwrap ( ) ;
81+ self . 0 . 0 . push ( Sequence :: Single ( a. into ( ) ) ) ;
6582 }
66- ( Sequence :: Range ( _ , _ ) , Sequence :: Single ( _ ) ) => {
67- set . remove ( b ) ;
83+ ( a , NonZeroU32 :: MAX ) => {
84+ self . 0 . 0 . push ( Sequence :: Range ( a . into ( ) , SeqOrUid :: Asterisk ) )
6885 }
69- ( Sequence :: Range ( a1, a2) , Sequence :: Range ( b1, b2) ) => {
70- let min = a1. clone ( ) . min ( a2. clone ( ) ) . min ( b1. clone ( ) ) . min ( b2. clone ( ) ) ;
71- let max = a1. clone ( ) . max ( a2. clone ( ) ) . max ( b1. clone ( ) ) . max ( b2. clone ( ) ) ;
72- let _ = mem:: replace ( & mut set[ a] , Sequence :: Range ( min, max) ) ;
73- set. remove ( b) ;
86+ ( a, b) => {
87+ let b = NonZeroU32 :: new ( b. get ( ) . max ( 2 ) - 1 ) . unwrap ( ) ;
88+ self . 0 . 0 . push ( Sequence :: Range ( a. into ( ) , b. into ( ) ) ) ;
7489 }
7590 }
7691 }
7792
93+ // Add remaining singles that don't belong to any range to the
94+ // sequence set
95+ for single in singles {
96+ self . 0 . 0 . push ( single. into ( ) ) ;
97+ }
98+
99+ // Sort the merged sequence set
100+ self . 0 . 0 . sort_by_key ( |seq| match seq {
101+ Sequence :: Single ( a) => a. to_non_zero_u32 ( ) ,
102+ Sequence :: Range ( a, _) => a. to_non_zero_u32 ( ) ,
103+ } ) ;
104+
78105 self
79106 }
80107}
@@ -188,22 +215,17 @@ pub enum Sequence {
188215impl Sequence {
189216 pub fn normalize ( & mut self ) -> & mut Self {
190217 match self {
191- Sequence :: Single ( SeqOrUid :: Asterisk ) => {
192- let begin = NonZeroU32 :: new ( 1 ) . unwrap ( ) ;
193- let range = Sequence :: Range ( begin. into ( ) , SeqOrUid :: Asterisk ) ;
194- let _ = mem:: replace ( self , range) ;
195- }
196- Sequence :: Range ( SeqOrUid :: Value ( a) , SeqOrUid :: Value ( b) ) if * a == * b => {
197- let range = Sequence :: Single ( a. clone ( ) . into ( ) ) ;
218+ Sequence :: Range ( a, b) if * a == * b => {
219+ let range = Sequence :: Single ( ( * a) . into ( ) ) ;
198220 let _ = mem:: replace ( self , range) ;
199221 }
200- Sequence :: Range ( SeqOrUid :: Value ( a ) , SeqOrUid :: Value ( b ) ) if * a > * b => {
222+ Sequence :: Range ( a , b ) if * a > * b => {
201223 mem:: swap ( a, b) ;
202224 }
203225 _ => {
204226 // already normalized
205227 }
206- }
228+ } ;
207229
208230 self
209231 }
@@ -302,13 +324,22 @@ pub enum SeqOrUid {
302324 Asterisk ,
303325}
304326
327+ impl SeqOrUid {
328+ pub fn to_non_zero_u32 ( & self ) -> NonZeroU32 {
329+ match self {
330+ SeqOrUid :: Value ( n) => * n,
331+ SeqOrUid :: Asterisk => NonZeroU32 :: MAX ,
332+ }
333+ }
334+ }
335+
305336impl Ord for SeqOrUid {
306337 fn cmp ( & self , other : & Self ) -> Ordering {
307338 match ( self , other) {
308- ( SeqOrUid :: Asterisk , SeqOrUid :: Asterisk ) => Ordering :: Equal ,
309- ( _, SeqOrUid :: Asterisk ) => Ordering :: Greater ,
310- ( SeqOrUid :: Asterisk , _) => Ordering :: Less ,
311339 ( SeqOrUid :: Value ( a) , SeqOrUid :: Value ( b) ) => a. cmp ( b) ,
340+ ( SeqOrUid :: Asterisk , SeqOrUid :: Asterisk ) => Ordering :: Equal ,
341+ ( _, SeqOrUid :: Asterisk ) => Ordering :: Less ,
342+ ( SeqOrUid :: Asterisk , _) => Ordering :: Greater ,
312343 }
313344 }
314345}
@@ -321,7 +352,11 @@ impl PartialOrd for SeqOrUid {
321352
322353impl From < NonZeroU32 > for SeqOrUid {
323354 fn from ( value : NonZeroU32 ) -> Self {
324- Self :: Value ( value)
355+ if value == NonZeroU32 :: MAX {
356+ Self :: Asterisk
357+ } else {
358+ Self :: Value ( value)
359+ }
325360 }
326361}
327362
@@ -742,6 +777,28 @@ fn cleanup(remaining: VecDeque<(u32, u32)>) -> VecDeque<(u32, u32)> {
742777 stack
743778}
744779
780+ fn merge_ranges < T : Ord + Copy > ( mut ranges : Vec < Range < T > > ) -> Vec < Range < T > > {
781+ if ranges. is_empty ( ) {
782+ return ranges;
783+ }
784+
785+ ranges. sort_unstable_by_key ( |r| r. start ) ;
786+
787+ let mut merged = Vec :: with_capacity ( ranges. len ( ) ) ;
788+ merged. push ( ranges[ 0 ] . clone ( ) ) ;
789+
790+ for range in ranges. into_iter ( ) . skip ( 1 ) {
791+ let last = merged. last_mut ( ) . unwrap ( ) ;
792+ if range. start < last. end {
793+ last. end = last. end . max ( range. end ) ;
794+ } else {
795+ merged. push ( range) ;
796+ }
797+ }
798+
799+ merged
800+ }
801+
745802#[ cfg( test) ]
746803mod tests {
747804 use std:: num:: NonZeroU32 ;
@@ -1022,12 +1079,40 @@ mod tests {
10221079 }
10231080 }
10241081
1082+ #[ test]
1083+ fn ordering_sequence ( ) {
1084+ let tests = vec ! [
1085+ ( "1" , "1" , Some ( Ordering :: Equal ) ) ,
1086+ ( "1" , "2" , Some ( Ordering :: Less ) ) ,
1087+ ( "2" , "1" , Some ( Ordering :: Greater ) ) ,
1088+ ( "1" , "2:4" , Some ( Ordering :: Less ) ) ,
1089+ ( "2" , "2:4" , None ) ,
1090+ ( "4" , "2:4" , None ) ,
1091+ ( "7" , "2:4" , Some ( Ordering :: Greater ) ) ,
1092+ ( "2:4" , "1" , Some ( Ordering :: Greater ) ) ,
1093+ ( "2:4" , "2" , None ) ,
1094+ ( "2:4" , "4" , None ) ,
1095+ ( "2:4" , "7" , Some ( Ordering :: Less ) ) ,
1096+ ( "1:2" , "3:4" , Some ( Ordering :: Less ) ) ,
1097+ ( "3:4" , "1:2" , Some ( Ordering :: Greater ) ) ,
1098+ ( "1:2" , "2:4" , None ) ,
1099+ ( "2:4" , "3:8" , None ) ,
1100+ ] ;
1101+
1102+ for ( a, b, expected) in tests {
1103+ let a = Sequence :: try_from ( a) . unwrap ( ) ;
1104+ let b = Sequence :: try_from ( b) . unwrap ( ) ;
1105+ let got = a. partial_cmp ( & b) ;
1106+
1107+ assert_eq ! ( expected, got) ;
1108+ }
1109+ }
1110+
10251111 #[ test]
10261112 fn normalize_sequence ( ) {
10271113 let tests = vec ! [
1028- ( "*" , "1:*" ) ,
10291114 ( "1:*" , "1:*" ) ,
1030- ( "*:1" , "*:1 " ) ,
1115+ ( "*:1" , "1:* " ) ,
10311116 ( "1" , "1" ) ,
10321117 ( "1:1" , "1" ) ,
10331118 ( "1:2" , "1:2" ) ,
@@ -1045,16 +1130,17 @@ mod tests {
10451130 #[ test]
10461131 fn normalize_sequence_set ( ) {
10471132 let tests = [
1048- ( "1,2,3,4" , "1,2,3,4" ) ,
1049- ( "3,1,2,4" , "1,2,3,4" ) ,
1133+ ( "1,2,3,4" , "1:4" ) ,
1134+ ( "4,1,3,2" , "1:4" ) ,
1135+ ( "3,1,2,4" , "1:4" ) ,
10501136 ( "3:1,5" , "1:3,5" ) ,
10511137 ( "5,3:1" , "1:3,5" ) ,
10521138 ( "3,3:1" , "1:3" ) ,
10531139 ( "3:1,1" , "1:3" ) ,
10541140 ( "3:1,2:5" , "1:5" ) ,
10551141 ( "3:1,4:9" , "1:3,4:9" ) ,
10561142 ( "9:4,3:1" , "1:3,4:9" ) ,
1057- ( "8:10,3:1,2:5,9" , "1:5,8:10" ) ,
1143+ ( "8:10,12, 3:1,2:5,9" , "1:5,8:10,12 " ) ,
10581144 ] ;
10591145
10601146 for ( test, expected) in tests {
0 commit comments