#[repr(transparent)]pub struct Request<'a>(_);
Expand description
A type-erased request for the value or action defined by Property
Requests can be either a ‘Satisfiable’ request for a value, in which case the methods
satisfy
and satisfy_with
can be used.
Alternatively they may be an ‘Actionable’ request, in which case
get_action
returns an associated value.
Whether a request is ‘Actionable’ or ‘Satisfiable’ depends on the property, mechanism and side and is documented in the documentation of the mechanism implementation in question.
Implementations
sourceimpl<'a> Request<'a>
impl<'a> Request<'a>
sourcepub fn is<P: Property<'a>>(&self) -> bool
pub fn is<P: Property<'a>>(&self) -> bool
Returns true iff this Request is for the Property P
.
Using this method is generally not necessary as satisfy
,
satisfy_with
and get_action
can used
efficiently without.
sourcepub fn get_action<P: Property<'a>>(&mut self) -> Option<&'a P::Value>
pub fn get_action<P: Property<'a>>(&mut self) -> Option<&'a P::Value>
Get a reference to the associated value of an ‘Actionable’ Request for P
.
This method does not work for all requests, even if Self::is
returned true for the
given P
, as ‘Satisfiable’ requests are instead requesting a value for P
.
get_action
will return None
if the request is not an Actionable
request for the
given P
, or if called for the same P
multiple times.
// Since get_action returns `None` if P doesn't match, `if let` constructs are a nice way
// to check for the different options
if let Some(url) = request.get_action::<OpenID20AuthenticateInBrowser>() {
do_something(url);
return Ok(());
}
if let Some(url) = request.get_action::<Saml20AuthenticateInBrowser>() {
do_something_else(url);
return Ok(());
}
Ok(())
sourcepub fn satisfy<P: for<'p> Property<'p>>(
&mut self,
answer: &<P as Property<'_>>::Value
) -> Result<&mut Self, SessionError>
pub fn satisfy<P: for<'p> Property<'p>>(
&mut self,
answer: &<P as Property<'_>>::Value
) -> Result<&mut Self, SessionError>
Satisfy a ‘Satisfiable’ request using the provided value.
If the type of the request is P
and the request was not yet satisfied, this method
will satisfy the request and return an opaque Err
that must be bubbled up.
If the request is not for the property P
, already satisfied or not a ‘Satisfiable’
request this method will always return Ok(&mut Self)
.
This behaviour allows to easily chain multiple calls using the ?
operator:
request
.satisfy::<AuthId>("authid")? // if `P` is AuthId this will immediately return
.satisfy::<Password>(b"password")?
// It's important that errors are returned so the last call should have a `?` too.
.satisfy::<AuthzId>("authzid")?;
faulty use of satisfy
/satisfy_with
It’s important to note that calls will succeed if the request is not for this property. Thus care must be taken when satisfying requests to prevent bugs:
if let Some(password) = self.try_get_cached_password() {
request.satisfy::<Password>(password)?;
// This is wrong, as the above call will *succeed* if `AuthId` was requested but this
// return may prevent the `satisfy` below from ever being evaluated.
return Ok(());
} else {
let password = self.ask_user_for_password()?;
request.satisfy::<Password>(password)?;
}
request.satisfy::<AuthId>("foobar")?;
If generating the value is expensive or requires interactivity using the method
satisfy_with
may be preferable.
sourcepub fn satisfy_with<'p, P: SizedProperty<'p>, F>(
&mut self,
closure: F
) -> Result<&mut Self, SessionError>where
F: FnOnce() -> Result<P::Value, SessionError>,
pub fn satisfy_with<'p, P: SizedProperty<'p>, F>(
&mut self,
closure: F
) -> Result<&mut Self, SessionError>where
F: FnOnce() -> Result<P::Value, SessionError>,
Satisfy a ‘Satisfiable’ request using the provided closure.
If the type of the request is P
and the request was not yet satisfied, this method
will evaluate the closure and satisfy the request, returning an opaque Err
that must be
bubbled up.
If the request is not for the property P
, already satisfied or not a ‘Satisfiable’
request this method will is guaranteed to not evaluate the provided closure and return an
Ok(&mut Self)
.
This behaviour allows to easily chain multiple calls using the ?
operator:
// Skipping the interactive asking if the password was cached previously
if let Some(password) = try_get_cached_password() {
// Several calls for satisfy may exist, but only the first value set will ever be used.
request.satisfy::<Password>(password)?;
}
request
.satisfy::<AuthId>(ask_user_for_authid()?)?
.satisfy::<Password>(ask_user_for_password()?)?;
faulty use of satisfy
/satisfy_with
It’s important to note that calls will succeed if the request is not for this property. Thus care must be taken when satisfying requests to prevent bugs:
if let Some(password) = try_get_cached_password() {
request.satisfy::<Password>(password)?;
// This is wrong, as the above call will *succeed* if `AuthId` was requested but this
// return may prevent the `satisfy` below from ever being evaluated.
return Ok(());
} else {
let password = ask_user_for_password()?;
request.satisfy::<Password>(password)?;
}
request.satisfy::<AuthId>("foobar")?;
If the value for a property is static or readily available using
satisfy
may be preferable.