@@ -305,6 +305,7 @@ impl SourceItemOrderingModuleItemKind {
305
305
pub struct SourceItemOrderingModuleItemGroupings {
306
306
groups : Vec < ( String , Vec < SourceItemOrderingModuleItemKind > ) > ,
307
307
lut : HashMap < SourceItemOrderingModuleItemKind , usize > ,
308
+ back_lut : HashMap < SourceItemOrderingModuleItemKind , String > ,
308
309
}
309
310
310
311
impl SourceItemOrderingModuleItemGroupings {
@@ -320,6 +321,30 @@ impl SourceItemOrderingModuleItemGroupings {
320
321
lut
321
322
}
322
323
324
+ fn build_back_lut (
325
+ groups : & [ ( String , Vec < SourceItemOrderingModuleItemKind > ) ] ,
326
+ ) -> HashMap < SourceItemOrderingModuleItemKind , String > {
327
+ let mut lut = HashMap :: new ( ) ;
328
+ for ( group_name, items) in groups {
329
+ for item in items {
330
+ lut. insert ( item. clone ( ) , group_name. clone ( ) ) ;
331
+ }
332
+ }
333
+ lut
334
+ }
335
+
336
+ pub fn grouping_name_of ( & self , item : & SourceItemOrderingModuleItemKind ) -> Option < & String > {
337
+ self . back_lut . get ( item)
338
+ }
339
+
340
+ pub fn grouping_names ( & self ) -> Vec < String > {
341
+ self . groups . iter ( ) . map ( |( name, _) | name. clone ( ) ) . collect ( )
342
+ }
343
+
344
+ pub fn is_grouping ( & self , grouping : & str ) -> bool {
345
+ self . groups . iter ( ) . any ( |( g, _) | g == grouping)
346
+ }
347
+
323
348
pub fn module_level_order_of ( & self , item : & SourceItemOrderingModuleItemKind ) -> Option < usize > {
324
349
self . lut . get ( item) . copied ( )
325
350
}
@@ -330,7 +355,8 @@ impl From<&[(&str, &[SourceItemOrderingModuleItemKind])]> for SourceItemOrdering
330
355
let groups: Vec < ( String , Vec < SourceItemOrderingModuleItemKind > ) > =
331
356
value. iter ( ) . map ( |item| ( item. 0 . to_string ( ) , item. 1 . to_vec ( ) ) ) . collect ( ) ;
332
357
let lut = Self :: build_lut ( & groups) ;
333
- Self { groups, lut }
358
+ let back_lut = Self :: build_back_lut ( & groups) ;
359
+ Self { groups, lut, back_lut }
334
360
}
335
361
}
336
362
@@ -348,6 +374,7 @@ impl<'de> Deserialize<'de> for SourceItemOrderingModuleItemGroupings {
348
374
let groups = Vec :: < ( String , Vec < SourceItemOrderingModuleItemKind > ) > :: deserialize ( deserializer) ?;
349
375
let items_total: usize = groups. iter ( ) . map ( |( _, v) | v. len ( ) ) . sum ( ) ;
350
376
let lut = Self :: build_lut ( & groups) ;
377
+ let back_lut = Self :: build_back_lut ( & groups) ;
351
378
352
379
let mut expected_items = SourceItemOrderingModuleItemKind :: all_variants ( ) ;
353
380
for item in lut. keys ( ) {
@@ -370,7 +397,7 @@ impl<'de> Deserialize<'de> for SourceItemOrderingModuleItemGroupings {
370
397
) ) ;
371
398
}
372
399
373
- Ok ( Self { groups, lut } )
400
+ Ok ( Self { groups, lut, back_lut } )
374
401
} else if items_total != all_items. len ( ) {
375
402
Err ( de:: Error :: custom ( format ! (
376
403
"Some module item kinds were configured more than once, or were missing, in the source ordering configuration. \
@@ -482,6 +509,83 @@ impl Serialize for SourceItemOrderingTraitAssocItemKinds {
482
509
}
483
510
}
484
511
512
+ /// Describes which specific groupings should have their items ordered
513
+ /// alphabetically.
514
+ ///
515
+ /// This is separate from defining and enforcing groupings. For example,
516
+ /// defining enums are grouped before structs still allows for an enum B to be
517
+ /// placed before an enum A. Only when enforcing ordering within the grouping,
518
+ /// will it be checked if A is placed before B.
519
+ #[ derive( Clone , Debug ) ]
520
+ pub enum SourceItemOrderingWithinModuleItemGroupings {
521
+ /// All groupings should have their items ordered.
522
+ All ,
523
+
524
+ /// None of the groupings should have their order checked.
525
+ None ,
526
+
527
+ /// Only the specified groupings should have their order checked.
528
+ Custom ( Vec < String > ) ,
529
+ }
530
+
531
+ impl SourceItemOrderingWithinModuleItemGroupings {
532
+ pub fn ordered_within ( & self , grouping_name : & String ) -> bool {
533
+ match self {
534
+ SourceItemOrderingWithinModuleItemGroupings :: All => true ,
535
+ SourceItemOrderingWithinModuleItemGroupings :: None => false ,
536
+ SourceItemOrderingWithinModuleItemGroupings :: Custom ( groups) => groups. contains ( grouping_name) ,
537
+ }
538
+ }
539
+ }
540
+
541
+ /// Helper struct for deserializing the [`SourceItemOrderingWithinModuleItemGroupings`].
542
+ #[ derive( Deserialize ) ]
543
+ #[ serde( untagged) ]
544
+ enum StringOrVecOfString {
545
+ String ( String ) ,
546
+ Vec ( Vec < String > ) ,
547
+ }
548
+
549
+ impl < ' de > Deserialize < ' de > for SourceItemOrderingWithinModuleItemGroupings {
550
+ fn deserialize < D > ( deserializer : D ) -> Result < Self , D :: Error >
551
+ where
552
+ D : Deserializer < ' de > ,
553
+ {
554
+ let description = "The available options for configuring an ordering within module item groups are: \
555
+ \" all\" , \" none\" , or a list of module item group names \
556
+ (as configured with the `module-item-order-groupings` configuration option).";
557
+
558
+ match StringOrVecOfString :: deserialize ( deserializer) {
559
+ Ok ( StringOrVecOfString :: String ( preset) ) if preset == "all" => {
560
+ Ok ( SourceItemOrderingWithinModuleItemGroupings :: All )
561
+ } ,
562
+ Ok ( StringOrVecOfString :: String ( preset) ) if preset == "none" => {
563
+ Ok ( SourceItemOrderingWithinModuleItemGroupings :: None )
564
+ } ,
565
+ Ok ( StringOrVecOfString :: String ( preset) ) => Err ( de:: Error :: custom ( format ! (
566
+ "Unknown configuration option: {preset}.\n {description}"
567
+ ) ) ) ,
568
+ Ok ( StringOrVecOfString :: Vec ( groupings) ) => {
569
+ Ok ( SourceItemOrderingWithinModuleItemGroupings :: Custom ( groupings) )
570
+ } ,
571
+ Err ( e) => Err ( de:: Error :: custom ( format ! ( "{e}\n {description}" ) ) ) ,
572
+ }
573
+ }
574
+ }
575
+
576
+ impl Serialize for SourceItemOrderingWithinModuleItemGroupings {
577
+ fn serialize < S > ( & self , serializer : S ) -> Result < S :: Ok , S :: Error >
578
+ where
579
+ S : ser:: Serializer ,
580
+ {
581
+ match self {
582
+ SourceItemOrderingWithinModuleItemGroupings :: All => serializer. serialize_str ( "all" ) ,
583
+ SourceItemOrderingWithinModuleItemGroupings :: None => serializer. serialize_str ( "none" ) ,
584
+ SourceItemOrderingWithinModuleItemGroupings :: Custom ( vec) => vec. serialize ( serializer) ,
585
+ }
586
+ }
587
+ }
588
+
485
589
// these impls are never actually called but are used by the various config options that default to
486
590
// empty lists
487
591
macro_rules! unimplemented_serialize {
0 commit comments