1c67d6573Sopenharmony_ciuse std::char; 2c67d6573Sopenharmony_ciuse std::cmp; 3c67d6573Sopenharmony_ciuse std::fmt::Debug; 4c67d6573Sopenharmony_ciuse std::slice; 5c67d6573Sopenharmony_ciuse std::u8; 6c67d6573Sopenharmony_ci 7c67d6573Sopenharmony_ciuse crate::unicode; 8c67d6573Sopenharmony_ci 9c67d6573Sopenharmony_ci// This module contains an *internal* implementation of interval sets. 10c67d6573Sopenharmony_ci// 11c67d6573Sopenharmony_ci// The primary invariant that interval sets guards is canonical ordering. That 12c67d6573Sopenharmony_ci// is, every interval set contains an ordered sequence of intervals where 13c67d6573Sopenharmony_ci// no two intervals are overlapping or adjacent. While this invariant is 14c67d6573Sopenharmony_ci// occasionally broken within the implementation, it should be impossible for 15c67d6573Sopenharmony_ci// callers to observe it. 16c67d6573Sopenharmony_ci// 17c67d6573Sopenharmony_ci// Since case folding (as implemented below) breaks that invariant, we roll 18c67d6573Sopenharmony_ci// that into this API even though it is a little out of place in an otherwise 19c67d6573Sopenharmony_ci// generic interval set. (Hence the reason why the `unicode` module is imported 20c67d6573Sopenharmony_ci// here.) 21c67d6573Sopenharmony_ci// 22c67d6573Sopenharmony_ci// Some of the implementation complexity here is a result of me wanting to 23c67d6573Sopenharmony_ci// preserve the sequential representation without using additional memory. 24c67d6573Sopenharmony_ci// In many cases, we do use linear extra memory, but it is at most 2x and it 25c67d6573Sopenharmony_ci// is amortized. If we relaxed the memory requirements, this implementation 26c67d6573Sopenharmony_ci// could become much simpler. The extra memory is honestly probably OK, but 27c67d6573Sopenharmony_ci// character classes (especially of the Unicode variety) can become quite 28c67d6573Sopenharmony_ci// large, and it would be nice to keep regex compilation snappy even in debug 29c67d6573Sopenharmony_ci// builds. (In the past, I have been careless with this area of code and it has 30c67d6573Sopenharmony_ci// caused slow regex compilations in debug mode, so this isn't entirely 31c67d6573Sopenharmony_ci// unwarranted.) 32c67d6573Sopenharmony_ci// 33c67d6573Sopenharmony_ci// Tests on this are relegated to the public API of HIR in src/hir.rs. 34c67d6573Sopenharmony_ci 35c67d6573Sopenharmony_ci#[derive(Clone, Debug, Eq, PartialEq)] 36c67d6573Sopenharmony_cipub struct IntervalSet<I> { 37c67d6573Sopenharmony_ci ranges: Vec<I>, 38c67d6573Sopenharmony_ci} 39c67d6573Sopenharmony_ci 40c67d6573Sopenharmony_ciimpl<I: Interval> IntervalSet<I> { 41c67d6573Sopenharmony_ci /// Create a new set from a sequence of intervals. Each interval is 42c67d6573Sopenharmony_ci /// specified as a pair of bounds, where both bounds are inclusive. 43c67d6573Sopenharmony_ci /// 44c67d6573Sopenharmony_ci /// The given ranges do not need to be in any specific order, and ranges 45c67d6573Sopenharmony_ci /// may overlap. 46c67d6573Sopenharmony_ci pub fn new<T: IntoIterator<Item = I>>(intervals: T) -> IntervalSet<I> { 47c67d6573Sopenharmony_ci let mut set = IntervalSet { ranges: intervals.into_iter().collect() }; 48c67d6573Sopenharmony_ci set.canonicalize(); 49c67d6573Sopenharmony_ci set 50c67d6573Sopenharmony_ci } 51c67d6573Sopenharmony_ci 52c67d6573Sopenharmony_ci /// Add a new interval to this set. 53c67d6573Sopenharmony_ci pub fn push(&mut self, interval: I) { 54c67d6573Sopenharmony_ci // TODO: This could be faster. e.g., Push the interval such that 55c67d6573Sopenharmony_ci // it preserves canonicalization. 56c67d6573Sopenharmony_ci self.ranges.push(interval); 57c67d6573Sopenharmony_ci self.canonicalize(); 58c67d6573Sopenharmony_ci } 59c67d6573Sopenharmony_ci 60c67d6573Sopenharmony_ci /// Return an iterator over all intervals in this set. 61c67d6573Sopenharmony_ci /// 62c67d6573Sopenharmony_ci /// The iterator yields intervals in ascending order. 63c67d6573Sopenharmony_ci pub fn iter(&self) -> IntervalSetIter<'_, I> { 64c67d6573Sopenharmony_ci IntervalSetIter(self.ranges.iter()) 65c67d6573Sopenharmony_ci } 66c67d6573Sopenharmony_ci 67c67d6573Sopenharmony_ci /// Return an immutable slice of intervals in this set. 68c67d6573Sopenharmony_ci /// 69c67d6573Sopenharmony_ci /// The sequence returned is in canonical ordering. 70c67d6573Sopenharmony_ci pub fn intervals(&self) -> &[I] { 71c67d6573Sopenharmony_ci &self.ranges 72c67d6573Sopenharmony_ci } 73c67d6573Sopenharmony_ci 74c67d6573Sopenharmony_ci /// Expand this interval set such that it contains all case folded 75c67d6573Sopenharmony_ci /// characters. For example, if this class consists of the range `a-z`, 76c67d6573Sopenharmony_ci /// then applying case folding will result in the class containing both the 77c67d6573Sopenharmony_ci /// ranges `a-z` and `A-Z`. 78c67d6573Sopenharmony_ci /// 79c67d6573Sopenharmony_ci /// This returns an error if the necessary case mapping data is not 80c67d6573Sopenharmony_ci /// available. 81c67d6573Sopenharmony_ci pub fn case_fold_simple(&mut self) -> Result<(), unicode::CaseFoldError> { 82c67d6573Sopenharmony_ci let len = self.ranges.len(); 83c67d6573Sopenharmony_ci for i in 0..len { 84c67d6573Sopenharmony_ci let range = self.ranges[i]; 85c67d6573Sopenharmony_ci if let Err(err) = range.case_fold_simple(&mut self.ranges) { 86c67d6573Sopenharmony_ci self.canonicalize(); 87c67d6573Sopenharmony_ci return Err(err); 88c67d6573Sopenharmony_ci } 89c67d6573Sopenharmony_ci } 90c67d6573Sopenharmony_ci self.canonicalize(); 91c67d6573Sopenharmony_ci Ok(()) 92c67d6573Sopenharmony_ci } 93c67d6573Sopenharmony_ci 94c67d6573Sopenharmony_ci /// Union this set with the given set, in place. 95c67d6573Sopenharmony_ci pub fn union(&mut self, other: &IntervalSet<I>) { 96c67d6573Sopenharmony_ci // This could almost certainly be done more efficiently. 97c67d6573Sopenharmony_ci self.ranges.extend(&other.ranges); 98c67d6573Sopenharmony_ci self.canonicalize(); 99c67d6573Sopenharmony_ci } 100c67d6573Sopenharmony_ci 101c67d6573Sopenharmony_ci /// Intersect this set with the given set, in place. 102c67d6573Sopenharmony_ci pub fn intersect(&mut self, other: &IntervalSet<I>) { 103c67d6573Sopenharmony_ci if self.ranges.is_empty() { 104c67d6573Sopenharmony_ci return; 105c67d6573Sopenharmony_ci } 106c67d6573Sopenharmony_ci if other.ranges.is_empty() { 107c67d6573Sopenharmony_ci self.ranges.clear(); 108c67d6573Sopenharmony_ci return; 109c67d6573Sopenharmony_ci } 110c67d6573Sopenharmony_ci 111c67d6573Sopenharmony_ci // There should be a way to do this in-place with constant memory, 112c67d6573Sopenharmony_ci // but I couldn't figure out a simple way to do it. So just append 113c67d6573Sopenharmony_ci // the intersection to the end of this range, and then drain it before 114c67d6573Sopenharmony_ci // we're done. 115c67d6573Sopenharmony_ci let drain_end = self.ranges.len(); 116c67d6573Sopenharmony_ci 117c67d6573Sopenharmony_ci let mut ita = 0..drain_end; 118c67d6573Sopenharmony_ci let mut itb = 0..other.ranges.len(); 119c67d6573Sopenharmony_ci let mut a = ita.next().unwrap(); 120c67d6573Sopenharmony_ci let mut b = itb.next().unwrap(); 121c67d6573Sopenharmony_ci loop { 122c67d6573Sopenharmony_ci if let Some(ab) = self.ranges[a].intersect(&other.ranges[b]) { 123c67d6573Sopenharmony_ci self.ranges.push(ab); 124c67d6573Sopenharmony_ci } 125c67d6573Sopenharmony_ci let (it, aorb) = 126c67d6573Sopenharmony_ci if self.ranges[a].upper() < other.ranges[b].upper() { 127c67d6573Sopenharmony_ci (&mut ita, &mut a) 128c67d6573Sopenharmony_ci } else { 129c67d6573Sopenharmony_ci (&mut itb, &mut b) 130c67d6573Sopenharmony_ci }; 131c67d6573Sopenharmony_ci match it.next() { 132c67d6573Sopenharmony_ci Some(v) => *aorb = v, 133c67d6573Sopenharmony_ci None => break, 134c67d6573Sopenharmony_ci } 135c67d6573Sopenharmony_ci } 136c67d6573Sopenharmony_ci self.ranges.drain(..drain_end); 137c67d6573Sopenharmony_ci } 138c67d6573Sopenharmony_ci 139c67d6573Sopenharmony_ci /// Subtract the given set from this set, in place. 140c67d6573Sopenharmony_ci pub fn difference(&mut self, other: &IntervalSet<I>) { 141c67d6573Sopenharmony_ci if self.ranges.is_empty() || other.ranges.is_empty() { 142c67d6573Sopenharmony_ci return; 143c67d6573Sopenharmony_ci } 144c67d6573Sopenharmony_ci 145c67d6573Sopenharmony_ci // This algorithm is (to me) surprisingly complex. A search of the 146c67d6573Sopenharmony_ci // interwebs indicate that this is a potentially interesting problem. 147c67d6573Sopenharmony_ci // Folks seem to suggest interval or segment trees, but I'd like to 148c67d6573Sopenharmony_ci // avoid the overhead (both runtime and conceptual) of that. 149c67d6573Sopenharmony_ci // 150c67d6573Sopenharmony_ci // The following is basically my Shitty First Draft. Therefore, in 151c67d6573Sopenharmony_ci // order to grok it, you probably need to read each line carefully. 152c67d6573Sopenharmony_ci // Simplifications are most welcome! 153c67d6573Sopenharmony_ci // 154c67d6573Sopenharmony_ci // Remember, we can assume the canonical format invariant here, which 155c67d6573Sopenharmony_ci // says that all ranges are sorted, not overlapping and not adjacent in 156c67d6573Sopenharmony_ci // each class. 157c67d6573Sopenharmony_ci let drain_end = self.ranges.len(); 158c67d6573Sopenharmony_ci let (mut a, mut b) = (0, 0); 159c67d6573Sopenharmony_ci 'LOOP: while a < drain_end && b < other.ranges.len() { 160c67d6573Sopenharmony_ci // Basically, the easy cases are when neither range overlaps with 161c67d6573Sopenharmony_ci // each other. If the `b` range is less than our current `a` 162c67d6573Sopenharmony_ci // range, then we can skip it and move on. 163c67d6573Sopenharmony_ci if other.ranges[b].upper() < self.ranges[a].lower() { 164c67d6573Sopenharmony_ci b += 1; 165c67d6573Sopenharmony_ci continue; 166c67d6573Sopenharmony_ci } 167c67d6573Sopenharmony_ci // ... similarly for the `a` range. If it's less than the smallest 168c67d6573Sopenharmony_ci // `b` range, then we can add it as-is. 169c67d6573Sopenharmony_ci if self.ranges[a].upper() < other.ranges[b].lower() { 170c67d6573Sopenharmony_ci let range = self.ranges[a]; 171c67d6573Sopenharmony_ci self.ranges.push(range); 172c67d6573Sopenharmony_ci a += 1; 173c67d6573Sopenharmony_ci continue; 174c67d6573Sopenharmony_ci } 175c67d6573Sopenharmony_ci // Otherwise, we have overlapping ranges. 176c67d6573Sopenharmony_ci assert!(!self.ranges[a].is_intersection_empty(&other.ranges[b])); 177c67d6573Sopenharmony_ci 178c67d6573Sopenharmony_ci // This part is tricky and was non-obvious to me without looking 179c67d6573Sopenharmony_ci // at explicit examples (see the tests). The trickiness stems from 180c67d6573Sopenharmony_ci // two things: 1) subtracting a range from another range could 181c67d6573Sopenharmony_ci // yield two ranges and 2) after subtracting a range, it's possible 182c67d6573Sopenharmony_ci // that future ranges can have an impact. The loop below advances 183c67d6573Sopenharmony_ci // the `b` ranges until they can't possible impact the current 184c67d6573Sopenharmony_ci // range. 185c67d6573Sopenharmony_ci // 186c67d6573Sopenharmony_ci // For example, if our `a` range is `a-t` and our next three `b` 187c67d6573Sopenharmony_ci // ranges are `a-c`, `g-i`, `r-t` and `x-z`, then we need to apply 188c67d6573Sopenharmony_ci // subtraction three times before moving on to the next `a` range. 189c67d6573Sopenharmony_ci let mut range = self.ranges[a]; 190c67d6573Sopenharmony_ci while b < other.ranges.len() 191c67d6573Sopenharmony_ci && !range.is_intersection_empty(&other.ranges[b]) 192c67d6573Sopenharmony_ci { 193c67d6573Sopenharmony_ci let old_range = range; 194c67d6573Sopenharmony_ci range = match range.difference(&other.ranges[b]) { 195c67d6573Sopenharmony_ci (None, None) => { 196c67d6573Sopenharmony_ci // We lost the entire range, so move on to the next 197c67d6573Sopenharmony_ci // without adding this one. 198c67d6573Sopenharmony_ci a += 1; 199c67d6573Sopenharmony_ci continue 'LOOP; 200c67d6573Sopenharmony_ci } 201c67d6573Sopenharmony_ci (Some(range1), None) | (None, Some(range1)) => range1, 202c67d6573Sopenharmony_ci (Some(range1), Some(range2)) => { 203c67d6573Sopenharmony_ci self.ranges.push(range1); 204c67d6573Sopenharmony_ci range2 205c67d6573Sopenharmony_ci } 206c67d6573Sopenharmony_ci }; 207c67d6573Sopenharmony_ci // It's possible that the `b` range has more to contribute 208c67d6573Sopenharmony_ci // here. In particular, if it is greater than the original 209c67d6573Sopenharmony_ci // range, then it might impact the next `a` range *and* it 210c67d6573Sopenharmony_ci // has impacted the current `a` range as much as possible, 211c67d6573Sopenharmony_ci // so we can quit. We don't bump `b` so that the next `a` 212c67d6573Sopenharmony_ci // range can apply it. 213c67d6573Sopenharmony_ci if other.ranges[b].upper() > old_range.upper() { 214c67d6573Sopenharmony_ci break; 215c67d6573Sopenharmony_ci } 216c67d6573Sopenharmony_ci // Otherwise, the next `b` range might apply to the current 217c67d6573Sopenharmony_ci // `a` range. 218c67d6573Sopenharmony_ci b += 1; 219c67d6573Sopenharmony_ci } 220c67d6573Sopenharmony_ci self.ranges.push(range); 221c67d6573Sopenharmony_ci a += 1; 222c67d6573Sopenharmony_ci } 223c67d6573Sopenharmony_ci while a < drain_end { 224c67d6573Sopenharmony_ci let range = self.ranges[a]; 225c67d6573Sopenharmony_ci self.ranges.push(range); 226c67d6573Sopenharmony_ci a += 1; 227c67d6573Sopenharmony_ci } 228c67d6573Sopenharmony_ci self.ranges.drain(..drain_end); 229c67d6573Sopenharmony_ci } 230c67d6573Sopenharmony_ci 231c67d6573Sopenharmony_ci /// Compute the symmetric difference of the two sets, in place. 232c67d6573Sopenharmony_ci /// 233c67d6573Sopenharmony_ci /// This computes the symmetric difference of two interval sets. This 234c67d6573Sopenharmony_ci /// removes all elements in this set that are also in the given set, 235c67d6573Sopenharmony_ci /// but also adds all elements from the given set that aren't in this 236c67d6573Sopenharmony_ci /// set. That is, the set will contain all elements in either set, 237c67d6573Sopenharmony_ci /// but will not contain any elements that are in both sets. 238c67d6573Sopenharmony_ci pub fn symmetric_difference(&mut self, other: &IntervalSet<I>) { 239c67d6573Sopenharmony_ci // TODO(burntsushi): Fix this so that it amortizes allocation. 240c67d6573Sopenharmony_ci let mut intersection = self.clone(); 241c67d6573Sopenharmony_ci intersection.intersect(other); 242c67d6573Sopenharmony_ci self.union(other); 243c67d6573Sopenharmony_ci self.difference(&intersection); 244c67d6573Sopenharmony_ci } 245c67d6573Sopenharmony_ci 246c67d6573Sopenharmony_ci /// Negate this interval set. 247c67d6573Sopenharmony_ci /// 248c67d6573Sopenharmony_ci /// For all `x` where `x` is any element, if `x` was in this set, then it 249c67d6573Sopenharmony_ci /// will not be in this set after negation. 250c67d6573Sopenharmony_ci pub fn negate(&mut self) { 251c67d6573Sopenharmony_ci if self.ranges.is_empty() { 252c67d6573Sopenharmony_ci let (min, max) = (I::Bound::min_value(), I::Bound::max_value()); 253c67d6573Sopenharmony_ci self.ranges.push(I::create(min, max)); 254c67d6573Sopenharmony_ci return; 255c67d6573Sopenharmony_ci } 256c67d6573Sopenharmony_ci 257c67d6573Sopenharmony_ci // There should be a way to do this in-place with constant memory, 258c67d6573Sopenharmony_ci // but I couldn't figure out a simple way to do it. So just append 259c67d6573Sopenharmony_ci // the negation to the end of this range, and then drain it before 260c67d6573Sopenharmony_ci // we're done. 261c67d6573Sopenharmony_ci let drain_end = self.ranges.len(); 262c67d6573Sopenharmony_ci 263c67d6573Sopenharmony_ci // We do checked arithmetic below because of the canonical ordering 264c67d6573Sopenharmony_ci // invariant. 265c67d6573Sopenharmony_ci if self.ranges[0].lower() > I::Bound::min_value() { 266c67d6573Sopenharmony_ci let upper = self.ranges[0].lower().decrement(); 267c67d6573Sopenharmony_ci self.ranges.push(I::create(I::Bound::min_value(), upper)); 268c67d6573Sopenharmony_ci } 269c67d6573Sopenharmony_ci for i in 1..drain_end { 270c67d6573Sopenharmony_ci let lower = self.ranges[i - 1].upper().increment(); 271c67d6573Sopenharmony_ci let upper = self.ranges[i].lower().decrement(); 272c67d6573Sopenharmony_ci self.ranges.push(I::create(lower, upper)); 273c67d6573Sopenharmony_ci } 274c67d6573Sopenharmony_ci if self.ranges[drain_end - 1].upper() < I::Bound::max_value() { 275c67d6573Sopenharmony_ci let lower = self.ranges[drain_end - 1].upper().increment(); 276c67d6573Sopenharmony_ci self.ranges.push(I::create(lower, I::Bound::max_value())); 277c67d6573Sopenharmony_ci } 278c67d6573Sopenharmony_ci self.ranges.drain(..drain_end); 279c67d6573Sopenharmony_ci } 280c67d6573Sopenharmony_ci 281c67d6573Sopenharmony_ci /// Converts this set into a canonical ordering. 282c67d6573Sopenharmony_ci fn canonicalize(&mut self) { 283c67d6573Sopenharmony_ci if self.is_canonical() { 284c67d6573Sopenharmony_ci return; 285c67d6573Sopenharmony_ci } 286c67d6573Sopenharmony_ci self.ranges.sort(); 287c67d6573Sopenharmony_ci assert!(!self.ranges.is_empty()); 288c67d6573Sopenharmony_ci 289c67d6573Sopenharmony_ci // Is there a way to do this in-place with constant memory? I couldn't 290c67d6573Sopenharmony_ci // figure out a way to do it. So just append the canonicalization to 291c67d6573Sopenharmony_ci // the end of this range, and then drain it before we're done. 292c67d6573Sopenharmony_ci let drain_end = self.ranges.len(); 293c67d6573Sopenharmony_ci for oldi in 0..drain_end { 294c67d6573Sopenharmony_ci // If we've added at least one new range, then check if we can 295c67d6573Sopenharmony_ci // merge this range in the previously added range. 296c67d6573Sopenharmony_ci if self.ranges.len() > drain_end { 297c67d6573Sopenharmony_ci let (last, rest) = self.ranges.split_last_mut().unwrap(); 298c67d6573Sopenharmony_ci if let Some(union) = last.union(&rest[oldi]) { 299c67d6573Sopenharmony_ci *last = union; 300c67d6573Sopenharmony_ci continue; 301c67d6573Sopenharmony_ci } 302c67d6573Sopenharmony_ci } 303c67d6573Sopenharmony_ci let range = self.ranges[oldi]; 304c67d6573Sopenharmony_ci self.ranges.push(range); 305c67d6573Sopenharmony_ci } 306c67d6573Sopenharmony_ci self.ranges.drain(..drain_end); 307c67d6573Sopenharmony_ci } 308c67d6573Sopenharmony_ci 309c67d6573Sopenharmony_ci /// Returns true if and only if this class is in a canonical ordering. 310c67d6573Sopenharmony_ci fn is_canonical(&self) -> bool { 311c67d6573Sopenharmony_ci for pair in self.ranges.windows(2) { 312c67d6573Sopenharmony_ci if pair[0] >= pair[1] { 313c67d6573Sopenharmony_ci return false; 314c67d6573Sopenharmony_ci } 315c67d6573Sopenharmony_ci if pair[0].is_contiguous(&pair[1]) { 316c67d6573Sopenharmony_ci return false; 317c67d6573Sopenharmony_ci } 318c67d6573Sopenharmony_ci } 319c67d6573Sopenharmony_ci true 320c67d6573Sopenharmony_ci } 321c67d6573Sopenharmony_ci} 322c67d6573Sopenharmony_ci 323c67d6573Sopenharmony_ci/// An iterator over intervals. 324c67d6573Sopenharmony_ci#[derive(Debug)] 325c67d6573Sopenharmony_cipub struct IntervalSetIter<'a, I>(slice::Iter<'a, I>); 326c67d6573Sopenharmony_ci 327c67d6573Sopenharmony_ciimpl<'a, I> Iterator for IntervalSetIter<'a, I> { 328c67d6573Sopenharmony_ci type Item = &'a I; 329c67d6573Sopenharmony_ci 330c67d6573Sopenharmony_ci fn next(&mut self) -> Option<&'a I> { 331c67d6573Sopenharmony_ci self.0.next() 332c67d6573Sopenharmony_ci } 333c67d6573Sopenharmony_ci} 334c67d6573Sopenharmony_ci 335c67d6573Sopenharmony_cipub trait Interval: 336c67d6573Sopenharmony_ci Clone + Copy + Debug + Default + Eq + PartialEq + PartialOrd + Ord 337c67d6573Sopenharmony_ci{ 338c67d6573Sopenharmony_ci type Bound: Bound; 339c67d6573Sopenharmony_ci 340c67d6573Sopenharmony_ci fn lower(&self) -> Self::Bound; 341c67d6573Sopenharmony_ci fn upper(&self) -> Self::Bound; 342c67d6573Sopenharmony_ci fn set_lower(&mut self, bound: Self::Bound); 343c67d6573Sopenharmony_ci fn set_upper(&mut self, bound: Self::Bound); 344c67d6573Sopenharmony_ci fn case_fold_simple( 345c67d6573Sopenharmony_ci &self, 346c67d6573Sopenharmony_ci intervals: &mut Vec<Self>, 347c67d6573Sopenharmony_ci ) -> Result<(), unicode::CaseFoldError>; 348c67d6573Sopenharmony_ci 349c67d6573Sopenharmony_ci /// Create a new interval. 350c67d6573Sopenharmony_ci fn create(lower: Self::Bound, upper: Self::Bound) -> Self { 351c67d6573Sopenharmony_ci let mut int = Self::default(); 352c67d6573Sopenharmony_ci if lower <= upper { 353c67d6573Sopenharmony_ci int.set_lower(lower); 354c67d6573Sopenharmony_ci int.set_upper(upper); 355c67d6573Sopenharmony_ci } else { 356c67d6573Sopenharmony_ci int.set_lower(upper); 357c67d6573Sopenharmony_ci int.set_upper(lower); 358c67d6573Sopenharmony_ci } 359c67d6573Sopenharmony_ci int 360c67d6573Sopenharmony_ci } 361c67d6573Sopenharmony_ci 362c67d6573Sopenharmony_ci /// Union the given overlapping range into this range. 363c67d6573Sopenharmony_ci /// 364c67d6573Sopenharmony_ci /// If the two ranges aren't contiguous, then this returns `None`. 365c67d6573Sopenharmony_ci fn union(&self, other: &Self) -> Option<Self> { 366c67d6573Sopenharmony_ci if !self.is_contiguous(other) { 367c67d6573Sopenharmony_ci return None; 368c67d6573Sopenharmony_ci } 369c67d6573Sopenharmony_ci let lower = cmp::min(self.lower(), other.lower()); 370c67d6573Sopenharmony_ci let upper = cmp::max(self.upper(), other.upper()); 371c67d6573Sopenharmony_ci Some(Self::create(lower, upper)) 372c67d6573Sopenharmony_ci } 373c67d6573Sopenharmony_ci 374c67d6573Sopenharmony_ci /// Intersect this range with the given range and return the result. 375c67d6573Sopenharmony_ci /// 376c67d6573Sopenharmony_ci /// If the intersection is empty, then this returns `None`. 377c67d6573Sopenharmony_ci fn intersect(&self, other: &Self) -> Option<Self> { 378c67d6573Sopenharmony_ci let lower = cmp::max(self.lower(), other.lower()); 379c67d6573Sopenharmony_ci let upper = cmp::min(self.upper(), other.upper()); 380c67d6573Sopenharmony_ci if lower <= upper { 381c67d6573Sopenharmony_ci Some(Self::create(lower, upper)) 382c67d6573Sopenharmony_ci } else { 383c67d6573Sopenharmony_ci None 384c67d6573Sopenharmony_ci } 385c67d6573Sopenharmony_ci } 386c67d6573Sopenharmony_ci 387c67d6573Sopenharmony_ci /// Subtract the given range from this range and return the resulting 388c67d6573Sopenharmony_ci /// ranges. 389c67d6573Sopenharmony_ci /// 390c67d6573Sopenharmony_ci /// If subtraction would result in an empty range, then no ranges are 391c67d6573Sopenharmony_ci /// returned. 392c67d6573Sopenharmony_ci fn difference(&self, other: &Self) -> (Option<Self>, Option<Self>) { 393c67d6573Sopenharmony_ci if self.is_subset(other) { 394c67d6573Sopenharmony_ci return (None, None); 395c67d6573Sopenharmony_ci } 396c67d6573Sopenharmony_ci if self.is_intersection_empty(other) { 397c67d6573Sopenharmony_ci return (Some(self.clone()), None); 398c67d6573Sopenharmony_ci } 399c67d6573Sopenharmony_ci let add_lower = other.lower() > self.lower(); 400c67d6573Sopenharmony_ci let add_upper = other.upper() < self.upper(); 401c67d6573Sopenharmony_ci // We know this because !self.is_subset(other) and the ranges have 402c67d6573Sopenharmony_ci // a non-empty intersection. 403c67d6573Sopenharmony_ci assert!(add_lower || add_upper); 404c67d6573Sopenharmony_ci let mut ret = (None, None); 405c67d6573Sopenharmony_ci if add_lower { 406c67d6573Sopenharmony_ci let upper = other.lower().decrement(); 407c67d6573Sopenharmony_ci ret.0 = Some(Self::create(self.lower(), upper)); 408c67d6573Sopenharmony_ci } 409c67d6573Sopenharmony_ci if add_upper { 410c67d6573Sopenharmony_ci let lower = other.upper().increment(); 411c67d6573Sopenharmony_ci let range = Self::create(lower, self.upper()); 412c67d6573Sopenharmony_ci if ret.0.is_none() { 413c67d6573Sopenharmony_ci ret.0 = Some(range); 414c67d6573Sopenharmony_ci } else { 415c67d6573Sopenharmony_ci ret.1 = Some(range); 416c67d6573Sopenharmony_ci } 417c67d6573Sopenharmony_ci } 418c67d6573Sopenharmony_ci ret 419c67d6573Sopenharmony_ci } 420c67d6573Sopenharmony_ci 421c67d6573Sopenharmony_ci /// Compute the symmetric difference the given range from this range. This 422c67d6573Sopenharmony_ci /// returns the union of the two ranges minus its intersection. 423c67d6573Sopenharmony_ci fn symmetric_difference( 424c67d6573Sopenharmony_ci &self, 425c67d6573Sopenharmony_ci other: &Self, 426c67d6573Sopenharmony_ci ) -> (Option<Self>, Option<Self>) { 427c67d6573Sopenharmony_ci let union = match self.union(other) { 428c67d6573Sopenharmony_ci None => return (Some(self.clone()), Some(other.clone())), 429c67d6573Sopenharmony_ci Some(union) => union, 430c67d6573Sopenharmony_ci }; 431c67d6573Sopenharmony_ci let intersection = match self.intersect(other) { 432c67d6573Sopenharmony_ci None => return (Some(self.clone()), Some(other.clone())), 433c67d6573Sopenharmony_ci Some(intersection) => intersection, 434c67d6573Sopenharmony_ci }; 435c67d6573Sopenharmony_ci union.difference(&intersection) 436c67d6573Sopenharmony_ci } 437c67d6573Sopenharmony_ci 438c67d6573Sopenharmony_ci /// Returns true if and only if the two ranges are contiguous. Two ranges 439c67d6573Sopenharmony_ci /// are contiguous if and only if the ranges are either overlapping or 440c67d6573Sopenharmony_ci /// adjacent. 441c67d6573Sopenharmony_ci fn is_contiguous(&self, other: &Self) -> bool { 442c67d6573Sopenharmony_ci let lower1 = self.lower().as_u32(); 443c67d6573Sopenharmony_ci let upper1 = self.upper().as_u32(); 444c67d6573Sopenharmony_ci let lower2 = other.lower().as_u32(); 445c67d6573Sopenharmony_ci let upper2 = other.upper().as_u32(); 446c67d6573Sopenharmony_ci cmp::max(lower1, lower2) <= cmp::min(upper1, upper2).saturating_add(1) 447c67d6573Sopenharmony_ci } 448c67d6573Sopenharmony_ci 449c67d6573Sopenharmony_ci /// Returns true if and only if the intersection of this range and the 450c67d6573Sopenharmony_ci /// other range is empty. 451c67d6573Sopenharmony_ci fn is_intersection_empty(&self, other: &Self) -> bool { 452c67d6573Sopenharmony_ci let (lower1, upper1) = (self.lower(), self.upper()); 453c67d6573Sopenharmony_ci let (lower2, upper2) = (other.lower(), other.upper()); 454c67d6573Sopenharmony_ci cmp::max(lower1, lower2) > cmp::min(upper1, upper2) 455c67d6573Sopenharmony_ci } 456c67d6573Sopenharmony_ci 457c67d6573Sopenharmony_ci /// Returns true if and only if this range is a subset of the other range. 458c67d6573Sopenharmony_ci fn is_subset(&self, other: &Self) -> bool { 459c67d6573Sopenharmony_ci let (lower1, upper1) = (self.lower(), self.upper()); 460c67d6573Sopenharmony_ci let (lower2, upper2) = (other.lower(), other.upper()); 461c67d6573Sopenharmony_ci (lower2 <= lower1 && lower1 <= upper2) 462c67d6573Sopenharmony_ci && (lower2 <= upper1 && upper1 <= upper2) 463c67d6573Sopenharmony_ci } 464c67d6573Sopenharmony_ci} 465c67d6573Sopenharmony_ci 466c67d6573Sopenharmony_cipub trait Bound: 467c67d6573Sopenharmony_ci Copy + Clone + Debug + Eq + PartialEq + PartialOrd + Ord 468c67d6573Sopenharmony_ci{ 469c67d6573Sopenharmony_ci fn min_value() -> Self; 470c67d6573Sopenharmony_ci fn max_value() -> Self; 471c67d6573Sopenharmony_ci fn as_u32(self) -> u32; 472c67d6573Sopenharmony_ci fn increment(self) -> Self; 473c67d6573Sopenharmony_ci fn decrement(self) -> Self; 474c67d6573Sopenharmony_ci} 475c67d6573Sopenharmony_ci 476c67d6573Sopenharmony_ciimpl Bound for u8 { 477c67d6573Sopenharmony_ci fn min_value() -> Self { 478c67d6573Sopenharmony_ci u8::MIN 479c67d6573Sopenharmony_ci } 480c67d6573Sopenharmony_ci fn max_value() -> Self { 481c67d6573Sopenharmony_ci u8::MAX 482c67d6573Sopenharmony_ci } 483c67d6573Sopenharmony_ci fn as_u32(self) -> u32 { 484c67d6573Sopenharmony_ci self as u32 485c67d6573Sopenharmony_ci } 486c67d6573Sopenharmony_ci fn increment(self) -> Self { 487c67d6573Sopenharmony_ci self.checked_add(1).unwrap() 488c67d6573Sopenharmony_ci } 489c67d6573Sopenharmony_ci fn decrement(self) -> Self { 490c67d6573Sopenharmony_ci self.checked_sub(1).unwrap() 491c67d6573Sopenharmony_ci } 492c67d6573Sopenharmony_ci} 493c67d6573Sopenharmony_ci 494c67d6573Sopenharmony_ciimpl Bound for char { 495c67d6573Sopenharmony_ci fn min_value() -> Self { 496c67d6573Sopenharmony_ci '\x00' 497c67d6573Sopenharmony_ci } 498c67d6573Sopenharmony_ci fn max_value() -> Self { 499c67d6573Sopenharmony_ci '\u{10FFFF}' 500c67d6573Sopenharmony_ci } 501c67d6573Sopenharmony_ci fn as_u32(self) -> u32 { 502c67d6573Sopenharmony_ci self as u32 503c67d6573Sopenharmony_ci } 504c67d6573Sopenharmony_ci 505c67d6573Sopenharmony_ci fn increment(self) -> Self { 506c67d6573Sopenharmony_ci match self { 507c67d6573Sopenharmony_ci '\u{D7FF}' => '\u{E000}', 508c67d6573Sopenharmony_ci c => char::from_u32((c as u32).checked_add(1).unwrap()).unwrap(), 509c67d6573Sopenharmony_ci } 510c67d6573Sopenharmony_ci } 511c67d6573Sopenharmony_ci 512c67d6573Sopenharmony_ci fn decrement(self) -> Self { 513c67d6573Sopenharmony_ci match self { 514c67d6573Sopenharmony_ci '\u{E000}' => '\u{D7FF}', 515c67d6573Sopenharmony_ci c => char::from_u32((c as u32).checked_sub(1).unwrap()).unwrap(), 516c67d6573Sopenharmony_ci } 517c67d6573Sopenharmony_ci } 518c67d6573Sopenharmony_ci} 519c67d6573Sopenharmony_ci 520c67d6573Sopenharmony_ci// Tests for interval sets are written in src/hir.rs against the public API. 521