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<$( $l:lifetime ),*> ) => {
314        create_part_conversions!($Key<$($l ),* ; R> where R: KeyRole);
315        create_role_conversions!($Key<$($l ),* >);
316
317        // We now handle converting both the part and the role at the same
318        // time.
319
320        macro_rules! f {
321            ( <$from_parts:ty, $from_role:ty> -> <$to_parts:ty, $to_role:ty> ) => {
322                impl<$($l ),*> From<$Key<$($l, )* $from_parts, $from_role>> for $Key<$($l, )* $to_parts, $to_role>
323                {
324                    fn from(p: $Key<$($l, )* $from_parts, $from_role>) -> Self {
325                        let mut k: Self = convert!(p);
326                        k.set_role(<$to_role>::role());
327                        k
328                    }
329                }
330
331                impl<$($l ),*> From<&$($l)* $Key<$($l, )* $from_parts, $from_role>> for &$($l)* $Key<$($l, )* $to_parts, $to_role>
332                {
333                    fn from(p: &$($l)* $Key<$from_parts, $from_role>) -> Self {
334                        convert_ref!(p)
335                    }
336                }
337
338                impl<$($l ),*> From<&$($l)* mut $Key<$($l, )* $from_parts, $from_role>> for &$($l)* mut $Key<$($l, )* $to_parts, $to_role>
339                {
340                    fn from(p: &$($l)* mut $Key<$from_parts, $from_role>) -> Self {
341                        convert_ref!(p)
342                    }
343                }
344            }
345        }
346
347        macro_rules! f_try {
348            ( <$from_parts:ty, $from_role:ty> -> <SecretParts, $to_role:ty> ) => {
349                impl<$($l ),*> TryFrom<$Key<$($l, )* $from_parts, $from_role>> for $Key<$($l, )* SecretParts, $to_role>
350                {
351                    type Error = anyhow::Error;
352                    fn try_from(p: $Key<$($l, )* $from_parts, $from_role>) -> Result<Self> {
353                        // First, just change the role.
354                        let mut k: $Key<$($l, )* $from_parts, $to_role> = p.into();
355                        k.set_role(<$to_role>::role());
356                        // Now change the parts.
357                        k.try_into()
358                    }
359                }
360
361                impl<$($l ),*> TryFrom<&$($l)* $Key<$($l, )* $from_parts, $from_role>> for &$($l)* $Key<$($l, )* SecretParts, $to_role>
362                {
363                    type Error = anyhow::Error;
364                    fn try_from(p: &$($l)* $Key<$($l, )* $from_parts, $from_role>) -> Result<Self> {
365                        // First, just change the role.
366                        let k: &$($l)* $Key<$($l, )* $from_parts, $to_role> = p.into();
367                        // Now change the parts.
368                        k.try_into()
369                    }
370                }
371
372                impl<$($l ),*> TryFrom<&$($l)* mut $Key<$($l, )* $from_parts, $from_role>> for &$($l)* mut $Key<$($l, )* SecretParts, $to_role>
373                {
374                    type Error = anyhow::Error;
375                    fn try_from(p: &$($l)* mut $Key<$($l, )* $from_parts, $from_role>) -> Result<Self> {
376                        // First, just change the role.
377                        let k: &$($l)* mut $Key<$($l, )* $from_parts, $to_role> = p.into();
378                        // Now change the parts.
379                        k.try_into()
380                    }
381                }
382            }
383        }
384
385        // The calls that are comment out are the calls for the
386        // combinations where either the KeyParts or the KeyRole does not
387        // change.
388
389        //f!(<PublicParts, PrimaryRole> -> <PublicParts, PrimaryRole>);
390        //f!(<PublicParts, PrimaryRole> -> <PublicParts, SubordinateRole>);
391        //f!(<PublicParts, PrimaryRole> -> <PublicParts, UnspecifiedRole>);
392        //f!(<PublicParts, PrimaryRole> -> <SecretParts, PrimaryRole>);
393        f_try!(<PublicParts, PrimaryRole> -> <SecretParts, SubordinateRole>);
394        f_try!(<PublicParts, PrimaryRole> -> <SecretParts, UnspecifiedRole>);
395        //f!(<PublicParts, PrimaryRole> -> <UnspecifiedParts, PrimaryRole>);
396        f!(<PublicParts, PrimaryRole> -> <UnspecifiedParts, SubordinateRole>);
397        f!(<PublicParts, PrimaryRole> -> <UnspecifiedParts, UnspecifiedRole>);
398
399        //f!(<PublicParts, SubordinateRole> -> <PublicParts, PrimaryRole>);
400        //f!(<PublicParts, SubordinateRole> -> <PublicParts, SubordinateRole>);
401        //f!(<PublicParts, SubordinateRole> -> <PublicParts, UnspecifiedRole>);
402        f_try!(<PublicParts, SubordinateRole> -> <SecretParts, PrimaryRole>);
403        //f!(<PublicParts, SubordinateRole> -> <SecretParts, SubordinateRole>);
404        f_try!(<PublicParts, SubordinateRole> -> <SecretParts, UnspecifiedRole>);
405        f!(<PublicParts, SubordinateRole> -> <UnspecifiedParts, PrimaryRole>);
406        //f!(<PublicParts, SubordinateRole> -> <UnspecifiedParts, SubordinateRole>);
407        f!(<PublicParts, SubordinateRole> -> <UnspecifiedParts, UnspecifiedRole>);
408
409        //f!(<PublicParts, UnspecifiedRole> -> <PublicParts, PrimaryRole>);
410        //f!(<PublicParts, UnspecifiedRole> -> <PublicParts, SubordinateRole>);
411        //f!(<PublicParts, UnspecifiedRole> -> <PublicParts, UnspecifiedRole>);
412        f_try!(<PublicParts, UnspecifiedRole> -> <SecretParts, PrimaryRole>);
413        f_try!(<PublicParts, UnspecifiedRole> -> <SecretParts, SubordinateRole>);
414        //f!(<PublicParts, UnspecifiedRole> -> <SecretParts, UnspecifiedRole>);
415        f!(<PublicParts, UnspecifiedRole> -> <UnspecifiedParts, PrimaryRole>);
416        f!(<PublicParts, UnspecifiedRole> -> <UnspecifiedParts, SubordinateRole>);
417        //f!(<PublicParts, UnspecifiedRole> -> <UnspecifiedParts, UnspecifiedRole>);
418
419        //f!(<SecretParts, PrimaryRole> -> <PublicParts, PrimaryRole>);
420        f!(<SecretParts, PrimaryRole> -> <PublicParts, SubordinateRole>);
421        f!(<SecretParts, PrimaryRole> -> <PublicParts, UnspecifiedRole>);
422        //f!(<SecretParts, PrimaryRole> -> <SecretParts, PrimaryRole>);
423        //f!(<SecretParts, PrimaryRole> -> <SecretParts, SubordinateRole>);
424        //f!(<SecretParts, PrimaryRole> -> <SecretParts, UnspecifiedRole>);
425        //f!(<SecretParts, PrimaryRole> -> <UnspecifiedParts, PrimaryRole>);
426        f!(<SecretParts, PrimaryRole> -> <UnspecifiedParts, SubordinateRole>);
427        f!(<SecretParts, PrimaryRole> -> <UnspecifiedParts, UnspecifiedRole>);
428
429        f!(<SecretParts, SubordinateRole> -> <PublicParts, PrimaryRole>);
430        //f!(<SecretParts, SubordinateRole> -> <PublicParts, SubordinateRole>);
431        f!(<SecretParts, SubordinateRole> -> <PublicParts, UnspecifiedRole>);
432        //f!(<SecretParts, SubordinateRole> -> <SecretParts, PrimaryRole>);
433        //f!(<SecretParts, SubordinateRole> -> <SecretParts, SubordinateRole>);
434        //f!(<SecretParts, SubordinateRole> -> <SecretParts, UnspecifiedRole>);
435        f!(<SecretParts, SubordinateRole> -> <UnspecifiedParts, PrimaryRole>);
436        //f!(<SecretParts, SubordinateRole> -> <UnspecifiedParts, SubordinateRole>);
437        f!(<SecretParts, SubordinateRole> -> <UnspecifiedParts, UnspecifiedRole>);
438
439        f!(<SecretParts, UnspecifiedRole> -> <PublicParts, PrimaryRole>);
440        f!(<SecretParts, UnspecifiedRole> -> <PublicParts, SubordinateRole>);
441        //f!(<SecretParts, UnspecifiedRole> -> <PublicParts, UnspecifiedRole>);
442        //f!(<SecretParts, UnspecifiedRole> -> <SecretParts, PrimaryRole>);
443        //f!(<SecretParts, UnspecifiedRole> -> <SecretParts, SubordinateRole>);
444        //f!(<SecretParts, UnspecifiedRole> -> <SecretParts, UnspecifiedRole>);
445        f!(<SecretParts, UnspecifiedRole> -> <UnspecifiedParts, PrimaryRole>);
446        f!(<SecretParts, UnspecifiedRole> -> <UnspecifiedParts, SubordinateRole>);
447        //f!(<SecretParts, UnspecifiedRole> -> <UnspecifiedParts, UnspecifiedRole>);
448
449        //f!(<UnspecifiedParts, PrimaryRole> -> <PublicParts, PrimaryRole>);
450        f!(<UnspecifiedParts, PrimaryRole> -> <PublicParts, SubordinateRole>);
451        f!(<UnspecifiedParts, PrimaryRole> -> <PublicParts, UnspecifiedRole>);
452        //f!(<UnspecifiedParts, PrimaryRole> -> <SecretParts, PrimaryRole>);
453        f_try!(<UnspecifiedParts, PrimaryRole> -> <SecretParts, SubordinateRole>);
454        f_try!(<UnspecifiedParts, PrimaryRole> -> <SecretParts, UnspecifiedRole>);
455        //f!(<UnspecifiedParts, PrimaryRole> -> <UnspecifiedParts, PrimaryRole>);
456        //f!(<UnspecifiedParts, PrimaryRole> -> <UnspecifiedParts, SubordinateRole>);
457        //f!(<UnspecifiedParts, PrimaryRole> -> <UnspecifiedParts, UnspecifiedRole>);
458
459        f!(<UnspecifiedParts, SubordinateRole> -> <PublicParts, PrimaryRole>);
460        //f!(<UnspecifiedParts, SubordinateRole> -> <PublicParts, SubordinateRole>);
461        f!(<UnspecifiedParts, SubordinateRole> -> <PublicParts, UnspecifiedRole>);
462        f_try!(<UnspecifiedParts, SubordinateRole> -> <SecretParts, PrimaryRole>);
463        //f!(<UnspecifiedParts, SubordinateRole> -> <SecretParts, SubordinateRole>);
464        f_try!(<UnspecifiedParts, SubordinateRole> -> <SecretParts, UnspecifiedRole>);
465        //f!(<UnspecifiedParts, SubordinateRole> -> <UnspecifiedParts, PrimaryRole>);
466        //f!(<UnspecifiedParts, SubordinateRole> -> <UnspecifiedParts, SubordinateRole>);
467        //f!(<UnspecifiedParts, SubordinateRole> -> <UnspecifiedParts, UnspecifiedRole>);
468
469        f!(<UnspecifiedParts, UnspecifiedRole> -> <PublicParts, PrimaryRole>);
470        f!(<UnspecifiedParts, UnspecifiedRole> -> <PublicParts, SubordinateRole>);
471        //f!(<UnspecifiedParts, UnspecifiedRole> -> <PublicParts, UnspecifiedRole>);
472        f_try!(<UnspecifiedParts, UnspecifiedRole> -> <SecretParts, PrimaryRole>);
473        f_try!(<UnspecifiedParts, UnspecifiedRole> -> <SecretParts, SubordinateRole>);
474        //f!(<UnspecifiedParts, UnspecifiedRole> -> <SecretParts, UnspecifiedRole>);
475        //f!(<UnspecifiedParts, UnspecifiedRole> -> <UnspecifiedParts, PrimaryRole>);
476        //f!(<UnspecifiedParts, UnspecifiedRole> -> <UnspecifiedParts, SubordinateRole>);
477        //f!(<UnspecifiedParts, UnspecifiedRole> -> <UnspecifiedParts, UnspecifiedRole>);
478
479
480        impl<$($l, )* P, R> $Key<$($l, )* P, R> where P: KeyParts, R: KeyRole
481        {
482            /// Changes the key's role tag to `PrimaryRole`.
483            pub fn role_into_primary(self) -> $Key<$($l, )* P, PrimaryRole> {
484                let mut k: $Key<$($l, )* P, PrimaryRole> = convert!(self);
485                k.set_role(PrimaryRole::role());
486                k
487            }
488
489            /// Changes the key's role tag to `PrimaryRole`.
490            pub fn role_as_primary(&$($l)* self) -> &$($l)* $Key<$($l, )* P, PrimaryRole> {
491                convert_ref!(self)
492            }
493
494            /// Changes the key's role tag to `PrimaryRole`.
495            pub fn role_as_primary_mut(&$($l)* mut self) -> &$($l)* mut $Key<$($l, )* P, PrimaryRole> {
496                convert_ref!(self)
497            }
498
499            /// Changes the key's role tag to `SubordinateRole`.
500            pub fn role_into_subordinate(self) -> $Key<$($l, )* P, SubordinateRole>
501            {
502                let mut k: $Key<$($l, )* P, SubordinateRole> = convert!(self);
503                k.set_role(SubordinateRole::role());
504                k
505            }
506
507            /// Changes the key's role tag to `SubordinateRole`.
508            pub fn role_as_subordinate(&$($l)* self) -> &$($l)* $Key<$($l, )* P, SubordinateRole>
509            {
510                convert_ref!(self)
511            }
512
513            /// Changes the key's role tag to `SubordinateRole`.
514            pub fn role_as_subordinate_mut(&$($l)* mut self) -> &$($l)* mut $Key<$($l, )* P, SubordinateRole>
515            {
516                convert_ref!(self)
517            }
518
519            /// Changes the key's role tag to `UnspecifiedRole`.
520            pub fn role_into_unspecified(self) -> $Key<$($l, )* P, UnspecifiedRole>
521            {
522                let mut k: $Key<$($l, )* P, UnspecifiedRole> = convert!(self);
523                k.set_role(UnspecifiedRole::role());
524                k
525            }
526
527            /// Changes the key's role tag to `UnspecifiedRole`.
528            pub fn role_as_unspecified(&$($l)* self) -> &$($l)* $Key<$($l, )* P, UnspecifiedRole>
529            {
530                convert_ref!(self)
531            }
532
533            /// Changes the key's role tag to `UnspecifiedRole`.
534            pub fn role_as_unspecified_mut(&$($l)* mut self) -> &$($l)* mut $Key<$($l, )* P, UnspecifiedRole>
535            {
536                convert_ref!(self)
537            }
538        }
539    }
540}
541
542create_conversions!(Key<>);
543create_conversions!(Key4<>);
544create_conversions!(Key6<>);
545create_conversions!(KeyBundle<>);
546
547// A hack, since the type has to be an ident, which means that we
548// can't use <>.
549type KeyComponentAmalgamation<'a, P, R> = ComponentAmalgamation<'a, Key<P, R>>;
550create_conversions!(KeyComponentAmalgamation<'a>);
551
552create_part_conversions!(PrimaryKeyAmalgamation<'a;>);
553create_part_conversions!(SubordinateKeyAmalgamation<'a;>);
554create_part_conversions!(ErasedKeyAmalgamation<'a;>);
555create_part_conversions!(ValidPrimaryKeyAmalgamation<'a;>);
556create_part_conversions!(ValidSubordinateKeyAmalgamation<'a;>);
557create_part_conversions!(ValidErasedKeyAmalgamation<'a;>);