klick-domain 0.4.11

Calculate the carbon footprints for wastewater treatment plants
Documentation
use std::str::FromStr;

use thiserror::Error;
use time::OffsetDateTime;
use uuid::Uuid;

#[derive(Debug, Clone)]
pub struct Project<D> {
    pub id: Id,
    pub created_at: OffsetDateTime,
    pub modified_at: Option<OffsetDateTime>,
    pub data: D,
}

#[derive(Debug, Clone, Copy, PartialEq, Hash)]
pub struct Id(Uuid);

impl Id {
    #[must_use]
    #[allow(clippy::new_without_default)]
    pub fn new() -> Self {
        Self(Uuid::new_v4())
    }

    #[must_use]
    pub const fn from_uuid(uuid: Uuid) -> Self {
        Self(uuid)
    }

    #[must_use]
    pub const fn to_uuid(&self) -> Uuid {
        self.0
    }
}

impl ToString for Id {
    fn to_string(&self) -> String {
        self.0.simple().to_string()
    }
}

#[derive(Debug, Error)]
#[error("Invalid project ID")]
pub struct IdParseError;

impl FromStr for Id {
    type Err = IdParseError;
    fn from_str(from: &str) -> Result<Self, Self::Err> {
        let uuid = from.parse::<Uuid>().map_err(|_| IdParseError)?;
        Ok(Self(uuid))
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use uuid::uuid;

    const EXAMPLE_ID: Uuid = uuid!("157296c3-4a0c-4794-91bb-34008da55535");

    #[test]
    fn id_to_string() {
        let id = Id::from_uuid(EXAMPLE_ID);
        assert_eq!(id.to_string(), "157296c34a0c479491bb34008da55535");
    }

    #[test]
    fn parse() {
        let id = "157296c3-4a0c-4794-91bb-34008da55535"
            .parse::<Id>()
            .unwrap();
        assert_eq!(id.0, EXAMPLE_ID);

        let id = "157296c34a0c479491bb34008da55535".parse::<Id>().unwrap();
        assert_eq!(id.0, EXAMPLE_ID);

        let id = "157296C34A0C479491BB34008DA55535".parse::<Id>().unwrap();
        assert_eq!(id.0, EXAMPLE_ID);
    }
}