identity_verification/verification_method/
method_ref.rs

1// Copyright 2020-2023 IOTA Stiftung
2// SPDX-License-Identifier: Apache-2.0
3
4use core::fmt::Debug;
5use core::fmt::Formatter;
6
7use identity_core::common::KeyComparable;
8
9use crate::verification_method::VerificationMethod;
10use identity_did::CoreDID;
11use identity_did::DIDUrl;
12
13/// A reference to a verification method, either a `DID` or embedded `Method`.
14#[derive(Clone, PartialEq, Eq, Deserialize, Serialize)]
15#[serde(untagged)]
16pub enum MethodRef {
17  /// A [`VerificationMethod`] embedded in a verification relationship.
18  Embed(VerificationMethod),
19  /// A reference to a [`VerificationMethod`] in a verification relationship.
20  Refer(DIDUrl),
21}
22
23impl MethodRef {
24  /// Returns a reference to the `MethodRef` id.
25  pub fn id(&self) -> &DIDUrl {
26    match self {
27      Self::Embed(inner) => inner.id(),
28      Self::Refer(inner) => inner,
29    }
30  }
31
32  /// Returns a reference to the [`MethodRef`] controller.
33  ///
34  /// Always `None` for [`MethodRef::Refer`].
35  pub fn controller(&self) -> Option<&CoreDID> {
36    match self {
37      Self::Embed(inner) => Some(inner.controller()),
38      Self::Refer(_) => None,
39    }
40  }
41
42  /// Returns a `bool` indicating if the `MethodRef` is an embedded `Method`.
43  #[inline]
44  pub fn is_embedded(&self) -> bool {
45    matches!(self, Self::Embed(_))
46  }
47
48  /// Returns a `bool` indicating if the `MethodRef` is a `DID` reference.
49  #[inline]
50  pub fn is_referred(&self) -> bool {
51    matches!(self, Self::Refer(_))
52  }
53
54  /// Maps the [`MethodRef`] by applying a function `f` to the inner
55  /// [`VerificationMethod`] or [`DIDUrl`]. This can be useful for DID methods
56  /// where the DID is not known before the document has been published.
57  pub fn map<F>(self, f: F) -> MethodRef
58  where
59    F: FnMut(CoreDID) -> CoreDID,
60  {
61    match self {
62      MethodRef::Embed(method) => MethodRef::Embed(method.map(f)),
63      MethodRef::Refer(id) => MethodRef::Refer(id.map(f)),
64    }
65  }
66
67  /// Fallible version of [`MethodRef::map`].
68  pub fn try_map<F, E>(self, f: F) -> Result<MethodRef, E>
69  where
70    F: FnMut(CoreDID) -> Result<CoreDID, E>,
71  {
72    Ok(match self {
73      MethodRef::Embed(method) => MethodRef::Embed(method.try_map(f)?),
74      MethodRef::Refer(id) => MethodRef::Refer(id.try_map(f)?),
75    })
76  }
77
78  /// Returns the inner `Method` if this is an embedded `MethodRef`.
79  ///
80  /// Note: Returns `Err(self)` as a failure case.
81  ///
82  /// # Errors
83  ///
84  /// Fails if `MethodRef` is not an embedded method.
85  pub fn try_into_embedded(self) -> Result<VerificationMethod, Box<Self>> {
86    match self {
87      Self::Embed(inner) => Ok(inner),
88      Self::Refer(_) => Err(self.into()),
89    }
90  }
91
92  /// Returns the inner `Method` if this is an referenced `MethodRef`.
93  ///
94  /// Note: Returns `Err(self)` as a failure case.
95  ///
96  /// # Errors
97  ///
98  /// Fails if `MethodRef` is not an referenced method.
99  pub fn try_into_referenced(self) -> Result<DIDUrl, Box<Self>> {
100    match self {
101      Self::Embed(_) => Err(self.into()),
102      Self::Refer(inner) => Ok(inner),
103    }
104  }
105}
106
107impl Debug for MethodRef {
108  fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
109    match self {
110      Self::Embed(inner) => Debug::fmt(inner, f),
111      Self::Refer(inner) => Debug::fmt(inner, f),
112    }
113  }
114}
115
116impl From<VerificationMethod> for MethodRef {
117  #[inline]
118  fn from(other: VerificationMethod) -> Self {
119    Self::Embed(other)
120  }
121}
122
123impl From<DIDUrl> for MethodRef {
124  #[inline]
125  fn from(other: DIDUrl) -> Self {
126    Self::Refer(other)
127  }
128}
129
130impl AsRef<DIDUrl> for MethodRef {
131  #[inline]
132  fn as_ref(&self) -> &DIDUrl {
133    self.id()
134  }
135}
136
137impl KeyComparable for MethodRef {
138  type Key = DIDUrl;
139
140  #[inline]
141  fn key(&self) -> &Self::Key {
142    self.id()
143  }
144}