This repository has been archived on 2022-05-30. You can view files and clone it, but cannot push or open issues or pull requests.
nrid.rs/src/sentence.rs

160 lines
4.6 KiB
Rust

/*!
* Provides traits and helpers for generating and manipulating written lanuage constructs
*/
/// A type that can be compiled into a sentence.
pub trait ToSentence {
/// Sentencifies self. The result should be suitable to be placed within a sentence.
fn to_sentence(&self) -> String;
/// Sentencifies self, upper-casing the first letter and adding a period to the end. Using this is discouraged due to its lack of flexibility (i.e. needing alternate punctuation or a lowercase first letter).
fn to_sentence_finalize(&self) -> String {
let s = self.to_sentence();
let mut c = s.chars();
match s.len() {
0 => format!(""),
1 => format!("{}.", s.to_uppercase()),
_ => format!("{}{}.", c.nth(0).unwrap().to_uppercase(), c.as_str()),
}
}
}
impl<'a, T> ToSentence for T where T: AsRef<[&'a str]> {
fn to_sentence(&self) -> String {
let s = self.as_ref();
let len = s.len();
let mut str = String::new();
for (i, seg) in s.iter().map(|s| s.as_ref()).enumerate() {
if i == 0 {
str.push_str(seg);
} else if i == len-1 {
if len == 2 {
str.push_str(&format!(" and {}", seg));
} else {
str.push_str(&format!(", and {}", seg));
}
} else {
str.push_str(&format!(", {}", seg));
}
}
str
}
}
// impl<T> ToSentence for T where T: AsRef<[String]> {
// fn to_sentence(&self) -> String {
// let s = self.as_ref();
// let len = s.len();
// let mut str = String::new();
// for (i, seg) in s.iter().map(|s| s.as_ref()).enumerate() {
// if i == 0 {
// str.push_str(seg);
// } else if i == len {
// if len == 2 {
// str.push_str(&format!(" and {}", seg));
// } else {
// str.push_str(&format!(", and {}", seg));
// }
// } else {
// str.push_str(&format!(", {}", seg));
// }
// }
// str
// }
// }
#[cfg(test)]
mod test {
use super::ToSentence;
const STRING_SLICE_A: &'static [&'static str] = &[
"a",
];
const STRING_SLICE_B: &'static [&'static str] = &[
"a",
"b",
];
const STRING_SLICE_C: &'static [&'static str] = &[
"a",
"b",
"c",
"d",
"e",
"f",
"g",
];
#[test]
fn str_slice_to_sentence() {
assert_eq!(STRING_SLICE_A.to_sentence(), "a");
assert_eq!(STRING_SLICE_B.to_sentence(), "a and b");
assert_eq!(STRING_SLICE_C.to_sentence(), "a, b, c, d, e, f, and g");
}
#[test]
fn str_slice_to_sentence_finalize() {
assert_eq!(STRING_SLICE_A.to_sentence_finalize(), "A.");
assert_eq!(STRING_SLICE_B.to_sentence_finalize(), "A and b.");
assert_eq!(STRING_SLICE_C.to_sentence_finalize(), "A, b, c, d, e, f, and g.");
}
#[test]
fn string_vec_to_sentence() {
let vec: Vec<String> = vec!{
"a".to_owned(),
};
assert_eq!(vec.iter().map(|e| e.as_ref()).collect::<Vec<&str>>().to_sentence(), "a");
let vec: Vec<String> = vec!{
"a".to_owned(),
"b".to_owned(),
};
assert_eq!(vec.iter().map(|e| e.as_ref()).collect::<Vec<&str>>().to_sentence(), "a and b");
let vec: Vec<String> = vec!{
"a".to_owned(),
"b".to_owned(),
"c".to_owned(),
"d".to_owned(),
"e".to_owned(),
"f".to_owned(),
"g".to_owned(),
};
assert_eq!(vec.iter().map(|e| e.as_ref()).collect::<Vec<&str>>().to_sentence(), "a, b, c, d, e, f, and g");
}
#[test]
fn string_vec_to_sentence_finalize() {
let vec: Vec<String> = vec!{
"a".to_owned(),
};
assert_eq!(vec.iter().map(|e| e.as_ref()).collect::<Vec<&str>>().to_sentence_finalize(), "A.");
let vec: Vec<String> = vec!{
"a".to_owned(),
"b".to_owned(),
};
assert_eq!(vec.iter().map(|e| e.as_ref()).collect::<Vec<&str>>().to_sentence_finalize(), "A and b.");
let vec: Vec<String> = vec!{
"a".to_owned(),
"b".to_owned(),
"c".to_owned(),
"d".to_owned(),
"e".to_owned(),
"f".to_owned(),
"g".to_owned(),
};
assert_eq!(vec.iter().map(|e| e.as_ref()).collect::<Vec<&str>>().to_sentence_finalize(), "A, b, c, d, e, f, and g.");
}
}