| // Copyright (c) 2021 The vulkano developers | |
| // Licensed under the Apache License, Version 2.0 | |
| // <LICENSE-APACHE or | |
| // https://www.apache.org/licenses/LICENSE-2.0> or the MIT | |
| // license <LICENSE-MIT or https://opensource.org/licenses/MIT>, | |
| // at your option. All files in the project carrying such | |
| // notice may not be copied, modified, or distributed except | |
| // according to those terms. | |
| use std::ops::Range; | |
| /// A set of ordered types. | |
| /// | |
| /// Implemented as an ordered list of ranges that do not touch or overlap. | |
| #[derive(Clone, Debug, Default)] | |
| pub struct RangeSet<T>(Vec<Range<T>>); | |
| impl<T: Ord + Copy> RangeSet<T> { | |
| /// Returns a new empty `RangeSet`. | |
| #[inline] | |
| pub fn new() -> Self { | |
| RangeSet(Vec::new()) | |
| } | |
| /// Returns whether all elements of `range` are contained in the set. | |
| #[inline] | |
| pub fn contains(&self, elements: Range<T>) -> bool { | |
| self.0 | |
| .iter() | |
| .any(|range| range.start <= elements.end && range.end >= elements.end) | |
| } | |
| /// Removes all ranges from the set. | |
| #[inline] | |
| pub fn clear(&mut self) { | |
| self.0.clear(); | |
| } | |
| /// Inserts the elements of `range` into the set. | |
| pub fn insert(&mut self, elements: Range<T>) { | |
| // Find the first range that is not less than `elements`, and the first range that is greater. | |
| let index_start = self | |
| .0 | |
| .iter() | |
| .position(|range| range.end >= elements.start) | |
| .unwrap_or(self.0.len()); | |
| let index_end = self | |
| .0 | |
| .iter() | |
| .position(|range| range.start > elements.end) | |
| .unwrap_or(self.0.len()); | |
| if index_start == index_end { | |
| // `elements` fits in between index_start - 1 and index_start. | |
| self.0.insert(index_start, elements); | |
| } else { | |
| // `elements` touches the ranges between index_start and index_end. | |
| // Expand `elements` with the touched ranges, then store it in the first. | |
| self.0[index_start] = self.0[index_start..index_end] | |
| .iter() | |
| .fold(elements, |Range { start, end }, range| { | |
| start.min(range.start)..end.max(range.end) | |
| }); | |
| // Delete the remaining elements. | |
| self.0.drain(index_start + 1..index_end); | |
| } | |
| } | |
| } |