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;
#[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(" ")
}
#[must_use]
pub fn sentence() -> String {
build_sentence(COMMON_WORDS, 0, SENTENCE_WORDS)
}
#[must_use]
pub fn paragraph() -> String {
COMMON_P.to_string()
}
#[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."
);
}
}