@@ -89,6 +89,12 @@ const USELESS_METHODS: &[&str] = &[
8989///
9090/// assert_eq!(generator.suggest_name("b2"), "b2");
9191/// assert_eq!(generator.suggest_name("b"), "b3");
92+ ///
93+ /// // Multi-byte UTF-8 identifiers (e.g. CJK) are handled correctly
94+ /// assert_eq!(generator.suggest_name("日本語"), "日本語");
95+ /// assert_eq!(generator.suggest_name("日本語"), "日本語1");
96+ /// assert_eq!(generator.suggest_name("données3"), "données3");
97+ /// assert_eq!(generator.suggest_name("données"), "données4");
9298/// ```
9399#[ derive( Debug , Default ) ]
94100pub struct NameGenerator {
@@ -262,11 +268,15 @@ impl NameGenerator {
262268 /// Remove the numeric suffix from the name
263269 ///
264270 /// # Examples
265- /// `a1b2c3` -> `a1b2c`
271+ /// `a1b2c3` -> ( `a1b2c`, Some(3))
266272 fn split_numeric_suffix ( name : & str ) -> ( & str , Option < usize > ) {
267273 let pos =
268274 name. rfind ( |c : char | !c. is_numeric ( ) ) . expect ( "Name cannot be empty or all-numeric" ) ;
269- let ( prefix, suffix) = name. split_at ( pos + 1 ) ;
275+ // `rfind` returns the byte offset of the matched character, which may be
276+ // multi-byte (e.g. CJK identifiers). Use `ceil_char_boundary` to advance
277+ // past the full character to the next valid split point.
278+ let split = name. ceil_char_boundary ( pos + 1 ) ;
279+ let ( prefix, suffix) = name. split_at ( split) ;
270280 ( prefix, suffix. parse ( ) . ok ( ) )
271281 }
272282}
0 commit comments