rjango 0.1.1

A full-stack Rust backend framework inspired by Django
Documentation
const COMMON_P: &str = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.";
const COMMON_WORDS: &[&str] = &[
    "lorem",
    "ipsum",
    "dolor",
    "sit",
    "amet",
    "consectetur",
    "adipiscing",
    "elit",
    "sed",
    "do",
    "eiusmod",
    "tempor",
    "incididunt",
    "ut",
    "labore",
    "et",
    "dolore",
    "magna",
    "aliqua",
];
const WORDS: &[&str] = &[
    "dolor",
    "sit",
    "amet",
    "consectetur",
    "adipiscing",
    "elit",
    "sed",
    "do",
    "eiusmod",
    "tempor",
    "incididunt",
    "ut",
    "labore",
    "et",
    "dolore",
    "magna",
    "aliqua",
    "enim",
    "minim",
    "veniam",
    "quis",
    "nostrud",
    "exercitation",
    "ullamco",
];
const SENTENCE_WORDS: usize = 8;
const SENTENCES_PER_PARAGRAPH: usize = 3;

/// Return a deterministic lorem ipsum word sequence.
#[must_use]
pub fn words(count: usize, common: bool) -> String {
    if count == 0 {
        return String::new();
    }

    let source = if common { COMMON_WORDS } else { WORDS };

    (0..count)
        .map(|index| source[index % source.len()])
        .collect::<Vec<_>>()
        .join(" ")
}

/// Return a deterministic lorem ipsum sentence.
#[must_use]
pub fn sentence() -> String {
    build_sentence(COMMON_WORDS, 0, SENTENCE_WORDS)
}

/// Return the canonical lorem ipsum paragraph.
#[must_use]
pub fn paragraph() -> String {
    COMMON_P.to_string()
}

/// Return one or more deterministic lorem ipsum paragraphs.
#[must_use]
pub fn paragraphs(count: usize, common: bool) -> String {
    if count == 0 {
        return String::new();
    }

    (0..count)
        .map(|index| {
            if common && index == 0 {
                COMMON_P.to_string()
            } else {
                generated_paragraph(index)
            }
        })
        .collect::<Vec<_>>()
        .join("\n\n")
}

fn generated_paragraph(seed: usize) -> String {
    (0..SENTENCES_PER_PARAGRAPH)
        .map(|sentence_index| {
            build_sentence(
                WORDS,
                seed * 5 + sentence_index * SENTENCE_WORDS,
                SENTENCE_WORDS,
            )
        })
        .collect::<Vec<_>>()
        .join(" ")
}

fn build_sentence(source: &[&str], start: usize, count: usize) -> String {
    let words = (0..count)
        .map(|index| source[(start + index) % source.len()])
        .collect::<Vec<_>>()
        .join(" ");

    let mut chars = words.chars();
    let mut sentence = match chars.next() {
        Some(first) => first.to_ascii_uppercase().to_string(),
        None => String::new(),
    };
    sentence.push_str(chars.as_str());
    sentence.push('.');
    sentence
}

#[cfg(test)]
mod tests {
    use super::{paragraph, paragraphs, sentence, words};

    #[test]
    fn words_returns_expected_common_prefix() {
        assert_eq!(words(5, true), "lorem ipsum dolor sit amet");
    }

    #[test]
    fn words_cycles_deterministically_for_generated_text() {
        assert_eq!(
            words(6, false),
            "dolor sit amet consectetur adipiscing elit"
        );
        assert_eq!(words(26, false).split_whitespace().count(), 26);
    }

    #[test]
    fn sentence_and_paragraph_use_expected_text() {
        assert_eq!(
            sentence(),
            "Lorem ipsum dolor sit amet consectetur adipiscing elit."
        );
        assert_eq!(
            paragraph(),
            "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."
        );
    }

    #[test]
    fn paragraphs_include_common_first_paragraph_when_requested() {
        let generated = paragraphs(2, true);
        let parts: Vec<_> = generated.split("\n\n").collect();

        assert_eq!(parts.len(), 2);
        assert_eq!(parts[0], paragraph());
        assert_eq!(
            parts[1],
            "Elit sed do eiusmod tempor incididunt ut labore. Et dolore magna aliqua enim minim veniam quis. Nostrud exercitation ullamco dolor sit amet consectetur adipiscing."
        );
    }
}