Skip to content

Duration type conversions are difficult to use in practice #121

Open
@ryan-summers

Description

@ryan-summers

In a hypothetical scenario where a user wants to divide a Seconds<u32> in half, and the value is unknown, the library performs truncation on the result because the result type assumes the LHS type. For example, Seconds(1) / 2 is equal to zero duration. This is obviously not desired, so code should protect against this condition.

To guard against this, a logical step is to then instead convert from seconds -> milliseconds before dividing. Milliseconds::from(Seconds(1)) / 2. However, because From<Seconds> is not implemented for Milliseconds<u32>, but rather only Milliseconds<u64>, this means that a library that is generic over the Clock has to implement an additional traitbound over the clock type.

fn half_duration_in_future<C>(seconds: u32, clock: C) -> Instant<C>
where
    C: embedded_time::Clock,

    // Necessary trait bound to divide seconds reliably
    C::T: core::convert::TryFrom<u64>
{
    let now = clock.try_now().unwrap();

    let step = Milliseconds::from(Seconds(seconds)) / 2;

    now + step
} 

This then propagates throughout the whole code base, as all functions taking the generic clock are also required to carry the C::T: core::convert::TryFrom<u64> bound as well (e.g. if the division is done on some internal object).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions