Struct fundu::DurationParser
source · pub struct DurationParser { /* private fields */ }
standard
only.Expand description
A parser with a customizable set of TimeUnit
s with default identifiers.
See also the module level documentation for more details and more information about the format.
Examples
A parser with the default set of time units
use std::time::Duration;
use fundu::DurationParser;
let parser = DurationParser::new();
assert_eq!(parser.parse("42Ms").unwrap(), Duration::new(0, 42_000));
The parser is reusable and the set of time units is fully customizable
use fundu::{DurationParser, TimeUnit::*};
use std::time::Duration;
let parser = DurationParser::with_time_units(&[NanoSecond, Minute, Hour]);
for (input, expected) in &[
("9e3ns", Duration::new(0, 9000)),
("10m", Duration::new(600, 0)),
("1.1h", Duration::new(3960, 0)),
("7", Duration::new(7, 0)),
] {
assert_eq!(parser.parse(input).unwrap(), *expected);
}
Implementations§
source§impl DurationParser
impl DurationParser
sourcepub const fn new() -> Self
pub const fn new() -> Self
Construct the parser with the default set of TimeUnit
s.
Examples
use std::time::Duration;
use fundu::DurationParser;
use fundu::TimeUnit::*;
assert_eq!(
DurationParser::new().parse("1").unwrap(),
Duration::new(1, 0)
);
assert_eq!(
DurationParser::new().parse("1s").unwrap(),
Duration::new(1, 0)
);
assert_eq!(
DurationParser::new().parse("42.0e9ns").unwrap(),
Duration::new(42, 0)
);
assert_eq!(
DurationParser::new().get_current_time_units(),
vec![
NanoSecond,
MicroSecond,
MilliSecond,
Second,
Minute,
Hour,
Day,
Week
]
);
sourcepub fn with_time_units(time_units: &[TimeUnit]) -> Self
pub fn with_time_units(time_units: &[TimeUnit]) -> Self
sourcepub const fn without_time_units() -> Self
pub const fn without_time_units() -> Self
sourcepub const fn with_all_time_units() -> Self
pub const fn with_all_time_units() -> Self
sourcepub const fn builder<'a>() -> DurationParserBuilder<'a>
pub const fn builder<'a>() -> DurationParserBuilder<'a>
Use the DurationParserBuilder
to construct a DurationParser
.
The DurationParserBuilder
is more ergonomic in some use cases than using
DurationParser
directly. Using this method is the same like invoking
DurationParserBuilder::default
.
See DurationParserBuilder
for more details.
Examples
use std::time::Duration;
use fundu::DurationParser;
use fundu::TimeUnit::*;
let parser = DurationParser::builder()
.all_time_units()
.default_unit(MicroSecond)
.allow_delimiter(|byte| byte.is_ascii_whitespace())
.build();
assert_eq!(parser.parse("1 \t\nns").unwrap(), Duration::new(0, 1));
assert_eq!(parser.parse("1").unwrap(), Duration::new(0, 1_000));
// instead of
let mut parser = DurationParser::with_all_time_units();
parser
.default_unit(MicroSecond)
.allow_delimiter(Some(|byte| byte == b' '));
assert_eq!(parser.parse("1 ns").unwrap(), Duration::new(0, 1));
assert_eq!(parser.parse("1").unwrap(), Duration::new(0, 1_000));
sourcepub fn parse(&self, source: &str) -> Result<Duration, ParseError>
pub fn parse(&self, source: &str) -> Result<Duration, ParseError>
Parse the source
string into a std::time::Duration
depending on the current set of
configured TimeUnit
s.
See the module-level documentation for more information on the format.
Examples
use std::time::Duration;
use fundu::DurationParser;
assert_eq!(
DurationParser::new().parse("1.2e-1s").unwrap(),
Duration::new(0, 120_000_000),
);
sourcepub fn parse_negative(&self, source: &str) -> Result<Duration, ParseError>
Available on crate feature negative
only.
pub fn parse_negative(&self, source: &str) -> Result<Duration, ParseError>
negative
only.Parse a source string into a time::Duration
which can be negative.
This method is only available when activating the negative
feature and saturates at
time::Duration::MIN
for parsed negative durations and at time::Duration::MAX
for
positive durations.
Examples
use fundu::DurationParser;
assert_eq!(
DurationParser::new().parse_negative("-10.2e-1s").unwrap(),
time::Duration::new(-1, -20_000_000),
);
assert_eq!(
DurationParser::new().parse_negative("1.2e-1s").unwrap(),
time::Duration::new(0, 120_000_000),
);
sourcepub fn default_unit(&mut self, unit: TimeUnit) -> &mut Self
pub fn default_unit(&mut self, unit: TimeUnit) -> &mut Self
Set the default TimeUnit
to unit
.
The default time unit is applied when no time unit was given in the input string. If the
default time unit is not set with this method the parser defaults to TimeUnit::Second
.
Examples
use std::time::Duration;
use fundu::DurationParser;
use fundu::TimeUnit::*;
assert_eq!(
DurationParser::with_all_time_units()
.default_unit(NanoSecond)
.parse("42")
.unwrap(),
Duration::new(0, 42)
);
sourcepub fn allow_delimiter(&mut self, delimiter: Option<Delimiter>) -> &mut Self
pub fn allow_delimiter(&mut self, delimiter: Option<Delimiter>) -> &mut Self
If Some
, allow one or more Delimiter
between the number and the TimeUnit
.
A Delimiter
is defined as closure taking a byte and returning true if the delimiter
matched. Per default no delimiter is allowed between the number and the TimeUnit
. Note
this setting implicitly allows the delimiter at the end of the string, but only if no time
unit was present. As usual the default time unit is assumed.
Examples
use std::time::Duration;
use fundu::{DurationParser, ParseError};
let mut parser = DurationParser::new();
assert_eq!(
parser.parse("123 ns"),
Err(ParseError::TimeUnit(
3,
"Invalid time unit: ' ns'".to_string()
))
);
parser.allow_delimiter(Some(|byte| byte == b' '));
assert_eq!(parser.parse("123 ns"), Ok(Duration::new(0, 123)));
parser.allow_delimiter(Some(|byte| matches!(byte, b'\t' | b'\n' | b'\r' | b' ')));
assert_eq!(parser.parse("123 ns"), Ok(Duration::new(0, 123)));
assert_eq!(parser.parse("123\t\n\r ns"), Ok(Duration::new(0, 123)));
sourcepub fn disable_exponent(&mut self, value: bool) -> &mut Self
pub fn disable_exponent(&mut self, value: bool) -> &mut Self
If true, disable parsing an exponent.
If an exponent is encountered in the input string and this setting is active this results
in an ParseError::Syntax
.
Examples
use fundu::{DurationParser, ParseError};
let mut parser = DurationParser::new();
parser.disable_exponent(true);
assert_eq!(
parser.parse("123e+1"),
Err(ParseError::Syntax(3, "No exponent allowed".to_string()))
);
sourcepub fn disable_fraction(&mut self, value: bool) -> &mut Self
pub fn disable_fraction(&mut self, value: bool) -> &mut Self
If true, disable parsing a fraction in the source string.
This setting will disable parsing a fraction and a point delimiter will cause an error
ParseError::Syntax
. It does not prevent Duration
s from being smaller than seconds.
Examples
use std::time::Duration;
use fundu::{DurationParser, ParseError};
let mut parser = DurationParser::new();
parser.disable_fraction(true);
assert_eq!(
parser.parse("123.456"),
Err(ParseError::Syntax(3, "No fraction allowed".to_string()))
);
assert_eq!(parser.parse("123e-2"), Ok(Duration::new(1, 230_000_000)));
assert_eq!(parser.parse("123ns"), Ok(Duration::new(0, 123)));
sourcepub fn disable_infinity(&mut self, value: bool) -> &mut Self
pub fn disable_infinity(&mut self, value: bool) -> &mut Self
If true, disable parsing infinity
This setting will disable parsing infinity values like (inf
or infinity
).
Examples
use fundu::{DurationParser, ParseError};
let mut parser = DurationParser::new();
parser.disable_infinity(true);
assert_eq!(
parser.parse("inf"),
Err(ParseError::Syntax(0, format!("Invalid input: 'inf'")))
);
assert_eq!(
parser.parse("infinity"),
Err(ParseError::Syntax(0, format!("Invalid input: 'infinity'")))
);
assert_eq!(
parser.parse("+inf"),
Err(ParseError::Syntax(1, format!("Invalid input: 'inf'")))
);
sourcepub fn number_is_optional(&mut self, value: bool) -> &mut Self
pub fn number_is_optional(&mut self, value: bool) -> &mut Self
If true, this setting makes a number in the source string optional.
If no number is present, then 1
is assumed. If a number is present then it must still
consist of either a whole part or fraction part, if not disabled with
DurationParser::disable_fraction
.
Examples
use std::time::Duration;
use fundu::DurationParser;
let mut parser = DurationParser::new();
parser.number_is_optional(true);
for input in &["ns", "e-9", "e-3Ms"] {
assert_eq!(parser.parse(input), Ok(Duration::new(0, 1)));
}
sourcepub fn parse_multiple(&mut self, delimiter: Option<Delimiter>) -> &mut Self
pub fn parse_multiple(&mut self, delimiter: Option<Delimiter>) -> &mut Self
If set to some Delimiter
, parse possibly multiple durations and sum them up.
If Delimiter
is set to None
, this functionality is disabled. The Delimiter
may or
may not occur to separate the durations. If the delimiter does not occur the next duration
is recognized by a leading digit.
Like a single duration, the summed up durations saturate at Duration::MAX
. Parsing
multiple durations is short-circuiting and parsing stops after the first ParseError
was encountered. Note that parsing doesn’t stop when reaching Duration::MAX
, so any
ParseError
s later in the input string are still reported.
Usage together with number format customizations
The number format and other aspects can be customized as usual via the methods within this struct and have the known effect. However, there are some interesting constellations:
If DurationParser::allow_delimiter
is set to some delimiter, the Delimiter
of this
method and the Delimiter
of the allow_delimiter
method can be equal either in parts or
in a whole without having side-effects on each other. But, if simultaneously
DurationParser::number_is_optional
is set to true, then the resulting Duration
will
differ:
use std::time::Duration;
use fundu::DurationParser;
let delimiter = |byte| matches!(byte, b' ' | b'\t');
let mut parser = DurationParser::new();
parser
.parse_multiple(Some(delimiter))
.number_is_optional(true);
// Here, the parser parses `1`, `s`, `1` and then `ns` separately
assert_eq!(parser.parse("1 s 1 ns"), Ok(Duration::new(3, 1)));
// Here, the parser parses `1 s` and then `1 ns`.
parser.allow_delimiter(Some(delimiter));
assert_eq!(parser.parse("1 s 1 ns"), Ok(Duration::new(1, 1)));
Examples
use std::time::Duration;
use fundu::DurationParser;
let mut parser = DurationParser::new();
parser.parse_multiple(Some(|byte| matches!(byte, b' ' | b'\t')));
assert_eq!(parser.parse("1.5h 2e+2ns"), Ok(Duration::new(5400, 200)));
assert_eq!(parser.parse("55s500ms"), Ok(Duration::new(55, 500_000_000)));
assert_eq!(parser.parse("1\t1"), Ok(Duration::new(2, 0)));
assert_eq!(parser.parse("1. .1"), Ok(Duration::new(1, 100_000_000)));
assert_eq!(parser.parse("2h"), Ok(Duration::new(2 * 60 * 60, 0)));
assert_eq!(
parser.parse("300ms20s 5d"),
Ok(Duration::new(5 * 60 * 60 * 24 + 20, 300_000_000))
);
sourcepub fn get_current_time_units(&self) -> Vec<TimeUnit>
pub fn get_current_time_units(&self) -> Vec<TimeUnit>
Return the currently defined set of TimeUnit
.
Examples
use fundu::{DurationParser, TimeUnit::*};
let parser = DurationParser::without_time_units();
assert_eq!(
parser.get_current_time_units(),
vec![]
);
assert_eq!(
DurationParser::with_time_units(&[NanoSecond]).get_current_time_units(),
vec![NanoSecond]
);
Trait Implementations§
source§impl Debug for DurationParser
impl Debug for DurationParser
source§impl Default for DurationParser
impl Default for DurationParser
source§impl PartialEq<DurationParser> for DurationParser
impl PartialEq<DurationParser> for DurationParser
source§fn eq(&self, other: &DurationParser) -> bool
fn eq(&self, other: &DurationParser) -> bool
self
and other
values to be equal, and is used
by ==
.