rust_persian_tools/digits/
mod.rs1use std::borrow::Cow;
17use std::ops::Range;
18
19pub fn fa_to_en(input: impl AsRef<str>) -> String {
21 convert(input, 1776..1786, -1728)
25}
26
27pub fn fa_to_en_mut(input: &mut String) {
29 convert_mut(input, 1776..1786, -1728)
30}
31
32pub fn en_to_fa(input: impl AsRef<str>) -> String {
34 convert(input, 48..58, 1728)
38}
39
40pub fn en_to_fa_mut(input: &mut String) {
42 convert_mut(input, 48..58, 1728)
43}
44
45pub fn en_to_ar(input: impl AsRef<str>) -> String {
47 convert(input, 48..58, 1584)
51}
52
53pub fn en_to_ar_mut(input: &mut String) {
55 convert_mut(input, 48..58, 1584)
56}
57
58pub fn ar_to_en(input: impl AsRef<str>) -> String {
60 convert(input, 1632..1642, -1584)
64}
65
66pub fn ar_to_en_mut(input: &mut String) {
68 convert_mut(input, 1632..1642, -1584)
69}
70
71pub fn fa_to_ar(input: impl AsRef<str>) -> String {
73 convert(input, 1776..1786, -144)
77}
78
79pub fn fa_to_ar_mut(input: &mut String) {
81 convert_mut(input, 1776..1786, -144)
82}
83
84pub fn ar_to_fa(input: impl AsRef<str>) -> String {
86 convert(input, 1632..1642, 144)
90}
91
92pub fn ar_to_fa_mut(input: &mut String) {
94 convert_mut(input, 1632..1642, 144)
95}
96
97pub trait DigitsAr2Fa {
99 fn digits_ar_to_fa(&self) -> String;
100}
101
102pub trait DigitsAr2FaMut {
104 fn digits_ar_to_fa_mut(&mut self);
105}
106
107pub trait DigitsAr2En {
109 fn digits_ar_to_en(&self) -> String;
110}
111
112pub trait DigitsAr2EnMut {
114 fn digits_ar_to_en_mut(&mut self);
115}
116
117pub trait DigitsFa2Ar {
119 fn digits_fa_to_ar(&self) -> String;
120}
121
122pub trait DigitsFa2ArMut {
124 fn digits_fa_to_ar_mut(&mut self);
125}
126
127pub trait DigitsFa2En {
129 fn digits_fa_to_en(&self) -> String;
130}
131
132pub trait DigitsFa2EnMut {
134 fn digits_fa_to_en_mut(&mut self);
135}
136
137pub trait DigitsEn2Ar {
139 fn digits_en_to_ar(&self) -> String;
140}
141
142pub trait DigitsEn2ArMut {
144 fn digits_en_to_ar_mut(&mut self);
145}
146
147pub trait DigitsEn2Fa {
149 fn digits_en_to_fa(&self) -> String;
150}
151
152pub trait DigitsEn2FaMut {
154 fn digits_en_to_fa_mut(&mut self);
155}
156
157impl DigitsAr2Fa for str {
158 fn digits_ar_to_fa(&self) -> String {
159 ar_to_fa(self)
160 }
161}
162
163impl DigitsAr2Fa for String {
164 fn digits_ar_to_fa(&self) -> String {
165 ar_to_fa(self)
166 }
167}
168
169impl DigitsAr2Fa for Cow<'_, str> {
170 fn digits_ar_to_fa(&self) -> String {
171 ar_to_fa(self)
172 }
173}
174
175impl DigitsAr2FaMut for String {
176 fn digits_ar_to_fa_mut(&mut self) {
177 ar_to_fa_mut(self)
178 }
179}
180
181impl DigitsAr2FaMut for Cow<'_, str> {
182 fn digits_ar_to_fa_mut(&mut self) {
183 ar_to_fa_mut(self.to_mut())
184 }
185}
186
187impl DigitsAr2En for str {
188 fn digits_ar_to_en(&self) -> String {
189 ar_to_en(self)
190 }
191}
192
193impl DigitsAr2En for String {
194 fn digits_ar_to_en(&self) -> String {
195 ar_to_en(self)
196 }
197}
198
199impl DigitsAr2En for Cow<'_, str> {
200 fn digits_ar_to_en(&self) -> String {
201 ar_to_en(self)
202 }
203}
204
205impl DigitsAr2EnMut for String {
206 fn digits_ar_to_en_mut(&mut self) {
207 ar_to_en_mut(self)
208 }
209}
210
211impl DigitsAr2EnMut for Cow<'_, str> {
212 fn digits_ar_to_en_mut(&mut self) {
213 ar_to_en_mut(self.to_mut())
214 }
215}
216
217impl DigitsFa2Ar for str {
218 fn digits_fa_to_ar(&self) -> String {
219 fa_to_ar(self)
220 }
221}
222
223impl DigitsFa2Ar for String {
224 fn digits_fa_to_ar(&self) -> String {
225 fa_to_ar(self)
226 }
227}
228
229impl DigitsFa2Ar for Cow<'_, str> {
230 fn digits_fa_to_ar(&self) -> String {
231 fa_to_ar(self)
232 }
233}
234
235impl DigitsFa2ArMut for String {
236 fn digits_fa_to_ar_mut(&mut self) {
237 fa_to_ar_mut(self)
238 }
239}
240
241impl DigitsFa2ArMut for Cow<'_, str> {
242 fn digits_fa_to_ar_mut(&mut self) {
243 fa_to_ar_mut(self.to_mut())
244 }
245}
246
247impl DigitsFa2En for str {
248 fn digits_fa_to_en(&self) -> String {
249 fa_to_en(self)
250 }
251}
252
253impl DigitsFa2En for String {
254 fn digits_fa_to_en(&self) -> String {
255 fa_to_en(self)
256 }
257}
258
259impl DigitsFa2En for Cow<'_, str> {
260 fn digits_fa_to_en(&self) -> String {
261 fa_to_en(self)
262 }
263}
264
265impl DigitsFa2EnMut for String {
266 fn digits_fa_to_en_mut(&mut self) {
267 fa_to_en_mut(self)
268 }
269}
270
271impl DigitsFa2EnMut for Cow<'_, str> {
272 fn digits_fa_to_en_mut(&mut self) {
273 fa_to_en_mut(self.to_mut())
274 }
275}
276
277impl DigitsEn2Ar for str {
278 fn digits_en_to_ar(&self) -> String {
279 en_to_ar(self)
280 }
281}
282
283impl DigitsEn2Ar for String {
284 fn digits_en_to_ar(&self) -> String {
285 en_to_ar(self)
286 }
287}
288
289impl DigitsEn2Ar for Cow<'_, str> {
290 fn digits_en_to_ar(&self) -> String {
291 en_to_ar(self)
292 }
293}
294
295impl DigitsEn2ArMut for String {
296 fn digits_en_to_ar_mut(&mut self) {
297 en_to_ar_mut(self)
298 }
299}
300
301impl DigitsEn2ArMut for Cow<'_, str> {
302 fn digits_en_to_ar_mut(&mut self) {
303 en_to_ar_mut(self.to_mut())
304 }
305}
306
307impl DigitsEn2Ar for u8 {
308 fn digits_en_to_ar(&self) -> String {
309 let mut string = self.to_string();
310 string.digits_en_to_ar_mut();
311 string
312 }
313}
314
315impl DigitsEn2Ar for i8 {
316 fn digits_en_to_ar(&self) -> String {
317 let mut string = self.to_string();
318 string.digits_en_to_ar_mut();
319 string
320 }
321}
322
323impl DigitsEn2Ar for u16 {
324 fn digits_en_to_ar(&self) -> String {
325 let mut string = self.to_string();
326 string.digits_en_to_ar_mut();
327 string
328 }
329}
330
331impl DigitsEn2Ar for i16 {
332 fn digits_en_to_ar(&self) -> String {
333 let mut string = self.to_string();
334 string.digits_en_to_ar_mut();
335 string
336 }
337}
338
339impl DigitsEn2Ar for u32 {
340 fn digits_en_to_ar(&self) -> String {
341 let mut string = self.to_string();
342 string.digits_en_to_ar_mut();
343 string
344 }
345}
346
347impl DigitsEn2Ar for i32 {
348 fn digits_en_to_ar(&self) -> String {
349 let mut string = self.to_string();
350 string.digits_en_to_ar_mut();
351 string
352 }
353}
354
355impl DigitsEn2Ar for u64 {
356 fn digits_en_to_ar(&self) -> String {
357 let mut string = self.to_string();
358 string.digits_en_to_ar_mut();
359 string
360 }
361}
362
363impl DigitsEn2Ar for i64 {
364 fn digits_en_to_ar(&self) -> String {
365 let mut string = self.to_string();
366 string.digits_en_to_ar_mut();
367 string
368 }
369}
370
371impl DigitsEn2Ar for u128 {
372 fn digits_en_to_ar(&self) -> String {
373 let mut string = self.to_string();
374 string.digits_en_to_ar_mut();
375 string
376 }
377}
378
379impl DigitsEn2Ar for i128 {
380 fn digits_en_to_ar(&self) -> String {
381 let mut string = self.to_string();
382 string.digits_en_to_ar_mut();
383 string
384 }
385}
386
387impl DigitsEn2Ar for usize {
388 fn digits_en_to_ar(&self) -> String {
389 let mut string = self.to_string();
390 string.digits_en_to_ar_mut();
391 string
392 }
393}
394
395impl DigitsEn2Ar for isize {
396 fn digits_en_to_ar(&self) -> String {
397 let mut string = self.to_string();
398 string.digits_en_to_ar_mut();
399 string
400 }
401}
402
403impl DigitsEn2Ar for f32 {
404 fn digits_en_to_ar(&self) -> String {
405 let mut string = self.to_string();
406 string.digits_en_to_ar_mut();
407 string
408 }
409}
410
411impl DigitsEn2Ar for f64 {
412 fn digits_en_to_ar(&self) -> String {
413 let mut string = self.to_string();
414 string.digits_en_to_ar_mut();
415 string
416 }
417}
418
419impl DigitsEn2Fa for str {
420 fn digits_en_to_fa(&self) -> String {
421 en_to_fa(self)
422 }
423}
424
425impl DigitsEn2Fa for String {
426 fn digits_en_to_fa(&self) -> String {
427 en_to_fa(self)
428 }
429}
430
431impl DigitsEn2Fa for Cow<'_, str> {
432 fn digits_en_to_fa(&self) -> String {
433 en_to_fa(self)
434 }
435}
436
437impl DigitsEn2FaMut for String {
438 fn digits_en_to_fa_mut(&mut self) {
439 en_to_fa_mut(self)
440 }
441}
442
443impl DigitsEn2FaMut for Cow<'_, str> {
444 fn digits_en_to_fa_mut(&mut self) {
445 en_to_fa_mut(self.to_mut())
446 }
447}
448
449impl DigitsEn2Fa for u8 {
450 fn digits_en_to_fa(&self) -> String {
451 let mut string = self.to_string();
452 string.digits_en_to_fa_mut();
453 string
454 }
455}
456
457impl DigitsEn2Fa for i8 {
458 fn digits_en_to_fa(&self) -> String {
459 let mut string = self.to_string();
460 string.digits_en_to_fa_mut();
461 string
462 }
463}
464
465impl DigitsEn2Fa for u16 {
466 fn digits_en_to_fa(&self) -> String {
467 let mut string = self.to_string();
468 string.digits_en_to_fa_mut();
469 string
470 }
471}
472
473impl DigitsEn2Fa for i16 {
474 fn digits_en_to_fa(&self) -> String {
475 let mut string = self.to_string();
476 string.digits_en_to_fa_mut();
477 string
478 }
479}
480
481impl DigitsEn2Fa for u32 {
482 fn digits_en_to_fa(&self) -> String {
483 let mut string = self.to_string();
484 string.digits_en_to_fa_mut();
485 string
486 }
487}
488
489impl DigitsEn2Fa for i32 {
490 fn digits_en_to_fa(&self) -> String {
491 let mut string = self.to_string();
492 string.digits_en_to_fa_mut();
493 string
494 }
495}
496
497impl DigitsEn2Fa for u64 {
498 fn digits_en_to_fa(&self) -> String {
499 let mut string = self.to_string();
500 string.digits_en_to_fa_mut();
501 string
502 }
503}
504
505impl DigitsEn2Fa for i64 {
506 fn digits_en_to_fa(&self) -> String {
507 let mut string = self.to_string();
508 string.digits_en_to_fa_mut();
509 string
510 }
511}
512
513impl DigitsEn2Fa for u128 {
514 fn digits_en_to_fa(&self) -> String {
515 let mut string = self.to_string();
516 string.digits_en_to_fa_mut();
517 string
518 }
519}
520
521impl DigitsEn2Fa for i128 {
522 fn digits_en_to_fa(&self) -> String {
523 let mut string = self.to_string();
524 string.digits_en_to_fa_mut();
525 string
526 }
527}
528
529impl DigitsEn2Fa for usize {
530 fn digits_en_to_fa(&self) -> String {
531 let mut string = self.to_string();
532 string.digits_en_to_fa_mut();
533 string
534 }
535}
536
537impl DigitsEn2Fa for isize {
538 fn digits_en_to_fa(&self) -> String {
539 let mut string = self.to_string();
540 string.digits_en_to_fa_mut();
541 string
542 }
543}
544
545impl DigitsEn2Fa for f32 {
546 fn digits_en_to_fa(&self) -> String {
547 let mut string = self.to_string();
548 string.digits_en_to_fa_mut();
549 string
550 }
551}
552
553impl DigitsEn2Fa for f64 {
554 fn digits_en_to_fa(&self) -> String {
555 let mut string = self.to_string();
556 string.digits_en_to_fa_mut();
557 string
558 }
559}
560
561#[inline]
562fn convert(input: impl AsRef<str>, range: Range<u32>, diff: i64) -> String {
563 let mut index = 0;
564 let mut result = String::new();
565 input
566 .as_ref()
567 .match_indices(|code| range.contains(&(code as u32)))
568 .map(|(index, char_str)| unsafe { (index, char_str.chars().next().unwrap_unchecked()) })
569 .for_each(|(char_index, old_char)| unsafe {
570 result += input.as_ref().get_unchecked(index..char_index);
571 let new_char = char::from_u32_unchecked((old_char as i64 + diff) as u32);
572 result.push(new_char);
573 index = char_index + old_char.len_utf8();
574 });
575 result += unsafe { input.as_ref().get_unchecked(index..) };
576 result
577}
578
579#[inline]
580fn convert_mut(input: &mut String, range: Range<u32>, diff: i64) {
581 input
582 .rmatch_indices(|code| range.contains(&(code as u32)))
583 .map(|(index, char_str)| unsafe { (index, char_str.chars().next().unwrap_unchecked()) })
584 .collect::<Vec<_>>()
585 .into_iter()
586 .for_each(|(char_index, old_char)| unsafe {
587 let char = char::from_u32_unchecked((old_char as i64 + diff) as u32);
588 input.remove(char_index);
589 input.insert(char_index, char);
590 });
591}
592
593#[cfg(test)]
594mod tests {
595 use super::*;
596
597 #[test]
598 fn digits_fa_to_en_test() {
599 assert_eq!("123۴۵۶".digits_fa_to_en(), "123456");
600 let mut n = "۸۹123۴۵".to_string();
601 n.digits_fa_to_en_mut();
602 assert_eq!(n, "8912345");
603 let mut n = Cow::Borrowed("۰۱۲۳۴۵۶۷۸۹");
604 n.digits_fa_to_en_mut();
605 assert_eq!(n, Cow::<str>::Owned("0123456789".to_string()));
606 }
607
608 #[test]
609 fn digits_en_to_fa_test() {
610 let mut n = "123۴۵۶".to_string();
611 n.digits_en_to_fa_mut();
612 assert_eq!(n, "۱۲۳۴۵۶");
613 assert_eq!(123i8.digits_en_to_fa(), "۱۲۳");
614 assert_eq!(1234567891usize.digits_en_to_fa(), "۱۲۳۴۵۶۷۸۹۱");
615 assert_eq!(3.14f64.digits_en_to_fa(), "۳.۱۴");
616 assert_eq!("٤٥٦".to_string().digits_en_to_fa(), "٤٥٦");
617 let mut n = Cow::Borrowed("123۴۵۶");
618 n.digits_en_to_fa_mut();
619 assert_eq!(n, Cow::<str>::Owned("۱۲۳۴۵۶".to_string()));
620 }
621
622 #[test]
623 fn digits_en_to_ar_test() {
624 let mut n = "123٤٥٦".to_string();
625 n.digits_en_to_ar_mut();
626 assert_eq!(n, "١٢٣٤٥٦");
627 assert_eq!(123i8.digits_en_to_ar(), "١٢٣");
628 assert_eq!(1234567891usize.digits_en_to_ar(), "١٢٣٤٥٦٧٨٩١");
629 assert_eq!(3.14f64.digits_en_to_ar(), "٣.١٤");
630 assert_eq!("۴۵۶".to_string().digits_en_to_ar(), "۴۵۶");
631 let mut n = Cow::Borrowed("123٤٥٦");
632 n.digits_en_to_ar_mut();
633 assert_eq!(n, Cow::<str>::Owned("١٢٣٤٥٦".to_string()));
634 }
635
636 #[test]
637 fn digits_ar_to_en_test() {
638 assert_eq!("٠١٢٣٤٥٦٧٨٩".digits_ar_to_en(), "0123456789");
639 let mut n = "89١٢٣4٥".to_string();
640 n.digits_ar_to_en_mut();
641 assert_eq!(n, "8912345");
642 let mut n = Cow::Borrowed("0123۴۵۶789");
643 n.digits_ar_to_en_mut();
644 assert_eq!(n, Cow::<str>::Owned("0123۴۵۶789".to_string()));
645 }
646
647 #[test]
648 fn digits_fa_to_ar_test() {
649 assert_eq!("۰۱۲۳۴۵۶۷۸۹".digits_fa_to_ar(), "٠١٢٣٤٥٦٧٨٩");
650 let mut n = "۱۷۸۲۳۴۰۵۶۹".to_string();
651 n.digits_fa_to_ar_mut();
652 assert_eq!(n, "١٧٨٢٣٤٠٥٦٩");
653 assert_eq!("۷۸٤۲۳٤۴".to_string().digits_fa_to_ar(), "٧٨٤٢٣٤٤");
654 let mut n = Cow::Borrowed("٤٤٤444۴۴۴");
655 n.digits_fa_to_ar_mut();
656 assert_eq!(n, Cow::<str>::Owned("٤٤٤444٤٤٤".to_string()));
657 }
658
659 #[test]
660 fn digits_ar_to_fa_test() {
661 assert_eq!("٠١٢٣٤٥٦٧٨٩".digits_ar_to_fa(), "۰۱۲۳۴۵۶۷۸۹");
662 let mut n = "١٧٨٢٣٤٠٥٦٩".to_string();
663 n.digits_ar_to_fa_mut();
664 assert_eq!(n, "۱۷۸۲۳۴۰۵۶۹");
665 assert_eq!("٧٨٤٢٣٤٤".to_string().digits_ar_to_fa(), "۷۸۴۲۳۴۴");
666 let mut n = Cow::Borrowed("٤٤٤444٤٤٤");
667 n.digits_ar_to_fa_mut();
668 assert_eq!(n, Cow::<str>::Owned("۴۴۴444۴۴۴".to_string()));
669 }
670}