use std::cmp::{max, min, Ordering};
use crate::{AllocPolicy, Constraint};
#[allow(missing_docs)]
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
pub struct Range {
pub min: u64,
pub max: u64,
}
impl std::fmt::Debug for Range {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "[ {:016x}, {:016x} ]", self.min, self.max)
}
}
impl Range {
pub fn new<T>(min: T, max: T) -> Self
where
u64: From<T>,
{
let umin = u64::from(min);
let umax = u64::from(max);
if umin > umax || (umin == 0 && umax == u64::MAX) {
panic!("interval_tree: Range({}, {}) is invalid", umin, umax);
}
Range {
min: umin,
max: umax,
}
}
pub fn with_size<T>(base: T, size: T) -> Self
where
u64: From<T>,
{
let umin = u64::from(base);
let umax = u64::from(size).checked_add(umin).unwrap();
if umin > umax || (umin == 0 && umax == std::u64::MAX) {
panic!("interval_tree: Range({}, {}) is invalid", umin, umax);
}
Range {
min: umin,
max: umax,
}
}
pub fn new_point<T>(value: T) -> Self
where
u64: From<T>,
{
let val = u64::from(value);
Range { min: val, max: val }
}
pub fn len(&self) -> u64 {
self.max - self.min + 1
}
pub fn is_empty(&self) -> bool {
false
}
pub fn intersect(&self, other: &Range) -> bool {
max(self.min, other.min) <= min(self.max, other.max)
}
pub fn contain(&self, other: &Range) -> bool {
self.min <= other.min && self.max >= other.max
}
pub fn align_to(&self, align: u64) -> Option<Range> {
match align {
0 | 1 => Some(*self),
_ => {
if align & (align - 1) != 0 {
return None;
}
if let Some(min) = self.min.checked_add(align - 1).map(|v| v & !(align - 1)) {
if min <= self.max {
return Some(Range::new(min, self.max));
}
}
None
}
}
}
}
impl PartialOrd for Range {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
match self.min.cmp(&other.min) {
Ordering::Equal => Some(self.max.cmp(&other.max)),
res => Some(res),
}
}
}
impl Ord for Range {
fn cmp(&self, other: &Self) -> Ordering {
match self.min.cmp(&other.min) {
Ordering::Equal => self.max.cmp(&other.max),
res => res,
}
}
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Eq, Ord)]
pub enum NodeState<T> {
Free,
Allocated,
Valued(T),
}
impl<T> NodeState<T> {
fn take(&mut self) -> Self {
std::mem::replace(self, NodeState::<T>::Free)
}
fn replace(&mut self, value: NodeState<T>) -> Self {
std::mem::replace(self, value)
}
fn as_ref(&self) -> NodeState<&T> {
match self {
NodeState::<T>::Valued(ref x) => NodeState::<&T>::Valued(x),
NodeState::<T>::Allocated => NodeState::<&T>::Allocated,
NodeState::<T>::Free => NodeState::<&T>::Free,
}
}
fn as_mut(&mut self) -> NodeState<&mut T> {
match self {
NodeState::<T>::Valued(ref mut x) => NodeState::<&mut T>::Valued(x),
NodeState::<T>::Allocated => NodeState::<&mut T>::Allocated,
NodeState::<T>::Free => NodeState::<&mut T>::Free,
}
}
fn is_free(&self) -> bool {
matches!(self, NodeState::<T>::Free)
}
}
impl<T> From<NodeState<T>> for Option<T> {
fn from(n: NodeState<T>) -> Option<T> {
match n {
NodeState::<T>::Free | NodeState::<T>::Allocated => None,
NodeState::<T>::Valued(data) => Some(data),
}
}
}
#[derive(Debug, PartialEq, Eq)]
struct InnerNode<T> {
key: Range,
data: NodeState<T>,
left: Option<Node<T>>,
right: Option<Node<T>>,
height: u32,
max_key: u64,
}
impl<T> InnerNode<T> {
fn new(key: Range, data: NodeState<T>) -> Self {
InnerNode {
key,
data,
left: None,
right: None,
height: 1,
max_key: key.max,
}
}
}
#[derive(Debug, PartialEq, Eq)]
struct Node<T>(Box<InnerNode<T>>);
impl<T> Node<T> {
fn new(key: Range, data: Option<T>) -> Self {
let value = if let Some(t) = data {
NodeState::Valued(t)
} else {
NodeState::Free
};
Node(Box::new(InnerNode::new(key, value)))
}
fn search(&self, key: &Range) -> Option<&Self> {
match self.0.key.cmp(key) {
Ordering::Equal => Some(self),
Ordering::Less => self.0.right.as_ref().and_then(|node| node.search(key)),
Ordering::Greater => self.0.left.as_ref().and_then(|node| node.search(key)),
}
}
fn search_superset(&self, key: &Range) -> Option<&Self> {
if self.0.key.contain(key) {
Some(self)
} else if key.max < self.0.key.min && self.0.left.is_some() {
self.0.left.as_ref().unwrap().search_superset(key)
} else if key.min > self.0.key.max && self.0.right.is_some() {
self.0.right.as_ref().unwrap().search_superset(key)
} else {
None
}
}
fn search_superset_mut(&mut self, key: &Range) -> Option<&mut Self> {
if self.0.key.contain(key) {
Some(self)
} else if key.max < self.0.key.min && self.0.left.is_some() {
self.0.left.as_mut().unwrap().search_superset_mut(key)
} else if key.min > self.0.key.max && self.0.right.is_some() {
self.0.right.as_mut().unwrap().search_superset_mut(key)
} else {
None
}
}
fn insert(mut self, key: Range, data: Option<T>) -> Self {
match self.0.key.cmp(&key) {
Ordering::Equal => {
panic!("interval_tree: key {:?} exists", key);
}
Ordering::Less => {
if self.0.key.intersect(&key) {
panic!(
"interval_tree: key {:?} intersects with existing {:?}",
key, self.0.key
);
}
match self.0.right {
None => self.0.right = Some(Node::new(key, data)),
Some(_) => self.0.right = self.0.right.take().map(|n| n.insert(key, data)),
}
}
Ordering::Greater => {
if self.0.key.intersect(&key) {
panic!(
"interval_tree: key {:?} intersects with existing {:?}",
key, self.0.key
);
}
match self.0.left {
None => self.0.left = Some(Node::new(key, data)),
Some(_) => self.0.left = self.0.left.take().map(|n| n.insert(key, data)),
}
}
}
self.updated_node()
}
fn update(&mut self, key: &Range, data: NodeState<T>) -> Option<T> {
match self.0.key.cmp(key) {
Ordering::Equal => {
match (self.0.data.as_ref(), data.as_ref()) {
(NodeState::<&T>::Free, NodeState::<&T>::Free)
| (NodeState::<&T>::Free, NodeState::<&T>::Valued(_))
| (NodeState::<&T>::Allocated, NodeState::<&T>::Free)
| (NodeState::<&T>::Allocated, NodeState::<&T>::Allocated)
| (NodeState::<&T>::Valued(_), NodeState::<&T>::Free)
| (NodeState::<&T>::Valued(_), NodeState::<&T>::Allocated) => {
panic!("try to update unallocated interval tree node");
}
_ => {}
}
self.0.data.replace(data).into()
}
Ordering::Less => match self.0.right.as_mut() {
None => None,
Some(node) => node.update(key, data),
},
Ordering::Greater => match self.0.left.as_mut() {
None => None,
Some(node) => node.update(key, data),
},
}
}
fn delete(mut self, key: &Range) -> (Option<T>, Option<Self>) {
match self.0.key.cmp(key) {
Ordering::Equal => {
let data = self.0.data.take();
return (data.into(), self.delete_root());
}
Ordering::Less => {
if let Some(node) = self.0.right.take() {
let (data, right) = node.delete(key);
self.0.right = right;
return (data, Some(self.updated_node()));
}
}
Ordering::Greater => {
if let Some(node) = self.0.left.take() {
let (data, left) = node.delete(key);
self.0.left = left;
return (data, Some(self.updated_node()));
}
}
}
(None, Some(self))
}
fn rotate(self) -> Self {
let l = height(&self.0.left);
let r = height(&self.0.right);
match (l as i32) - (r as i32) {
1 | 0 | -1 => self,
2 => self.rotate_left_successor(),
-2 => self.rotate_right_successor(),
_ => unreachable!(),
}
}
fn rotate_left(mut self) -> Self {
let mut new_root = self.0.right.take().expect("Node is broken");
self.0.right = new_root.0.left.take();
self.update_cached_info();
new_root.0.left = Some(self);
new_root.update_cached_info();
new_root
}
fn rotate_right(mut self) -> Self {
let mut new_root = self.0.left.take().expect("Node is broken");
self.0.left = new_root.0.right.take();
self.update_cached_info();
new_root.0.right = Some(self);
new_root.update_cached_info();
new_root
}
fn rotate_left_successor(mut self) -> Self {
let left = self.0.left.take().expect("Node is broken");
if height(&left.0.left) < height(&left.0.right) {
let rotated = left.rotate_left();
self.0.left = Some(rotated);
self.update_cached_info();
} else {
self.0.left = Some(left);
}
self.rotate_right()
}
fn rotate_right_successor(mut self) -> Self {
let right = self.0.right.take().expect("Node is broken");
if height(&right.0.left) > height(&right.0.right) {
let rotated = right.rotate_right();
self.0.right = Some(rotated);
self.update_cached_info();
} else {
self.0.right = Some(right);
}
self.rotate_left()
}
fn delete_root(mut self) -> Option<Self> {
match (self.0.left.take(), self.0.right.take()) {
(None, None) => None,
(Some(l), None) => Some(l),
(None, Some(r)) => Some(r),
(Some(l), Some(r)) => Some(Self::combine_subtrees(l, r)),
}
}
fn get_new_root(mut self) -> (Self, Option<Self>) {
match self.0.left.take() {
None => {
let remaining = self.0.right.take();
(self, remaining)
}
Some(left) => {
let (min_node, left) = left.get_new_root();
self.0.left = left;
(min_node, Some(self.updated_node()))
}
}
}
fn combine_subtrees(l: Self, r: Self) -> Self {
let (mut new_root, remaining) = r.get_new_root();
new_root.0.left = Some(l);
new_root.0.right = remaining;
new_root.updated_node()
}
fn find_candidate(&self, constraint: &Constraint) -> Option<&Self> {
match constraint.policy {
AllocPolicy::FirstMatch => self.first_match(constraint),
AllocPolicy::Default => self.first_match(constraint),
}
}
fn first_match(&self, constraint: &Constraint) -> Option<&Self> {
let mut candidate = if self.0.left.is_some() {
self.0.left.as_ref().unwrap().first_match(constraint)
} else {
None
};
if candidate.is_none() && self.check_constraint(constraint) {
candidate = Some(self);
}
if candidate.is_none() && self.0.right.is_some() {
candidate = self.0.right.as_ref().unwrap().first_match(constraint);
}
candidate
}
fn check_constraint(&self, constraint: &Constraint) -> bool {
if self.0.data.is_free() {
let min = std::cmp::max(self.0.key.min, constraint.min);
let max = std::cmp::min(self.0.key.max, constraint.max);
if min <= max {
let key = Range::new(min, max);
if constraint.align == 0 || constraint.align == 1 {
return key.len() >= constraint.size;
}
return match key.align_to(constraint.align) {
None => false,
Some(aligned_key) => aligned_key.len() >= constraint.size,
};
}
}
false
}
fn update_cached_info(&mut self) {
self.0.height = max(height(&self.0.left), height(&self.0.right)) + 1;
self.0.max_key = max(
max_key(&self.0.left),
max(max_key(&self.0.right), self.0.key.max),
);
}
fn updated_node(mut self) -> Self {
self.update_cached_info();
self.rotate()
}
}
fn height<T>(node: &Option<Node<T>>) -> u32 {
node.as_ref().map_or(0, |n| n.0.height)
}
fn max_key<T>(node: &Option<Node<T>>) -> u64 {
node.as_ref().map_or(0, |n| n.0.max_key)
}
#[derive(Debug, Default, PartialEq, Eq)]
pub struct IntervalTree<T> {
root: Option<Node<T>>,
}
impl<T> IntervalTree<T> {
pub fn new() -> Self {
IntervalTree { root: None }
}
pub fn is_empty(&self) -> bool {
self.root.is_none()
}
pub fn get(&self, key: &Range) -> Option<NodeState<&T>> {
match self.root {
None => None,
Some(ref node) => node.search(key).map(|n| n.0.data.as_ref()),
}
}
pub fn get_superset(&self, key: &Range) -> Option<(&Range, NodeState<&T>)> {
match self.root {
None => None,
Some(ref node) => node
.search_superset(key)
.map(|n| (&n.0.key, n.0.data.as_ref())),
}
}
pub fn get_superset_mut(&mut self, key: &Range) -> Option<(&Range, NodeState<&mut T>)> {
match self.root {
None => None,
Some(ref mut node) => node
.search_superset_mut(key)
.map(|n| (&n.0.key, n.0.data.as_mut())),
}
}
pub fn get_by_id<U>(&self, id: U) -> Option<&T>
where
u64: From<U>,
{
match self.root {
None => None,
Some(ref node) => {
let key = Range::new_point(id);
match node.search_superset(&key) {
Some(node) => node.0.data.as_ref().into(),
None => None,
}
}
}
}
pub fn get_by_id_mut<U>(&mut self, id: U) -> Option<&mut T>
where
u64: From<U>,
{
match self.root {
None => None,
Some(ref mut node) => {
let key = Range::new_point(id);
match node.search_superset_mut(&key) {
Some(node) => node.0.data.as_mut().into(),
None => None,
}
}
}
}
pub fn insert(&mut self, key: Range, data: Option<T>) {
match self.root.take() {
None => self.root = Some(Node::new(key, data)),
Some(node) => self.root = Some(node.insert(key, data)),
}
}
pub fn update(&mut self, key: &Range, data: T) -> Option<T> {
match self.root.as_mut() {
None => None,
Some(node) => node.update(key, NodeState::<T>::Valued(data)),
}
}
pub fn delete(&mut self, key: &Range) -> Option<T> {
match self.root.take() {
Some(node) => {
let (data, root) = node.delete(key);
self.root = root;
data
}
None => None,
}
}
pub fn allocate(&mut self, constraint: &Constraint) -> Option<Range> {
if constraint.size == 0 {
return None;
}
let candidate = match self.root.as_mut() {
None => None,
Some(node) => node.find_candidate(constraint),
};
match candidate {
None => None,
Some(node) => {
let node_key = node.0.key;
let range = Range::new(
max(node_key.min, constraint.min),
min(node_key.max, constraint.max),
);
let aligned_key = range.align_to(constraint.align).unwrap();
let result = Range::new(aligned_key.min, aligned_key.min + constraint.size - 1);
if node_key.min == aligned_key.min && node_key.len() == constraint.size {
self.root
.as_mut()
.unwrap()
.update(&node_key, NodeState::<T>::Allocated);
return Some(node_key);
}
self.delete(&node_key);
if aligned_key.min > node_key.min {
self.insert(Range::new(node_key.min, aligned_key.min - 1), None);
}
self.insert(result, None);
if result.max < node_key.max {
self.insert(Range::new(result.max + 1, node_key.max), None);
}
self.root
.as_mut()
.unwrap()
.update(&result, NodeState::<T>::Allocated);
Some(result)
}
}
}
pub fn free(&mut self, key: &Range) -> Option<T> {
let result = self.delete(key);
let mut range = *key;
if range.min > 0 {
if let Some((r, v)) = self.get_superset(&Range::new(range.min - 1, range.min - 1)) {
if v.is_free() {
range.min = r.min;
}
}
}
if range.max < std::u64::MAX {
if let Some((r, v)) = self.get_superset(&Range::new(range.max + 1, range.max + 1)) {
if v.is_free() {
range.max = r.max;
}
}
}
if range.min < key.min {
self.delete(&Range::new(range.min, key.min - 1));
}
if range.max > key.max {
self.delete(&Range::new(key.max + 1, range.max));
}
self.insert(range, None);
result
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
#[should_panic]
fn test_new_range() {
let _ = Range::new(2u8, 1u8);
}
#[test]
#[should_panic]
fn test_new_range_overflow() {
let _ = Range::new(0u64, std::u64::MAX);
}
#[test]
fn test_range_intersect() {
let range_a = Range::new(1u8, 4u8);
let range_b = Range::new(4u16, 6u16);
let range_c = Range::new(2u32, 3u32);
let range_d = Range::new(4u64, 4u64);
let range_e = Range::new(5u32, 6u32);
assert!(range_a.intersect(&range_b));
assert!(range_b.intersect(&range_a));
assert!(range_a.intersect(&range_c));
assert!(range_c.intersect(&range_a));
assert!(range_a.intersect(&range_d));
assert!(range_d.intersect(&range_a));
assert!(!range_a.intersect(&range_e));
assert!(!range_e.intersect(&range_a));
assert_eq!(range_a.len(), 4);
assert_eq!(range_d.len(), 1);
}
#[test]
fn test_range_contain() {
let range_a = Range::new(2u8, 6u8);
assert!(range_a.contain(&Range::new(2u8, 3u8)));
assert!(range_a.contain(&Range::new(3u8, 4u8)));
assert!(range_a.contain(&Range::new(5u8, 5u8)));
assert!(range_a.contain(&Range::new(5u8, 6u8)));
assert!(range_a.contain(&Range::new(6u8, 6u8)));
assert!(!range_a.contain(&Range::new(1u8, 1u8)));
assert!(!range_a.contain(&Range::new(1u8, 2u8)));
assert!(!range_a.contain(&Range::new(1u8, 3u8)));
assert!(!range_a.contain(&Range::new(1u8, 7u8)));
assert!(!range_a.contain(&Range::new(7u8, 8u8)));
assert!(!range_a.contain(&Range::new(6u8, 7u8)));
assert!(!range_a.contain(&Range::new(7u8, 8u8)));
}
#[test]
fn test_range_align_to() {
let range_a = Range::new(2u32, 6);
assert_eq!(range_a.align_to(0), Some(Range::new(2u64, 6u64)));
assert_eq!(range_a.align_to(1), Some(Range::new(2u8, 6u8)));
assert_eq!(range_a.align_to(2), Some(Range::new(2u16, 6u16)));
assert_eq!(range_a.align_to(4), Some(Range::new(4u32, 6u32)));
assert_eq!(range_a.align_to(8), None);
assert_eq!(range_a.align_to(3), None);
let range_b = Range::new(0xFFFF_FFFF_FFFF_FFFDu64, 0xFFFF_FFFF_FFFF_FFFFu64);
assert_eq!(
range_b.align_to(2),
Some(Range::new(0xFFFF_FFFF_FFFF_FFFEu64, 0xFFFF_FFFF_FFFF_FFFF))
);
assert_eq!(range_b.align_to(4), None);
}
#[test]
fn test_range_ord() {
let range_a = Range::new(1u32, 4u32);
let range_b = Range::new(1u32, 4u32);
let range_c = Range::new(1u32, 3u32);
let range_d = Range::new(1u32, 5u32);
let range_e = Range::new(2u32, 2u32);
assert_eq!(range_a, range_b);
assert_eq!(range_b, range_a);
assert!(range_a > range_c);
assert!(range_c < range_a);
assert!(range_a < range_d);
assert!(range_d > range_a);
assert!(range_a < range_e);
assert!(range_e > range_a);
}
#[should_panic]
#[test]
fn test_tree_insert_equal() {
let mut tree = IntervalTree::<u64>::new();
tree.insert(Range::new(0x100u16, 0x200), Some(1));
tree.insert(Range::new(0x100u32, 0x200), None);
}
#[should_panic]
#[test]
fn test_tree_insert_intersect_on_right() {
let mut tree = IntervalTree::<u64>::new();
tree.insert(Range::new(0x100, 0x200u32), Some(1));
tree.insert(Range::new(0x200, 0x2ffu64), None);
}
#[should_panic]
#[test]
fn test_tree_insert_intersect_on_left() {
let mut tree = IntervalTree::<u64>::new();
tree.insert(Range::new(0x100, 0x200u32), Some(1));
tree.insert(Range::new(0x000, 0x100u64), None);
}
#[test]
fn test_tree_get_superset() {
let mut tree = IntervalTree::<u64>::new();
tree.insert(Range::new(0x100u32, 0x100u32), Some(1));
tree.insert(Range::new(0x001u16, 0x008u16), None);
tree.insert(Range::new(0x009u16, 0x00fu16), None);
tree.insert(Range::new(0x200u16, 0x2ffu16), None);
let mut constraint = Constraint::new(8u64);
constraint.min = 0x211;
constraint.max = 0x21f;
constraint.align = 0x8;
tree.allocate(&constraint);
assert_eq!(
tree.get_superset(&Range::new(0x100u32, 0x100)),
Some((&Range::new(0x100, 0x100u32), NodeState::Valued(&1)))
);
assert_eq!(
tree.get_superset(&Range::new(0x200u16, 0x200)),
Some((&Range::new(0x200, 0x217u64), NodeState::Free))
);
assert_eq!(
tree.get_superset(&Range::new(0x2ffu32, 0x2ff)),
Some((&Range::new(0x220, 0x2ffu32), NodeState::Free))
);
assert_eq!(
tree.get_superset(&Range::new(0x218u16, 0x21f)),
Some((&Range::new(0x218, 0x21fu16), NodeState::Allocated))
);
assert_eq!(tree.get_superset(&Range::new(0x2ffu32, 0x300)), None);
assert_eq!(tree.get_superset(&Range::new(0x300u32, 0x300)), None);
assert_eq!(tree.get_superset(&Range::new(0x1ffu32, 0x300)), None);
}
#[test]
fn test_tree_get_superset_mut() {
let mut tree = IntervalTree::<u64>::new();
tree.insert(Range::new(0x100u32, 0x100u32), Some(1));
tree.insert(Range::new(0x200u16, 0x2ffu16), None);
let mut constraint = Constraint::new(8u64);
constraint.min = 0x211;
constraint.max = 0x21f;
constraint.align = 0x8;
tree.allocate(&constraint);
assert_eq!(
tree.get_superset_mut(&Range::new(0x100u32, 0x100u32)),
Some((&Range::new(0x100u32, 0x100u32), NodeState::Valued(&mut 1)))
);
assert_eq!(
tree.get_superset_mut(&Range::new(0x218u64, 0x21fu64)),
Some((&Range::new(0x218u64, 0x21fu64), NodeState::Allocated))
);
assert_eq!(
tree.get_superset_mut(&Range::new(0x2ffu32, 0x2ffu32)),
Some((&Range::new(0x220u32, 0x2ffu32), NodeState::Free))
);
assert_eq!(tree.get_superset(&Range::new(0x2ffu32, 0x300)), None);
assert_eq!(tree.get_superset(&Range::new(0x300u32, 0x300)), None);
assert_eq!(tree.get_superset(&Range::new(0x1ffu32, 0x300)), None);
}
#[test]
fn test_tree_update() {
let mut tree = IntervalTree::<u64>::new();
tree.insert(Range::new(0x100u32, 0x100u32), None);
tree.insert(Range::new(0x200u32, 0x2ffu32), None);
let constraint = Constraint::new(2u32);
let key = tree.allocate(&constraint);
assert_eq!(key, Some(Range::new(0x200u32, 0x201u32)));
let old = tree.update(&Range::new(0x200u32, 0x201u32), 2);
assert_eq!(old, None);
let old = tree.update(&Range::new(0x200u32, 0x201u32), 3);
assert_eq!(old, Some(2));
let old = tree.update(&Range::new(0x200u32, 0x200u32), 4);
assert_eq!(old, None);
let old = tree.update(&Range::new(0x200u32, 0x203u32), 5);
assert_eq!(old, None);
tree.delete(&Range::new(0x200u32, 0x201u32));
let old = tree.update(&Range::new(0x200u32, 0x201u32), 2);
assert_eq!(old, None);
}
#[test]
fn test_tree_delete() {
let mut tree = IntervalTree::<u64>::new();
assert_eq!(tree.get(&Range::new(0x101u32, 0x101u32)), None);
assert!(tree.is_empty());
tree.insert(Range::new(0x100u32, 0x100u32), Some(1));
tree.insert(Range::new(0x001u16, 0x00fu16), None);
tree.insert(Range::new(0x200u32, 0x2ffu32), None);
assert!(!tree.is_empty());
assert_eq!(
tree.get(&Range::new(0x100u32, 0x100u32)),
Some(NodeState::Valued(&1))
);
assert_eq!(
tree.get(&Range::new(0x200u32, 0x2ffu32)),
Some(NodeState::Free)
);
assert_eq!(tree.get(&Range::new(0x101u32, 0x101u32)), None);
let old = tree.delete(&Range::new(0x001u16, 0x00fu16));
assert_eq!(old, None);
let old = tree.delete(&Range::new(0x100u32, 0x100u32));
assert_eq!(old, Some(1));
let old = tree.delete(&Range::new(0x200u32, 0x2ffu32));
assert_eq!(old, None);
assert!(tree.is_empty());
assert_eq!(tree.get(&Range::new(0x100u32, 0x100u32)), None);
assert_eq!(tree.get(&Range::new(0x200u32, 0x2ffu32)), None);
}
#[test]
fn test_allocate_free() {
let mut tree = IntervalTree::<u64>::new();
let mut constraint = Constraint::new(1u8);
assert_eq!(tree.allocate(&constraint), None);
tree.insert(Range::new(0x100u16, 0x100u16), None);
tree.insert(Range::new(0x200u16, 0x2ffu16), None);
let key = tree.allocate(&constraint);
assert_eq!(key, Some(Range::new(0x100u16, 0x100u16)));
let old = tree.update(&Range::new(0x100u16, 0x100u16), 2);
assert_eq!(old, None);
let val = tree.get(&Range::new(0x100u16, 0x100u16));
assert_eq!(val, Some(NodeState::Valued(&2)));
constraint.min = 0x100;
constraint.max = 0x100;
assert_eq!(tree.allocate(&constraint), None);
constraint.min = 0x201;
constraint.max = 0x300;
constraint.align = 0x8;
constraint.size = 0x10;
assert_eq!(
tree.allocate(&constraint),
Some(Range::new(0x208u16, 0x217u16))
);
let old = tree.free(&Range::new(0x208u16, 0x217u16));
assert_eq!(old, None);
assert_eq!(
tree.allocate(&constraint),
Some(Range::new(0x208u16, 0x217u16))
);
constraint.size = 0x100;
assert_eq!(tree.allocate(&constraint), None);
constraint.min = 0x200;
constraint.max = 0x2ff;
constraint.align = 0x8;
constraint.size = 0x100;
assert_eq!(tree.allocate(&constraint), None);
tree.update(&Range::new(0x208u16, 0x217u16), 0x10);
assert_eq!(tree.allocate(&constraint), None);
let old = tree.free(&Range::new(0x208u16, 0x217u16));
assert_eq!(old, Some(0x10));
assert_eq!(
tree.allocate(&constraint),
Some(Range::new(0x200u32, 0x2ffu32))
);
}
#[test]
fn test_with_size() {
let range_a = Range::with_size(1u8, 3u8);
let range_b = Range::with_size(4u16, 2u16);
let range_c = Range::with_size(2u32, 1u32);
let range_d = Range::with_size(4u64, 0u64);
let range_e = Range::with_size(5u32, 1u32);
assert_eq!(range_a, Range::new(1u8, 4u8));
assert_eq!(range_b, Range::new(4u16, 6u16));
assert_eq!(range_c, Range::new(2u32, 3u32));
assert_eq!(range_d, Range::new(4u64, 4u64));
assert_eq!(range_e, Range::new(5u32, 6u32));
}
#[test]
fn test_new_point() {
let range_a = Range::new_point(1u8);
let range_b = Range::new_point(2u16);
let range_c = Range::new_point(3u32);
let range_d = Range::new_point(4u64);
let range_e = Range::new_point(5u32);
assert_eq!(range_a, Range::with_size(1u8, 0u8));
assert_eq!(range_b, Range::with_size(2u16, 0u16));
assert_eq!(range_c, Range::with_size(3u32, 0u32));
assert_eq!(range_d, Range::with_size(4u64, 0u64));
assert_eq!(range_e, Range::with_size(5u32, 0u32));
}
#[test]
fn test_get_by_id() {
let mut tree = IntervalTree::<u32>::new();
tree.insert(Range::new(0x100u16, 0x100u16), Some(1));
tree.insert(Range::new(0x001u32, 0x005u32), Some(2));
tree.insert(Range::new(0x200u16, 0x2ffu16), None);
assert_eq!(tree.get_by_id(0x100u16), Some(&1));
assert_eq!(tree.get_by_id(0x002u32), Some(&2));
assert_eq!(tree.get_by_id(0x210u32), None);
assert_eq!(tree.get_by_id(0x2ffu64), None);
}
#[test]
fn test_get_by_id_mut() {
let mut tree = IntervalTree::<u32>::new();
tree.insert(Range::new(0x100u16, 0x100u16), Some(1));
tree.insert(Range::new(0x001u32, 0x005u32), Some(2));
tree.insert(Range::new(0x200u16, 0x2ffu16), None);
assert_eq!(tree.get_by_id_mut(0x100u16), Some(&mut 1));
assert_eq!(tree.get_by_id_mut(0x002u32), Some(&mut 2));
assert_eq!(tree.get_by_id_mut(0x210u32), None);
assert_eq!(tree.get_by_id_mut(0x2ffu64), None);
}
}