haz-domain 0.2.0

Shared domain types for the haz task runner (identifiers, paths, errors).
Documentation
//! `TagName`: a workspace-scoped tag identifier.

use nutype::nutype;

use crate::name::validation::{NameError, validate};

/// A validated tag name.
///
/// Construction is via [`TagName::try_new`] (or the standard
/// [`std::str::FromStr`] interface). Both delegate to the shared
/// identifier validator and propagate a [`NameError`] describing
/// the violated `ID-*` rule.
///
/// # Examples
///
/// ```
/// use haz_domain::name::TagName;
///
/// let t = TagName::try_new("typescript").unwrap();
/// assert_eq!(t.to_string(), "typescript");
/// ```
#[nutype(
    validate(with = validate, error = NameError),
    derive(
        Debug,
        Clone,
        PartialEq,
        Eq,
        PartialOrd,
        Ord,
        Hash,
        Display,
        FromStr,
        AsRef,
    ),
)]
pub struct TagName(String);

#[cfg(test)]
mod tests {
    use crate::name::TagName;

    #[test]
    fn id_004_case_sensitive_equality() {
        let upper = TagName::try_new("Release").unwrap();
        let lower = TagName::try_new("release").unwrap();
        assert_ne!(upper, lower);
    }

    #[test]
    fn round_trip_via_try_new_and_display() {
        let n = TagName::try_new("typescript").unwrap();
        assert_eq!(n.to_string(), "typescript");
    }
}