| 
					
				 | 
			
			
				@@ -4,6 +4,8 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 //! Sets for lazily storing ordered, non-overlapping ranges of integers. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+use std::cmp; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+use std::iter; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 use std::slice; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 use std::str::FromStr; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 use std::u32; 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -240,8 +242,8 @@ impl ProtoSet { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         false 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    /// Retain only the `Version`s in this `ProtoSet` for which the predicate 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    /// `F` returns `true`. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /// Returns all the `Version`s in `self` which are not also in the `other` 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /// `ProtoSet`. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     /// 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     /// # Examples 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     /// 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -250,24 +252,45 @@ impl ProtoSet { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     /// use protover::protoset::ProtoSet; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     /// 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     /// # fn do_test() -> Result<bool, ProtoverError> { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    /// let mut protoset: ProtoSet = "1,3-5,9".parse()?; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /// let protoset: ProtoSet = "1,3-6,10-12,15-16".parse()?; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /// let other: ProtoSet = "2,5-7,9-11,14-20".parse()?; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     /// 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    /// // Keep only versions less than or equal to 8: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    /// protoset.retain(|x| x <= &8); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /// let subset: ProtoSet = protoset.and_not_in(&other); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     /// 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    /// assert_eq!(protoset.expand(), vec![1, 3, 4, 5]); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /// assert_eq!(subset.expand(), vec![1, 3, 4, 12]); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     /// # 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     /// # Ok(true) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     /// # } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     /// # fn main() { do_test(); }  // wrap the test so we can use the ? operator 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     /// ``` 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    // XXX we could probably do something more efficient here. —isis 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    pub fn retain<F>(&mut self, f: F) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        where F: FnMut(&Version) -> bool 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        let mut expanded: Vec<Version> = self.clone().expand(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        expanded.retain(f); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        *self = expanded.into(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    pub fn and_not_in(&self, other: &Self) -> Self { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if self.is_empty() || other.is_empty() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            return self.clone(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        let pairs = self.iter().flat_map(|&(lo, hi)| { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            let the_end = (hi + 1, hi + 1); // special case to mark the end of the range. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            let excluded_ranges = other 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                .iter() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                .cloned() // have to be owned tuples, to match iter::once(the_end). 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                .skip_while(move|&(_, hi2)| hi2 < lo) // skip the non-overlapping ranges. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                .take_while(move|&(lo2, _)| lo2 <= hi) // take all the overlapping ones. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                .chain(iter::once(the_end)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            let mut nextlo = lo; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            excluded_ranges.filter_map(move |(excluded_lo, excluded_hi)| { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                let pair = if nextlo < excluded_lo { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    Some((nextlo, excluded_lo - 1)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    None 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                nextlo = cmp::min(excluded_hi, u32::MAX - 1) + 1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                pair 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            }) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        let pairs = pairs.collect(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        ProtoSet::is_ok(ProtoSet{ pairs }).expect("should be already sorted") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 |