#![deny(missing_docs)]
pub mod interval_tree;
pub use interval_tree::{IntervalTree, NodeState, Range};
#[derive(thiserror::Error, Debug, Eq, PartialEq)]
pub enum Error {
#[error("invalid boundary constraint: min ({0}), max ({1})")]
InvalidBoundary(u64, u64),
}
pub type Result<T> = std::result::Result<T, Error>;
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum AllocPolicy {
Default,
FirstMatch,
}
#[derive(Copy, Clone, Debug)]
pub struct Constraint {
pub size: u64,
pub min: u64,
pub max: u64,
pub align: u64,
pub policy: AllocPolicy,
}
impl Constraint {
pub fn new<T>(size: T) -> Self
where
u64: From<T>,
{
Constraint {
size: u64::from(size),
min: 0,
max: u64::MAX,
align: 1,
policy: AllocPolicy::Default,
}
}
pub fn min<T>(mut self, min: T) -> Self
where
u64: From<T>,
{
self.min = u64::from(min);
self
}
pub fn max<T>(mut self, max: T) -> Self
where
u64: From<T>,
{
self.max = u64::from(max);
self
}
pub fn align<T>(mut self, align: T) -> Self
where
u64: From<T>,
{
self.align = u64::from(align);
self
}
pub fn policy(mut self, policy: AllocPolicy) -> Self {
self.policy = policy;
self
}
pub fn validate(&self) -> Result<()> {
if self.max < self.min {
return Err(Error::InvalidBoundary(self.min, self.max));
}
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_set_min() {
let constraint = Constraint::new(2_u64).min(1_u64);
assert_eq!(constraint.min, 1_u64);
}
#[test]
fn test_set_max() {
let constraint = Constraint::new(2_u64).max(100_u64);
assert_eq!(constraint.max, 100_u64);
}
#[test]
fn test_set_align() {
let constraint = Constraint::new(2_u64).align(8_u64);
assert_eq!(constraint.align, 8_u64);
}
#[test]
fn test_set_policy() {
let mut constraint = Constraint::new(2_u64).policy(AllocPolicy::FirstMatch);
assert_eq!(constraint.policy, AllocPolicy::FirstMatch);
constraint = constraint.policy(AllocPolicy::Default);
assert_eq!(constraint.policy, AllocPolicy::Default);
}
#[test]
fn test_consistently_change_constraint() {
let constraint = Constraint::new(2_u64)
.min(1_u64)
.max(100_u64)
.align(8_u64)
.policy(AllocPolicy::FirstMatch);
assert_eq!(constraint.min, 1_u64);
assert_eq!(constraint.max, 100_u64);
assert_eq!(constraint.align, 8_u64);
assert_eq!(constraint.policy, AllocPolicy::FirstMatch);
}
#[test]
fn test_set_invalid_boundary() {
let constraint = Constraint::new(2_u64).max(1000_u64).min(999_u64);
assert!(constraint.validate().is_ok());
let constraint = Constraint::new(2_u64).max(999_u64).min(1000_u64);
assert_eq!(
constraint.validate(),
Err(Error::InvalidBoundary(1000u64, 999u64))
);
}
}