master
Avril 4 years ago
parent a36aa03c48
commit 21a535e8f1
Signed by: flanchan
GPG Key ID: 284488987C31F630

@ -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));
}

Loading…
Cancel
Save