kutil_std/string/
conjunction.rs

1use super::super::iter::*;
2
3/// Join with conjunction.
4pub trait JoinConjunction<'own> {
5    /// Join iterated strings as human-readable in English with a conjunction
6    /// and an Oxford comma.
7    ///
8    /// Examples:
9    ///
10    /// * "one"
11    /// * "one or two"
12    /// * "one, two, or three"
13    /// * "one, two, three, or four"
14    fn join_conjunction(&'own self, conjunction: &str) -> String;
15}
16
17impl<'own, IterableT, ItemT> JoinConjunction<'own> for IterableT
18where
19    ItemT: AsRef<str> + 'own,
20    &'own IterableT: IntoIterator<Item = ItemT> + 'own,
21{
22    fn join_conjunction(&'own self, conjunction: &str) -> String {
23        let mut options = String::new();
24
25        let mut has_at_least_two = false;
26        for (item, first, last) in IterateWithFirstLast::new(self) {
27            if !first {
28                if last {
29                    if has_at_least_two {
30                        options.push_str(", ");
31                    } else {
32                        options.push(' ');
33                    }
34                    options.push_str(conjunction);
35                    options.push(' ');
36                } else {
37                    options.push_str(", ");
38                    has_at_least_two = true;
39                }
40            }
41
42            options.push_str(item.as_ref());
43        }
44
45        options
46    }
47}