DurationUnits

Struct DurationUnits 

Source
pub(crate) struct DurationUnits {
    values: [u64; 10],
    fraction: Option<u32>,
    sign: Sign,
    min: Option<Unit>,
    max: Option<Unit>,
    any_non_zero_units: bool,
}
Expand description

A container for holding a partially parsed duration.

This is used for parsing into Span, SignedDuration and (hopefully soon) std::time::Duration. It’s also used for both the ISO 8601 duration and “friendly” format.

This replaced a significant chunk of code that was bespoke to each combination of duration type and format.

The idea behind it is that we parse each duration component as an unsigned 64-bit integer and keep track of the sign separately. This is a critical aspect that was motivated by being able to roundtrip all legal values of a 96-bit signed integer number of nanoseconds (i.e., SignedDuration). In particular, if we used i64 to represent each component, then it makes it much more difficult to parse, e.g., 9223372036854775808 seconds ago. Namely, 9223372036854775808 is not a valid i64 but -9223372036854775808 is. Notably, the sign is indicated by a suffix, so we don’t know it’s negative when parsing the integer itself. So we represent all components as their unsigned absolute value and apply the sign at the end.

This also centralizes a lot of thorny duration math and opens up the opportunity for tighter optimization.

Fields§

§values: [u64; 10]

The parsed unit values in descending order. That is, nanoseconds are at index 0 while years are at index 9.

§fraction: Option<u32>

Any fractional component parsed. The fraction is necessarily a fraction of the minimum unit if present.

§sign: Sign

The sign of the duration. This may be set at any time.

Note that this defaults to zero! So callers will always want to set this.

§min: Option<Unit>

The smallest unit value that was explicitly set.

§max: Option<Unit>

The largest unit value that was explicitly set.

§any_non_zero_units: bool

Whether there are any non-zero units.

Implementations§

Source§

impl DurationUnits

Source

pub(crate) fn set_unit_value( &mut self, unit: Unit, value: u64, ) -> Result<(), Error>

Set the duration component value for the given unit.

The value here is always unsigned. To deal with negative values, set the sign independently. It will be accounted for when using one of this type’s methods for converting to a concrete duration type.

§Panics

When this is called after set_fraction.

§Errors

Since this is meant to be used in service of duration parsing and all duration parsing proceeds from largest to smallest units, this will return an error if the given unit is bigger than or equal to any previously set unit. This also implies that this can only be called at most once for each unit value.

Source

pub(crate) fn set_hms( &mut self, hours: u64, minutes: u64, seconds: u64, fraction: Option<u32>, ) -> Result<(), Error>

A convenience routine for setting values parsed from an HH:MM:SS format (including the fraction).

§Errors

This forwards errors from DurationUnits::set_unit_value. It will also return an error is the minimum parsed unit (so far) is smaller than days. (Since HH:MM:SS can only appear after units of years, months, weeks or days.)

Source

pub(crate) fn set_fraction(&mut self, fraction: u32) -> Result<(), Error>

Set the fractional value.

This is always interpreted as a fraction of the minimal unit.

Callers must ensure this is called after the last call to DurationUnits::set_unit_value.

§Panics

When fraction is not in the range 0..=999_999_999. Callers are expected to uphold this invariant.

§Errors

This will return an error if the minimum unit is Unit::Nanosecond. (Because fractional nanoseconds are not supported.) This will also return an error if the minimum unit is bigger than Unit::Hour.

Source

pub(crate) fn set_sign(&mut self, sign: Sign)

Set the sign associated with the components.

The sign applies to the entire duration. There is no support for having some components signed and some unsigned.

If no sign is set, then it is assumed to be zero. Note also that even if a sign is explicitly set and all unit values are zero, then the sign will be set to zero.

Source

pub(crate) fn to_span(&self) -> Result<Span, Error>

Convert these duration components to a Span.

§Errors

If any individual unit exceeds the limits of a Span, or if the units combine to exceed what can be represented by a Span, then this returns an error.

This also returns an error if no units were set.

Source

fn to_span_general(&self) -> Result<Span, Error>

The “general” implementation of DurationUnits::to_span.

This handles all possible cases, including fractional units, with good error handling. Basically, we take this path when we think an error could occur. But this function is more bloaty and does more work, so the more it can be avoided, the better.

Source

pub(crate) fn to_signed_duration(&self) -> Result<SignedDuration, Error>

Convert these duration components to a SignedDuration.

§Errors

If the total number of nanoseconds represented by all units combined exceeds what can bit in a 96-bit signed integer, then an error is returned.

An error is also returned if any calendar units (days or greater) were set or if no units were set.

Source

fn to_signed_duration_general(&self) -> Result<SignedDuration, Error>

The “general” implementation of DurationUnits::to_signed_duration.

This handles all possible cases, including fractional units, with good error handling. Basically, we take this path when we think an error could occur. But this function is more bloaty and does more work, so the more it can be avoided, the better.

Source

pub(crate) fn to_unsigned_duration(&self) -> Result<Duration, Error>

Convert these duration components to a core::time::Duration.

§Errors

If the total number of nanoseconds represented by all units combined exceeds what can bit in a 96-bit signed integer, then an error is returned.

An error is also returned if any calendar units (days or greater) were set or if no units were set.

Source

fn to_unsigned_duration_general(&self) -> Result<Duration, Error>

The “general” implementation of DurationUnits::to_unsigned_duration.

This handles all possible cases, including fractional units, with good error handling. Basically, we take this path when we think an error could occur. But this function is more bloaty and does more work, so the more it can be avoided, the better.

Source

pub(crate) fn get_min(&self) -> Option<Unit>

Returns the minimum unit set.

This only returns None when no units have been set.

Source

fn get_min_max_units(&self) -> Result<(Unit, Unit), Error>

Returns the minimum and maximum units set.

This returns an error if no units were set. (Since this means there were no parsed duration components.)

Source

fn get_unit_value(&self, unit: Unit) -> Result<i64, Error>

Returns the corresponding unit value using the set signed-ness.

Source

fn get_fraction(&self) -> Result<Option<i32>, Error>

Returns the fraction using the set signed-ness.

This returns None when no fraction has been set.

Source

fn get_sign(&self) -> Sign

Returns the sign that should be applied to each individual unit.

Trait Implementations§

Source§

impl Debug for DurationUnits

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Default for DurationUnits

Source§

fn default() -> DurationUnits

Returns the “default value” for a type. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.