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: 'own + AsRef<str>,
20    &'own IterableT: 'own + IntoIterator<Item = ItemT>,
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}