@@ -63,14 +63,27 @@ struct CatalystIdInner {
6363 /// - `true`: The key is used for encryption.
6464 /// - `false`: The key is used for signing (signature key).
6565 encryption : bool ,
66- /// Indicates if this is an `id` type, or a `uri` type.
66+ /// Indicates if this is an `id` type, or a `uri` type o .
6767 /// Used by the serialization functions.
6868 /// `true` = format as an `Id`
6969 /// `false` = format as a `Uri`
70- id : bool ,
70+ r#type : CatalysIdType ,
71+ }
72+
73+ #[ derive( Debug , Clone , Default ) ]
74+ enum CatalysIdType {
75+ /// format as an `Id`
76+ Id ,
77+ /// format as a `Uri`
78+ #[ default]
79+ Uri ,
80+ /// format as a admin `Uri`
81+ AdminUri ,
7182}
7283
7384impl CatalystId {
85+ /// Admin URI scheme for Catalyst
86+ pub const ADMIN_SCHEME : & Scheme = Scheme :: new_or_panic ( "admin.catalyst" ) ;
7487 /// Encryption Key Identifier Fragment
7588 const ENCRYPTION_FRAGMENT : & EStr < Fragment > = EStr :: new_or_panic ( "encrypt" ) ;
7689 /// Maximum allowable Nonce Value
@@ -140,7 +153,7 @@ impl CatalystId {
140153 role : RoleId :: default ( ) , // Defaulted, use `with_role()` to change it.
141154 rotation : KeyRotation :: default ( ) , // Defaulted, use `with_rotation()` to change it.
142155 encryption : false , // Defaulted, use `with_encryption()` to change it.
143- id : false , // Default to `URI` formatted.
156+ r#type : CatalysIdType :: default ( ) , // Default to `URI` formatted.
144157 } ) ;
145158
146159 Self { inner }
@@ -150,28 +163,51 @@ impl CatalystId {
150163 #[ must_use]
151164 pub fn as_uri ( self ) -> Self {
152165 let inner = Arc :: try_unwrap ( self . inner ) . unwrap_or_else ( |v| ( * v) . clone ( ) ) ;
153- let inner = Arc :: new ( CatalystIdInner { id : false , ..inner } ) ;
166+ let inner = Arc :: new ( CatalystIdInner {
167+ r#type : CatalysIdType :: Uri ,
168+ ..inner
169+ } ) ;
154170 Self { inner }
155171 }
156172
157173 /// The `CatalystId` is formatted as a id.
158174 #[ must_use]
159175 pub fn as_id ( self ) -> Self {
160176 let inner = Arc :: try_unwrap ( self . inner ) . unwrap_or_else ( |v| ( * v) . clone ( ) ) ;
161- let inner = Arc :: new ( CatalystIdInner { id : true , ..inner } ) ;
177+ let inner = Arc :: new ( CatalystIdInner {
178+ r#type : CatalysIdType :: Id ,
179+ ..inner
180+ } ) ;
181+ Self { inner }
182+ }
183+
184+ /// The `CatalystId` is formatted as a admin URI.
185+ #[ must_use]
186+ pub fn as_admin ( self ) -> Self {
187+ let inner = Arc :: try_unwrap ( self . inner ) . unwrap_or_else ( |v| ( * v) . clone ( ) ) ;
188+ let inner = Arc :: new ( CatalystIdInner {
189+ r#type : CatalysIdType :: AdminUri ,
190+ ..inner
191+ } ) ;
162192 Self { inner }
163193 }
164194
165195 /// Was `CatalystId` formatted as an id when it was parsed.
166196 #[ must_use]
167197 pub fn is_id ( & self ) -> bool {
168- self . inner . id
198+ matches ! ( self . inner. r#type, CatalysIdType :: Id )
199+ }
200+
201+ /// Is `CatalystId` formatted as an Admin.
202+ #[ must_use]
203+ pub fn is_admin ( & self ) -> bool {
204+ matches ! ( self . inner. r#type, CatalysIdType :: AdminUri )
169205 }
170206
171207 /// Was `CatalystId` formatted as an uri when it was parsed.
172208 #[ must_use]
173209 pub fn is_uri ( & self ) -> bool {
174- ! self . inner . id
210+ matches ! ( self . inner. r#type , CatalysIdType :: Uri )
175211 }
176212
177213 /// Add or change the username in a Catalyst ID URI.
@@ -588,27 +624,26 @@ impl FromStr for CatalystId {
588624 /// This will parse a URI or a RAW ID.\
589625 /// The only difference between them is a URI has the scheme, a raw ID does not.
590626 fn from_str ( s : & str ) -> Result < Self , Self :: Err > {
591- // Did we serialize an ID?
592- let mut id = false ;
593-
594- // Check if we have a scheme, and if not default it to the catalyst ID scheme.
595- let raw_uri = {
627+ let ( uri, r#type) = {
596628 if s. contains ( "://" ) {
597- s. to_owned ( )
629+ let uri = Uri :: parse ( s. to_owned ( ) ) ?;
630+ // Check if its the correct scheme.
631+ let r#type = if uri. scheme ( ) == Self :: SCHEME {
632+ CatalysIdType :: Uri
633+ } else if uri. scheme ( ) == Self :: ADMIN_SCHEME {
634+ CatalysIdType :: AdminUri
635+ } else {
636+ return Err ( errors:: CatalystIdError :: InvalidScheme ) ;
637+ } ;
638+ ( uri, r#type)
598639 } else {
599- id = true ;
600640 // It might be a RAW ID, so try and parse with the correct scheme.
601- format ! ( "{}://{}" , CatalystId :: SCHEME , s)
641+ let uri = Uri :: parse ( format ! ( "{}://{}" , Self :: SCHEME , s) ) ?;
642+ let r#type = CatalysIdType :: Id ;
643+ ( uri, r#type)
602644 }
603645 } ;
604646
605- let uri = Uri :: parse ( raw_uri) ?;
606-
607- // Check if its the correct scheme.
608- if uri. scheme ( ) != CatalystId :: SCHEME {
609- return Err ( errors:: CatalystIdError :: InvalidScheme ) ;
610- }
611-
612647 // Decode the network and subnet
613648 let auth = uri
614649 . authority ( )
@@ -684,36 +719,26 @@ impl FromStr for CatalystId {
684719 }
685720 } ;
686721
687- let cat_id = {
688- let mut cat_id = Self :: new ( network, subnet, role0_pk)
689- . with_role ( role_index)
690- . with_rotation ( rotation) ;
691-
692- if uri. has_fragment ( ) {
693- if uri. fragment ( ) == Some ( Self :: ENCRYPTION_FRAGMENT ) {
694- cat_id = cat_id. with_encryption ( ) ;
695- } else {
696- return Err ( errors:: CatalystIdError :: InvalidEncryptionKeyFragment ) ;
697- }
698- }
699-
700- if let Some ( username) = username {
701- cat_id = cat_id. with_username ( & username) ;
702- }
703-
704- if let Some ( nonce) = nonce {
705- cat_id = cat_id. with_specific_nonce ( nonce) ;
706- }
707-
708- // Default to URI, so only set it as an ID if its not a URI.
709- if id {
710- cat_id = cat_id. as_id ( ) ;
711- }
712-
713- cat_id
722+ let encryption = match uri. fragment ( ) {
723+ None => false ,
724+ Some ( f) if f == Self :: ENCRYPTION_FRAGMENT => true ,
725+ Some ( _) => return Err ( errors:: CatalystIdError :: InvalidEncryptionKeyFragment ) ,
714726 } ;
715727
716- Ok ( cat_id)
728+ let inner = CatalystIdInner {
729+ network : network. to_string ( ) ,
730+ subnet : subnet. map ( ToString :: to_string) ,
731+ role0_pk,
732+ r#type,
733+ rotation,
734+ role : role_index,
735+ username,
736+ nonce,
737+ encryption,
738+ }
739+ . into ( ) ;
740+
741+ Ok ( Self { inner } )
717742 }
718743}
719744
@@ -722,8 +747,10 @@ impl Display for CatalystId {
722747 & self ,
723748 f : & mut Formatter < ' _ > ,
724749 ) -> Result < ( ) , std:: fmt:: Error > {
725- if !self . inner . id {
726- write ! ( f, "{}://" , Self :: SCHEME . as_str( ) ) ?;
750+ match self . inner . r#type {
751+ CatalysIdType :: Uri => write ! ( f, "{}://" , Self :: SCHEME . as_str( ) ) ?,
752+ CatalysIdType :: AdminUri => write ! ( f, "{}://" , Self :: ADMIN_SCHEME . as_str( ) ) ?,
753+ CatalysIdType :: Id => { } ,
727754 }
728755
729756 let mut needs_at = false ;
@@ -754,9 +781,9 @@ impl Display for CatalystId {
754781 ) ?;
755782
756783 // Role and Rotation are only serialized if its NOT and ID or they are not the defaults.
757- if !self . inner . role . is_default ( ) || !self . inner . rotation . is_default ( ) || !self . inner . id {
784+ if !self . inner . role . is_default ( ) || !self . inner . rotation . is_default ( ) || !self . is_id ( ) {
758785 write ! ( f, "/{}" , self . inner. role) ?;
759- if !self . inner . rotation . is_default ( ) || !self . inner . id {
786+ if !self . inner . rotation . is_default ( ) || !self . is_id ( ) {
760787 write ! ( f, "/{}" , self . inner. rotation) ?;
761788 }
762789 }
0 commit comments