use std::{iter, mem, ops};
use std::cmp::{min, max};
use std::sync::Arc;
pub trait Block: Clone {
type Item: Copy + Eq + Ord;
fn new(min: Self::Item, max: Self::Item) -> Self;
fn min(&self) -> Self::Item;
fn max(&self) -> Self::Item;
fn next(item: Self::Item) -> Option<Self::Item>;
fn bounds(&self) -> (Self::Item, Self::Item) {
(self.min(), self.max())
}
fn contains(&self, item: Self::Item) -> bool {
self.min() <= item && self.max() >= item
}
fn intersects(&self, other: &Self) -> bool {
self.min() <= other.max() && self.max() >= other.min()
}
fn is_encompassed(&self, other: &Self) -> bool {
other.min() <= self.min() && other.max() >= self.max()
}
fn sum(&self, other: &Self) -> Option<Self>
where Self: Sized {
if self.intersects(other) {
Some(Self::new(
min(self.min(), other.min()),
max(self.max(), other.max())
))
}
else if Self::next(self.max()) == Some(other.min()) {
Some(Self::new(self.min(), other.max()))
}
else if Self::next(other.max()) == Some(self.min()) {
Some(Self::new(other.min(), self.max()))
}
else {
None
}
}
fn is_equivalent(&self, other: &Self) -> bool {
self.min() == other.min() && self.max() == other.max()
}
}
#[derive(Debug)]
pub struct Chain<T: Block>([T]);
impl<T: Block> Chain<T> {
pub fn as_slice(&self) -> &[T] {
&self.0
}
pub fn empty() -> &'static Self {
#[allow(clippy::transmute_ptr_to_ptr)]
unsafe { mem::transmute::<&[T], _>(&[]) }
}
pub fn is_encompassed<C: AsRef<Chain<T>>>(&self, other: &C) -> bool {
let mut other = &other.as_ref().0;
if other.is_empty() {
return self.0.is_empty()
}
for block in self.iter() {
while other.first().unwrap().max() < block.min() {
other = match other.split_first() {
Some((_, tail)) if !tail.is_empty() => tail,
_ => return false,
}
}
if !block.is_encompassed(&other.first().unwrap()) {
return false
}
}
true
}
pub fn trim<C: AsRef<Chain<T>>>(
&self, other: &C
) -> Result<(), OwnedChain<T>> {
let other = other.as_ref();
if other.0.is_empty() {
return Err(OwnedChain::empty())
}
if self.0.is_empty() {
return Ok(())
}
let mut other_iter = other.iter();
let mut other_item = other_iter.next().unwrap();
let mut self_iter = self.iter();
let mut self_item = {
self_iter.next().map(|item| (item.min(), item.max())).unwrap()
};
let mut res: Result<usize, Vec<_>> = Ok(0);
let mut i = 1;
loop {
if i == 100 {
break
} else {
i += 1;
}
if other_item.max() < self_item.0 {
match other_iter.next() {
Some(item) => {
other_item = item;
continue;
}
None => break
}
}
if self_item.0 >= other_item.min()
&& self_item.1 <= other_item.max() {
match res {
Ok(ref mut idx) => *idx += 1,
Err(ref mut vec) => {
vec.push(T::new(self_item.0, self_item.1));
}
}
self_item = match self_iter.next() {
Some(item) => (item.min(), item.max()),
None => {
match res {
Ok(_) => return Ok(()),
Err(_) => break,
}
}
}
}
else {
let (keep, redo) = if self_item.1 < other_item.min() {
(None, None)
}
else if self_item.1 <= other_item.max() {
(
Some(T::new(
max(self_item.0, other_item.min()),
self_item.1
)),
None
)
}
else {
(
Some(T::new(
max(self_item.0, other_item.min()),
other_item.max())
),
Some((
T::next(other_item.max()).unwrap(),
self_item.1
))
)
};
if let Ok(idx) = res {
res = Err(self.0[..idx].into());
}
if let Some(keep) = keep {
match res {
Err(ref mut vec) => vec.push(keep),
_ => unreachable!()
}
}
match redo {
Some(item) => self_item = item,
None => {
match self_iter.next() {
Some(item) => {
self_item = (item.min(), item.max())
}
None => {
break;
}
}
}
}
}
}
let res = match res {
Ok(idx) => self.0[..idx].into(),
Err(vec) => vec
};
Err(unsafe { OwnedChain::from_vec_unchecked(res) })
}
}
impl<T: Block> ops::Deref for Chain<T> {
type Target = [T];
fn deref(&self) -> &Self::Target {
self.as_slice()
}
}
impl<T: Block> AsRef<[T]> for Chain<T> {
fn as_ref(&self) -> &[T] {
self.as_slice()
}
}
impl<T: Block> PartialEq for Chain<T> {
fn eq(&self, other: &Chain<T>) -> bool {
let mut other_iter = other.iter();
for my_block in self.iter() {
if let Some(other_block) = other_iter.next() {
if my_block.min() != other_block.min() || my_block.max() != other_block.max() {
return false
}
} else {
return false
}
}
true
}
}
impl<T: Block> Eq for Chain<T> {}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct OwnedChain<T: Block>(Vec<T>);
impl<T: Block> OwnedChain<T> {
unsafe fn from_vec_unchecked(vec: Vec<T>) -> Self {
OwnedChain(vec)
}
pub fn empty() -> Self {
OwnedChain(Vec::new())
}
pub fn as_chain(&self) -> &Chain<T> {
#[allow(clippy::transmute_ptr_to_ptr)]
unsafe { mem::transmute(self.0.as_slice()) }
}
}
impl<T: Block> iter::FromIterator<T> for OwnedChain<T> {
fn from_iter<I>(iter: I) -> Self
where I: IntoIterator<Item=T> {
let mut res = Vec::new();
let mut iter = iter.into_iter();
while let Some(block) = iter.next() {
if let Some((last_min, last_max)) = res.last().map(Block::bounds) {
if block.min() < last_min {
return from_iter_unsorted(res, block, iter)
}
else if block.min() <= last_max {
if block.max() > last_max {
*res.last_mut().unwrap() = T::new(
last_min, block.max()
);
}
}
else if T::next(last_max) == Some(block.min()) {
*res.last_mut().unwrap() = T::new(last_min, block.max())
}
else {
res.push(block)
}
}
else {
res.push(block)
}
}
unsafe { Self::from_vec_unchecked(res) }
}
}
fn from_iter_unsorted<T: Block, I: Iterator<Item=T>>(
mut res: Vec<T>,
block: T,
iter: I,
) -> OwnedChain<T> {
merge_or_add_block(&mut res, block);
for block in iter {
merge_or_add_block(&mut res, block);
}
res.sort_unstable_by_key(|block| block.min());
unsafe { OwnedChain::from_vec_unchecked(res) }
}
fn merge_or_add_block<T: Block>(res: &mut Vec<T>, block: T) {
for elem in res.iter_mut() {
if let Some(sum) = elem.sum(&block) {
*elem = sum;
return
}
}
res.push(block)
}
impl<T: Block> From<Vec<T>> for OwnedChain<T> {
fn from(src: Vec<T>) -> Self {
<Self as iter::FromIterator<T>>::from_iter(src)
}
}
impl<'a, T: Block + Clone> From<&'a [T]> for OwnedChain<T> {
fn from(src: &'a [T]) -> Self {
<Self as iter::FromIterator<T>>::from_iter(
src.iter().cloned()
)
}
}
impl<T: Block> ops::Deref for OwnedChain<T> {
type Target = Chain<T>;
fn deref(&self) -> &Self::Target {
self.as_chain()
}
}
impl<T: Block> AsRef<Chain<T>> for OwnedChain<T> {
fn as_ref(&self) -> &Chain<T> {
self.as_chain()
}
}
impl<T: Block> AsRef<[T]> for OwnedChain<T> {
fn as_ref(&self) -> &[T] {
self.as_chain().as_ref()
}
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct SharedChain<T: Block + 'static>(Option<Arc<OwnedChain<T>>>);
impl<T: Block + 'static> SharedChain<T> {
pub fn from_owned(owned: OwnedChain<T>) -> Self {
if owned.is_empty() {
SharedChain(None)
}
else {
SharedChain(Some(Arc::new(owned)))
}
}
pub fn empty() -> Self {
SharedChain(None)
}
pub fn as_chain(&self) -> &Chain<T> {
match self.0.as_ref() {
Some(chain) => chain.as_chain(),
None => Chain::empty(),
}
}
}
impl<T: Block + 'static, F> From<F> for SharedChain<T>
where OwnedChain<T>: From<F> {
fn from(f: F) -> Self {
Self::from_owned(OwnedChain::from(f))
}
}
impl<T: Block + 'static> iter::FromIterator<T> for SharedChain<T> {
fn from_iter<I>(iter: I) -> Self
where I: IntoIterator<Item=T> {
OwnedChain::from_iter(iter).into()
}
}
impl<T: Block + 'static> ops::Deref for SharedChain<T> {
type Target = Chain<T>;
fn deref(&self) -> &Self::Target {
self.as_chain()
}
}
impl<T: Block + 'static> AsRef<Chain<T>> for SharedChain<T> {
fn as_ref(&self) -> &Chain<T> {
self.as_chain()
}
}
impl<T: Block + 'static> AsRef<[T]> for SharedChain<T> {
fn as_ref(&self) -> &[T] {
self.as_chain().as_ref()
}
}
#[cfg(test)]
mod test {
use super::*;
impl Block for (u8, u8) {
type Item = u8;
fn new(min: u8, max: u8) -> Self { (min, max) }
fn min(&self) -> u8 { self.0 }
fn max(&self) -> u8 { self.1 }
fn next(item: u8) -> Option<u8> { item.checked_add(1) }
}
#[test]
fn from_iter() {
assert_eq!(
OwnedChain::from([(1,4), (6,8), (23,48)].as_ref()).as_slice(),
&[(1,4), (6,8), (23,48)][..]
);
assert_eq!(
OwnedChain::from([(1,4), (5,8), (23,48)].as_ref()).as_slice(),
&[(1,8), (23,48)][..]
);
assert_eq!(
OwnedChain::from([(1,4), (3,8), (23,48)].as_ref()).as_slice(),
&[(1,8), (23,48)][..]
);
assert_eq!(
OwnedChain::from([(1,4), (23,48), (6,8)].as_ref()).as_slice(),
&[(1,4), (6,8), (23,48)][..]
);
assert_eq!(
OwnedChain::from([(1,4), (23,48), (5,8)].as_ref()).as_slice(),
&[(1,8), (23,48)][..]
);
assert_eq!(
OwnedChain::from([(1,4), (23,48), (3,8)].as_ref()).as_slice(),
&[(1,8), (23,48)][..]
);
assert_eq!(
OwnedChain::from([(5,8), (3,6), (4,8)].as_ref()).as_slice(),
&[(3, 8)][..]
);
}
#[test]
fn is_encompassed() {
let chain = OwnedChain::from([(1,4), (11,18), (23,48)].as_ref());
assert!(
OwnedChain::from([(1,4), (13,18), (23,48)].as_ref())
.is_encompassed(&chain)
);
assert!(
OwnedChain::from([(3,4)].as_ref())
.is_encompassed(&chain)
);
assert!(
!OwnedChain::from([(3,9)].as_ref())
.is_encompassed(&chain)
);
assert!(
!OwnedChain::from([(3,9)].as_ref())
.is_encompassed(&OwnedChain::from([(0,2)].as_ref()))
);
}
#[test]
fn trim() {
assert_eq!(
OwnedChain::from([(10,15)].as_ref()).trim(
&OwnedChain::from([(5,8)].as_ref())
),
Err(OwnedChain::empty())
);
assert_eq!(
OwnedChain::from([(10,15), (20, 25)].as_ref()).trim(
&OwnedChain::from([(5,18)].as_ref())
),
Err(OwnedChain::from([(10,15)].as_ref()))
);
assert_eq!(
OwnedChain::from([(10,15), (20, 25)].as_ref()).trim(
&OwnedChain::from([(5,15)].as_ref())
),
Err(OwnedChain::from([(10,15)].as_ref()))
);
assert_eq!(
OwnedChain::from([(10,15), (20, 25)].as_ref()).trim(
&OwnedChain::from([(10,18)].as_ref())
),
Err(OwnedChain::from([(10,15)].as_ref()))
);
assert_eq!(
OwnedChain::from([(10,15), (20, 25)].as_ref()).trim(
&OwnedChain::from([(10,15)].as_ref())
),
Err(OwnedChain::from([(10,15)].as_ref()))
);
assert_eq!(
OwnedChain::from([(10,15), (20, 25)].as_ref()).trim(
&OwnedChain::from([(10,25)].as_ref())
),
Ok(())
);
assert_eq!(
OwnedChain::from([(10,15), (20, 25)].as_ref()).trim(
&OwnedChain::from([(10,15), (20,25)].as_ref())
),
Ok(())
);
assert_eq!(
OwnedChain::from([(10,15), (20, 25)].as_ref()).trim(
&OwnedChain::from([(8,17), (19,50)].as_ref())
),
Ok(())
);
assert_eq!(
OwnedChain::from([(10,15), (20, 25)].as_ref()).trim(
&OwnedChain::from([(8,17), (19,50), (70,80)].as_ref())
),
Ok(())
);
assert_eq!(
OwnedChain::from([(10,15), (20, 25)].as_ref()).trim(
&OwnedChain::from([(2, 6), (8,17), (19,50), (70,80)].as_ref())
),
Ok(())
);
assert_eq!(
OwnedChain::from([(10,15), (20, 25)].as_ref()).trim(
&OwnedChain::from([(12,13)].as_ref())
),
Err(OwnedChain::from([(12,13)].as_ref()))
);
assert_eq!(
OwnedChain::from([(10,15), (20, 25)].as_ref()).trim(
&OwnedChain::from([(10,13)].as_ref())
),
Err(OwnedChain::from([(10,13)].as_ref()))
);
assert_eq!(
OwnedChain::from([(10,15), (20, 25)].as_ref()).trim(
&OwnedChain::from([(8,13)].as_ref())
),
Err(OwnedChain::from([(10,13)].as_ref()))
);
assert_eq!(
OwnedChain::from([(10,15), (20, 25)].as_ref()).trim(
&OwnedChain::from([(12,15)].as_ref())
),
Err(OwnedChain::from([(12,15)].as_ref()))
);
assert_eq!(
OwnedChain::from([(10,15), (20, 25)].as_ref()).trim(
&OwnedChain::from([(12,17)].as_ref())
),
Err(OwnedChain::from([(12,15)].as_ref()))
);
assert_eq!(
OwnedChain::from([(10,15), (20, 25)].as_ref()).trim(
&OwnedChain::from([(8,17)].as_ref())
),
Err(OwnedChain::from([(10,15)].as_ref()))
);
assert_eq!(
OwnedChain::from([(1,4), (10,15), (20, 25)].as_ref()).trim(
&OwnedChain::from([(8,17)].as_ref())
),
Err(OwnedChain::from([(10,15)].as_ref()))
);
assert_eq!(
OwnedChain::from([(10,15), (20, 25)].as_ref()).trim(
&OwnedChain::from([(12,15), (22,23), (50,70)].as_ref())
),
Err(OwnedChain::from([(12,15), (22,23)].as_ref()))
);
}
#[test]
fn trim_bigger() {
let bigger = OwnedChain::from([(1,5), (10,18), (23,48)].as_ref());
let smaller = OwnedChain::from([(1,4), (11,17), (23,48)].as_ref());
let intersection = bigger.trim(&smaller).err().unwrap();
assert_eq!(smaller, intersection);
}
}