You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
genmarkov/src/range.rs

297 lines
7.1 KiB

//! Workarounds for ridiculously janky `std::ops::Range*` polymorphism
use super::*;
use std::{
ops::{
Range,
RangeFrom,
RangeInclusive,
RangeTo,
RangeToInclusive,
RangeFull,
Bound,
RangeBounds,
},
str::{
FromStr,
},
fmt,
error,
};
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum DynRange<T>
{
Range(Range<T>),
From(RangeFrom<T>),
Inclusive(RangeInclusive<T>),
To(RangeTo<T>),
ToInclusive(RangeToInclusive<T>),
Full(RangeFull),
}
#[macro_export] macro_rules! impl_from {
(Full, RangeFull) => {
impl<T> From<RangeFull> for DynRange<T>
{
#[inline] fn from(from: RangeFull) -> Self
{
Self::Full(from)
}
}
};
($name:ident, $range:tt) => {
impl<T> From<$range <T>> for DynRange<T>
{
#[inline] fn from(from: $range<T>) -> Self
{
Self::$name(from)
}
}
};
}
impl_from!(Range, Range);
impl_from!(From, RangeFrom);
impl_from!(Inclusive, RangeInclusive);
impl_from!(To, RangeTo);
impl_from!(ToInclusive, RangeToInclusive);
impl_from!(Full, RangeFull);
macro_rules! bounds {
($self:ident, $bound:ident) => {
match $self {
DynRange::Range(from) => from.$bound(),
DynRange::From(from) => from.$bound(),
DynRange::Inclusive(i) => i.$bound(),
DynRange::To(i) => i.$bound(),
DynRange::ToInclusive(i) => i.$bound(),
DynRange::Full(_) => (..).$bound(),
}
};
}
impl<T> RangeBounds<T> for DynRange<T>
{
fn start_bound(&self) -> Bound<&T> {
bounds!(self, start_bound)
}
fn end_bound(&self) -> Bound<&T> {
bounds!(self, end_bound)
}
}
impl<'a, T> RangeBounds<T> for &'a DynRange<T>
{
fn start_bound(&self) -> Bound<&T> {
bounds!(self, start_bound)
}
fn end_bound(&self) -> Bound<&T> {
bounds!(self, end_bound)
}
}
impl<T: fmt::Display> fmt::Display for DynRange<T>
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
{
match self {
Self::Range(from) => write!(f, "{}..{}", from.start, from.end),
Self::From(from) => write!(f, "{}..", from.start),
Self::Inclusive(from) => write!(f, "{}..={}", from.start(), from.end()),
Self::To(from) => write!(f, "..{}", from.end),
Self::ToInclusive(from) => write!(f, "..={}", from.end),
Self::Full(_) => write!(f, ".."),
}
}
}
use std::any::{
Any,
};
impl<T: 'static> DynRange<T>
{
#[inline]
pub fn into_boxed(self) -> Box<dyn Any /*TODO: + Send + Sync */+ 'static>
{
self.into_inner()
}
fn into_inner(self) -> Box<dyn Any + 'static>
{
match self {
Self::Range(from) => Box::new(from),
Self::From(from) => Box::new(from),
Self::Inclusive(from) => Box::new(from),
Self::To(from) => Box::new(from),
Self::ToInclusive(from) => Box::new(from),
Self::Full(_) => Box::new(..),
}
}
fn inner_mut(&mut self) -> &mut dyn Any
{
match self {
Self::Range(from) => from,
Self::From(from) => from,
Self::Inclusive(from) => from,
Self::To(from) => from,
Self::ToInclusive(from) => from,
Self::Full(f) => f,
}
}
fn inner_ref(&self) -> &dyn Any
{
match self {
Self::Range(from) => from,
Self::From(from) => from,
Self::Inclusive(from) => from,
Self::To(from) => from,
Self::ToInclusive(from) => from,
Self::Full(_) => &(..),
}
}
pub fn downcast_ref<R: RangeBounds<T> + 'static>(&self) -> Option<&R>
{
self.inner_ref().downcast_ref()
}
pub fn downcast_mut<R: RangeBounds<T> + 'static>(&mut self) -> Option<&mut R>
{
self.inner_mut().downcast_mut()
}
pub fn downcast<R: RangeBounds<T> + 'static>(self) -> Result<R, Self>
{
self.into_inner().downcast::<R>()
.map(|x| *x)
.map_err(|b| {
todo!("make this bullshit properly unboxable ehh...")
})
//Box::<(dyn std::any::Any + 'static)>::downcast(Box::new(self)).map_ok(|ok| *ok)
}
}
#[derive(Debug)]
pub struct ParseError(DynRange<()>, Option<Box<dyn error::Error+'static>>);
impl ParseError
{
fn new<R: Into<DynRange<()>>>(which: R, err: impl error::Error + 'static) -> Self
{
Self(which.into(), Some(Box::new(err)))
}
fn none(which: impl Into<DynRange<()>>) -> Self
{
Self(which.into(), None)
}
fn map<T: Into<DynRange<()>>>(self, to: T) -> Self
{
Self (to.into(), self.1)
}
}
impl error::Error for ParseError
{
fn source(&self) -> Option<&(dyn error::Error + 'static)> {
if let Some(this) = self.1.as_ref() {
Some(this.as_ref())
} else {
None
}
}
}
impl fmt::Display for ParseError
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
{
write!(f, "failed to parse range in format `{:?}`", self.0)?;
if let Some(this) = self.1.as_ref() {
write!(f, ": {}", this)?;
}
Ok(())
}
}
impl<T: FromStr> FromStr for DynRange<T>
where T::Err: error::Error + 'static
{
type Err = ParseError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
if s== ".." {
Ok(Self::Full(..))
} else if s.starts_with("..=") {
Ok(Self::ToInclusive(..=T::from_str(&s[3..]).map_err(|x| ParseError::new(..=(), x))?))
} else if s.starts_with("..") {
Ok(Self::To(..(T::from_str(&s[2..])).map_err(|x| ParseError::new(..(), x))?))
} else if s.ends_with("..") {
Ok(Self::From(T::from_str(&s[..s.len()-2]).map_err(|x| ParseError::new(().., x))?..))
} else {
fn try_next_incl<'a, T: FromStr>(m: &mut impl Iterator<Item=&'a str>) -> Result<RangeInclusive<T>, ParseError>
where T::Err: error::Error + 'static
{
let (first, second) = if let Some(first) = m.next() {
if let Some(seocond) = m.next() {
(first,seocond)
} else {
return Err(ParseError::none(()..=()));
}
} else {
return Err(ParseError::none(()..=()));
};
let first: T = first.parse().map_err(|x| ParseError::new(()..=(), x))?;
let second: T = second.parse().map_err(|x| ParseError::new(()..=(), x))?;
Ok(first..=second)
}
fn try_next<'a, T: FromStr>(m: &mut impl Iterator<Item=&'a str>) -> Result<Range<T>, ParseError>
where T::Err: error::Error + 'static
{
let (first, second) = if let Some(first) = m.next() {
if let Some(seocond) = m.next() {
(first,seocond)
} else {
return Err(ParseError::none(()..()));
}
} else {
return Err(ParseError::none(()..()));
};
let first: T = first.parse().map_err(|x| ParseError::new(()..(), x))?;
let second: T = second.parse().map_err(|x| ParseError::new(()..(), x))?;
Ok(first..second)
}
let mut split = s.split("..=").fuse();
let mut last_err = ParseError::none(()..());
match loop {
match try_next_incl(&mut split) {
Err(ParseError(_, None)) => break Err(last_err), // iter empty
Err(other) => last_err = other,
Ok(value) => break Ok(Self::Inclusive(value)),
}
} {
Ok(v) => return Ok(v),
Err(e) => last_err = e,
};
let mut split = s.split("..").fuse();
match loop {
match try_next(&mut split) {
Err(ParseError(_, None)) => break Err(last_err), // iter empty
Err(other) => last_err = other,
Ok(value) => break Ok(Self::Range(value)),
}
} {
Ok(v) => Ok(v),
Err(e) => Err(e),
}
}
}
}