@@ -241,6 +241,7 @@ impl SourceItemOrderingModuleItemKind {
241241pub struct SourceItemOrderingModuleItemGroupings {
242242 groups : Vec < ( String , Vec < SourceItemOrderingModuleItemKind > ) > ,
243243 lut : HashMap < SourceItemOrderingModuleItemKind , usize > ,
244+ back_lut : HashMap < SourceItemOrderingModuleItemKind , String > ,
244245}
245246
246247impl SourceItemOrderingModuleItemGroupings {
@@ -256,6 +257,22 @@ impl SourceItemOrderingModuleItemGroupings {
256257 lut
257258 }
258259
260+ fn build_back_lut (
261+ groups : & [ ( String , Vec < SourceItemOrderingModuleItemKind > ) ] ,
262+ ) -> HashMap < SourceItemOrderingModuleItemKind , String > {
263+ let mut lut = HashMap :: new ( ) ;
264+ for ( group_name, items) in groups {
265+ for item in items {
266+ lut. insert ( item. clone ( ) , group_name. clone ( ) ) ;
267+ }
268+ }
269+ lut
270+ }
271+
272+ pub fn grouping_name_of ( & self , item : & SourceItemOrderingModuleItemKind ) -> Option < String > {
273+ self . back_lut . get ( item) . cloned ( )
274+ }
275+
259276 pub fn module_level_order_of ( & self , item : & SourceItemOrderingModuleItemKind ) -> Option < usize > {
260277 self . lut . get ( item) . copied ( )
261278 }
@@ -266,7 +283,8 @@ impl From<&[(&str, &[SourceItemOrderingModuleItemKind])]> for SourceItemOrdering
266283 let groups: Vec < ( String , Vec < SourceItemOrderingModuleItemKind > ) > =
267284 value. iter ( ) . map ( |item| ( item. 0 . to_string ( ) , item. 1 . to_vec ( ) ) ) . collect ( ) ;
268285 let lut = Self :: build_lut ( & groups) ;
269- Self { groups, lut }
286+ let back_lut = Self :: build_back_lut ( & groups) ;
287+ Self { groups, lut, back_lut }
270288 }
271289}
272290
@@ -284,6 +302,7 @@ impl<'de> Deserialize<'de> for SourceItemOrderingModuleItemGroupings {
284302 let groups = Vec :: < ( String , Vec < SourceItemOrderingModuleItemKind > ) > :: deserialize ( deserializer) ?;
285303 let items_total: usize = groups. iter ( ) . map ( |( _, v) | v. len ( ) ) . sum ( ) ;
286304 let lut = Self :: build_lut ( & groups) ;
305+ let back_lut = Self :: build_back_lut ( & groups) ;
287306
288307 let mut expected_items = SourceItemOrderingModuleItemKind :: all_variants ( ) ;
289308 for item in lut. keys ( ) {
@@ -306,7 +325,7 @@ impl<'de> Deserialize<'de> for SourceItemOrderingModuleItemGroupings {
306325 ) ) ;
307326 }
308327
309- Ok ( Self { groups, lut } )
328+ Ok ( Self { groups, lut, back_lut } )
310329 } else if items_total != all_items. len ( ) {
311330 Err ( de:: Error :: custom ( format ! (
312331 "Some module item kinds were configured more than once, or were missing, in the source ordering configuration. \
@@ -418,6 +437,83 @@ impl Serialize for SourceItemOrderingTraitAssocItemKinds {
418437 }
419438}
420439
440+ /// Describes which specific groupings should have their items ordered
441+ /// alphabetically.
442+ ///
443+ /// This is separate from defining and enforcing groupings. For example,
444+ /// defining enums are grouped before structs still allows for an enum B to be
445+ /// placed before an enum A. Only when enforcing ordering within the grouping,
446+ /// will it be checked if A is placed before B.
447+ #[ derive( Clone , Debug ) ]
448+ pub enum SourceItemOrderingWithinModuleItemGroupings {
449+ /// All groupings should have their items ordered.
450+ All ,
451+
452+ /// None of the groupings should have their order checked.
453+ None ,
454+
455+ /// Only the specified groupings should have their order checked.
456+ Custom ( Vec < String > ) ,
457+ }
458+
459+ impl SourceItemOrderingWithinModuleItemGroupings {
460+ pub fn ordered_within ( & self , grouping_name : & String ) -> bool {
461+ match self {
462+ SourceItemOrderingWithinModuleItemGroupings :: All => true ,
463+ SourceItemOrderingWithinModuleItemGroupings :: None => false ,
464+ SourceItemOrderingWithinModuleItemGroupings :: Custom ( groups) => groups. contains ( grouping_name) ,
465+ }
466+ }
467+ }
468+
469+ /// Helper struct for deserializing the [`SourceItemOrderingWithinModuleItemGroupings`].
470+ #[ derive( Deserialize ) ]
471+ #[ serde( untagged) ]
472+ enum StringOrVecOfString {
473+ String ( String ) ,
474+ Vec ( Vec < String > ) ,
475+ }
476+
477+ impl < ' de > Deserialize < ' de > for SourceItemOrderingWithinModuleItemGroupings {
478+ fn deserialize < D > ( deserializer : D ) -> Result < Self , D :: Error >
479+ where
480+ D : Deserializer < ' de > ,
481+ {
482+ let description = "The available options for configuring an ordering within module item groups are: \
483+ \" all\" , \" none\" , or a list of module item group names \
484+ (as configured with the `module_item_order_groupings` configuration option).";
485+
486+ match StringOrVecOfString :: deserialize ( deserializer) {
487+ Ok ( StringOrVecOfString :: String ( preset) ) if preset == "all" => {
488+ Ok ( SourceItemOrderingWithinModuleItemGroupings :: All )
489+ } ,
490+ Ok ( StringOrVecOfString :: String ( preset) ) if preset == "none" => {
491+ Ok ( SourceItemOrderingWithinModuleItemGroupings :: None )
492+ } ,
493+ Ok ( StringOrVecOfString :: String ( preset) ) => Err ( de:: Error :: custom ( format ! (
494+ "Unknown configuration option: {preset}.\n {description}"
495+ ) ) ) ,
496+ Ok ( StringOrVecOfString :: Vec ( groupings) ) => {
497+ Ok ( SourceItemOrderingWithinModuleItemGroupings :: Custom ( groupings) )
498+ } ,
499+ Err ( e) => Err ( de:: Error :: custom ( format ! ( "{e}\n {description}" ) ) ) ,
500+ }
501+ }
502+ }
503+
504+ impl Serialize for SourceItemOrderingWithinModuleItemGroupings {
505+ fn serialize < S > ( & self , serializer : S ) -> Result < S :: Ok , S :: Error >
506+ where
507+ S : ser:: Serializer ,
508+ {
509+ match self {
510+ SourceItemOrderingWithinModuleItemGroupings :: All => serializer. serialize_str ( "all" ) ,
511+ SourceItemOrderingWithinModuleItemGroupings :: None => serializer. serialize_str ( "none" ) ,
512+ SourceItemOrderingWithinModuleItemGroupings :: Custom ( vec) => vec. serialize ( serializer) ,
513+ }
514+ }
515+ }
516+
421517// these impls are never actually called but are used by the various config options that default to
422518// empty lists
423519macro_rules! unimplemented_serialize {
0 commit comments