@@ -1584,7 +1584,7 @@ fn render_enum(
15841584 lines. push ( format ! ( "#[derive({})]" , derives. join( ", " ) ) ) ;
15851585 lines. push ( format ! (
15861586 "#[serde(rename_all = \" {}\" )]" ,
1587- config . enum_naming_case ( ) . serde_rename_all ( )
1587+ enum_serde_rename_all ( values , config )
15881588 ) ) ;
15891589
15901590 match values {
@@ -1605,8 +1605,9 @@ fn render_enum(
16051605
16061606 match values {
16071607 EnumValues :: String ( string_values) => {
1608+ let use_screaming_snake_variants = uses_screaming_snake_variants ( string_values) ;
16081609 for s in string_values {
1609- let variant_name = enum_variant_name ( s ) ;
1610+ let variant_name = enum_string_variant_name ( s , use_screaming_snake_variants ) ;
16101611 lines. push ( format ! ( " #[sea_orm(string_value = \" {}\" )]" , s) ) ;
16111612 lines. push ( format ! ( " {}," , variant_name) ) ;
16121613 }
@@ -1631,6 +1632,20 @@ fn render_enum(
16311632fn enum_variant_name ( s : & str ) -> String {
16321633 let pascal = to_pascal_case ( s) ;
16331634
1635+ finalize_enum_variant_name ( pascal)
1636+ }
1637+
1638+ fn enum_string_variant_name ( s : & str , use_screaming_snake_variants : bool ) -> String {
1639+ let pascal = if use_screaming_snake_variants {
1640+ screaming_snake_to_pascal_case ( s)
1641+ } else {
1642+ to_pascal_case ( s)
1643+ } ;
1644+
1645+ finalize_enum_variant_name ( pascal)
1646+ }
1647+
1648+ fn finalize_enum_variant_name ( pascal : String ) -> String {
16341649 // Handle empty string
16351650 if pascal. is_empty ( ) {
16361651 return "Value" . to_string ( ) ;
@@ -1649,6 +1664,56 @@ fn enum_variant_name(s: &str) -> String {
16491664 pascal
16501665}
16511666
1667+ fn enum_serde_rename_all ( values : & EnumValues , config : & SeaOrmConfig ) -> & ' static str {
1668+ match values {
1669+ EnumValues :: String ( string_values) if uses_screaming_snake_variants ( string_values) => {
1670+ "SCREAMING_SNAKE_CASE"
1671+ }
1672+ _ => config. enum_naming_case ( ) . serde_rename_all ( ) ,
1673+ }
1674+ }
1675+
1676+ fn uses_screaming_snake_variants ( values : & [ String ] ) -> bool {
1677+ !values. is_empty ( ) && values. iter ( ) . all ( |value| is_screaming_snake_value ( value) )
1678+ }
1679+
1680+ fn is_screaming_snake_value ( value : & str ) -> bool {
1681+ let mut has_ascii_upper = false ;
1682+
1683+ for ch in value. chars ( ) {
1684+ if ch. is_ascii_lowercase ( ) {
1685+ return false ;
1686+ }
1687+ if ch. is_ascii_uppercase ( ) {
1688+ has_ascii_upper = true ;
1689+ continue ;
1690+ }
1691+ if ch. is_ascii_digit ( ) || ch == '_' {
1692+ continue ;
1693+ }
1694+ return false ;
1695+ }
1696+
1697+ has_ascii_upper
1698+ }
1699+
1700+ fn screaming_snake_to_pascal_case ( value : & str ) -> String {
1701+ value
1702+ . split ( '_' )
1703+ . filter ( |segment| !segment. is_empty ( ) )
1704+ . map ( |segment| {
1705+ let mut chars = segment. chars ( ) ;
1706+ let first = chars
1707+ . next ( )
1708+ . expect ( "empty segments are filtered before PascalCase conversion" ) ;
1709+ let mut out = String :: new ( ) ;
1710+ out. push ( first. to_ascii_uppercase ( ) ) ;
1711+ out. extend ( chars. map ( |ch| ch. to_ascii_lowercase ( ) ) ) ;
1712+ out
1713+ } )
1714+ . collect ( )
1715+ }
1716+
16521717fn to_pascal_case ( s : & str ) -> String {
16531718 let mut result = String :: new ( ) ;
16541719 let mut capitalize = true ;
@@ -2182,6 +2247,8 @@ mod helper_tests {
21822247 #[ case( "pending" , "Pending" ) ]
21832248 #[ case( "in_stock" , "InStock" ) ]
21842249 #[ case( "info-level" , "InfoLevel" ) ]
2250+ #[ case( "ACTIVE" , "ACTIVE" ) ]
2251+ #[ case( "ERROR_LEVEL" , "ERRORLEVEL" ) ]
21852252 #[ case( "1critical" , "N1critical" ) ]
21862253 #[ case( "123abc" , "N123abc" ) ]
21872254 #[ case( "1_critical" , "N1Critical" ) ]
@@ -2190,6 +2257,33 @@ mod helper_tests {
21902257 assert_eq ! ( enum_variant_name( input) , expected) ;
21912258 }
21922259
2260+ #[ test]
2261+ fn test_render_enum_uses_screaming_snake_serde_for_uppercase_values ( ) {
2262+ let mut lines = Vec :: new ( ) ;
2263+ let config = SeaOrmConfig :: default ( ) ;
2264+ let values = EnumValues :: String ( vec ! [ "PENDING" . into( ) , "IN_PROGRESS" . into( ) ] ) ;
2265+
2266+ render_enum ( & mut lines, "orders" , "order_status" , & values, & config) ;
2267+
2268+ let result = lines. join ( "\n " ) ;
2269+ assert ! ( result. contains( "#[serde(rename_all = \" SCREAMING_SNAKE_CASE\" )]" ) ) ;
2270+ assert ! ( result. contains( " #[sea_orm(string_value = \" PENDING\" )]\n Pending," ) ) ;
2271+ assert ! ( result. contains( " #[sea_orm(string_value = \" IN_PROGRESS\" )]\n InProgress," ) ) ;
2272+ }
2273+
2274+ #[ test]
2275+ fn test_is_screaming_snake_value_rejects_invalid_symbol ( ) {
2276+ assert ! ( !is_screaming_snake_value( "PENDING-REVIEW" ) ) ;
2277+ }
2278+
2279+ #[ test]
2280+ fn test_screaming_snake_to_pascal_case_ignores_empty_segments ( ) {
2281+ assert_eq ! (
2282+ screaming_snake_to_pascal_case( "PENDING__REVIEW" ) ,
2283+ "PendingReview"
2284+ ) ;
2285+ }
2286+
21932287 fn string_enum_order_status ( ) -> ( & ' static str , EnumValues ) {
21942288 (
21952289 "order_status" ,
0 commit comments