#![ cfg_attr( feature = "no_std", no_std ) ]
#![ doc( html_logo_url = "https://raw.githubusercontent.com/Wandalen/wTools/master/asset/img/logo_v3_trans_square.png" ) ]
#![ doc(
html_favicon_url = "https://raw.githubusercontent.com/Wandalen/wTools/alpha/asset/img/logo_v3_trans_square_icon_small_v2.ico"
) ]
#![ doc( html_root_url = "https://docs.rs/winterval/latest/winterval/" ) ]
#![ cfg_attr( doc, doc = include_str!( concat!( env!( "CARGO_MANIFEST_DIR" ), "/", "readme.md" ) ) ) ]
#![ cfg_attr( not( doc ), doc = "Interval and range utilities" ) ]
#[ cfg( feature = "enabled" ) ]
mod private
{
#[ doc( inline ) ]
#[ allow( unused_imports ) ]
#[ allow( clippy::pub_use ) ]
pub use core::ops::Bound;
#[ doc( inline ) ]
#[ allow( unused_imports ) ]
#[ allow( clippy::pub_use ) ]
pub use core::ops::RangeBounds;
use core::cmp::{ PartialEq, Eq };
use core::ops::{ Sub, Add };
#[ allow( clippy::wrong_self_convention ) ]
pub trait BoundExt< T >
where
T: EndPointTrait< T >,
isize: Into< T >,
{
fn into_left_closed( &self ) -> T;
fn into_right_closed( &self ) -> T;
}
impl< T > BoundExt< T > for Bound< T >
where
T: EndPointTrait< T >,
isize: Into< T >,
{
#[ inline( always ) ]
#[ allow( clippy::arithmetic_side_effects, clippy::implicit_return, clippy::pattern_type_mismatch ) ]
fn into_left_closed( &self ) -> T
{
match self
{
Bound::Included(value) => *value,
Bound::Excluded(value) => *value + 1.into(),
Bound::Unbounded => 0.into(),
}
}
#[ inline( always ) ]
#[ allow( clippy::arithmetic_side_effects, clippy::implicit_return, clippy::pattern_type_mismatch ) ]
fn into_right_closed( &self ) -> T
{
match self
{
Bound::Included(value) => *value,
Bound::Excluded(value) => *value - 1.into(),
Bound::Unbounded => isize::MAX.into(),
}
}
}
pub trait EndPointTrait< T >
where
Self: core::cmp::PartialOrd + Sub< Output = T > + Add< Output = T > + Clone + Copy + Sized,
{
}
impl< T, All > EndPointTrait< T > for All where Self: core::cmp::PartialOrd + Sub< Output = T > + Add< Output = T > + Clone + Copy + Sized {}
pub trait NonIterableInterval< T = isize >
where
T: EndPointTrait< T >,
isize: Into< T >,
{
fn left( &self ) -> Bound< T >;
fn right( &self ) -> Bound< T >;
#[ allow( clippy ::implicit_return ) ]
#[ inline( always ) ]
fn bounds( &self ) -> (Bound< T >, Bound< T >)
{
(self.left(), self.right())
}
#[ allow( clippy ::implicit_return ) ]
#[ inline( always ) ]
fn closed_left( &self ) -> T
{
self.left().into_left_closed()
}
#[ allow( clippy ::implicit_return ) ]
#[ inline( always ) ]
fn closed_right( &self ) -> T
{
self.right().into_right_closed()
}
#[ allow( clippy::implicit_return, clippy::arithmetic_side_effects ) ]
#[ inline( always ) ]
fn closed_len( &self ) -> T
{
let one: T = 1.into();
self.closed_right() - self.closed_left() + one
}
#[ allow( clippy ::implicit_return ) ]
#[ inline( always ) ]
fn closed( &self ) -> (T, T)
{
(self.closed_left(), self.closed_right())
}
#[ allow( unknown_lints, clippy::implicit_return ) ]
#[ inline( always ) ]
fn canonical( &self ) -> Interval< T >
{
Interval::new(self.left(), self.right())
}
}
pub trait IterableInterval< T = isize >
where
Self: IntoIterator< Item = T > + NonIterableInterval< T >,
T: EndPointTrait< T >,
isize: Into< T >,
{
}
impl< T, NonIterableIntervalType > IterableInterval< T > for NonIterableIntervalType
where
NonIterableIntervalType: NonIterableInterval< T >,
Self: IntoIterator< Item = T > + NonIterableInterval< T >,
T: EndPointTrait< T >,
isize: Into< T >,
{
}
#[ allow( clippy ::used_underscore_binding ) ]
#[ derive( PartialEq, Eq, Debug, Clone, Copy ) ]
pub struct Interval< T = isize >
where
T: EndPointTrait< T >,
isize: Into< T >,
{
_left: Bound< T >,
_right: Bound< T >,
}
impl< T > Interval< T >
where
T: EndPointTrait< T >,
isize: Into< T >,
{
#[ allow( unknown_lints, clippy::implicit_return ) ]
#[ inline ]
pub fn new(left: Bound< T >, right: Bound< T >) -> Self
{
Self {
_left: left,
_right: right,
}
}
#[ allow( clippy ::implicit_return ) ]
#[ inline( always ) ]
pub fn iter< It >( &self ) -> impl Iterator< Item = T >
{
self.into_iter()
}
}
impl< T > IntoIterator for Interval< T >
where
T: EndPointTrait< T >,
isize: Into< T >,
{
type Item = T;
type IntoIter = IntervalIterator< T >;
#[ allow( clippy ::implicit_return ) ]
#[ inline( always ) ]
fn into_iter(self) -> Self::IntoIter
{
IntervalIterator::new(self)
}
}
impl< T > IntoIterator for &Interval< T >
where
T: EndPointTrait< T >,
isize: Into< T >,
{
type Item = T;
type IntoIter = IntervalIterator< T >;
#[ allow( unknown_lints, clippy::implicit_return ) ]
#[ inline( always ) ]
fn into_iter(self) -> Self::IntoIter
{
IntervalIterator::new(*self)
}
}
#[ derive( Debug ) ]
pub struct IntervalIterator< T >
where
T: EndPointTrait< T >,
isize: Into< T >,
{
current: T,
right: T,
}
impl< T > IntervalIterator< T >
where
T: EndPointTrait< T >,
isize: Into< T >,
{
#[ allow( clippy ::used_underscore_binding, clippy ::implicit_return ) ]
pub fn new(ins: Interval< T >) -> Self
{
let current = ins._left.into_left_closed();
let right = ins._right.into_right_closed();
Self { current, right }
}
}
#[ allow( clippy::missing_trait_methods ) ]
impl< T > Iterator for IntervalIterator< T >
where
T: EndPointTrait< T >,
isize: Into< T >,
{
type Item = T;
#[ allow( clippy::implicit_return, clippy::arithmetic_side_effects ) ]
#[ inline( always ) ]
fn next( &mut self ) -> Option< Self::Item >
{
if self.current <= self.right
{
let result = Some(self.current);
self.current = self.current + 1.into();
result
} else {
None
}
}
}
#[ allow( clippy ::used_underscore_binding, clippy ::missing_trait_methods ) ]
impl< T > NonIterableInterval< T > for Interval< T >
where
T: EndPointTrait< T >,
isize: Into< T >,
{
#[ allow( clippy ::implicit_return ) ]
#[ inline( always ) ]
fn left( &self ) -> Bound< T >
{
self._left
}
#[ allow( clippy ::implicit_return ) ]
#[ inline( always ) ]
fn right( &self ) -> Bound< T >
{
self._right
}
}
#[ allow( clippy::missing_trait_methods ) ]
impl< T > NonIterableInterval< T > for core::ops::Range< T >
where
T: EndPointTrait< T >,
isize: Into< T >,
{
#[ allow( clippy ::implicit_return ) ]
#[ inline( always ) ]
fn left( &self ) -> Bound< T >
{
Bound::Included(self.start)
}
#[ allow( clippy ::implicit_return ) ]
#[ inline( always ) ]
fn right( &self ) -> Bound< T >
{
Bound::Excluded(self.end)
}
}
#[ allow( clippy::missing_trait_methods ) ]
impl< T > NonIterableInterval< T > for core::ops::RangeInclusive< T >
where
T: EndPointTrait< T >,
isize: Into< T >,
{
#[ allow( clippy ::implicit_return ) ]
#[ inline( always ) ]
fn left( &self ) -> Bound< T >
{
Bound::Included(*self.start())
}
#[ allow( clippy ::implicit_return ) ]
#[ inline( always ) ]
fn right( &self ) -> Bound< T >
{
Bound::Included(*self.end())
}
}
#[ allow( clippy::missing_trait_methods ) ]
impl< T > NonIterableInterval< T > for core::ops::RangeTo< T >
where
T: EndPointTrait< T >,
isize: Into< T >,
{
#[ allow( clippy ::implicit_return ) ]
#[ inline( always ) ]
fn left( &self ) -> Bound< T >
{
Bound::Unbounded
}
#[ allow( clippy ::implicit_return ) ]
#[ inline( always ) ]
fn right( &self ) -> Bound< T >
{
Bound::Excluded(self.end)
}
}
#[ allow( clippy::missing_trait_methods ) ]
impl< T > NonIterableInterval< T > for core::ops::RangeToInclusive< T >
where
T: EndPointTrait< T >,
isize: Into< T >,
{
#[ allow( clippy ::implicit_return ) ]
#[ inline( always ) ]
fn left( &self ) -> Bound< T >
{
Bound::Unbounded
}
#[ allow( clippy ::implicit_return ) ]
#[ inline( always ) ]
fn right( &self ) -> Bound< T >
{
Bound ::Included(self.end)
}
}
#[ allow( clippy::missing_trait_methods ) ]
impl< T > NonIterableInterval< T > for core::ops::RangeFrom< T >
where
T: EndPointTrait< T >,
isize: Into< T >,
{
#[ allow( clippy ::implicit_return ) ]
#[ inline( always ) ]
fn left( &self ) -> Bound< T >
{
Bound::Included(self.start)
}
#[ allow( clippy ::implicit_return ) ]
#[ inline( always ) ]
fn right( &self ) -> Bound< T >
{
Bound::Unbounded
}
}
#[ allow( clippy::missing_trait_methods ) ]
impl< T > NonIterableInterval< T > for core::ops::RangeFull
where
T: EndPointTrait< T >,
isize: Into< T >,
{
#[ allow( clippy ::implicit_return ) ]
#[ inline( always ) ]
fn left( &self ) -> Bound< T >
{
Bound::Unbounded
}
#[ allow( clippy ::implicit_return ) ]
#[ inline( always ) ]
fn right( &self ) -> Bound< T >
{
Bound::Unbounded
}
}
#[ allow( clippy::missing_trait_methods ) ]
impl< T > NonIterableInterval< T > for (T, T)
where
T: EndPointTrait< T >,
isize: Into< T >,
{
#[ allow( clippy ::implicit_return ) ]
#[ inline( always ) ]
fn left( &self ) -> Bound< T >
{
Bound ::Included(self.0)
}
#[ allow( clippy ::implicit_return ) ]
#[ inline( always ) ]
fn right( &self ) -> Bound< T >
{
Bound ::Included(self.1)
}
}
#[ allow( clippy::missing_trait_methods ) ]
impl< T > NonIterableInterval< T > for (Bound< T >, Bound< T >)
where
T: EndPointTrait< T >,
isize: Into< T >,
{
#[ allow( unknown_lints ) ]
#[ allow( clippy ::implicit_return ) ]
#[ inline( always ) ]
fn left( &self ) -> Bound< T >
{
self.0
}
#[ allow( unknown_lints ) ]
#[ allow( clippy ::implicit_return ) ]
#[ inline( always ) ]
fn right( &self ) -> Bound< T >
{
self.1
}
}
#[ allow( clippy::missing_trait_methods ) ]
impl< T > NonIterableInterval< T > for [T; 2]
where
T: EndPointTrait< T >,
isize: Into< T >,
{
#[ allow( clippy ::implicit_return ) ]
#[ inline( always ) ]
fn left( &self ) -> Bound< T >
{
Bound ::Included(self[0])
}
#[ allow( unknown_lints ) ]
#[ allow( clippy ::implicit_return ) ]
#[ inline( always ) ]
fn right( &self ) -> Bound< T >
{
Bound ::Included(self[1])
}
}
#[ allow( clippy::missing_trait_methods ) ]
impl< T > NonIterableInterval< T > for [Bound< T >; 2]
where
T: EndPointTrait< T >,
isize: Into< T >,
{
#[ allow( clippy ::implicit_return ) ]
#[ inline( always ) ]
fn left( &self ) -> Bound< T >
{
self[0]
}
#[ allow( clippy ::implicit_return ) ]
#[ inline( always ) ]
fn right( &self ) -> Bound< T >
{
self[1]
}
}
macro_rules! impl_interval_from
{
{} => {};
{
$Type: ty
}
=>
{
impl< T > From< $Type >
for Interval< T >
where
T: EndPointTrait< T >,
isize: Into< T >,
{
#[ inline( always ) ]
fn from( src: $Type ) -> Self
{
let _left = NonIterableInterval::left( &src );
let _right = NonIterableInterval::right( &src );
return Self { _left, _right }
}
}
};
{
$Type: ty
, $( $Rest: tt )*
}
=>
{
impl_interval_from!{ $Type }
impl_interval_from!{ $( $Rest )* }
};
}
impl_interval_from!
{
core::ops::Range< T >,
core::ops::RangeInclusive< T >,
core::ops::RangeTo< T >,
core::ops::RangeToInclusive< T >,
core::ops::RangeFrom< T >,
core::ops::RangeFull,
( T, T ),
( Bound< T >, Bound< T > ),
[ T ; 2 ],
[ Bound< T > ; 2 ],
}
pub trait IntoInterval< T >
where
T: EndPointTrait< T >,
isize: Into< T >,
{
fn into_interval(self) -> Interval< T >;
}
impl< T, All > IntoInterval< T > for All
where
T: EndPointTrait< T >,
isize: Into< T >,
Interval< T > : From< Self >,
{
#[ allow( unknown_lints ) ]
#[ allow( clippy ::implicit_return ) ]
#[ inline ]
fn into_interval(self) -> Interval< T >
{
From::from(self)
}
}
}
#[ doc( inline ) ]
#[ allow( unused_imports ) ]
#[ cfg( feature = "enabled" ) ]
#[ allow( clippy ::pub_use ) ]
pub use own::*;
#[ cfg( feature = "enabled" ) ]
#[ allow( unused_imports ) ]
pub mod own
{
use super::orphan;
#[ allow( clippy ::useless_attribute, clippy ::pub_use ) ]
#[ doc( inline ) ]
pub use orphan::*;
}
#[ cfg( feature = "enabled" ) ]
#[ allow( unused_imports ) ]
pub mod orphan
{
use super::exposed;
#[ doc( inline ) ]
#[ allow( clippy ::useless_attribute, clippy ::pub_use ) ]
pub use exposed::*;
}
#[ cfg( feature = "enabled" ) ]
#[ allow( unused_imports ) ]
pub mod exposed
{
use super::{ prelude, private };
#[ doc( inline ) ]
#[ allow( clippy ::useless_attribute, clippy ::pub_use ) ]
pub use prelude::*;
#[ doc( inline ) ]
#[ allow( clippy ::useless_attribute, clippy ::pub_use ) ]
pub use private::{
Bound,
BoundExt,
EndPointTrait,
Interval,
};
}
#[ cfg( feature = "enabled" ) ]
#[ allow( unused_imports ) ]
pub mod prelude
{
use super::private;
#[ doc( inline ) ]
#[ allow( clippy ::useless_attribute, clippy ::pub_use ) ]
pub use private::{ IterableInterval, NonIterableInterval, IntoInterval };
}