1mod utils;
2
3use wasm_bindgen::prelude::*;
4
5#[cfg(feature = "wee_alloc")]
8#[global_allocator]
9static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT;
10
11#[wasm_bindgen]
12pub fn latin_to_cyrillic(input: String) -> String {
17 let mut output = String::new();
18 let mut iter = input.chars().peekable();
19
20 while let Some(c) = iter.next() {
21 match c {
22 's' => output.push('с'),
23 'o' => output.push('о'),
24 'e' => output.push('е'),
25 'a' => output.push('а'),
26 'i' => output.push('и'),
27 'n' => {
28 if let Some(&next) = iter.peek() {
29 if next == 'j' {
30 output.push('њ');
31 iter.next();
32 } else {
33 output.push('н');
34 }
35 } else {
36 output.push('н');
37 }
38 }
39 't' => output.push('т'),
40 'r' => output.push('р'),
41 'd' => {
42 if let Some(&next) = iter.peek() {
43 if next == 'ž' {
44 output.push('џ');
45 iter.next();
46 } else {
47 output.push('д');
48 }
49 } else {
50 output.push('д');
51 }
52 }
53 'l' => {
54 if let Some(&next) = iter.peek() {
55 if next == 'j' {
56 output.push('љ');
57 iter.next();
58 } else {
59 output.push('л');
60 }
61 } else {
62 output.push('л');
63 }
64 }
65 'u' => output.push('у'),
66 'k' => output.push('к'),
67 'm' => output.push('м'),
68 'b' => output.push('б'),
69 'p' => output.push('п'),
70 'z' => output.push('з'),
71 'š' => output.push('ш'),
72 'v' => output.push('в'),
73 'j' => output.push('ј'),
74 'h' => output.push('х'),
75 'f' => output.push('ф'),
76 'ž' => output.push('ж'),
77 'g' => output.push('г'),
78 'c' => output.push('ц'),
79 'č' => output.push('ч'),
80 'đ' => output.push('ђ'),
81 'ć' => output.push('ћ'),
82 'S' => output.push('С'),
83 'O' => output.push('О'),
84 'E' => output.push('Е'),
85 'I' => output.push('И'),
86 'A' => output.push('А'),
87 'N' => {
88 if let Some(&next) = iter.peek() {
89 if next == 'j' {
90 output.push('Њ');
91 iter.next();
92 } else {
93 output.push('Н');
94 }
95 } else {
96 output.push('Н');
97 }
98 }
99 'T' => output.push('Т'),
100 'R' => output.push('Р'),
101 'D' => {
102 if let Some(&next) = iter.peek() {
103 if next == 'ž' {
104 output.push('Џ');
105 iter.next();
106 } else {
107 output.push('Д');
108 }
109 } else {
110 output.push('Д');
111 }
112 }
113 'L' => {
114 if let Some(&next) = iter.peek() {
115 if next == 'j' {
116 output.push('Љ');
117 iter.next();
118 } else {
119 output.push('Л');
120 }
121 } else {
122 output.push('Л');
123 }
124 }
125 'U' => output.push('У'),
126 'K' => output.push('К'),
127 'M' => output.push('М'),
128 'B' => output.push('Б'),
129 'P' => output.push('П'),
130 'Z' => output.push('З'),
131 'Š' => output.push('Ш'),
132 'V' => output.push('В'),
133 'J' => output.push('Ј'),
134 'H' => output.push('Х'),
135 'F' => output.push('Ф'),
136 'Ž' => output.push('Ж'),
137 'G' => output.push('Г'),
138 'C' => output.push('Ц'),
139 'Č' => output.push('Ч'),
140 'Ć' => output.push('Ћ'),
141 'Đ' => output.push('Ђ'),
142 _ => output.push(c),
143 }
144 }
145
146 output
147}
148#[cfg(test)]
155mod tests {
156 use super::*;
158
159 #[test]
160 fn test_azbuka_small() {
161 assert_eq!(
162 latin_to_cyrillic("abvgdđežzijklljmnnjoprstćufhcčdžš".to_string()),
163 "абвгдђежзијклљмнњопрстћуфхцчџш"
164 );
165 }
166
167 #[test]
168 fn test_azbuka_big() {
169 assert_eq!(
170 latin_to_cyrillic("ABVGDĐEŽZIJKLLjMNNjOPRSTĆUFHCČDžŠ".to_string()),
171 "АБВГДЂЕЖЗИЈКЛЉМНЊОПРСТЋУФХЦЧЏШ"
172 );
173 }
174 #[test]
175 fn test_azbuka_small_1000000() {
176 assert_eq!(
177 latin_to_cyrillic(
178 "abvgdđežzijklljmnnjoprstćufhcčdžš"
179 .repeat(1000000)
180 .to_string()
181 ),
182 "абвгдђежзијклљмнњопрстћуфхцчџш".repeat(1000000)
183 );
184 }
185
186 #[test]
187 fn test_azbuka_big_1000000() {
188 assert_eq!(
189 latin_to_cyrillic(
190 "ABVGDĐEŽZIJKLLjMNNjOPRSTĆUFHCČDžŠ"
191 .repeat(1000000)
192 .to_string()
193 ),
194 "АБВГДЂЕЖЗИЈКЛЉМНЊОПРСТЋУФХЦЧЏШ".repeat(1000000)
195 );
196 }
197 #[test]
198 fn test_njljdž() {
199 assert_eq!(latin_to_cyrillic("njljdžNjLjDž".to_string()), "њљџЊЉЏ");
200 }
201}