pub struct Request<'a>(/* private fields */);error_generic_member_access #99301)Expand description
Request supports generic, type-driven access to data. Its use is currently restricted to thestandard library in cases where trait authors wish to allow trait implementors to share genericinformation across trait boundaries. The motivating and prototypical use case iscore::error::Error which would otherwise require a method per concrete type (eg.std::backtrace::Backtrace instance that implementors want to expose to users).
§Data flow
To describe the intended data flow for Request objects, let’s consider two conceptual usersseparated by API boundaries:
Consumer - the consumer requests objects using a Request instance; eg a crate that offersfancy
Error/Resultreporting to users wants to request a Backtrace from a givendyn Error.Producer - the producer provides objects when requested via Request; eg. a library with anan
Errorimplementation that automatically captures backtraces at the time instances arecreated.
The consumer only needs to know where to submit their request and are expected to handle therequest not being fulfilled by the use ofOption<T> in the responses offered by the producer.
- A Producer initializes the value of one of its fields of a specific type. (or is otherwiseprepared to generate a value requested). eg,
backtrace::Backtraceorstd::backtrace::Backtrace - A Consumer requests an object of a specific type (say
std::backtrace::Backtrace). In thecase of adyn Errortrait object (the Producer), there are functions calledrequest_refandrequest_valueto simplify obtaining anOption<T>for a given type. - The Producer, when requested, populates the given Request object which is given as a mutablereference.
- The Consumer extracts a value or reference to the requested type from the
Requestobjectwrapped in anOption<T>; in the case ofdyn Errorthe aforementionedrequest_refandrequest_valuemethods mean thatdyn Errorusers don’t have to deal with theRequesttype atall (butErrorimplementors do). TheNonecase of theOptionsuggests only that theProducer cannot currently offer an instance of the requested type, not it can’t or never will.
§Examples
The best way to demonstrate this is using an example implementation ofError’sprovide traitmethod:
#![feature(error_generic_member_access)]usecore::fmt;usecore::error::Request;usecore::error::request_ref;#[derive(Debug)]enumMyLittleTeaPot { Empty,}#[derive(Debug)]structMyBacktrace {// ...}implMyBacktrace {fnnew() -> MyBacktrace {// ...}}#[derive(Debug)]structError { backtrace: MyBacktrace,}implfmt::DisplayforError {fnfmt(&self, f:&mutfmt::Formatter<'_>) -> fmt::Result {write!(f,"Example Error") }}implstd::error::ErrorforError {fnprovide<'a>(&'aself, request:&mutRequest<'a>) { request .provide_ref::<MyBacktrace>(&self.backtrace); }}fnmain() {letbacktrace = MyBacktrace::new();leterror = Error { backtrace };letdyn_error =&erroras&dynstd::error::Error;letbacktrace_ref = request_ref::<MyBacktrace>(dyn_error).unwrap();assert!(core::ptr::eq(&error.backtrace, backtrace_ref));assert!(request_ref::<MyLittleTeaPot>(dyn_error).is_none());}Implementations§
Source§impl<'a>Request<'a>
impl<'a>Request<'a>
Sourcepub fnprovide_value<T>(&mut self, value: T) -> &mut Selfwhere T: 'static,
🔬This is a nightly-only experimental API. (error_generic_member_access #99301)
pub fnprovide_value<T>(&mut self, value: T) -> &mut Selfwhere T: 'static,
error_generic_member_access #99301)Provides a value or other type with only static lifetimes.
§Examples
Provides anu8.
#![feature(error_generic_member_access)]usecore::error::Request;#[derive(Debug)]structSomeConcreteType { field: u8 }implstd::fmt::DisplayforSomeConcreteType {fnfmt(&self, f:&mutstd::fmt::Formatter<'_>) -> std::fmt::Result {write!(f,"{} failed",self.field) }}implstd::error::ErrorforSomeConcreteType {fnprovide<'a>(&'aself, request:&mutRequest<'a>) { request.provide_value::<u8>(self.field); }}Sourcepub fnprovide_value_with<T>(&mut self, fulfil: implFnOnce() -> T) -> &mut Selfwhere T: 'static,
🔬This is a nightly-only experimental API. (error_generic_member_access #99301)
pub fnprovide_value_with<T>(&mut self, fulfil: implFnOnce() -> T) -> &mut Selfwhere T: 'static,
error_generic_member_access #99301)Provides a value or other type with only static lifetimes computed using a closure.
§Examples
Provides aString by cloning.
#![feature(error_generic_member_access)]usecore::error::Request;#[derive(Debug)]structSomeConcreteType { field: String }implstd::fmt::DisplayforSomeConcreteType {fnfmt(&self, f:&mutstd::fmt::Formatter<'_>) -> std::fmt::Result {write!(f,"{} failed",self.field) }}implstd::error::ErrorforSomeConcreteType {fnprovide<'a>(&'aself, request:&mutRequest<'a>) { request.provide_value_with::<String>(||self.field.clone()); }}Sourcepub fnprovide_ref<T: ?Sized + 'static>(&mut self, value:&'a T) -> &mut Self
🔬This is a nightly-only experimental API. (error_generic_member_access #99301)
pub fnprovide_ref<T: ?Sized + 'static>(&mut self, value:&'a T) -> &mut Self
error_generic_member_access #99301)Provides a reference. The referee type must be bounded by'static,but may be unsized.
§Examples
Provides a reference to a field as a&str.
#![feature(error_generic_member_access)]usecore::error::Request;#[derive(Debug)]structSomeConcreteType { field: String }implstd::fmt::DisplayforSomeConcreteType {fnfmt(&self, f:&mutstd::fmt::Formatter<'_>) -> std::fmt::Result {write!(f,"{} failed",self.field) }}implstd::error::ErrorforSomeConcreteType {fnprovide<'a>(&'aself, request:&mutRequest<'a>) { request.provide_ref::<str>(&self.field); }}Sourcepub fnprovide_ref_with<T: ?Sized + 'static>( &mut self, fulfil: implFnOnce() ->&'a T,) -> &mut Self
🔬This is a nightly-only experimental API. (error_generic_member_access #99301)
pub fnprovide_ref_with<T: ?Sized + 'static>( &mut self, fulfil: implFnOnce() ->&'a T,) -> &mut Self
error_generic_member_access #99301)Provides a reference computed using a closure. The referee typemust be bounded by'static, but may be unsized.
§Examples
Provides a reference to a field as a&str.
#![feature(error_generic_member_access)]usecore::error::Request;#[derive(Debug)]structSomeConcreteType { business: String, party: String }fntoday_is_a_weekday() -> bool {true}implstd::fmt::DisplayforSomeConcreteType {fnfmt(&self, f:&mutstd::fmt::Formatter<'_>) -> std::fmt::Result {write!(f,"{} failed",self.business) }}implstd::error::ErrorforSomeConcreteType {fnprovide<'a>(&'aself, request:&mutRequest<'a>) { request.provide_ref_with::<str>(|| {iftoday_is_a_weekday() {&self.business }else{&self.party } }); }}Sourcepub fnwould_be_satisfied_by_value_of<T>(&self) ->boolwhere T: 'static,
🔬This is a nightly-only experimental API. (error_generic_member_access #99301)
pub fnwould_be_satisfied_by_value_of<T>(&self) ->boolwhere T: 'static,
error_generic_member_access #99301)Checks if theRequest would be satisfied if provided with avalue of the specified type. If the type does not match or hasalready been provided, returns false.
§Examples
Checks if au8 still needs to be provided and then providesit.
#![feature(error_generic_member_access)]usecore::error::Request;usecore::error::request_value;#[derive(Debug)]structParent(Option<u8>);implstd::fmt::DisplayforParent {fnfmt(&self, f:&mutstd::fmt::Formatter<'_>) -> std::fmt::Result {write!(f,"a parent failed") }}implstd::error::ErrorforParent {fnprovide<'a>(&'aself, request:&mutRequest<'a>) {if letSome(v) =self.0{ request.provide_value::<u8>(v); } }}#[derive(Debug)]structChild { parent: Parent,}implChild {// Pretend that this takes a lot of resources to evaluate.fnan_expensive_computation(&self) ->Option<u8> {Some(99) }}implstd::fmt::DisplayforChild {fnfmt(&self, f:&mutstd::fmt::Formatter<'_>) -> std::fmt::Result {write!(f,"child failed: \n because of parent: {}",self.parent) }}implstd::error::ErrorforChild {fnprovide<'a>(&'aself, request:&mutRequest<'a>) {// In general, we don't know if this call will provide // an `u8` value or not...self.parent.provide(request);// ...so we check to see if the `u8` is needed before // we run our expensive computation.ifrequest.would_be_satisfied_by_value_of::<u8>() {if letSome(v) =self.an_expensive_computation() { request.provide_value::<u8>(v); } }// The request will be satisfied now, regardless of if // the parent provided the value or we did.assert!(!request.would_be_satisfied_by_value_of::<u8>()); }}letparent = Parent(Some(42));letchild = Child { parent };assert_eq!(Some(42), request_value::<u8>(&child));letparent = Parent(None);letchild = Child { parent };assert_eq!(Some(99), request_value::<u8>(&child));Sourcepub fnwould_be_satisfied_by_ref_of<T>(&self) ->boolwhere T: ?Sized + 'static,
🔬This is a nightly-only experimental API. (error_generic_member_access #99301)
pub fnwould_be_satisfied_by_ref_of<T>(&self) ->boolwhere T: ?Sized + 'static,
error_generic_member_access #99301)Checks if theRequest would be satisfied if provided with areference to a value of the specified type.
If the type does not match or has already been provided, returns false.
§Examples
Checks if a&str still needs to be provided and then providesit.
#![feature(error_generic_member_access)]usecore::error::Request;usecore::error::request_ref;#[derive(Debug)]structParent(Option<String>);implstd::fmt::DisplayforParent {fnfmt(&self, f:&mutstd::fmt::Formatter<'_>) -> std::fmt::Result {write!(f,"a parent failed") }}implstd::error::ErrorforParent {fnprovide<'a>(&'aself, request:&mutRequest<'a>) {if letSome(v) =&self.0{ request.provide_ref::<str>(v); } }}#[derive(Debug)]structChild { parent: Parent, name: String,}implChild {// Pretend that this takes a lot of resources to evaluate.fnan_expensive_computation(&self) ->Option<&str> {Some(&self.name) }}implstd::fmt::DisplayforChild {fnfmt(&self, f:&mutstd::fmt::Formatter<'_>) -> std::fmt::Result {write!(f,"{} failed: \n {}",self.name,self.parent) }}implstd::error::ErrorforChild {fnprovide<'a>(&'aself, request:&mutRequest<'a>) {// In general, we don't know if this call will provide // a `str` reference or not...self.parent.provide(request);// ...so we check to see if the `&str` is needed before // we run our expensive computation.ifrequest.would_be_satisfied_by_ref_of::<str>() {if letSome(v) =self.an_expensive_computation() { request.provide_ref::<str>(v); } }// The request will be satisfied now, regardless of if // the parent provided the reference or we did.assert!(!request.would_be_satisfied_by_ref_of::<str>()); }}letparent = Parent(Some("parent".into()));letchild = Child { parent, name:"child".into() };assert_eq!(Some("parent"), request_ref::<str>(&child));letparent = Parent(None);letchild = Child { parent, name:"child".into() };assert_eq!(Some("child"), request_ref::<str>(&child));