Skip to main content

sequoia_openpgp/packet/key/
conversions.rs

1//! Conversion functions for `Key` and associated types.
2
3use std::convert::TryFrom;
4
5use crate::Error;
6use crate::cert::prelude::*;
7use crate::packet::prelude::*;
8use crate::packet::key::{
9    KeyParts,
10    KeyRole,
11    PrimaryRole,
12    PublicParts,
13    SubordinateRole,
14    SecretParts,
15    UnspecifiedParts,
16    UnspecifiedRole
17};
18use crate::Result;
19
20macro_rules! convert {
21    ( $x:ident ) => {
22        // XXX: This is ugly, but how can we do better?
23        { // XXX: Appease rustc 1.80.1 which doesn't like annotations on expressions.
24        #[allow(clippy::missing_transmute_annotations)]
25        unsafe { std::mem::transmute($x) }
26        }
27    }
28}
29
30macro_rules! convert_ref {
31    ( $x:ident ) => {
32        // XXX: This is ugly, but how can we do better?
33        #[allow(clippy::missing_transmute_annotations)]
34        unsafe { std::mem::transmute($x) }
35    }
36}
37
38// Make it possible to go from an arbitrary Key<P, R> to an
39// arbitrary Key<P', R'> (or &Key<P, R> to &Key<P', R'>) in a
40// single .into().
41//
42// To allow the programmer to make the intent clearer, also
43// provide explicit conversion function.
44
45// In principle, this is as easy as the following:
46//
47//     impl<P, P2, R, R2> From<Key<P, R>> for Key<P2, R2>
48//         where P: KeyParts, P2: KeyParts, R: KeyRole, R2: KeyRole
49//     {
50//         fn from(p: Key<P, R>) -> Self {
51//             unimplemented!()
52//         }
53//     }
54//
55// But that results in:
56//
57//     error[E0119]: conflicting implementations of trait `std::convert::From<packet::Key<_, _>>` for type `packet::Key<_, _>`:
58//     = note: conflicting implementation in crate `core`:
59//             - impl<T> std::convert::From<T> for T;
60//
61// Unfortunately, it's not enough to make one type variable
62// concrete, as the following errors demonstrate:
63//
64//     error[E0119]: conflicting implementations of trait `std::convert::From<packet::Key<packet::key::PublicParts, _>>` for type `packet::Key<packet::key::PublicParts, _>`:
65//     ...
66//         = note: conflicting implementation in crate `core`:
67//                 - impl<T> std::convert::From<T> for T;
68//
69//     impl<P, R, R2> From<Key<P, R>> for Key<PublicParts, R2>
70//         where P: KeyParts, R: KeyRole, R2: KeyRole
71//     {
72//         fn from(p: Key<P, R>) -> Self {
73//             unimplemented!()
74//         }
75//     }
76//
77//   error[E0119]: conflicting implementations of trait `std::convert::From<packet::Key<packet::key::PublicParts, _>>` for type `packet::Key<packet::key::PublicParts, _>`:
78//      --> openpgp/src/packet/key.rs:186:5
79//   ...
80//       = note: conflicting implementation in crate `core`:
81//               - impl<T> std::convert::From<T> for T;
82//   impl<P2, R, R2> From<Key<PublicParts, R>> for Key<P2, R2>
83//       where P2: KeyParts, R: KeyRole, R2: KeyRole
84//   {
85//       fn from(p: Key<PublicParts, R>) -> Self {
86//           unimplemented!()
87//       }
88//   }
89//
90// To solve this, we need at least one generic variable to be
91// concrete on both sides of the `From`.
92
93macro_rules! create_part_conversions {
94    ( $Key:ident<$( $l:lifetime ),*; $( $g:ident ),*>) => {
95        create_part_conversions!($Key<$($l),*; $($g),*> where );
96    };
97    ( $Key:ident<$( $l:lifetime ),*; $( $g:ident ),*> where $( $w:ident: $c:path ),* ) => {
98        // Convert between two KeyParts for a constant KeyRole.
99        // Unfortunately, we can't let the KeyRole vary as otherwise we
100        // get conflicting types when we do the same to convert between
101        // two KeyRoles for a constant KeyParts. :(
102        macro_rules! p {
103            ( <$from_parts:ty> -> <$to_parts:ty> ) => {
104                impl<$($l, )* $($g, )* > From<$Key<$($l, )* $from_parts, $($g, )* >> for $Key<$($l, )* $to_parts, $($g, )* >
105                    where $($w: $c ),*
106                {
107                    fn from(p: $Key<$($l, )* $from_parts, $($g, )* >) -> Self {
108                        convert!(p)
109                    }
110                }
111
112                impl<$($l, )* $($g, )* > From<&$($l)* $Key<$($l, )* $from_parts, $($g, )* >> for &$($l)* $Key<$($l, )* $to_parts, $($g, )* >
113                    where $($w: $c ),*
114                {
115                    fn from(p: &$($l)* $Key<$($l, )* $from_parts, $($g, )* >) -> Self {
116                        convert_ref!(p)
117                    }
118                }
119
120                impl<$($l, )* $($g, )* > From<&$($l)* mut $Key<$($l, )* $from_parts, $($g, )* >> for &$($l)* mut $Key<$($l, )* $to_parts, $($g, )* >
121                    where $($w: $c ),*
122                {
123                    fn from(p: &$($l)* mut $Key<$($l, )* $from_parts, $($g, )* >) -> Self {
124                        convert_ref!(p)
125                    }
126                }
127            }
128        }
129
130        // Likewise, but using TryFrom.
131        macro_rules! p_try {
132            ( <$from_parts:ty> -> <$to_parts:ty>) => {
133                impl<$($l, )* $($g, )* > TryFrom<$Key<$($l, )* $from_parts, $($g, )* >> for $Key<$($l, )* $to_parts, $($g, )* >
134                    where $($w: $c ),*
135                {
136                    type Error = anyhow::Error;
137                    fn try_from(p: $Key<$($l, )* $from_parts, $($g, )* >) -> Result<Self> {
138                        p.parts_into_secret()
139                    }
140                }
141
142                impl<$($l, )* $($g, )* > TryFrom<&$($l)* $Key<$($l, )* $from_parts, $($g, )* >> for &$($l)* $Key<$($l, )* $to_parts, $($g, )* >
143                    where $($w: $c ),*
144                {
145                    type Error = anyhow::Error;
146                    fn try_from(p: &$($l)* $Key<$($l, )* $from_parts, $($g, )* >) -> Result<Self> {
147                        if p.has_secret() {
148                            Ok(convert_ref!(p))
149                        } else {
150                            Err(Error::InvalidArgument("No secret key".into())
151                                .into())
152                        }
153                    }
154                }
155
156                impl<$($l, )* $($g, )* > TryFrom<&$($l)* mut $Key<$($l, )* $from_parts, $($g, )* >> for &$($l)* mut $Key<$($l, )* $to_parts, $($g, )* >
157                    where $($w: $c ),*
158                {
159                    type Error = anyhow::Error;
160                    fn try_from(p: &$($l)* mut $Key<$($l, )* $from_parts, $($g, )* >) -> Result<Self> {
161                        if p.has_secret() {
162                            Ok(convert_ref!(p))
163                        } else {
164                            Err(Error::InvalidArgument("No secret key".into())
165                                .into())
166                        }
167                    }
168                }
169            }
170        }
171
172
173        p_try!(<PublicParts> -> <SecretParts>);
174        p!(<PublicParts> -> <UnspecifiedParts>);
175
176        p!(<SecretParts> -> <PublicParts>);
177        p!(<SecretParts> -> <UnspecifiedParts>);
178
179        p!(<UnspecifiedParts> -> <PublicParts>);
180        p_try!(<UnspecifiedParts> -> <SecretParts>);
181
182
183        impl<$($l, )* P, $($g, )*> $Key<$($l, )* P, $($g, )*> where P: KeyParts, $($w: $c ),*
184        {
185            /// Changes the key's parts tag to `PublicParts`.
186            pub fn parts_into_public(self) -> $Key<$($l, )* PublicParts, $($g, )*> {
187                // Ideally, we'd use self.into() to do the actually
188                // conversion.  But, because P is not concrete, we get the
189                // following error:
190                //
191                //     error[E0277]: the trait bound `packet::Key<packet::key::PublicParts, R>: std::convert::From<packet::Key<P, R>>` is not satisfied
192                //        --> openpgp/src/packet/key.rs:401:18
193                //         |
194                //     401 |             self.into()
195                //         |                  ^^^^ the trait `std::convert::From<packet::Key<P, R>>` is not implemented for `packet::Key<packet::key::PublicParts, R>`
196                //         |
197                //         = help: consider adding a `where packet::Key<packet::key::PublicParts, R>: std::convert::From<packet::Key<P, R>>` bound
198                //         = note: required because of the requirements on the impl of `std::convert::Into<packet::Key<packet::key::PublicParts, R>>` for `packet::Key<P, R>`
199                //
200                // But we can't implement implement `From<Key<P, R>>` for
201                // `Key<PublicParts, R>`, because that conflicts with a
202                // standard conversion!  (See the comment for the `p`
203                // macro above.)
204                //
205                // Adding the trait bound is annoying, because then we'd
206                // have to add it everywhere that we use into.
207                convert!(self)
208            }
209
210            /// Changes the key's parts tag to `PublicParts`.
211            pub fn parts_as_public(&$($l)* self) -> &$($l)* $Key<$($l, )* PublicParts, $($g, )*> {
212                convert_ref!(self)
213            }
214
215            /// Changes the key's parts tag to `PublicParts`.
216            pub fn parts_as_public_mut(&$($l)* mut self) -> &$($l)* mut $Key<$($l, )* PublicParts, $($g, )*> {
217                convert_ref!(self)
218            }
219
220            /// Changes the key's parts tag to `SecretParts`.
221            pub fn parts_into_secret(self) -> Result<$Key<$($l, )* SecretParts, $($g, )*>> {
222                if self.has_secret() {
223                    Ok(convert!(self))
224                } else {
225                    Err(Error::InvalidArgument("No secret key".into()).into())
226                }
227            }
228
229            /// Changes the key's parts tag to `SecretParts`.
230            pub fn parts_as_secret(&$($l)* self) -> Result<&$($l)* $Key<$($l, )* SecretParts, $($g, )*>>
231            {
232                if self.has_secret() {
233                    Ok(convert_ref!(self))
234                } else {
235                    Err(Error::InvalidArgument("No secret key".into()).into())
236                }
237            }
238
239            /// Changes the key's parts tag to `SecretParts`.
240            pub fn parts_as_secret_mut(&$($l)* mut self) -> Result<&$($l)* mut $Key<$($l, )* SecretParts, $($g, )*>>
241            {
242                if self.has_secret() {
243                    Ok(convert_ref!(self))
244                } else {
245                    Err(Error::InvalidArgument("No secret key".into()).into())
246                }
247            }
248
249            /// Changes the key's parts tag to `UnspecifiedParts`.
250            pub fn parts_into_unspecified(self) -> $Key<$($l, )* UnspecifiedParts, $($g, )*> {
251                convert!(self)
252            }
253
254            /// Changes the key's parts tag to `UnspecifiedParts`.
255            pub fn parts_as_unspecified(&$($l)* self) -> &$($l)* $Key<$($l, )* UnspecifiedParts, $($g, )*> {
256                convert_ref!(self)
257            }
258
259            /// Changes the key's parts tag to `UnspecifiedParts`.
260            pub fn parts_as_unspecified_mut(&$($l)* mut self) -> &$($l)* mut $Key<$($l, )* UnspecifiedParts, $($g, )*> {
261                convert_ref!(self)
262            }
263        }
264    }
265}
266
267macro_rules! create_role_conversions {
268    ( $Key:ident<$( $l:lifetime ),*> ) => {
269        // Convert between two KeyRoles for a constant KeyParts.  See
270        // the comment for the p macro above.
271        macro_rules! r {
272            ( <$from_role:ty> -> <$to_role:ty>) => {
273                impl<$($l, )* P> From<$Key<$($l, )* P, $from_role>> for $Key<$($l, )* P, $to_role>
274                    where P: KeyParts
275                {
276                    fn from(p: $Key<$($l, )* P, $from_role>) -> Self {
277                        let mut k: Self = convert!(p);
278                        k.set_role(<$to_role>::role());
279                        k
280                    }
281                }
282
283                impl<$($l, )* P> From<&$($l)* $Key<$($l, )* P, $from_role>> for &$($l)* $Key<$($l, )* P, $to_role>
284                    where P: KeyParts
285                {
286                    fn from(p: &$($l)* $Key<$($l, )* P, $from_role>) -> Self {
287                        convert_ref!(p)
288                    }
289                }
290
291                impl<$($l, )* P> From<&$($l)* mut $Key<$($l, )* P, $from_role>> for &$($l)* mut $Key<$($l, )* P, $to_role>
292                    where P: KeyParts
293                {
294                    fn from(p: &$($l)* mut $Key<$($l, )* P, $from_role>) -> Self {
295                        convert_ref!(p)
296                    }
297                }
298            }
299        }
300
301        r!(<PrimaryRole> -> <SubordinateRole>);
302        r!(<PrimaryRole> -> <UnspecifiedRole>);
303
304        r!(<SubordinateRole> -> <PrimaryRole>);
305        r!(<SubordinateRole> -> <UnspecifiedRole>);
306
307        r!(<UnspecifiedRole> -> <PrimaryRole>);
308        r!(<UnspecifiedRole> -> <SubordinateRole>);
309    }
310}
311
312macro_rules! create_conversions {
313    ( $Key:ident ) => {
314        create_conversions!(@ $Key);
315    };
316    ( $Key:ident < $( $l:lifetime ),* > ) => {
317        create_conversions!(@ $Key $( $l ),*);
318    };
319    ( @ $Key:ident $( $l:lifetime ),* ) => {
320        create_part_conversions!($Key<$($l ),* ; R> where R: KeyRole);
321        create_role_conversions!($Key<$($l ),* >);
322
323        // We now handle converting both the part and the role at the same
324        // time.
325
326        macro_rules! f {
327            ( <$from_parts:ty, $from_role:ty> -> <$to_parts:ty, $to_role:ty> ) => {
328                impl<$($l ),*> From<$Key<$($l, )* $from_parts, $from_role>> for $Key<$($l, )* $to_parts, $to_role>
329                {
330                    fn from(p: $Key<$($l, )* $from_parts, $from_role>) -> Self {
331                        let mut k: Self = convert!(p);
332                        k.set_role(<$to_role>::role());
333                        k
334                    }
335                }
336
337                impl<$($l ),*> From<&$($l)* $Key<$($l, )* $from_parts, $from_role>> for &$($l)* $Key<$($l, )* $to_parts, $to_role>
338                {
339                    fn from(p: &$($l)* $Key<$from_parts, $from_role>) -> Self {
340                        convert_ref!(p)
341                    }
342                }
343
344                impl<$($l ),*> From<&$($l)* mut $Key<$($l, )* $from_parts, $from_role>> for &$($l)* mut $Key<$($l, )* $to_parts, $to_role>
345                {
346                    fn from(p: &$($l)* mut $Key<$from_parts, $from_role>) -> Self {
347                        convert_ref!(p)
348                    }
349                }
350            }
351        }
352
353        macro_rules! f_try {
354            ( <$from_parts:ty, $from_role:ty> -> <SecretParts, $to_role:ty> ) => {
355                impl<$($l ),*> TryFrom<$Key<$($l, )* $from_parts, $from_role>> for $Key<$($l, )* SecretParts, $to_role>
356                {
357                    type Error = anyhow::Error;
358                    fn try_from(p: $Key<$($l, )* $from_parts, $from_role>) -> Result<Self> {
359                        // First, just change the role.
360                        let mut k: $Key<$($l, )* $from_parts, $to_role> = p.into();
361                        k.set_role(<$to_role>::role());
362                        // Now change the parts.
363                        k.try_into()
364                    }
365                }
366
367                impl<$($l ),*> TryFrom<&$($l)* $Key<$($l, )* $from_parts, $from_role>> for &$($l)* $Key<$($l, )* SecretParts, $to_role>
368                {
369                    type Error = anyhow::Error;
370                    fn try_from(p: &$($l)* $Key<$($l, )* $from_parts, $from_role>) -> Result<Self> {
371                        // First, just change the role.
372                        let k: &$($l)* $Key<$($l, )* $from_parts, $to_role> = p.into();
373                        // Now change the parts.
374                        k.try_into()
375                    }
376                }
377
378                impl<$($l ),*> TryFrom<&$($l)* mut $Key<$($l, )* $from_parts, $from_role>> for &$($l)* mut $Key<$($l, )* SecretParts, $to_role>
379                {
380                    type Error = anyhow::Error;
381                    fn try_from(p: &$($l)* mut $Key<$($l, )* $from_parts, $from_role>) -> Result<Self> {
382                        // First, just change the role.
383                        let k: &$($l)* mut $Key<$($l, )* $from_parts, $to_role> = p.into();
384                        // Now change the parts.
385                        k.try_into()
386                    }
387                }
388            }
389        }
390
391        // The calls that are comment out are the calls for the
392        // combinations where either the KeyParts or the KeyRole does not
393        // change.
394
395        //f!(<PublicParts, PrimaryRole> -> <PublicParts, PrimaryRole>);
396        //f!(<PublicParts, PrimaryRole> -> <PublicParts, SubordinateRole>);
397        //f!(<PublicParts, PrimaryRole> -> <PublicParts, UnspecifiedRole>);
398        //f!(<PublicParts, PrimaryRole> -> <SecretParts, PrimaryRole>);
399        f_try!(<PublicParts, PrimaryRole> -> <SecretParts, SubordinateRole>);
400        f_try!(<PublicParts, PrimaryRole> -> <SecretParts, UnspecifiedRole>);
401        //f!(<PublicParts, PrimaryRole> -> <UnspecifiedParts, PrimaryRole>);
402        f!(<PublicParts, PrimaryRole> -> <UnspecifiedParts, SubordinateRole>);
403        f!(<PublicParts, PrimaryRole> -> <UnspecifiedParts, UnspecifiedRole>);
404
405        //f!(<PublicParts, SubordinateRole> -> <PublicParts, PrimaryRole>);
406        //f!(<PublicParts, SubordinateRole> -> <PublicParts, SubordinateRole>);
407        //f!(<PublicParts, SubordinateRole> -> <PublicParts, UnspecifiedRole>);
408        f_try!(<PublicParts, SubordinateRole> -> <SecretParts, PrimaryRole>);
409        //f!(<PublicParts, SubordinateRole> -> <SecretParts, SubordinateRole>);
410        f_try!(<PublicParts, SubordinateRole> -> <SecretParts, UnspecifiedRole>);
411        f!(<PublicParts, SubordinateRole> -> <UnspecifiedParts, PrimaryRole>);
412        //f!(<PublicParts, SubordinateRole> -> <UnspecifiedParts, SubordinateRole>);
413        f!(<PublicParts, SubordinateRole> -> <UnspecifiedParts, UnspecifiedRole>);
414
415        //f!(<PublicParts, UnspecifiedRole> -> <PublicParts, PrimaryRole>);
416        //f!(<PublicParts, UnspecifiedRole> -> <PublicParts, SubordinateRole>);
417        //f!(<PublicParts, UnspecifiedRole> -> <PublicParts, UnspecifiedRole>);
418        f_try!(<PublicParts, UnspecifiedRole> -> <SecretParts, PrimaryRole>);
419        f_try!(<PublicParts, UnspecifiedRole> -> <SecretParts, SubordinateRole>);
420        //f!(<PublicParts, UnspecifiedRole> -> <SecretParts, UnspecifiedRole>);
421        f!(<PublicParts, UnspecifiedRole> -> <UnspecifiedParts, PrimaryRole>);
422        f!(<PublicParts, UnspecifiedRole> -> <UnspecifiedParts, SubordinateRole>);
423        //f!(<PublicParts, UnspecifiedRole> -> <UnspecifiedParts, UnspecifiedRole>);
424
425        //f!(<SecretParts, PrimaryRole> -> <PublicParts, PrimaryRole>);
426        f!(<SecretParts, PrimaryRole> -> <PublicParts, SubordinateRole>);
427        f!(<SecretParts, PrimaryRole> -> <PublicParts, UnspecifiedRole>);
428        //f!(<SecretParts, PrimaryRole> -> <SecretParts, PrimaryRole>);
429        //f!(<SecretParts, PrimaryRole> -> <SecretParts, SubordinateRole>);
430        //f!(<SecretParts, PrimaryRole> -> <SecretParts, UnspecifiedRole>);
431        //f!(<SecretParts, PrimaryRole> -> <UnspecifiedParts, PrimaryRole>);
432        f!(<SecretParts, PrimaryRole> -> <UnspecifiedParts, SubordinateRole>);
433        f!(<SecretParts, PrimaryRole> -> <UnspecifiedParts, UnspecifiedRole>);
434
435        f!(<SecretParts, SubordinateRole> -> <PublicParts, PrimaryRole>);
436        //f!(<SecretParts, SubordinateRole> -> <PublicParts, SubordinateRole>);
437        f!(<SecretParts, SubordinateRole> -> <PublicParts, UnspecifiedRole>);
438        //f!(<SecretParts, SubordinateRole> -> <SecretParts, PrimaryRole>);
439        //f!(<SecretParts, SubordinateRole> -> <SecretParts, SubordinateRole>);
440        //f!(<SecretParts, SubordinateRole> -> <SecretParts, UnspecifiedRole>);
441        f!(<SecretParts, SubordinateRole> -> <UnspecifiedParts, PrimaryRole>);
442        //f!(<SecretParts, SubordinateRole> -> <UnspecifiedParts, SubordinateRole>);
443        f!(<SecretParts, SubordinateRole> -> <UnspecifiedParts, UnspecifiedRole>);
444
445        f!(<SecretParts, UnspecifiedRole> -> <PublicParts, PrimaryRole>);
446        f!(<SecretParts, UnspecifiedRole> -> <PublicParts, SubordinateRole>);
447        //f!(<SecretParts, UnspecifiedRole> -> <PublicParts, UnspecifiedRole>);
448        //f!(<SecretParts, UnspecifiedRole> -> <SecretParts, PrimaryRole>);
449        //f!(<SecretParts, UnspecifiedRole> -> <SecretParts, SubordinateRole>);
450        //f!(<SecretParts, UnspecifiedRole> -> <SecretParts, UnspecifiedRole>);
451        f!(<SecretParts, UnspecifiedRole> -> <UnspecifiedParts, PrimaryRole>);
452        f!(<SecretParts, UnspecifiedRole> -> <UnspecifiedParts, SubordinateRole>);
453        //f!(<SecretParts, UnspecifiedRole> -> <UnspecifiedParts, UnspecifiedRole>);
454
455        //f!(<UnspecifiedParts, PrimaryRole> -> <PublicParts, PrimaryRole>);
456        f!(<UnspecifiedParts, PrimaryRole> -> <PublicParts, SubordinateRole>);
457        f!(<UnspecifiedParts, PrimaryRole> -> <PublicParts, UnspecifiedRole>);
458        //f!(<UnspecifiedParts, PrimaryRole> -> <SecretParts, PrimaryRole>);
459        f_try!(<UnspecifiedParts, PrimaryRole> -> <SecretParts, SubordinateRole>);
460        f_try!(<UnspecifiedParts, PrimaryRole> -> <SecretParts, UnspecifiedRole>);
461        //f!(<UnspecifiedParts, PrimaryRole> -> <UnspecifiedParts, PrimaryRole>);
462        //f!(<UnspecifiedParts, PrimaryRole> -> <UnspecifiedParts, SubordinateRole>);
463        //f!(<UnspecifiedParts, PrimaryRole> -> <UnspecifiedParts, UnspecifiedRole>);
464
465        f!(<UnspecifiedParts, SubordinateRole> -> <PublicParts, PrimaryRole>);
466        //f!(<UnspecifiedParts, SubordinateRole> -> <PublicParts, SubordinateRole>);
467        f!(<UnspecifiedParts, SubordinateRole> -> <PublicParts, UnspecifiedRole>);
468        f_try!(<UnspecifiedParts, SubordinateRole> -> <SecretParts, PrimaryRole>);
469        //f!(<UnspecifiedParts, SubordinateRole> -> <SecretParts, SubordinateRole>);
470        f_try!(<UnspecifiedParts, SubordinateRole> -> <SecretParts, UnspecifiedRole>);
471        //f!(<UnspecifiedParts, SubordinateRole> -> <UnspecifiedParts, PrimaryRole>);
472        //f!(<UnspecifiedParts, SubordinateRole> -> <UnspecifiedParts, SubordinateRole>);
473        //f!(<UnspecifiedParts, SubordinateRole> -> <UnspecifiedParts, UnspecifiedRole>);
474
475        f!(<UnspecifiedParts, UnspecifiedRole> -> <PublicParts, PrimaryRole>);
476        f!(<UnspecifiedParts, UnspecifiedRole> -> <PublicParts, SubordinateRole>);
477        //f!(<UnspecifiedParts, UnspecifiedRole> -> <PublicParts, UnspecifiedRole>);
478        f_try!(<UnspecifiedParts, UnspecifiedRole> -> <SecretParts, PrimaryRole>);
479        f_try!(<UnspecifiedParts, UnspecifiedRole> -> <SecretParts, SubordinateRole>);
480        //f!(<UnspecifiedParts, UnspecifiedRole> -> <SecretParts, UnspecifiedRole>);
481        //f!(<UnspecifiedParts, UnspecifiedRole> -> <UnspecifiedParts, PrimaryRole>);
482        //f!(<UnspecifiedParts, UnspecifiedRole> -> <UnspecifiedParts, SubordinateRole>);
483        //f!(<UnspecifiedParts, UnspecifiedRole> -> <UnspecifiedParts, UnspecifiedRole>);
484
485
486        impl<$($l, )* P, R> $Key<$($l, )* P, R> where P: KeyParts, R: KeyRole
487        {
488            /// Changes the key's role tag to `PrimaryRole`.
489            pub fn role_into_primary(self) -> $Key<$($l, )* P, PrimaryRole> {
490                let mut k: $Key<$($l, )* P, PrimaryRole> = convert!(self);
491                k.set_role(PrimaryRole::role());
492                k
493            }
494
495            /// Changes the key's role tag to `PrimaryRole`.
496            pub fn role_as_primary(&$($l)* self) -> &$($l)* $Key<$($l, )* P, PrimaryRole> {
497                convert_ref!(self)
498            }
499
500            /// Changes the key's role tag to `PrimaryRole`.
501            pub fn role_as_primary_mut(&$($l)* mut self) -> &$($l)* mut $Key<$($l, )* P, PrimaryRole> {
502                convert_ref!(self)
503            }
504
505            /// Changes the key's role tag to `SubordinateRole`.
506            pub fn role_into_subordinate(self) -> $Key<$($l, )* P, SubordinateRole>
507            {
508                let mut k: $Key<$($l, )* P, SubordinateRole> = convert!(self);
509                k.set_role(SubordinateRole::role());
510                k
511            }
512
513            /// Changes the key's role tag to `SubordinateRole`.
514            pub fn role_as_subordinate(&$($l)* self) -> &$($l)* $Key<$($l, )* P, SubordinateRole>
515            {
516                convert_ref!(self)
517            }
518
519            /// Changes the key's role tag to `SubordinateRole`.
520            pub fn role_as_subordinate_mut(&$($l)* mut self) -> &$($l)* mut $Key<$($l, )* P, SubordinateRole>
521            {
522                convert_ref!(self)
523            }
524
525            /// Changes the key's role tag to `UnspecifiedRole`.
526            pub fn role_into_unspecified(self) -> $Key<$($l, )* P, UnspecifiedRole>
527            {
528                let mut k: $Key<$($l, )* P, UnspecifiedRole> = convert!(self);
529                k.set_role(UnspecifiedRole::role());
530                k
531            }
532
533            /// Changes the key's role tag to `UnspecifiedRole`.
534            pub fn role_as_unspecified(&$($l)* self) -> &$($l)* $Key<$($l, )* P, UnspecifiedRole>
535            {
536                convert_ref!(self)
537            }
538
539            /// Changes the key's role tag to `UnspecifiedRole`.
540            pub fn role_as_unspecified_mut(&$($l)* mut self) -> &$($l)* mut $Key<$($l, )* P, UnspecifiedRole>
541            {
542                convert_ref!(self)
543            }
544        }
545    }
546}
547
548create_conversions!(Key);
549create_conversions!(Key4);
550create_conversions!(Key6);
551create_conversions!(KeyBundle);
552
553// A hack, since the type has to be an ident, which means that we
554// can't use <>.
555type KeyComponentAmalgamation<'a, P, R> = ComponentAmalgamation<'a, Key<P, R>>;
556create_conversions!(KeyComponentAmalgamation<'a>);
557
558create_part_conversions!(PrimaryKeyAmalgamation<'a;>);
559create_part_conversions!(SubordinateKeyAmalgamation<'a;>);
560create_part_conversions!(ErasedKeyAmalgamation<'a;>);
561create_part_conversions!(ValidPrimaryKeyAmalgamation<'a;>);
562create_part_conversions!(ValidSubordinateKeyAmalgamation<'a;>);
563create_part_conversions!(ValidErasedKeyAmalgamation<'a;>);