1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
use std::collections::BTreeSet;

pub trait Inflector {
    fn inflect(&self, name_parts: &[String]) -> String;
}

pub struct KeywordAvoidingInflector<I> {
    keywords: BTreeSet<String>,
    inflector: I,
}

impl<I> KeywordAvoidingInflector<I> {
    pub fn new(keywords: BTreeSet<String>, inflector: I) -> Self {
        Self {
            keywords,
            inflector,
        }
    }
}

impl<I: Inflector> Inflector for KeywordAvoidingInflector<I> {
    fn inflect(&self, name_parts: &[String]) -> String {
        let raw_name = self.inflector.inflect(name_parts);

        if self.keywords.contains(&raw_name) {
            format!("{}_", raw_name)
        } else {
            raw_name
        }
    }
}

pub struct CombiningInflector {
    case: Case,
}

impl CombiningInflector {
    pub fn new(case: Case) -> Self {
        Self { case }
    }
}

impl Inflector for CombiningInflector {
    fn inflect(&self, name_parts: &[String]) -> String {
        self.case.to_case(&name_parts.join("_"))
    }
}

pub struct TailInflector {
    case: Case,
}

impl TailInflector {
    pub fn new(case: Case) -> Self {
        Self { case }
    }
}

impl Inflector for TailInflector {
    fn inflect(&self, name_parts: &[String]) -> String {
        self.case
            .to_case(name_parts.last().expect("TailInflector: empty name_parts"))
    }
}

pub enum Case {
    SnakeCase,
    CamelCase,
    PascalCase,
    ScreamingSnakeCase,
}

impl Case {
    fn to_case(&self, s: &str) -> String {
        use teeter_inflector::cases::camelcase::to_camel_case;
        use teeter_inflector::cases::pascalcase::to_pascal_case;
        use teeter_inflector::cases::screamingsnakecase::to_screaming_snake_case;
        use teeter_inflector::cases::snakecase::to_snake_case;

        match self {
            Self::SnakeCase => to_snake_case(s),
            Self::CamelCase => to_camel_case(s),
            Self::PascalCase => to_pascal_case(s),
            Self::ScreamingSnakeCase => to_screaming_snake_case(s),
        }
    }
}