Crate fundu_systemd

Source
Expand description

A simple to use, fast and accurate systemd time span parser fully compatible with the systemd time span format

fundu-systemd can parse rust strings like

&strDuration
"2 h"Duration::positive(2 * 60 * 60, 0)
"2hours"Duration::positive(2 * 60 * 60, 0)
"second"Duration::positive(1, 0)
"48hr"Duration::positive(48 * 60 * 60, 0)
"12.3 seconds"Duration::positive(12, 300_000_000)
"1y 12month"Duration::positive(63_115_200, 0)
"999us +1d"Duration::positive(86_400, 999_000)
"55s500ms"Duration::positive(55, 500_000_000)
"300ms20s 5day"Duration::positive(20 + 5 * 60 * 60 * 24, 300_000_000)
"123456789"Duration::positive(123_456_789, 0) (Default: Second)
"100"Duration::positive(0, 100_000) (when default is set to MicroSecond)
"infinity"variable: the maximum duration which is currently in use (see below)

Note that fundu parses into its own Duration which is a superset of other Durations like std::time::Duration, chrono::Duration and time::Duration. See the documentation how to easily handle the conversion between these durations.

§The Format

Supported time units:

  • nsec, ns (can be switched on, per default these are not included)
  • usec, us, µs
  • msec, ms
  • seconds, second, sec, s
  • minutes, minute, min, m
  • hours, hour, hr, h
  • days, day, d
  • weeks, week, w
  • months, month, M (defined as 30.44 days or a 1/12 year)
  • years, year, y (defined as 365.25 days)

Summary of the rest of the format:

  • Only numbers like "123 days" or with fraction "1.2 days" but without exponent (like "3e9 days") are allowed
  • For numbers without a time unit (like "1234") the default time unit is usually second but can be changed since in some case systemd uses a different granularity.
  • Time units without a number (like in "second") are allowed and a value of 1 is assumed.
  • The parsed duration represents the value exactly (without rounding errors as would occur in floating point calculations) as it is specified in the source string (just like systemd).
  • The maximum supported duration (Duration::MAX) has u64::MAX seconds (18_446_744_073_709_551_615) and 999_999_999 nano seconds. However, systemd uses u64::MAX micro seconds as maximum duration when parsing without nanos and u64::MAX nano seconds when parsing with nanos. fundu-systemd provides the parse and parse_nanos functions to reflect that. If you don’t like the maximum duration of systemd it’s still possible via parse_with_max and parse_nanos_with_max to adjust this limit to a duration ranging from Duration::ZERO to Duration::MAX.
  • The special value "infinity" evaluates to the maximum duration. Note the maximum duration depends on whether parsing with nano seconds or without. If the maximum duration is manually set to a different value then it evaluates to that maximum duration.
  • parsed durations larger than the maximum duration (like "100000000000000years") saturate at the maximum duration
  • Negative durations are not allowed, also no intermediate negative durations like in "5day -1ms" although the final duration would not be negative.
  • Any leading, trailing whitespace or whitespace between the number and the time unit (like in "1 \n sec") and multiple durations (like in "1week \n 2minutes") is ignored and follows the posix definition of whitespace which is:
    • Space (' ')
    • Horizontal Tab ('\x09')
    • Line Feed ('\x0A')
    • Vertical Tab ('\x0B')
    • Form Feed ('\x0C')
    • Carriage Return ('\x0D')

Please see also the systemd documentation for a description of their format.

§Examples

A re-usable parser providing different parse methods

use fundu::Duration;
use fundu_systemd::{TimeSpanParser, SYSTEMD_MAX_MICRO_DURATION, SYSTEMD_MAX_NANOS_DURATION};

const PARSER: TimeSpanParser = TimeSpanParser::new();

let parser = &PARSER;
assert_eq!(parser.parse("2h"), Ok(Duration::positive(2 * 60 * 60, 0)));
assert_eq!(parser.parse("second"), Ok(Duration::positive(1, 0)));
assert_eq!(
    parser.parse("48hr"),
    Ok(Duration::positive(48 * 60 * 60, 0))
);
assert_eq!(
    parser.parse("12.3 seconds"),
    Ok(Duration::positive(12, 300_000_000))
);
assert_eq!(
    parser.parse("300ms20s 5day"),
    Ok(Duration::positive(20 + 5 * 60 * 60 * 24, 300_000_000))
);
assert_eq!(
    parser.parse("123456789"),
    Ok(Duration::positive(123_456_789, 0))
);
assert_eq!(parser.parse("infinity"), Ok(SYSTEMD_MAX_MICRO_DURATION));

// Or parsing nano seconds
assert_eq!(
    parser.parse_nanos("7809 nsec"),
    Ok(Duration::positive(0, 7809))
);
assert_eq!(
    parser.parse_nanos("infinity"),
    Ok(SYSTEMD_MAX_NANOS_DURATION)
);

Change the default unit to something different than Second

use fundu::{Duration, TimeUnit};
use fundu_systemd::TimeSpanParser;

let parser = TimeSpanParser::with_default_unit(TimeUnit::MicroSecond);
assert_eq!(parser.parse("100"), Ok(Duration::positive(0, 100_000)));

let mut parser = TimeSpanParser::new();
parser.set_default_unit(TimeUnit::MicroSecond);

assert_eq!(parser.parse("100"), Ok(Duration::positive(0, 100_000)));

Or use one of the global methods parse, parse_nanos.

use fundu::{Duration, ParseError};
use fundu_systemd::{
    parse, parse_nanos, SYSTEMD_MAX_MICRO_DURATION, SYSTEMD_MAX_NANOS_DURATION,
};

assert_eq!(parse("123 sec", None, None), Ok(Duration::positive(123, 0)));

// This is an error with `parse` because the nano seconds are excluded
assert_eq!(
    parse("123 nsec", None, None),
    Err(ParseError::InvalidInput("nsec".to_string()))
);

// Use `parse_nanos` if the nano second time units should be included
assert_eq!(
    parse_nanos("123 nsec", None, None),
    Ok(Duration::positive(0, 123))
);

// The maximum duration differs depending on the method in use
assert_eq!(
    parse("infinity", None, None),
    Ok(SYSTEMD_MAX_MICRO_DURATION)
);
assert_eq!(
    parse_nanos("infinity", None, None),
    Ok(SYSTEMD_MAX_NANOS_DURATION)
);

// But can be easily changed
assert_eq!(
    parse_nanos("infinity", None, Some(Duration::MAX)),
    Ok(Duration::MAX)
);

For further details see parse, parse_nanos or the documentation of TimeSpanParser

Structs§

TimeSpanParser
The main systemd time span parser
TimeUnits
This struct is used internally to hold the time units without nano second time units
TimeUnitsWithNanos
This struct is used internally to hold the time units with nano second time units

Constants§

SYSTEMD_MAX_MICRO_DURATION
The maximum duration used when parsing with micro seconds precision
SYSTEMD_MAX_NANOS_DURATION
The maximum duration used when parsing with nano seconds precision

Functions§

parse
Parse the source string into a Duration
parse_nanos
Parse the source string into a Duration with nano second time units