@@ -5,6 +5,7 @@ use std::{
55 sync:: LazyLock ,
66} ;
77
8+ use rand;
89use regex:: Regex ;
910pub use value:: utils:: {
1011 display_map,
@@ -33,20 +34,31 @@ static NAME_NUMBER_RE: LazyLock<Regex> = LazyLock::new(|| Regex::new(r"(.*) \((\
3334
3435/// "Increment" a string.
3536/// E.g. `Foo` becomes `Foo (1)`, and `Foo (1)` becomes `Foo (2)`.
37+ /// If amt is None, uses 8 random hex characters instead.
3638/// Useful for strings (team names, device names) remain unique.
37- pub fn increment_name ( name : & str , amt : u64 ) -> String {
38- if let Some ( number) = NAME_NUMBER_RE
39- . captures ( name)
40- . and_then ( |c| c. get ( 2 ) )
41- . and_then ( |m| m. as_str ( ) . parse :: < u64 > ( ) . ok ( ) )
42- {
43- NAME_NUMBER_RE
44- . replace ( name, |caps : & regex:: Captures | {
45- format ! ( "{} ({})" , & caps[ 1 ] , number + amt)
46- } )
47- . into ( )
48- } else {
49- format ! ( "{name} ({amt})" )
39+ pub fn increment_name ( name : & str , amt : Option < u64 > ) -> String {
40+ match amt {
41+ Some ( amt) => {
42+ if let Some ( number) = NAME_NUMBER_RE
43+ . captures ( name)
44+ . and_then ( |c| c. get ( 2 ) )
45+ . and_then ( |m| m. as_str ( ) . parse :: < u64 > ( ) . ok ( ) )
46+ {
47+ NAME_NUMBER_RE
48+ . replace ( name, |caps : & regex:: Captures | {
49+ format ! ( "{} ({})" , & caps[ 1 ] , number + amt)
50+ } )
51+ . into ( )
52+ } else {
53+ format ! ( "{name} ({amt})" )
54+ }
55+ } ,
56+ None => {
57+ let hex_suffix: String = ( 0 ..8 )
58+ . map ( |_| format ! ( "{:x}" , rand:: random:: <u8 >( ) % 16 ) )
59+ . collect ( ) ;
60+ format ! ( "{name} ({hex_suffix})" )
61+ } ,
5062 }
5163}
5264
@@ -72,9 +84,17 @@ fn test_increment_name() {
7284 ( "Foo (a)" , "Foo (a) (1)" ) ,
7385 ] ;
7486 for ( test, expected) in cases {
75- assert_eq ! ( increment_name( test, 1 ) , expected) ;
87+ assert_eq ! ( increment_name( test, Some ( 1 ) ) , expected) ;
7688 }
7789
78- assert_eq ! ( increment_name( "Foo" , 50 ) , "Foo (50)" ) ;
79- assert_eq ! ( increment_name( "Foo (20)" , 50 ) , "Foo (70)" ) ;
90+ assert_eq ! ( increment_name( "Foo" , Some ( 50 ) ) , "Foo (50)" ) ;
91+ assert_eq ! ( increment_name( "Foo (20)" , Some ( 50 ) ) , "Foo (70)" ) ;
92+
93+ // Test None case - should generate 8 hex characters
94+ let result = increment_name ( "Test" , None ) ;
95+ assert ! ( result. starts_with( "Test (" ) ) ;
96+ assert ! ( result. ends_with( ")" ) ) ;
97+ let hex_part = & result[ 6 ..result. len ( ) - 1 ] ; // Extract hex part between "Test (" and ")"
98+ assert_eq ! ( hex_part. len( ) , 8 ) ;
99+ assert ! ( hex_part. chars( ) . all( |c| c. is_ascii_hexdigit( ) ) ) ;
80100}
0 commit comments