Insert locale-aware thousands separators into an integer string. Follows CPython's GroupGenerator logic for variable-width grouping.
(int_part: &str, locale: &LocaleInfo)
| 481 | /// Insert locale-aware thousands separators into an integer string. |
| 482 | /// Follows CPython's GroupGenerator logic for variable-width grouping. |
| 483 | fn insert_locale_grouping(int_part: &str, locale: &LocaleInfo) -> String { |
| 484 | if locale.grouping.is_empty() || locale.thousands_sep.is_empty() || int_part.len() <= 1 { |
| 485 | return int_part.to_string(); |
| 486 | } |
| 487 | |
| 488 | let mut group_idx = 0; |
| 489 | let mut group_size = locale.grouping[0] as usize; |
| 490 | |
| 491 | if group_size == 0 { |
| 492 | return int_part.to_string(); |
| 493 | } |
| 494 | |
| 495 | // Collect groups of digits from right to left |
| 496 | let len = int_part.len(); |
| 497 | let mut groups: Vec<&str> = Vec::new(); |
| 498 | let mut pos = len; |
| 499 | |
| 500 | loop { |
| 501 | if pos <= group_size { |
| 502 | groups.push(&int_part[..pos]); |
| 503 | break; |
| 504 | } |
| 505 | |
| 506 | groups.push(&int_part[pos - group_size..pos]); |
| 507 | pos -= group_size; |
| 508 | |
| 509 | // Advance to next group size |
| 510 | if group_idx + 1 < locale.grouping.len() { |
| 511 | let next = locale.grouping[group_idx + 1] as usize; |
| 512 | if next != 0 { |
| 513 | group_size = next; |
| 514 | group_idx += 1; |
| 515 | } |
| 516 | // 0 means repeat previous group size forever |
| 517 | } |
| 518 | } |
| 519 | |
| 520 | // Groups were collected right-to-left, reverse to get left-to-right |
| 521 | groups.reverse(); |
| 522 | groups.join(&locale.thousands_sep) |
| 523 | } |
| 524 | |
| 525 | /// Apply locale-aware grouping and decimal point replacement to a formatted number. |
| 526 | fn apply_locale_formatting(magnitude_str: String, locale: &LocaleInfo) -> String { |