1use radix_fmt::Radix;
2use std::fmt::Write;
3use std::iter::{self, successors};
4
5use super::*;
6
7multi_tilde_impl!(
11 TildeKindDigit,
12 [i8, i16, i32, i64, i128, u8, u16, u32, u64, u128, usize, isize],
13 self,
14 buf,
15 {
16 buf.push_str(self.to_string().as_str());
17 Ok(())
18 }
19);
20
21impl TildeKindChar for char {
26 fn format(&self, tkind: &TildeKind, buf: &mut String) -> Result<(), TildeError> {
27 match tkind {
28 TildeKind::Char(CharKind::At) => {
29 buf.push_str(format!("'{}'", self).as_str());
30 Ok(())
31 }
32 TildeKind::Char(CharKind::Nil) => {
33 buf.push_str(self.to_string().as_str());
34 Ok(())
35 }
36 _ => Err(TildeError::new(ErrorKind::RevealError, "cannot format to Char").into()),
37 }
38 }
39}
40
41multi_tilde_impl!(
45 TildeKindVa,
46 [f32, f64, char, i8, i16, i32, i64, i128, isize, u8, u16, u32, u64, u128, usize, String],
47 self,
48 buf,
49 {
50 buf.push_str(self.to_string().as_str());
51 Ok(())
52 }
53);
54
55impl TildeKindVa for bool {
56 fn format(&self, _: &TildeKind, buf: &mut String) -> Result<(), TildeError> {
57 if *self {
58 buf.push_str("true");
59 } else {
60 buf.push_str("false");
61 }
62 Ok(())
63 }
64}
65
66impl TildeKindVa for TildeNil {
67 fn format(&self, _: &TildeKind, buf: &mut String) -> Result<(), TildeError> {
68 buf.push_str("nil");
69 Ok(())
70 }
71}
72
73impl TildeKindVa for Vec<&dyn TildeAble> {
74 fn format(&self, _: &TildeKind, buf: &mut String) -> Result<(), TildeError> {
75 buf.push_str(format!("{:?}", self).as_str());
76 Ok(())
77 }
78}
79
80impl<'a, 'arg> TildeKindLoop for Args<'a, 'arg> {
84 fn format(&self, tkind: &TildeKind, buf: &mut String) -> Result<(), TildeError> {
85 match tkind {
86 TildeKind::Loop((_, TildeLoopKind::Nil | TildeLoopKind::NilColon)) => {
88 let a = self
89 .pop()
90 .ok_or::<TildeError>(TildeError::new(ErrorKind::FormatError, "run out args"))?;
91 tkind.match_reveal(a, buf)
92 }
93 TildeKind::Loop((vv, TildeLoopKind::At)) => {
94 'a: loop {
95 for t in vv {
96 if let TildeKind::LoopEnd = t.value {
97 if self.left_count() != 0 {
98 continue;
99 } else {
100 break 'a;
101 }
102 }
103 t.reveal(self, buf)?;
104 }
105 if self.left_count() == 0 {
107 break;
108 }
109 }
110
111 Ok(())
112 }
113 _ => Err(TildeError::new(ErrorKind::RevealError, "cannot format Arg to Loop").into()),
114 }
115 }
116}
117
118impl<'a> TildeKindLoop for Vec<&dyn TildeAble> {
119 fn format(&self, tkind: &TildeKind, buf: &mut String) -> Result<(), TildeError> {
120 match tkind {
121 TildeKind::Loop((_, TildeLoopKind::Nil)) => {
122 let mut new_kind = tkind.clone();
123
124 match &mut new_kind {
125 TildeKind::Loop((_, k @ TildeLoopKind::Nil)) => {
126 if self.len() != 0 {
127 *k = TildeLoopKind::At
128 } else {
129 return Ok(());
130 }
131 }
132 _ => unreachable!(),
133 };
134 new_kind.match_reveal(&Args::from(self.as_slice()), buf)
135 }
136 TildeKind::Loop((_, TildeLoopKind::NilColon)) => {
137 let mut new_kind = tkind.clone();
138 match &mut new_kind {
139 TildeKind::Loop((_, k @ TildeLoopKind::NilColon)) => *k = TildeLoopKind::At,
140 _ => unreachable!(),
141 };
142 new_kind.match_reveal(&Args::from(self.as_slice()), buf)
143 }
144 _ => Err(TildeError::new(ErrorKind::RevealError, "cannot format Vec to Loop").into()),
145 }
146 }
147}
148
149impl TildeKindCond for usize {
153 fn format(&self, tkind: &TildeKind, buf: &mut String) -> Result<(), TildeError> {
154 match tkind {
156 TildeKind::Cond((vv, TildeCondKind::Nil(true))) => match vv.get(*self) {
157 Some(tt) => {
158 tt.reveal(&TildeNil, buf)?;
159 Ok(())
160 }
161 None => {
162 let last = vv.len() - 1;
163 match vv.get(last) {
164 Some(tt) => {
165 tt.reveal(&TildeNil, buf)?;
166 Ok(())
167 }
168 None => Ok(()),
169 }
170 }
171 },
172 TildeKind::Cond((vv, TildeCondKind::Nil(false))) => match vv.get(*self) {
173 Some(tt) => {
174 tt.reveal(&TildeNil, buf)?;
175 Ok(())
176 }
177 None => Ok(()),
178 },
179 _ => Err(TildeError::new(ErrorKind::RevealError, "cannot format to Cond").into()),
180 }
181 }
182}
183
184impl TildeKindCond for bool {
185 fn format(&self, tkind: &TildeKind, buf: &mut String) -> Result<(), TildeError> {
186 match tkind {
187 TildeKind::Cond((vv, TildeCondKind::Colon)) => {
188 if *self {
189 vv.get(1)
190 .ok_or::<TildeError>(TildeError::new(
191 ErrorKind::FormatError,
192 "cannot get tilde",
193 ))?
194 .reveal(&TildeNil, buf)?;
195
196 Ok(())
197 } else {
198 vv.get(0)
199 .ok_or::<TildeError>(TildeError::new(
200 ErrorKind::FormatError,
201 "cannot get tilde",
202 ))?
203 .reveal(&TildeNil, buf)?;
204
205 Ok(())
206 }
207 }
208 _ => Err(TildeError::new(ErrorKind::RevealError, "cannot format to Cond").into()),
209 }
210 }
211}
212
213impl TildeKindCond for Option<&dyn TildeAble> {
214 fn format(&self, tkind: &TildeKind, buf: &mut String) -> Result<(), TildeError> {
215 match tkind {
216 TildeKind::Cond((vv, TildeCondKind::At)) => match self {
217 Some(a) => {
218 let k = TildeKind::VecTilde(vv.clone());
220 k.match_reveal(&Args::from([*a]), buf)
224 }
225 None => Ok(()),
226 },
227 _ => Err(TildeError::new(ErrorKind::RevealError, "cannot format to Cond").into()),
228 }
229 }
230}
231
232impl<'a, 'arg> TildeKindCond for Args<'a, 'arg> {
233 fn format(&self, tkind: &TildeKind, buf: &mut String) -> Result<(), TildeError> {
234 match tkind {
235 TildeKind::Cond((vv, TildeCondKind::Sharp)) => {
236 let l = self.left_count();
237 if l >= vv.len() {
238 vv[vv.len() - 1].reveal(self, buf)?;
239 Ok(())
240 } else {
241 vv[l].reveal(self, buf)?;
242 Ok(())
243 }
244 }
245 TildeKind::Cond((_, _)) => {
246 let a = self
247 .pop()
248 .ok_or::<TildeError>(TildeError::new(ErrorKind::FormatError, "run out args"))?;
249 tkind.match_reveal(a, buf)
250 }
251 _ => Err(TildeError::new(ErrorKind::RevealError, "cannot format to Cond").into()),
252 }
253 }
254}
255
256impl TildeKindVecTilde for TildeNil {
260 fn format(&self, tkind: &TildeKind, buf: &mut String) -> Result<(), TildeError> {
261 match tkind {
262 TildeKind::VecTilde(vv) => {
263 for v in vv {
264 v.reveal(self, buf)?;
265 }
266
267 Ok(())
268 }
269 _ => Err(TildeError::new(ErrorKind::RevealError, "cannot format to VecTilde").into()),
270 }
271 }
272}
273
274impl<'a, 'arg> TildeKindVecTilde for Args<'a, 'arg> {
275 fn format(&self, tkind: &TildeKind, buf: &mut String) -> Result<(), TildeError> {
276 match tkind {
277 TildeKind::VecTilde(vv) => {
278 for v in vv {
279 v.reveal(self, buf)?;
280 }
281 Ok(())
282 }
283 _ => Err(TildeError::new(ErrorKind::RevealError, "cannot format to VecTilde").into()),
284 }
285 }
286}
287
288impl<'a, 'arg> TildeKindStar for Args<'a, 'arg> {
292 fn format(&self, tkind: &TildeKind, _buf: &mut String) -> Result<(), TildeError> {
293 match tkind {
294 TildeKind::Star(StarKind::Hop) => {
295 self.back(); Ok(())
298 }
299 TildeKind::Star(StarKind::Skip) => {
300 self.pop();
301 Ok(())
302 }
303 _ => Err(TildeError::new(ErrorKind::RevealError, "cannot format to Star").into()),
304 }
305 }
306}
307
308impl TildeKindStandard for String {
312 fn format(&self, _: &TildeKind, buf: &mut String) -> Result<(), TildeError> {
313 buf.push_str(format!("\"{}\"", self).as_str());
314 Ok(())
315 }
316}
317
318impl TildeKindStandard for char {
319 fn format(&self, _: &TildeKind, buf: &mut String) -> Result<(), TildeError> {
320 buf.push_str(format!("'{}'", self).as_str());
321 Ok(())
322 }
323}
324
325multi_tilde_impl!(
326 TildeKindStandard,
327 [f32, f64, bool, i8, i16, i32, i64, i128, u8, u16, u32, u64, u128, usize, isize],
328 self,
329 buf,
330 {
331 buf.push_str(self.to_string().as_str());
332 Ok(())
333 }
334);
335
336const NUMERALS: [(usize, [&'static str; 10]); 4] = [
340 (
341 1000,
342 ["", "M", "MM", "MMM", "--", "-", "--", "---", "----", "--"],
343 ),
344 (
345 100,
346 ["", "C", "CC", "CCC", "CD", "D", "DC", "DCC", "DCCC", "CM"],
347 ),
348 (
349 10,
350 ["", "X", "XX", "XXX", "XL", "L", "LX", "LXX", "LXXX", "XC"],
351 ),
352 (
353 1,
354 ["", "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX"],
355 ),
356];
357
358fn into_roman(n: usize) -> Result<String, TildeError> {
360 if n > 3999 {
361 return Err(TildeError::new(
362 ErrorKind::FormatError,
363 "number is too big to reveal as roman numerals",
364 ));
365 }
366 Ok(NUMERALS
367 .iter()
368 .map(|&(base, nums)| nums[(n / base) % 10])
369 .collect())
370}
371
372const ONES: [&str; 20] = [
374 "zero",
375 "one",
376 "two",
377 "three",
378 "four",
379 "five",
380 "six",
381 "seven",
382 "eight",
383 "nine",
384 "ten",
385 "eleven",
386 "twelve",
387 "thirteen",
388 "fourteen",
389 "fifteen",
390 "sixteen",
391 "seventeen",
392 "eighteen",
393 "nineteen",
394];
395
396const ORDINAL_ONES: [&str; 20] = [
397 "zeroth",
398 "first",
399 "second",
400 "third",
401 "fourth",
402 "fifth",
403 "sixth",
404 "seventh",
405 "eighth",
406 "ninth",
407 "tenth",
408 "eleventh",
409 "twelfth",
410 "thirteenth",
411 "fourteenth",
412 "fifteenth",
413 "sixteenth",
414 "seventeenth",
415 "eighteenth",
416 "nineteenth",
417];
418
419const TENS: [&str; 10] = [
420 "zero", "ten", "twenty", "thirty", "forty", "fifty", "sixty", "seventy", "eighty", "ninety",
421];
422
423const ORDINAL_TENS: [&str; 10] = [
424 "zeroth",
425 "tenth",
426 "twentieth",
427 "thirtieth",
428 "fortieth",
429 "fiftieth",
430 "sixtieth",
431 "seventieth",
432 "eightieth",
433 "ninetieth",
434];
435
436const ORDERS: [&str; 7] = [
437 "zero",
438 "thousand",
439 "million",
440 "billion",
441 "trillion",
442 "quadrillion",
443 "quintillion", ];
445
446const ORDINAL_ORDERS: [&str; 7] = [
447 "zeroth",
448 "thousandth",
449 "millionth",
450 "billionth",
451 "trillionth",
452 "quadrillionth",
453 "quintillionth", ];
455
456pub fn into_english(num: usize, buf: &mut String) {
457 match num {
458 0..=19 => {
459 buf.push_str(ONES[num as usize]);
460 }
461 20..=99 => {
462 let upper = (num / 10) as usize;
463 match num % 10 {
464 0 => buf.push_str(TENS[upper]),
465 lower => {
466 buf.push_str(TENS[upper]);
467 buf.push_str("-");
468 into_english(lower, buf);
469 }
470 }
471 }
472 100..=999 => format_num(num, 100, "hundred", buf),
473 _ => {
474 let (div, order) = successors(Some(1_usize), |v| v.checked_mul(1000_usize))
475 .zip(ORDERS.iter())
476 .find(|&(e, _)| e > num / 1000)
477 .unwrap();
478
479 format_num(num, div, order, buf)
480 }
481 }
482}
483
484fn format_num(num: usize, div: usize, order: &str, buf: &mut String) {
485 match (num / div, num % div) {
486 (upper, 0) => {
487 into_english(upper, buf);
488 buf.push_str(" ");
489 buf.push_str(order)
490 }
491 (upper, lower) => {
492 into_english(upper, buf);
493 buf.push_str(" ");
494 buf.push_str(order);
495 buf.push_str(" ");
496 into_english(lower, buf);
497 }
498 }
499}
500
501pub fn into_ordinal_english(num: usize, buf: &mut String) {
502 match num {
503 0..=19 => {
504 buf.push_str(ORDINAL_ONES[num as usize]);
505 }
506 20..=99 => {
507 let upper = (num / 10) as usize;
508 match num % 10 {
509 0 => buf.push_str(ORDINAL_TENS[upper]),
510 lower => {
511 buf.push_str(TENS[upper]);
512 buf.push_str("-");
513 into_ordinal_english(lower, buf);
514 }
515 }
516 }
517 100..=999 => format_ordinal_num(num, 100, "hundred", buf),
518 _ => {
519 let (div, order) = successors(Some(1_usize), |v| v.checked_mul(1000_usize))
520 .zip(ORDERS.iter())
521 .find(|&(e, _)| e > num / 1000)
522 .unwrap();
523 format_ordinal_num(num, div, order, buf)
526 }
527 }
528}
529
530fn orders_to_ordinal(order: &str) -> &str {
531 ORDINAL_ORDERS[ORDERS.iter().position(|s| *s == order).unwrap()]
532}
533
534fn format_ordinal_num(num: usize, div: usize, order: &str, buf: &mut String) {
535 match (num / div, num % div) {
538 (upper, 0) => {
539 into_english(upper, buf);
540 buf.push_str(" ");
541 buf.push_str(orders_to_ordinal(order))
542 }
543 (upper, lower) => {
544 into_english(upper, buf);
545 buf.push_str(" ");
546 buf.push_str(order);
547 buf.push_str(" ");
548 into_ordinal_english(lower, buf);
549 }
550 }
551}
552
553fn format_helper(
554 buf: &mut String,
555 orginal: String,
556 mincol: &Option<usize>,
557 padchar: &Option<char>,
558 commachar: &Option<char>,
559 comma_interval: &Option<usize>,
560 flag: &Option<RadixFlag>,
561) -> Result<(), TildeError> {
562 let mut inner_buf = String::with_capacity(orginal.len());
563 if let Some(RadixFlag::Colon) = flag {
564 match comma_interval {
565 Some(n) => {
566 let commachar = match commachar {
567 Some(c) => *c,
568 None => ',',
569 };
570
571 if orginal.len() > *n {
572 let mut edge = orginal.len() % n;
573 if edge == 0 {
574 edge = *n;
575 };
576 inner_buf.push_str(&orginal[0..edge]);
577 loop {
578 if edge >= orginal.len() {
579 break;
580 }
581 inner_buf.push(commachar);
582 inner_buf.push_str(&orginal[edge..edge + n]);
583 edge += n;
584 }
585 } else {
586 inner_buf.push_str(&orginal);
587 }
588 }
589 None => (),
590 }
591 } else {
592 inner_buf = orginal
593 }
594
595 match mincol {
596 Some(n) => {
597 if *n > inner_buf.len() {
598 buf.push_str(
599 &iter::repeat(padchar.unwrap_or(' '))
600 .take(*n - inner_buf.len())
601 .collect::<String>(),
602 );
603 buf.push_str(&inner_buf);
604 } else {
605 buf.push_str(&inner_buf);
606 }
607 }
608 None => buf.push_str(&inner_buf),
609 }
610
611 Ok(())
612}
613
614impl TildeKindRadix for isize {
615 fn format(&self, tkind: &TildeKind, buf: &mut String) -> Result<(), TildeError> {
616 match tkind {
617 TildeKind::Radix((ra, mincol, padchar, commachar, comma_interval, flag)) => {
618 match (ra, mincol, padchar, commachar, comma_interval, flag) {
619 (ra, None, None, None, None, None) => {
620 if ra.is_none() {
621 if *self < 0 {
623 buf.push_str("negative ");
624 into_english(self.abs() as usize, buf)
625 } else {
626 into_english(self.abs() as usize, buf)
627 }
628 } else {
629 if *self < 0 {
631 write!(buf, "-{}", Radix::new(-*self, ra.unwrap())).map_err(
632 |e| TildeError::new(ErrorKind::FormatError, e.to_string()),
633 )?
634 } else {
635 write!(buf, "{}", Radix::new(*self, ra.unwrap())).map_err(|e| {
636 TildeError::new(ErrorKind::FormatError, e.to_string())
637 })?
638 }
639 }
640 }
641 (ra, None, None, None, None, Some(RadixFlag::Colon)) => {
642 if ra.is_none() {
643 if *self < 0 {
645 buf.push_str("negative ");
646 into_ordinal_english(self.abs() as usize, buf)
647 } else {
648 into_ordinal_english(self.abs() as usize, buf)
649 }
650 } else {
651 if *self < 0 {
654 buf.push('-');
655 let s = Radix::new(-*self, ra.unwrap()).to_string();
656 format_helper(buf, s, mincol, padchar, &Some(','), &Some(3), flag)?;
657 } else {
658 let s = Radix::new(*self, ra.unwrap()).to_string();
659 format_helper(buf, s, mincol, padchar, &Some(','), &Some(3), flag)?;
660 }
661 }
662 }
663
664 (None, None, None, None, None, Some(RadixFlag::At)) => {
665 if *self <= 0 {
667 return Err(TildeError::new(
668 ErrorKind::FormatError,
669 "negative cannot be roman numerals",
670 ));
671 } else {
672 buf.push_str(&into_roman(*self as usize)?);
673 }
674 }
675
676 (None, None, None, None, None, Some(RadixFlag::AtColon)) => {
677 return Err(TildeError::new(
678 ErrorKind::FormatError,
679 "old Roman numeral haven't supported yet",
680 ));
681 }
682
683 (ra, _, _, _, _, _) => {
684 if *self < 0 {
685 buf.push('-');
686 let s = Radix::new(-*self, ra.unwrap()).to_string();
687 format_helper(
688 buf,
689 s,
690 mincol,
691 padchar,
692 commachar,
693 comma_interval,
694 flag,
695 )?;
696 } else {
697 let s = Radix::new(*self, ra.unwrap()).to_string();
698 format_helper(
699 buf,
700 s,
701 mincol,
702 padchar,
703 commachar,
704 comma_interval,
705 flag,
706 )?;
707 }
708 }
709 }
710 }
711 _ => {
712 return Err(
713 TildeError::new(ErrorKind::RevealError, "cannot format to Radix").into(),
714 )
715 }
716 }
717 Ok(())
718 }
719}
720
721impl TildeKindRadix for i8 {
722 fn format(&self, tkind: &TildeKind, buf: &mut String) -> Result<(), TildeError> {
723 TildeKindRadix::format(&Into::<isize>::into(*self), tkind, buf)
724 }
725}
726
727impl TildeKindRadix for i16 {
728 fn format(&self, tkind: &TildeKind, buf: &mut String) -> Result<(), TildeError> {
729 TildeKindRadix::format(&Into::<isize>::into(*self), tkind, buf)
730 }
731}
732
733impl TildeKindRadix for i32 {
734 fn format(&self, tkind: &TildeKind, buf: &mut String) -> Result<(), TildeError> {
735 TildeKindRadix::format(&(*self as isize), tkind, buf)
736 }
737}
738
739impl TildeKindRadix for i64 {
740 fn format(&self, tkind: &TildeKind, buf: &mut String) -> Result<(), TildeError> {
741 TildeKindRadix::format(&(*self as isize), tkind, buf)
742 }
743}
744
745impl TildeKindRadix for i128 {
746 fn format(&self, tkind: &TildeKind, buf: &mut String) -> Result<(), TildeError> {
747 TildeKindRadix::format(&(*self as isize), tkind, buf)
748 }
749}
750
751impl TildeKindRadix for usize {
752 fn format(&self, tkind: &TildeKind, buf: &mut String) -> Result<(), TildeError> {
753 match tkind {
754 TildeKind::Radix((ra, mincol, padchar, commachar, comma_interval, flag)) => {
755 match (ra, mincol, padchar, commachar, comma_interval, flag) {
756 (ra, None, None, None, None, None) => {
757 if ra.is_none() {
758 into_english(*self, buf)
760 } else {
761 write!(buf, "{}", Radix::new(*self, ra.unwrap())).map_err(|e| {
763 TildeError::new(ErrorKind::FormatError, e.to_string())
764 })?
765 }
766 }
767 (ra, None, None, None, None, Some(RadixFlag::Colon)) => {
768 if ra.is_none() {
769 into_ordinal_english(*self, buf)
771 } else {
772 let s = Radix::new(*self, ra.unwrap()).to_string();
775 format_helper(buf, s, mincol, padchar, &Some(','), &Some(3), flag)?;
776 }
777 }
778
779 (None, None, None, None, None, Some(RadixFlag::At)) => {
780 buf.push_str(&into_roman(*self as usize)?);
782 }
783
784 (None, None, None, None, None, Some(RadixFlag::AtColon)) => {
785 return Err(TildeError::new(
786 ErrorKind::FormatError,
787 "old Roman numeral haven't supported yet",
788 ));
789 }
790
791 (ra, _, _, _, _, _) => {
792 let s = Radix::new(*self, ra.unwrap()).to_string();
793 format_helper(buf, s, mincol, padchar, commachar, comma_interval, flag)?;
794 }
795 }
796 }
797 _ => {
798 return Err(
799 TildeError::new(ErrorKind::RevealError, "cannot format to Radix").into(),
800 )
801 }
802 }
803 Ok(())
804 }
805}
806
807impl TildeKindRadix for u8 {
808 fn format(&self, tkind: &TildeKind, buf: &mut String) -> Result<(), TildeError> {
809 TildeKindRadix::format(&(*self as usize), tkind, buf)
810 }
811}
812impl TildeKindRadix for u16 {
813 fn format(&self, tkind: &TildeKind, buf: &mut String) -> Result<(), TildeError> {
814 TildeKindRadix::format(&(*self as usize), tkind, buf)
815 }
816}
817impl TildeKindRadix for u32 {
818 fn format(&self, tkind: &TildeKind, buf: &mut String) -> Result<(), TildeError> {
819 TildeKindRadix::format(&(*self as usize), tkind, buf)
820 }
821}
822
823impl TildeKindRadix for u64 {
824 fn format(&self, tkind: &TildeKind, buf: &mut String) -> Result<(), TildeError> {
825 TildeKindRadix::format(&(*self as usize), tkind, buf)
826 }
827}
828
829impl TildeKindRadix for u128 {
830 fn format(&self, tkind: &TildeKind, buf: &mut String) -> Result<(), TildeError> {
831 TildeKindRadix::format(&(*self as usize), tkind, buf)
832 }
833}
834
835#[cfg(test)]
836mod tests {
837 use super::*;
838
839 #[test]
840 fn test_into_english() {
841 let mut buf = String::new();
842 into_english(12345, &mut buf);
843 assert_eq!(
844 buf,
845 String::from("twelve thousand three hundred forty-five")
846 );
847
848 let mut buf = String::new();
849 into_english(0, &mut buf);
850 assert_eq!(buf, String::from("zero"));
851
852 let mut buf = String::new();
853 into_english(1000000000000000001, &mut buf);
854 assert_eq!(buf, String::from("one quintillion one"));
855
856 let mut buf = String::new();
857 into_english(2132314453234, &mut buf);
858 assert_eq!(buf, String::from("two trillion one hundred thirty-two billion three hundred fourteen million four hundred fifty-three thousand two hundred thirty-four"));
859 }
860
861 #[test]
862 fn test_into_ordinal_english() {
863 let mut buf = String::new();
864 into_ordinal_english(55, &mut buf);
865
866 assert_eq!(buf, String::from("fifty-fifth"));
867
868 let mut buf = String::new();
869 into_ordinal_english(345, &mut buf);
870
871 assert_eq!(buf, String::from("three hundred forty-fifth"));
872
873 let mut buf = String::new();
874 into_ordinal_english(12345, &mut buf);
875
876 assert_eq!(
877 buf,
878 String::from("twelve thousand three hundred forty-fifth")
879 );
880
881 let mut buf = String::new();
882 into_ordinal_english(1000000000000000, &mut buf);
883 assert_eq!(buf, String::from("one quadrillionth"));
884
885 let mut buf = String::new();
886 into_ordinal_english(1000000000000000001, &mut buf);
887 assert_eq!(buf, String::from("one quintillion first"));
888
889 let mut buf = String::new();
890 into_ordinal_english(2132314453234, &mut buf);
891 assert_eq!(buf, String::from("two trillion one hundred thirty-two billion three hundred fourteen million four hundred fifty-three thousand two hundred thirty-fourth"));
892 }
893
894 #[test]
895 fn test_radix_format() {
896 let mut buf = String::new();
897 assert!(write!(buf, "{}", Radix::new(17, 3)).is_ok());
898 assert_eq!(buf, String::from("122"));
899
900 let mut buf = String::new();
901 assert!(write!(buf, "{}", Radix::new(345, 2)).is_ok());
902 assert_eq!(buf, String::from("101011001"));
903 }
904
905 #[test]
906 fn test_format_helper() {
907 let mut buf = String::new();
908 assert!(format_helper(
909 &mut buf,
910 Radix::new(345, 2).to_string(),
911 &None,
912 &None,
913 &Some(','),
914 &Some(3),
915 &Some(RadixFlag::Colon),
916 )
917 .is_ok());
918 assert_eq!(buf, String::from("101,011,001"));
919
920 let mut buf = String::new();
921 assert!(format_helper(
922 &mut buf,
923 Radix::new(345, 2).to_string(),
924 &None,
925 &None,
926 &Some(','),
927 &Some(3),
928 &None,
929 )
930 .is_ok());
931 assert_eq!(buf, String::from("101011001"));
932
933 let mut buf = String::new();
934 assert!(format_helper(
935 &mut buf,
936 Radix::new(345, 3).to_string(),
937 &None,
938 &None,
939 &Some(','),
940 &Some(3),
941 &Some(RadixFlag::Colon),
942 )
943 .is_ok());
944 assert_eq!(buf, String::from("110,210"));
945
946 let mut buf = String::new();
947 assert!(format_helper(
948 &mut buf,
949 Radix::new(17, 3).to_string(),
950 &None,
951 &None,
952 &Some(','),
953 &Some(2),
954 &Some(RadixFlag::Colon),
955 )
956 .is_ok());
957 assert_eq!(buf, String::from("1,22"));
958
959 let mut buf = String::new();
960 assert!(format_helper(
961 &mut buf,
962 Radix::new(17, 10).to_string(),
963 &None,
964 &None,
965 &Some(','),
966 &Some(2),
967 &Some(RadixFlag::Colon),
968 )
969 .is_ok());
970 assert_eq!(buf, String::from("17"));
971
972 let mut buf = String::new();
973 assert!(format_helper(
974 &mut buf,
975 Radix::new(17, 10).to_string(),
976 &Some(5),
977 &Some('a'),
978 &Some(','),
979 &Some(2),
980 &Some(RadixFlag::Colon),
981 )
982 .is_ok());
983 assert_eq!(buf, String::from("aaa17"));
984 }
985}