pub struct Resolver<DOC = CoreDocument, CMD = SendSyncCommand<DOC>>{ /* private fields */ }
Expand description
Convenience type for resolving DID documents from different DID methods.
§Configuration
The resolver will only be able to resolve DID documents for methods it has been configured for. This is done by
attaching method specific handlers with Self::attach_handler
.
Implementations§
Source§impl<M, DOC> Resolver<DOC, M>
impl<M, DOC> Resolver<DOC, M>
Sourcepub fn new() -> Resolver<DOC, M>
pub fn new() -> Resolver<DOC, M>
Constructs a new Resolver
.
§Example
Construct a Resolver
that resolves DID documents of type
CoreDocument
.
let mut resolver = Resolver::<CoreDocument>::new();
// Now attach some handlers whose output can be converted to a `CoreDocument`.
Sourcepub async fn resolve<D>(&self, did: &D) -> Result<DOC, Error>where
D: DID,
pub async fn resolve<D>(&self, did: &D) -> Result<DOC, Error>where
D: DID,
Fetches the DID Document of the given DID.
§Errors
Errors if the resolver has not been configured to handle the method corresponding to the given DID or the resolution process itself fails.
§Example
async fn configure_and_resolve(
did: CoreDID,
) -> std::result::Result<CoreDocument, Box<dyn std::error::Error>> {
let resolver: Resolver = configure_resolver(Resolver::new());
let resolved_doc: CoreDocument = resolver.resolve(&did).await?;
Ok(resolved_doc)
}
fn configure_resolver(mut resolver: Resolver) -> Resolver {
resolver.attach_handler("foo".to_owned(), resolve_foo);
// Attach handlers for other DID methods we are interested in.
resolver
}
async fn resolve_foo(did: CoreDID) -> std::result::Result<CoreDocument, std::io::Error> {
todo!()
}
Source§impl<DOC> Resolver<DOC>where
DOC: 'static,
impl<DOC> Resolver<DOC>where
DOC: 'static,
Sourcepub fn attach_handler<D, F, Fut, DOCUMENT, E, DIDERR>(
&mut self,
method: String,
handler: F,
)
pub fn attach_handler<D, F, Fut, DOCUMENT, E, DIDERR>( &mut self, method: String, handler: F, )
Attach a new handler responsible for resolving DIDs of the given DID method.
The handler
is expected to be a closure taking an owned DID and asynchronously returning a DID Document
which can be converted to the type this Resolver
is parametrized over. The handler
is required to be
Clone
, Send
, Sync
and 'static
hence all captured variables must satisfy these bounds. In this regard
the move
keyword and (possibly) wrapping values in an Arc
may come in handy (see the example
below).
NOTE: If there already exists a handler for this method then it will be replaced with the new handler. In the case where one would like to have a “backup handler” for the same DID method, one can achieve this with composition.
§Example
// A client that can resolve DIDs of our invented "foo" method.
struct Client;
impl Client {
// Resolves some of the DIDs we are interested in.
async fn resolve(&self, _did: &CoreDID) -> std::result::Result<CoreDocument, std::io::Error> {
todo!()
}
}
// This way we can essentially produce (cheap) clones of our client.
let client = std::sync::Arc::new(Client {});
// Get a clone we can move into a handler.
let client_clone = client.clone();
// Construct a resolver that resolves documents of type `CoreDocument`.
let mut resolver = Resolver::<CoreDocument>::new();
// Now we want to attach a handler that uses the client to resolve DIDs whose method is "foo".
resolver.attach_handler("foo".to_owned(), move |did: CoreDID| {
// We want to resolve the did asynchronously, but since we do not know when it will be awaited we
// let the future take ownership of the client by moving a clone into the asynchronous block.
let future_client = client_clone.clone();
async move { future_client.resolve(&did).await }
});
Source§impl<DOC> Resolver<DOC, SingleThreadedCommand<DOC>>where
DOC: 'static,
impl<DOC> Resolver<DOC, SingleThreadedCommand<DOC>>where
DOC: 'static,
Sourcepub fn attach_handler<D, F, Fut, DOCUMENT, E, DIDERR>(
&mut self,
method: String,
handler: F,
)
pub fn attach_handler<D, F, Fut, DOCUMENT, E, DIDERR>( &mut self, method: String, handler: F, )
Attach a new handler responsible for resolving DIDs of the given DID method.
The handler
is expected to be a closure taking an owned DID and asynchronously returning a DID Document
which can be converted to the type this Resolver
is parametrized over. The handler
is required to be
Clone
and 'static
hence all captured variables must satisfy these bounds. In this regard the
move
keyword and (possibly) wrapping values in an std::rc::Rc
may come in handy (see the example below).
NOTE: If there already exists a handler for this method then it will be replaced with the new handler. In the case where one would like to have a “backup handler” for the same DID method, one can achieve this with composition.
§Example
// A client that can resolve DIDs of our invented "foo" method.
struct Client;
impl Client {
// Resolves some of the DIDs we are interested in.
async fn resolve(&self, _did: &CoreDID) -> std::result::Result<CoreDocument, std::io::Error> {
todo!()
}
}
// This way we can essentially produce (cheap) clones of our client.
let client = std::rc::Rc::new(Client {});
// Get a clone we can move into a handler.
let client_clone = client.clone();
// Construct a resolver that resolves documents of type `CoreDocument`.
let mut resolver = SingleThreadedResolver::<CoreDocument>::new();
// Now we want to attach a handler that uses the client to resolve DIDs whose method is "foo".
resolver.attach_handler("foo".to_owned(), move |did: CoreDID| {
// We want to resolve the did asynchronously, but since we do not know when it will be awaited we
// let the future take ownership of the client by moving a clone into the asynchronous block.
let future_client = client_clone.clone();
async move { future_client.resolve(&did).await }
});
Source§impl<DOC> Resolver<DOC, SingleThreadedCommand<DOC>>where
DOC: From<CoreDocument> + 'static,
impl<DOC> Resolver<DOC, SingleThreadedCommand<DOC>>where
DOC: From<CoreDocument> + 'static,
Sourcepub fn attach_did_jwk_handler(&mut self)
pub fn attach_did_jwk_handler(&mut self)
Attaches a handler capable of resolving did:jwk
DIDs.
Source§impl<DOC> Resolver<DOC>where
DOC: From<CoreDocument> + 'static,
impl<DOC> Resolver<DOC>where
DOC: From<CoreDocument> + 'static,
Sourcepub fn attach_did_jwk_handler(&mut self)
pub fn attach_did_jwk_handler(&mut self)
Attaches a handler capable of resolving did:jwk
DIDs.
Source§impl<DOC> Resolver<DOC>
impl<DOC> Resolver<DOC>
Sourcepub fn attach_iota_handler<CLI>(&mut self, client: CLI)
pub fn attach_iota_handler<CLI>(&mut self, client: CLI)
Convenience method for attaching a new handler responsible for resolving IOTA DIDs.
See also attach_handler
.
Sourcepub fn attach_multiple_iota_handlers<CLI, I>(&mut self, clients: I)where
CLI: DidResolutionHandler + Send + Sync + 'static,
I: IntoIterator<Item = (&'static str, CLI)>,
pub fn attach_multiple_iota_handlers<CLI, I>(&mut self, clients: I)where
CLI: DidResolutionHandler + Send + Sync + 'static,
I: IntoIterator<Item = (&'static str, CLI)>,
Convenience method for attaching multiple handlers responsible for resolving IOTA DIDs on multiple networks.
§Arguments
clients
- A collection of tuples where each tuple contains the name of the network name and its corresponding client.
§Examples
// Assume `client1` and `client2` are instances of identity clients `IdentityClientReadOnly`.
attach_multiple_iota_handlers(vec![("client1", client1), ("client2", client2)]);
§See Also
§Note
- Using
attach_iota_handler
orattach_handler
for the IOTA method would override all previously added clients. - This function does not validate the provided configuration. Ensure that the provided network name
corresponds with the client, possibly by using
client.network_name()
.
Trait Implementations§
Auto Trait Implementations§
impl<DOC, CMD> Freeze for Resolver<DOC, CMD>
impl<DOC, CMD> RefUnwindSafe for Resolver<DOC, CMD>where
DOC: RefUnwindSafe,
CMD: RefUnwindSafe,
impl<DOC, CMD> Send for Resolver<DOC, CMD>
impl<DOC, CMD> Sync for Resolver<DOC, CMD>
impl<DOC, CMD> Unpin for Resolver<DOC, CMD>
impl<DOC, CMD> UnwindSafe for Resolver<DOC, CMD>where
CMD: UnwindSafe,
DOC: UnwindSafe,
Blanket Implementations§
§impl<U> As for U
impl<U> As for U
§fn as_<T>(self) -> Twhere
T: CastFrom<U>,
fn as_<T>(self) -> Twhere
T: CastFrom<U>,
self
to type T
. The semantics of numeric casting with the as
operator are followed, so <T as As>::as_::<U>
can be used in the same way as T as U
for numeric conversions. Read more§impl<'a, T, E> AsTaggedExplicit<'a, E> for Twhere
T: 'a,
impl<'a, T, E> AsTaggedExplicit<'a, E> for Twhere
T: 'a,
§impl<'a, T, E> AsTaggedImplicit<'a, E> for Twhere
T: 'a,
impl<'a, T, E> AsTaggedImplicit<'a, E> for Twhere
T: 'a,
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
§impl<T> Conv for T
impl<T> Conv for T
§impl<T> ConvertTo<T> for Twhere
T: Send,
impl<T> ConvertTo<T> for Twhere
T: Send,
fn convert(self) -> Result<T, Error>
fn convert_unchecked(self) -> T
§impl<T> FmtForward for T
impl<T> FmtForward for T
§fn fmt_binary(self) -> FmtBinary<Self>where
Self: Binary,
fn fmt_binary(self) -> FmtBinary<Self>where
Self: Binary,
self
to use its Binary
implementation when Debug
-formatted.§fn fmt_display(self) -> FmtDisplay<Self>where
Self: Display,
fn fmt_display(self) -> FmtDisplay<Self>where
Self: Display,
self
to use its Display
implementation when
Debug
-formatted.§fn fmt_lower_exp(self) -> FmtLowerExp<Self>where
Self: LowerExp,
fn fmt_lower_exp(self) -> FmtLowerExp<Self>where
Self: LowerExp,
self
to use its LowerExp
implementation when
Debug
-formatted.§fn fmt_lower_hex(self) -> FmtLowerHex<Self>where
Self: LowerHex,
fn fmt_lower_hex(self) -> FmtLowerHex<Self>where
Self: LowerHex,
self
to use its LowerHex
implementation when
Debug
-formatted.§fn fmt_octal(self) -> FmtOctal<Self>where
Self: Octal,
fn fmt_octal(self) -> FmtOctal<Self>where
Self: Octal,
self
to use its Octal
implementation when Debug
-formatted.§fn fmt_pointer(self) -> FmtPointer<Self>where
Self: Pointer,
fn fmt_pointer(self) -> FmtPointer<Self>where
Self: Pointer,
self
to use its Pointer
implementation when
Debug
-formatted.§fn fmt_upper_exp(self) -> FmtUpperExp<Self>where
Self: UpperExp,
fn fmt_upper_exp(self) -> FmtUpperExp<Self>where
Self: UpperExp,
self
to use its UpperExp
implementation when
Debug
-formatted.§fn fmt_upper_hex(self) -> FmtUpperHex<Self>where
Self: UpperHex,
fn fmt_upper_hex(self) -> FmtUpperHex<Self>where
Self: UpperHex,
self
to use its UpperHex
implementation when
Debug
-formatted.§fn fmt_list(self) -> FmtList<Self>where
&'a Self: for<'a> IntoIterator,
fn fmt_list(self) -> FmtList<Self>where
&'a Self: for<'a> IntoIterator,
§impl<T> Instrument for T
impl<T> Instrument for T
§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self
into a Left
variant of Either<Self, Self>
if into_left
is true
.
Converts self
into a Right
variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self
into a Left
variant of Either<Self, Self>
if into_left(&self)
returns true
.
Converts self
into a Right
variant of Either<Self, Self>
otherwise. Read more§impl<T> IntoRequest<T> for T
impl<T> IntoRequest<T> for T
§fn into_request(self) -> Request<T>
fn into_request(self) -> Request<T>
T
in a Request
Source§impl<T> IntoRequest<T> for T
impl<T> IntoRequest<T> for T
Source§fn into_request(self) -> Request<T>
fn into_request(self) -> Request<T>
T
in a tonic::Request
§impl<T> Pipe for Twhere
T: ?Sized,
impl<T> Pipe for Twhere
T: ?Sized,
§fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> Rwhere
Self: Sized,
fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> Rwhere
Self: Sized,
§fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> Rwhere
R: 'a,
fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> Rwhere
R: 'a,
self
and passes that borrow into the pipe function. Read more§fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> Rwhere
R: 'a,
fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> Rwhere
R: 'a,
self
and passes that borrow into the pipe function. Read more§fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
§fn pipe_borrow_mut<'a, B, R>(
&'a mut self,
func: impl FnOnce(&'a mut B) -> R,
) -> R
fn pipe_borrow_mut<'a, B, R>( &'a mut self, func: impl FnOnce(&'a mut B) -> R, ) -> R
§fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
self
, then passes self.as_ref()
into the pipe function.§fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> R
fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> R
self
, then passes self.as_mut()
into the pipe
function.§fn pipe_deref<'a, T, R>(&'a self, func: impl FnOnce(&'a T) -> R) -> R
fn pipe_deref<'a, T, R>(&'a self, func: impl FnOnce(&'a T) -> R) -> R
self
, then passes self.deref()
into the pipe function.§impl<T> PolicyExt for Twhere
T: ?Sized,
impl<T> PolicyExt for Twhere
T: ?Sized,
§impl<T> Tap for T
impl<T> Tap for T
§fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
Borrow<B>
of a value. Read more§fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
BorrowMut<B>
of a value. Read more§fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
AsRef<R>
view of a value. Read more§fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
AsMut<R>
view of a value. Read more§fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
Deref::Target
of a value. Read more§fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
Deref::Target
of a value. Read more§fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self
fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self
.tap()
only in debug builds, and is erased in release builds.§fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self
fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self
.tap_mut()
only in debug builds, and is erased in release
builds.§fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
.tap_borrow()
only in debug builds, and is erased in release
builds.§fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Self
fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Self
.tap_borrow_mut()
only in debug builds, and is erased in release
builds.§fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Self
fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Self
.tap_ref()
only in debug builds, and is erased in release
builds.§fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Self
fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Self
.tap_ref_mut()
only in debug builds, and is erased in release
builds.§fn tap_deref_dbg<T>(self, func: impl FnOnce(&T)) -> Self
fn tap_deref_dbg<T>(self, func: impl FnOnce(&T)) -> Self
.tap_deref()
only in debug builds, and is erased in release
builds.