my_ecs/util/str.rs
1//! String utilities.
2
3/// Determines number of digits at the end of the string.
4///
5/// # Examples
6///
7/// ```
8/// use my_ecs::prelude::*;
9///
10/// assert_eq!(2, str_util::rdigit_num("hello42"));
11/// assert_eq!(0, str_util::rdigit_num("1a")); // Doesn't end with digits.
12/// ```
13pub fn rdigit_num(s: &str) -> usize {
14 let v = s.as_bytes();
15 v.iter().rev().take_while(|c| c.is_ascii_digit()).count()
16}
17
18/// Increases ascii number at the end of the string.
19///
20/// # Examples
21///
22/// ```
23/// use my_ecs::prelude::*;
24///
25/// let mut s = "hello01".to_owned();
26/// str_util::increase_rnumber(&mut s);
27/// assert_eq!("hello02", s.as_str());
28///
29/// let mut s = "hello99".to_owned();
30/// str_util::increase_rnumber(&mut s);
31/// assert_eq!("hello100", s.as_str());
32///
33/// let mut s = "hello".to_owned();
34/// str_util::increase_rnumber(&mut s);
35/// assert_eq!("hello", s.as_str()); // String doesn't end with number.
36/// ```
37pub fn increase_rnumber(s: &mut String) {
38 let n = rdigit_num(s);
39 if n == 0 {
40 return;
41 }
42
43 let mut carry = 1;
44 // Safety: In UTF-8, byte starts with 0 is same with the ascii character.
45 unsafe {
46 let v = s.as_bytes_mut();
47 for c in v.iter_mut().rev().take(n) {
48 if carry == 0 {
49 return;
50 }
51 let d = *c - b'0' + carry;
52 carry = d / 10;
53 *c = d % 10 + b'0';
54 }
55 if carry > 0 {
56 s.insert(s.len() - n, (carry + b'0') as char);
57 }
58 }
59}