|
|
|
@ -1,3 +1,5 @@
|
|
|
|
|
//! Parsing times from definition files
|
|
|
|
|
|
|
|
|
|
use std::{
|
|
|
|
|
str,
|
|
|
|
|
num::{self, NonZeroU64},
|
|
|
|
@ -24,7 +26,7 @@ impl Unit
|
|
|
|
|
{
|
|
|
|
|
/// Multiplier to get to miliseconds
|
|
|
|
|
#[inline]
|
|
|
|
|
pub const fn multiplier(&self) -> u64 {
|
|
|
|
|
const fn multiplier(&self) -> u64 {
|
|
|
|
|
use Unit::*;
|
|
|
|
|
match self {
|
|
|
|
|
Second => 1000,
|
|
|
|
@ -38,11 +40,13 @@ impl Unit
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// A time object parsed from the definition file.
|
|
|
|
|
#[derive(Debug, Clone, PartialEq, Eq, Hash, Ord,PartialOrd)]
|
|
|
|
|
pub struct Time
|
|
|
|
|
{
|
|
|
|
|
unit: Unit,
|
|
|
|
|
value: NonZeroU64,
|
|
|
|
|
|
|
|
|
|
/// Value in miliseconds
|
|
|
|
|
absolute: Option<NonZeroU64>,
|
|
|
|
|
}
|
|
|
|
@ -110,11 +114,17 @@ impl Time
|
|
|
|
|
|
|
|
|
|
impl Time
|
|
|
|
|
{
|
|
|
|
|
pub fn extend(self, other: Self) -> Result<Self, ParseError>
|
|
|
|
|
/// Get the absolute value of the interval in miliseconds
|
|
|
|
|
pub fn ms(&self) -> u64
|
|
|
|
|
{
|
|
|
|
|
self.absolute.unwrap().into()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn extend(self, other: Self) -> Result<Self, ParseError>
|
|
|
|
|
{
|
|
|
|
|
Ok(Self::try_from_ms(unsafe{NonZeroU64::new_unchecked(u64::from(self.absolute.unwrap()) + u64::from(other.absolute.unwrap()))})?)
|
|
|
|
|
}
|
|
|
|
|
pub fn parse_chars<I>(from: &mut I) -> Result<Self, ParseError>
|
|
|
|
|
fn parse_chars<I>(from: &mut I) -> Result<Self, ParseError>
|
|
|
|
|
where I: Iterator<Item=char>
|
|
|
|
|
{
|
|
|
|
|
let mut token = String::new();
|
|
|
|
@ -135,7 +145,7 @@ impl Time
|
|
|
|
|
'd' | 'D' => Some(Unit::Day),
|
|
|
|
|
'w' | 'W' => Some(Unit::Week),
|
|
|
|
|
'y' | 'Y' => Some(Unit::Year),
|
|
|
|
|
'A' => Some(Unit::Aeon),
|
|
|
|
|
'∞' => Some(Unit::Aeon),
|
|
|
|
|
white if white.is_whitespace() => continue,
|
|
|
|
|
_ => return Err(ParseError::UnexpectedToken(tok, i)),
|
|
|
|
|
};
|
|
|
|
@ -197,12 +207,54 @@ pub fn parse_many_into(string: impl AsRef<str>) -> Result<Time, ParseErrorMany>
|
|
|
|
|
}).unwrap_or(Err(ParseErrorMany{error: ParseError::Empty, line:0}))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
impl std::fmt::Display for Unit
|
|
|
|
|
{
|
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
|
|
|
|
|
{
|
|
|
|
|
use Unit::*;
|
|
|
|
|
write!(f, "{}", match self {
|
|
|
|
|
Second => 's',
|
|
|
|
|
Minute => 'm',
|
|
|
|
|
Hour => 'h',
|
|
|
|
|
Day => 'd',
|
|
|
|
|
Week => 'w',
|
|
|
|
|
Year => 'y',
|
|
|
|
|
Aeon => '∞',
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl std::fmt::Display for Time
|
|
|
|
|
{
|
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
|
|
|
|
|
{
|
|
|
|
|
write!(f, "{} {}", self.value, self.unit)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Shows which atom parse error originated
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
|
pub struct ParseErrorMany {
|
|
|
|
|
error: ParseError,
|
|
|
|
|
line: usize,
|
|
|
|
|
}
|
|
|
|
|
impl std::error::Error for ParseErrorMany{}
|
|
|
|
|
impl ParseErrorMany
|
|
|
|
|
{
|
|
|
|
|
/// The atom number that error originated
|
|
|
|
|
pub fn atom(&self) -> usize
|
|
|
|
|
{
|
|
|
|
|
self.line
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
impl std::error::Error for ParseErrorMany
|
|
|
|
|
{
|
|
|
|
|
/// The `ParseError` source of this error
|
|
|
|
|
fn source(&self) -> Option<&(dyn std::error::Error +'static)>
|
|
|
|
|
{
|
|
|
|
|
Some(&self.error)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
impl std::fmt::Display for ParseErrorMany
|
|
|
|
|
{
|
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
|
|
|
|
@ -217,6 +269,7 @@ type IntErrorKind = std::num::IntErrorKind;
|
|
|
|
|
#[cfg(not(nightly))]
|
|
|
|
|
type IntErrorKind = ();
|
|
|
|
|
|
|
|
|
|
/// Error in parsing `Time`
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
|
pub enum ParseError {
|
|
|
|
|
Empty,
|
|
|
|
@ -267,7 +320,7 @@ mod tests
|
|
|
|
|
#[test]
|
|
|
|
|
fn parse_single()
|
|
|
|
|
{
|
|
|
|
|
let time: Time = "100A".parse().expect("parse failed");
|
|
|
|
|
let time: Time = "100∞".parse().expect("parse failed");
|
|
|
|
|
assert_eq!(time, Time::new(NonZeroU64::try_from(100).unwrap(), Unit::Aeon));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|