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
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
use crate::Result;
use crate::{has_hardened_diacritic, has_softened_diacritic};

/// Defines a type as being able to convert to half-width katakana.
///
/// # Example
///
/// ```
/// use to_kana::{ToKana, HalfWidth};
///
/// assert_eq!("ワールド", "wa-rudo".kata().half_width().unwrap());
/// ```
pub trait HalfWidth {
    fn half_width(self) -> Result;
}

impl HalfWidth for &str {
    fn half_width(self) -> Result {
        let mut s = String::new();
        for c in self.chars() {
            let has_softened_diacritic = has_softened_diacritic(c);
            let has_hardened_diacritic = has_hardened_diacritic(c);
            let c = match c {
                'ー' => 'ー',
                'ア' => 'ア',
                'イ' => 'イ',
                'ウ' | 'ヴ' => 'ウ',
                'エ' => 'エ',
                'オ' => 'オ',
                'カ' | 'ガ' => 'カ',
                'キ' | 'ギ' => 'キ',
                'ク' | 'グ' => 'ク',
                'ケ' | 'ゲ' => 'ケ',
                'コ' | 'ゴ' => 'コ',
                'サ' | 'ザ' => 'サ',
                'シ' | 'ジ' => 'シ',
                'ス' | 'ズ' => 'ス',
                'セ' | 'ゼ' => 'セ',
                'ソ' | 'ゾ' => 'ソ',
                'タ' | 'ダ' => 'タ',
                'チ' | 'ヂ' => 'チ',
                'ツ' | 'ヅ' => 'ツ',
                'ッ' => 'ッ',
                'テ' | 'デ' => 'テ',
                'ト' | 'ド' => 'ト',
                'ナ' => 'ナ',
                'ニ' => 'ニ',
                'ヌ' => 'ヌ',
                'ネ' => 'ネ',
                'ノ' => 'ノ',
                'ハ' | 'バ' | 'パ' => 'ハ',
                'ヒ' | 'ビ' | 'ピ' => 'ヒ',
                'フ' | 'ブ' | 'プ' => 'フ',
                'ヘ' | 'ベ' | 'ペ' => 'ヘ',
                'ホ' | 'ボ' | 'ポ' => 'ホ',
                'マ' => 'マ',
                'ミ' => 'ミ',
                'ム' => 'ム',
                'メ' => 'メ',
                'モ' => 'モ',
                'ヤ' => 'ヤ',
                'ユ' => 'ユ',
                'ヨ' => 'ヨ',
                'ャ' => 'ャ',
                'ュ' => 'ュ',
                'ョ' => 'ョ',
                'ラ' => 'ラ',
                'リ' => 'リ',
                'ル' => 'ル',
                'レ' => 'レ',
                'ロ' => 'ロ',
                'ワ' => 'ワ',
                'ヲ' => 'ヲ',
                'ン' => 'ン',
                _ => c,
            };
            s.push(c);
            if has_softened_diacritic {
                s.push('゙');
            } else if has_hardened_diacritic {
                s.push('゚');
            }
        }
        Ok(s)
    }
}
impl HalfWidth for String {
    fn half_width(self) -> Result {
        let s: &str = &self;
        s.half_width()
    }
}
impl HalfWidth for Result {
    fn half_width(self) -> Result {
        self?.half_width()
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn half_width_aiueo() {
        assert_eq!("アイウエオ", "アイウエオ".half_width().unwrap());
    }

    #[test]
    fn half_width_kakikukeko() {
        assert_eq!(
            "ガギグゲゴ",
            "ガギグゲゴ".half_width().unwrap()
        );
    }
}