//! 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 { Range(Range), From(RangeFrom), Inclusive(RangeInclusive), To(RangeTo), ToInclusive(RangeToInclusive), Full(RangeFull), } #[macro_export] macro_rules! impl_from { (Full, RangeFull) => { impl From for DynRange { #[inline] fn from(from: RangeFull) -> Self { Self::Full(from) } } }; ($name:ident, $range:tt) => { impl From<$range > for DynRange { #[inline] fn from(from: $range) -> 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 RangeBounds for DynRange { fn start_bound(&self) -> Bound<&T> { bounds!(self, start_bound) } fn end_bound(&self) -> Bound<&T> { bounds!(self, end_bound) } } impl<'a, T> RangeBounds for &'a DynRange { fn start_bound(&self) -> Bound<&T> { bounds!(self, start_bound) } fn end_bound(&self) -> Bound<&T> { bounds!(self, end_bound) } } impl fmt::Display for DynRange { 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 DynRange { #[inline] pub fn into_boxed(self) -> Box { self.into_inner() } fn into_inner(self) -> Box { 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 + 'static>(&self) -> Option<&R> { self.inner_ref().downcast_ref() } pub fn downcast_mut + 'static>(&mut self) -> Option<&mut R> { self.inner_mut().downcast_mut() } pub fn downcast + 'static>(self) -> Result { self.into_inner().downcast::() .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>); impl ParseError { fn new>>(which: R, err: impl error::Error + 'static) -> Self { Self(which.into(), Some(Box::new(err))) } fn none(which: impl Into>) -> Self { Self(which.into(), None) } fn map>>(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 FromStr for DynRange where T::Err: error::Error + 'static { type Err = ParseError; fn from_str(s: &str) -> Result { 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) -> Result, 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) -> Result, 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), } } } }