@@ -427,19 +427,27 @@ impl From<&ast::Effect> for models::Effect {
427
427
}
428
428
429
429
impl From < & models:: PolicySet > for ast:: LiteralPolicySet {
430
+ // PANIC SAFETY: experimental feature
431
+ #[ allow( clippy:: expect_used) ]
430
432
fn from ( v : & models:: PolicySet ) -> Self {
431
- let templates = v. templates . iter ( ) . map ( |( key , value ) | {
433
+ let templates = v. templates . iter ( ) . map ( |tb | {
432
434
(
433
- ast:: PolicyID :: from_string ( key ) ,
434
- ast:: Template :: from ( ast:: TemplateBody :: from ( value ) ) ,
435
+ ast:: PolicyID :: from_string ( & tb . id ) ,
436
+ ast:: Template :: from ( ast:: TemplateBody :: from ( tb ) ) ,
435
437
)
436
438
} ) ;
437
439
438
- let links = v. links . iter ( ) . map ( |( key, value) | {
439
- (
440
- ast:: PolicyID :: from_string ( key) ,
441
- ast:: LiteralPolicy :: from ( value) ,
442
- )
440
+ let links = v. links . iter ( ) . map ( |p| {
441
+ // per docs in core.proto, for static policies, `link_id` is omitted/ignored,
442
+ // and the ID of the policy is the `template_id`.
443
+ let id = if p. is_template_link {
444
+ p. link_id
445
+ . as_ref ( )
446
+ . expect ( "template link should have a link_id" )
447
+ } else {
448
+ & p. template_id
449
+ } ;
450
+ ( ast:: PolicyID :: from_string ( id) , ast:: LiteralPolicy :: from ( p) )
443
451
} ) ;
444
452
445
453
Self :: new ( templates, links)
@@ -448,45 +456,16 @@ impl From<&models::PolicySet> for ast::LiteralPolicySet {
448
456
449
457
impl From < & ast:: LiteralPolicySet > for models:: PolicySet {
450
458
fn from ( v : & ast:: LiteralPolicySet ) -> Self {
451
- let templates = v
452
- . templates ( )
453
- . map ( |template| {
454
- (
455
- String :: from ( template. id ( ) . as_ref ( ) ) ,
456
- models:: TemplateBody :: from ( template) ,
457
- )
458
- } )
459
- . collect ( ) ;
460
- let links = v
461
- . policies ( )
462
- . map ( |policy| {
463
- (
464
- String :: from ( policy. id ( ) . as_ref ( ) ) ,
465
- models:: Policy :: from ( policy) ,
466
- )
467
- } )
468
- . collect ( ) ;
469
-
459
+ let templates = v. templates ( ) . map ( models:: TemplateBody :: from) . collect ( ) ;
460
+ let links = v. policies ( ) . map ( models:: Policy :: from) . collect ( ) ;
470
461
Self { templates, links }
471
462
}
472
463
}
473
464
474
465
impl From < & ast:: PolicySet > for models:: PolicySet {
475
466
fn from ( v : & ast:: PolicySet ) -> Self {
476
- let templates: HashMap < String , models:: TemplateBody > = v
477
- . all_templates ( )
478
- . map ( |t| ( String :: from ( t. id ( ) . as_ref ( ) ) , models:: TemplateBody :: from ( t) ) )
479
- . collect ( ) ;
480
- let links: HashMap < String , models:: Policy > = v
481
- . policies ( )
482
- . map ( |policy| {
483
- (
484
- String :: from ( policy. id ( ) . as_ref ( ) ) ,
485
- models:: Policy :: from ( policy) ,
486
- )
487
- } )
488
- . collect ( ) ;
489
-
467
+ let templates = v. all_templates ( ) . map ( models:: TemplateBody :: from) . collect ( ) ;
468
+ let links = v. policies ( ) . map ( models:: Policy :: from) . collect ( ) ;
490
469
Self { templates, links }
491
470
}
492
471
}
@@ -504,6 +483,39 @@ mod test {
504
483
505
484
use super :: * ;
506
485
486
+ // We add `PartialOrd` and `Ord` implementations for both `models::Policy` and
487
+ // `models::TemplateBody`, so that these can be sorted for testing purposes
488
+ impl Eq for models:: Policy { }
489
+ impl PartialOrd for models:: Policy {
490
+ fn partial_cmp ( & self , other : & Self ) -> Option < std:: cmp:: Ordering > {
491
+ Some ( self . cmp ( other) )
492
+ }
493
+ }
494
+ impl Ord for models:: Policy {
495
+ fn cmp ( & self , other : & Self ) -> std:: cmp:: Ordering {
496
+ // assumes that (link-id, template-id) pair is unique, otherwise we're
497
+ // technically violating `Ord` contract because there could exist two
498
+ // policies that return `Ordering::Equal` but are not equal with `Eq`
499
+ self . link_id ( )
500
+ . cmp ( other. link_id ( ) )
501
+ . then_with ( || self . template_id . cmp ( & other. template_id ) )
502
+ }
503
+ }
504
+ impl Eq for models:: TemplateBody { }
505
+ impl PartialOrd for models:: TemplateBody {
506
+ fn partial_cmp ( & self , other : & Self ) -> Option < std:: cmp:: Ordering > {
507
+ Some ( self . cmp ( other) )
508
+ }
509
+ }
510
+ impl Ord for models:: TemplateBody {
511
+ fn cmp ( & self , other : & Self ) -> std:: cmp:: Ordering {
512
+ // assumes that IDs are unique, otherwise we're technically violating
513
+ // `Ord` contract because there could exist two template-bodies that
514
+ // return `Ordering::Equal` but are not equal with `Eq`
515
+ self . id . cmp ( & other. id )
516
+ }
517
+ }
518
+
507
519
#[ test]
508
520
#[ allow( clippy:: too_many_lines) ]
509
521
fn policy_roundtrip ( ) {
@@ -739,10 +751,17 @@ mod test {
739
751
) ] ) ,
740
752
)
741
753
. unwrap ( ) ;
742
- let mps = models:: PolicySet :: from ( & ps) ;
743
- let mps_roundtrip = models:: PolicySet :: from ( & ast:: LiteralPolicySet :: from ( & mps) ) ;
754
+ let mut mps = models:: PolicySet :: from ( & ps) ;
755
+ let mut mps_roundtrip = models:: PolicySet :: from ( & ast:: LiteralPolicySet :: from ( & mps) ) ;
756
+
757
+ // we accept permutations as equivalent, so before comparison, we sort
758
+ // both `.templates` and `.links`
759
+ mps. templates . sort ( ) ;
760
+ mps_roundtrip. templates . sort ( ) ;
761
+ mps. links . sort ( ) ;
762
+ mps_roundtrip. links . sort ( ) ;
744
763
745
- // Can't compare LiteralPolicySets directly, so we compare their fields
764
+ // Can't compare `models::PolicySet` directly, so we compare their fields
746
765
assert_eq ! ( mps. templates, mps_roundtrip. templates) ;
747
766
assert_eq ! ( mps. links, mps_roundtrip. links) ;
748
767
}
@@ -802,8 +821,15 @@ mod test {
802
821
) ] ) ,
803
822
)
804
823
. unwrap ( ) ;
805
- let mps = models:: PolicySet :: from ( & ps) ;
806
- let mps_roundtrip = models:: PolicySet :: from ( & ast:: LiteralPolicySet :: from ( & mps) ) ;
824
+ let mut mps = models:: PolicySet :: from ( & ps) ;
825
+ let mut mps_roundtrip = models:: PolicySet :: from ( & ast:: LiteralPolicySet :: from ( & mps) ) ;
826
+
827
+ // we accept permutations as equivalent, so before comparison, we sort
828
+ // both `.templates` and `.links`
829
+ mps. templates . sort ( ) ;
830
+ mps_roundtrip. templates . sort ( ) ;
831
+ mps. links . sort ( ) ;
832
+ mps_roundtrip. links . sort ( ) ;
807
833
808
834
// Can't compare `models::PolicySet` directly, so we compare their fields
809
835
assert_eq ! ( mps. templates, mps_roundtrip. templates) ;
0 commit comments