libmirage 0.1.1

Rust bindings for libMirage
Documentation
use std::fmt;
use std::time::Duration;

pub(crate) fn duration_from_sectors(sectors: i32) -> Option<Duration> {
    // 75 sectors represent 1 second of audio.
    // See: <https://en.wikipedia.org/wiki/Compact_Disc_Digital_Audio#Bit_rate>
    const SECTORS_PER_SECOND: u64 = 75;
    const NANOS_PER_SECOND: u64 = 1_000_000_000;
    let sectors = u64::try_from(sectors).ok()?;
    // No overflow possible since 2^31 (i32::MAX) * 10^9 < 2^64 (u64::MAX)
    let duration_in_nanos = (sectors * NANOS_PER_SECOND) / SECTORS_PER_SECOND;
    Some(Duration::from_nanos(duration_in_nanos))
}

pub(crate) const RATIO: &str = "∶";

pub(crate) fn format_duration(f: &mut dyn fmt::Write, duration: Option<Duration>) -> fmt::Result {
    const SECONDS_PER_MINUTE: u128 = 60;
    const MILLISECONDS_PER_SECOND: u128 = 1_000;
    let Some(duration) = duration else {
        return write!(f, "(unknown)");
    };
    let total_milliseconds = duration.as_millis();
    let total_seconds = rounded_div_u128(total_milliseconds, MILLISECONDS_PER_SECOND);
    write!(
        f,
        "{}{RATIO}{:02}",
        total_seconds / SECONDS_PER_MINUTE,
        total_seconds % SECONDS_PER_MINUTE,
    )
}

// Adapted from the [rounded-div](https://github.com/KSXGitHub/rounded-div) crate.
const fn rounded_div_u128(dividend: u128, divisor: u128) -> u128 {
    let quotient = dividend / divisor;
    let remainder = dividend % divisor;
    quotient + (remainder << 1 >= divisor) as u128
}