44//! It is a modified version of the `FlatZinc` type from [`flatzinc-serde`](https://docs.rs/flatzinc-serde).
55use std:: collections:: BTreeMap ;
66use std:: fmt:: Display ;
7+ use std:: iter:: FusedIterator ;
78use std:: ops:: RangeInclusive ;
89use std:: rc:: Rc ;
910
@@ -153,15 +154,26 @@ impl<E: PartialOrd> RangeList<E> {
153154 }
154155}
155156
156- impl RangeList < i64 > {
157- /// Obtain an iterator over the values in this set.
158- ///
159- /// Currently only implemented for `i64` elements, as that is what is used in the AST.
160- pub fn iter ( & self ) -> impl Iterator < Item = i64 > + ' _ {
161- self . intervals . iter ( ) . flat_map ( |& ( start, end) | start..=end)
162- }
157+ macro_rules! impl_iter_fn {
158+ ( $int_type: ty) => {
159+ impl <' a> IntoIterator for & ' a RangeList <$int_type> {
160+ type Item = $int_type;
161+
162+ type IntoIter = RangeListIter <' a, $int_type>;
163+
164+ fn into_iter( self ) -> Self :: IntoIter {
165+ RangeListIter {
166+ current_interval: self . intervals. first( ) . copied( ) . unwrap_or( ( 1 , 0 ) ) ,
167+ tail: & self . intervals[ 1 ..] ,
168+ }
169+ }
170+ }
171+ } ;
163172}
164173
174+ impl_iter_fn ! ( i32 ) ;
175+ impl_iter_fn ! ( i64 ) ;
176+
165177impl < E : Copy + Ord > From < RangeInclusive < E > > for RangeList < E > {
166178 fn from ( value : RangeInclusive < E > ) -> Self {
167179 RangeList {
@@ -170,15 +182,81 @@ impl<E: Copy + Ord> From<RangeInclusive<E>> for RangeList<E> {
170182 }
171183}
172184
173- impl < E : Copy + Ord > FromIterator < E > for RangeList < E > {
174- fn from_iter < T : IntoIterator < Item = E > > ( iter : T ) -> Self {
175- let mut intervals: Vec < _ > = iter. into_iter ( ) . map ( |e| ( e, e) ) . collect ( ) ;
176- intervals. sort ( ) ;
185+ macro_rules! range_list_from_iter {
186+ ( $int_type: ty) => {
187+ impl FromIterator <$int_type> for RangeList <$int_type> {
188+ fn from_iter<T : IntoIterator <Item = $int_type>>( iter: T ) -> Self {
189+ let mut intervals: Vec <_> = iter. into_iter( ) . map( |e| ( e, e) ) . collect( ) ;
190+ intervals. sort( ) ;
191+ intervals. dedup( ) ;
192+
193+ let mut idx = 0 ;
194+
195+ while idx < intervals. len( ) - 1 {
196+ let current = intervals[ idx] ;
197+ let next = intervals[ idx + 1 ] ;
198+
199+ if current. 1 >= next. 0 - 1 {
200+ intervals[ idx] = ( current. 0 , next. 1 ) ;
201+ let _ = intervals. remove( idx + 1 ) ;
202+ } else {
203+ idx += 1 ;
204+ }
205+ }
206+
207+ RangeList { intervals }
208+ }
209+ }
210+ } ;
211+ }
212+
213+ range_list_from_iter ! ( i32 ) ;
214+ range_list_from_iter ! ( i64 ) ;
177215
178- RangeList { intervals }
179- }
216+ /// An [`Iterator`] over a [`RangeList`].
217+ #[ derive( Debug ) ]
218+ pub struct RangeListIter < ' a , E > {
219+ current_interval : ( E , E ) ,
220+ tail : & ' a [ ( E , E ) ] ,
221+ }
222+
223+ macro_rules! impl_range_list_iter {
224+ ( $int_type: ty) => {
225+ impl <' a> RangeListIter <' a, $int_type> {
226+ fn new( intervals: & ' a [ ( $int_type, $int_type) ] ) -> Self {
227+ RangeListIter {
228+ current_interval: intervals. first( ) . copied( ) . unwrap_or( ( 1 , 0 ) ) ,
229+ tail: & intervals[ 1 ..] ,
230+ }
231+ }
232+ }
233+
234+ impl Iterator for RangeListIter <' _, $int_type> {
235+ type Item = $int_type;
236+
237+ fn next( & mut self ) -> Option <Self :: Item > {
238+ let ( current_lb, current_ub) = self . current_interval;
239+
240+ if current_lb > current_ub {
241+ let ( next_interval, new_tail) = self . tail. split_first( ) ?;
242+ self . current_interval = * next_interval;
243+ self . tail = new_tail;
244+ }
245+
246+ let current_lb = self . current_interval. 0 ;
247+ self . current_interval. 0 += 1 ;
248+
249+ Some ( current_lb)
250+ }
251+ }
252+
253+ impl FusedIterator for RangeListIter <' _, $int_type> { }
254+ } ;
180255}
181256
257+ impl_range_list_iter ! ( i32 ) ;
258+ impl_range_list_iter ! ( i64 ) ;
259+
182260/// A literal in the instance.
183261#[ derive( Clone , Debug , PartialEq , Eq ) ]
184262pub enum Literal {
@@ -265,3 +343,33 @@ pub enum AnnotationLiteral {
265343 /// `Annotation::Atom(ident)` or an `Literal::Identifier`.
266344 Annotation ( AnnotationCall ) ,
267345}
346+
347+ #[ cfg( test) ]
348+ mod tests {
349+ use super :: * ;
350+
351+ #[ test]
352+ fn rangelist_from_iter_identifies_continuous_ranges ( ) {
353+ let set = RangeList :: from_iter ( [ 1 , 2 , 3 , 4 ] ) ;
354+
355+ assert ! ( set. is_continuous( ) ) ;
356+ }
357+
358+ #[ test]
359+ fn rangelist_from_iter_identifiers_non_continuous_ranges ( ) {
360+ let set = RangeList :: from_iter ( [ 1 , 3 , 4 , 6 ] ) ;
361+
362+ assert ! ( !set. is_continuous( ) ) ;
363+ }
364+
365+ #[ test]
366+ fn rangelist_iter_produces_elements_in_set ( ) {
367+ let set: RangeList < i32 > = RangeList :: from_iter ( [ 1 , 3 , 5 ] ) ;
368+
369+ let mut iter = set. into_iter ( ) ;
370+ assert_eq ! ( Some ( 1 ) , iter. next( ) ) ;
371+ assert_eq ! ( Some ( 3 ) , iter. next( ) ) ;
372+ assert_eq ! ( Some ( 5 ) , iter. next( ) ) ;
373+ assert_eq ! ( None , iter. next( ) ) ;
374+ }
375+ }
0 commit comments