1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
// Copyright 2020-2022 IOTA Stiftung
// SPDX-License-Identifier: Apache-2.0

use crate::did::DID;
use crate::error::Error;
use crate::error::Result;
use crate::verification::VerificationMethod;

/// Represents all possible verification method URI types
///
/// see [W3C DID-core spec](https://www.w3.org/TR/did-core/#relative-did-urls)
pub enum MethodUriType {
  Absolute,
  Relative,
}

/// Used to return absolute or relative method URI.
///
/// This trait is used to determine whether absolute or relative method URIs
/// should be used to sign data.
///
/// [More Info](https://www.w3.org/TR/did-core/#relative-did-urls)
pub trait TryMethod {
  /// Flag that determines whether absolute or rleative URI
  const TYPE: MethodUriType;

  /// Returns an absolute or relative method URI, if any, depending on the [`MethodUriType`].
  ///
  /// - [`MethodUriType::Absolute`] => "did:example:1234#method"
  /// - [`MethodUriType::Relative`] => "#method"
  fn method<D, U>(method: &VerificationMethod<D, U>) -> Option<String>
  where
    D: DID,
  {
    // Return None if there is no fragment on the method, even in the absolute case.
    let fragment: &str = method.id().fragment()?;

    match Self::TYPE {
      MethodUriType::Absolute => Some(method.id().to_string()),
      MethodUriType::Relative => Some(core::iter::once('#').chain(fragment.chars()).collect()),
    }
  }

  /// Returns String representation of absolute or relative method URI.
  ///
  /// # Errors
  ///
  /// Fails if an unsupported verification method is used.
  fn try_method<D, U>(method: &VerificationMethod<D, U>) -> Result<String>
  where
    D: DID,
  {
    Self::method(method).ok_or(Error::MissingIdFragment)
  }
}