ircv3_parse 4.0.0

Zero-copy parser for IRCv3 messages
Documentation
use proptest::{
    collection,
    prelude::{Just, Strategy},
    prop_compose, prop_oneof,
};

prop_compose! {
    pub fn rfc1123_strategy()(
        key in prop_oneof![
            rfc1123_label_strategy(),
            collection::vec(rfc1123_label_strategy(), 2..=10)
                .prop_map(|labels|fold_labels(labels, 253))
    ]) -> String { key }
}

prop_compose! {
    fn rfc1123_label_strategy()(
        first in "[a-zA-Z0-9]",
        middle in prop_oneof![
            Just("".to_string()),
            "[a-zA-Z0-9-]{0,61}[a-zA-Z0-9]".prop_map(|s| s),
            "[a-zA-Z0-9-]{61}[a-zA-Z0-9]".prop_map(|s| s),
        ]
    ) -> String {
        if middle.is_empty() {
            first
        } else {
            format!("{}{}", first, middle)
        }
    }
}

fn fold_labels(labels: Vec<String>, max_total_len: usize) -> String {
    labels
        .into_iter()
        .scan(0, |total_len, label| {
            let needed_len = if *total_len == 0 {
                label.len()
            } else {
                *total_len + 1 + label.len()
            };

            if needed_len <= max_total_len {
                *total_len = needed_len;
                Some(label)
            } else {
                None
            }
        })
        .collect::<Vec<_>>()
        .join(".")
}