@@ -535,6 +535,21 @@ where
535535 }
536536}
537537
538+ /// Parse a single "key:value" string into a (key, value) tuple
539+ /// Returns None if the string is invalid (e.g., missing colon, empty key/value)
540+ fn parse_key_value_tag ( tag : & str ) -> Option < ( String , String ) > {
541+ let parts: Vec < & str > = tag. splitn ( 2 , ':' ) . collect ( ) ;
542+ if parts. len ( ) == 2 && !parts[ 0 ] . is_empty ( ) && !parts[ 1 ] . is_empty ( ) {
543+ Some ( ( parts[ 0 ] . to_string ( ) , parts[ 1 ] . to_string ( ) ) )
544+ } else {
545+ error ! (
546+ "Failed to parse tag '{}', expected format 'key:value', ignoring" ,
547+ tag
548+ ) ;
549+ None
550+ }
551+ }
552+
538553pub fn deserialize_key_value_pairs < ' de , D > (
539554 deserializer : D ,
540555) -> Result < HashMap < String , String > , D :: Error >
@@ -559,14 +574,8 @@ where
559574 if tag. is_empty ( ) {
560575 continue ;
561576 }
562- let parts = tag. split ( ':' ) . collect :: < Vec < & str > > ( ) ;
563- if parts. len ( ) == 2 && !parts[ 0 ] . is_empty ( ) && !parts[ 1 ] . is_empty ( ) {
564- map. insert ( parts[ 0 ] . to_string ( ) , parts[ 1 ] . to_string ( ) ) ;
565- } else {
566- error ! (
567- "Failed to parse tag '{}', expected format 'key:value', ignoring" ,
568- tag
569- ) ;
577+ if let Some ( ( key, val) ) = parse_key_value_tag ( tag) {
578+ map. insert ( key, val) ;
570579 }
571580 }
572581
@@ -643,14 +652,8 @@ where
643652 let array: Vec < String > = Vec :: deserialize ( deserializer) ?;
644653 let mut map = HashMap :: new ( ) ;
645654 for s in array {
646- let parts = s. split ( ':' ) . collect :: < Vec < & str > > ( ) ;
647- if parts. len ( ) == 2 {
648- map. insert ( parts[ 0 ] . to_string ( ) , parts[ 1 ] . to_string ( ) ) ;
649- } else {
650- error ! (
651- "Failed to parse tag '{}', expected format 'key:value', ignoring" ,
652- s. trim( )
653- ) ;
655+ if let Some ( ( key, val) ) = parse_key_value_tag ( & s) {
656+ map. insert ( key, val) ;
654657 }
655658 }
656659 Ok ( map)
@@ -1480,4 +1483,78 @@ pub mod tests {
14801483 expected. insert ( "valid" . to_string ( ) , "tag" . to_string ( ) ) ;
14811484 assert_eq ! ( result. tags, expected) ;
14821485 }
1486+
1487+ #[ test]
1488+ fn test_deserialize_key_value_pairs_with_url_values ( ) {
1489+ #[ derive( Deserialize , Debug , PartialEq ) ]
1490+ struct TestStruct {
1491+ #[ serde( deserialize_with = "deserialize_key_value_pairs" ) ]
1492+ tags : HashMap < String , String > ,
1493+ }
1494+
1495+ let result = serde_json:: from_str :: < TestStruct > (
1496+ r#"{"tags": "git.repository_url:https://gitlab.ddbuild.io/DataDog/serverless-e2e-tests.git,env:prod"}"#
1497+ )
1498+ . expect ( "failed to parse JSON" ) ;
1499+ let mut expected = HashMap :: new ( ) ;
1500+ expected. insert (
1501+ "git.repository_url" . to_string ( ) ,
1502+ "https://gitlab.ddbuild.io/DataDog/serverless-e2e-tests.git" . to_string ( ) ,
1503+ ) ;
1504+ expected. insert ( "env" . to_string ( ) , "prod" . to_string ( ) ) ;
1505+ assert_eq ! ( result. tags, expected) ;
1506+ }
1507+
1508+ #[ test]
1509+ fn test_deserialize_key_value_pair_array_with_urls ( ) {
1510+ #[ derive( Deserialize , Debug , PartialEq ) ]
1511+ struct TestStruct {
1512+ #[ serde( deserialize_with = "deserialize_key_value_pair_array_to_hashmap" ) ]
1513+ tags : HashMap < String , String > ,
1514+ }
1515+
1516+ let result = serde_json:: from_str :: < TestStruct > (
1517+ r#"{"tags": ["git.repository_url:https://gitlab.ddbuild.io/DataDog/serverless-e2e-tests.git", "env:prod", "version:1.2.3"]}"#
1518+ )
1519+ . expect ( "failed to parse JSON" ) ;
1520+ let mut expected = HashMap :: new ( ) ;
1521+ expected. insert (
1522+ "git.repository_url" . to_string ( ) ,
1523+ "https://gitlab.ddbuild.io/DataDog/serverless-e2e-tests.git" . to_string ( ) ,
1524+ ) ;
1525+ expected. insert ( "env" . to_string ( ) , "prod" . to_string ( ) ) ;
1526+ expected. insert ( "version" . to_string ( ) , "1.2.3" . to_string ( ) ) ;
1527+ assert_eq ! ( result. tags, expected) ;
1528+ }
1529+
1530+ #[ test]
1531+ fn test_deserialize_key_value_pair_array_ignores_invalid ( ) {
1532+ #[ derive( Deserialize , Debug , PartialEq ) ]
1533+ struct TestStruct {
1534+ #[ serde( deserialize_with = "deserialize_key_value_pair_array_to_hashmap" ) ]
1535+ tags : HashMap < String , String > ,
1536+ }
1537+
1538+ let result = serde_json:: from_str :: < TestStruct > (
1539+ r#"{"tags": ["valid:tag", "invalid_no_colon", "another:good:value:with:colons"]}"# ,
1540+ )
1541+ . expect ( "failed to parse JSON" ) ;
1542+ let mut expected = HashMap :: new ( ) ;
1543+ expected. insert ( "valid" . to_string ( ) , "tag" . to_string ( ) ) ;
1544+ expected. insert ( "another" . to_string ( ) , "good:value:with:colons" . to_string ( ) ) ;
1545+ assert_eq ! ( result. tags, expected) ;
1546+ }
1547+
1548+ #[ test]
1549+ fn test_deserialize_key_value_pair_array_empty ( ) {
1550+ #[ derive( Deserialize , Debug , PartialEq ) ]
1551+ struct TestStruct {
1552+ #[ serde( deserialize_with = "deserialize_key_value_pair_array_to_hashmap" ) ]
1553+ tags : HashMap < String , String > ,
1554+ }
1555+
1556+ let result =
1557+ serde_json:: from_str :: < TestStruct > ( r#"{"tags": []}"# ) . expect ( "failed to parse JSON" ) ;
1558+ assert_eq ! ( result. tags, HashMap :: new( ) ) ;
1559+ }
14831560}
0 commit comments