cartulary 0.3.0-alpha.1

The knowledge layer of your project — decisions, issues, docs, all in one place.
Documentation
use crate::domain::model::body::Body;

/// Loaded content of a single companion file.
///
/// Today the adapter splits along the canonical / non-canonical
/// boundary: standardised companions decode to [`Text`], everything
/// else to [`Binary`]. Future iterations will refine the
/// classification through MIME / extension detection
/// (`Markdown`, `Image`, `Pdf`, `Svg`, …) so consumers can decide
/// rendering by content shape rather than by "is it one of the
/// known three".
///
/// [`Text`]: Self::Text
/// [`Binary`]: Self::Binary
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum CompanionContent {
    Text(Body),
    Binary(Vec<u8>),
}

impl CompanionContent {
    pub fn is_text(&self) -> bool {
        matches!(self, Self::Text(_))
    }

    pub fn is_binary(&self) -> bool {
        matches!(self, Self::Binary(_))
    }
}

#[cfg(test)]
pub mod strategy {
    use super::CompanionContent;
    use crate::domain::model::body::Body;
    use proptest::prelude::*;

    pub fn companion_content() -> impl Strategy<Value = CompanionContent> {
        prop_oneof![
            ".{0,100}".prop_map(|s| CompanionContent::Text(Body::new(&s))),
            proptest::collection::vec(any::<u8>(), 0..=64).prop_map(CompanionContent::Binary),
        ]
    }
}

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

    proptest! {
        #[test]
        fn classifiers_are_mutually_exclusive(c in strategy::companion_content()) {
            prop_assert!(c.is_text() ^ c.is_binary());
        }
    }

    #[test]
    fn text_variant_classifies_as_text() {
        let c = CompanionContent::Text(Body::new("hello"));
        assert!(c.is_text());
        assert!(!c.is_binary());
    }

    #[test]
    fn binary_variant_classifies_as_binary() {
        let c = CompanionContent::Binary(vec![0xff, 0xd8]);
        assert!(c.is_binary());
        assert!(!c.is_text());
    }
}