cargo-apple-runner 0.0.1

Cargo runner for bundling and launching applications on simulator / on device
Documentation
use core::fmt;
use std::str::FromStr;

use anyhow::Context;

#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct OSVersion {
    pub major: u16,
    pub minor: u8,
    pub patch: u8,
}

impl OSVersion {
    pub const MIN: Self = Self::from_packed(u32::MIN);
    pub const MAX: Self = Self::from_packed(u32::MAX);

    pub const fn from_packed(packed: u32) -> Self {
        let major = ((packed >> 16) & 0xFFFF) as u16;
        let minor = ((packed >> 8) & 0xFF) as u8;
        let patch = (packed & 0xFF) as u8;

        Self {
            major,
            minor,
            patch,
        }
    }
}

impl FromStr for OSVersion {
    type Err = anyhow::Error;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        let (major, rest) = s.split_once('.').context("missing version separator")?;
        let major: u16 = major.parse()?;
        if let Some((minor, patch)) = rest.split_once('.') {
            let minor: u8 = minor.parse()?;
            let patch: u8 = patch.parse()?;
            Ok(Self {
                major,
                minor,
                patch,
            })
        } else {
            let minor: u8 = rest.parse()?;
            Ok(Self {
                major,
                minor,
                patch: 0,
            })
        }
    }
}

impl fmt::Display for OSVersion {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{}.{}", self.major, self.minor)?;
        if self.patch != 0 {
            write!(f, ".{}", self.patch)?;
        }
        Ok(())
    }
}