@@ -440,11 +440,9 @@ impl Encode for Tag {
440440
441441impl DerOrd for Tag {
442442 fn der_cmp ( & self , other : & Self ) -> Result < Ordering > {
443- Ok ( self
444- . class ( )
445- . cmp ( & other. class ( ) )
446- . then_with ( || self . is_constructed ( ) . cmp ( & other. is_constructed ( ) ) )
447- . then_with ( || self . number ( ) . cmp ( & other. number ( ) ) ) )
443+ Ok ( ( self . class ( ) . cmp ( & other. class ( ) ) )
444+ . then_with ( || self . number ( ) . cmp ( & other. number ( ) ) )
445+ . then_with ( || self . is_constructed ( ) . cmp ( & other. is_constructed ( ) ) ) )
448446 }
449447}
450448
@@ -513,10 +511,12 @@ impl fmt::Debug for Tag {
513511
514512#[ cfg( test) ]
515513mod tests {
514+ use core:: cmp:: Ordering ;
515+
516516 use hex_literal:: hex;
517517
518518 use super :: { Class , Tag , TagNumber } ;
519- use crate :: { Decode , ErrorKind , Length , Reader , SliceReader } ;
519+ use crate :: { Decode , DerOrd , ErrorKind , Length , Reader , SliceReader } ;
520520
521521 #[ test]
522522 fn tag_class ( ) {
@@ -639,4 +639,93 @@ mod tests {
639639 assert_eq ! ( Tag :: peek( & reader) . unwrap( ) , Tag :: Integer ) ;
640640 assert_eq ! ( reader. position( ) , Length :: ZERO ) ; // Position unchanged
641641 }
642+
643+ #[ test]
644+ fn tag_order ( ) {
645+ // T-REC-X.680-202102
646+ // 8.6 The canonical order for tags is based on the outermost tag of each type and is defined as follows:
647+ // a) those elements or alternatives with universal class tags shall appear first, followed by those with
648+ // application class tags, followed by those with context-specific tags, followed by those with private class
649+ // tags;
650+ // b) within each class of tags, the elements or alternatives shall appear in ascending order of their tag
651+ // numbers.
652+ assert_eq ! ( Tag :: Boolean . der_cmp( & Tag :: Integer ) , Ok ( Ordering :: Less ) ) ;
653+ assert_eq ! ( Tag :: Integer . der_cmp( & Tag :: Null ) , Ok ( Ordering :: Less ) ) ;
654+ assert_eq ! ( Tag :: Null . der_cmp( & Tag :: Sequence ) , Ok ( Ordering :: Less ) ) ;
655+ assert_eq ! ( Tag :: Sequence . der_cmp( & Tag :: Ia5String ) , Ok ( Ordering :: Less ) ) ;
656+ assert_eq ! ( Tag :: Ia5String . der_cmp( & Tag :: BmpString ) , Ok ( Ordering :: Less ) ) ;
657+
658+ // universal class, then application class
659+ assert_eq ! (
660+ Tag :: BmpString . der_cmp( & Tag :: Application {
661+ constructed: true ,
662+ number: TagNumber ( 0 )
663+ } ) ,
664+ Ok ( Ordering :: Less )
665+ ) ;
666+ // ascending tag numbers
667+ assert_eq ! (
668+ Tag :: Application {
669+ constructed: true ,
670+ number: TagNumber ( 0 )
671+ }
672+ . der_cmp( & Tag :: Application {
673+ constructed: true ,
674+ number: TagNumber ( 1 )
675+ } ) ,
676+ Ok ( Ordering :: Less )
677+ ) ;
678+
679+ // ignore constructed bit
680+ assert_eq ! (
681+ Tag :: Application {
682+ constructed: true ,
683+ number: TagNumber ( 1 )
684+ }
685+ . der_cmp( & Tag :: Application {
686+ constructed: false ,
687+ number: TagNumber ( 2 )
688+ } ) ,
689+ Ok ( Ordering :: Less )
690+ ) ;
691+
692+ // for same tag numbers, order by constructed bit
693+ assert_eq ! (
694+ Tag :: Application {
695+ constructed: false ,
696+ number: TagNumber ( 2 )
697+ }
698+ . der_cmp( & Tag :: Application {
699+ constructed: true ,
700+ number: TagNumber ( 2 )
701+ } ) ,
702+ Ok ( Ordering :: Less )
703+ ) ;
704+
705+ // application class is before context-specific class
706+ assert_eq ! (
707+ Tag :: Application {
708+ constructed: true ,
709+ number: TagNumber ( 2 )
710+ }
711+ . der_cmp( & Tag :: ContextSpecific {
712+ constructed: true ,
713+ number: TagNumber ( 0 )
714+ } ) ,
715+ Ok ( Ordering :: Less )
716+ ) ;
717+
718+ // context-specific class is before private class
719+ assert_eq ! (
720+ Tag :: ContextSpecific {
721+ constructed: true ,
722+ number: TagNumber ( 10 )
723+ }
724+ . der_cmp( & Tag :: Private {
725+ constructed: true ,
726+ number: TagNumber ( 0 )
727+ } ) ,
728+ Ok ( Ordering :: Less )
729+ ) ;
730+ }
642731}
0 commit comments