From 3186e7b0cac5e3692d68ea1107cc26b970467b41 Mon Sep 17 00:00:00 2001 From: msrd0 Date: Thu, 3 Aug 2023 13:30:54 +0000 Subject: [PATCH] GitHub Pages for d60e99c266a39c05075277bde2208cb1d90c6f05 --- coverage.svg | 2 +- doc/.timestamp | 2 +- doc/gotham_restful/all.html | 4 +- doc/gotham_restful/attr.create.html | 4 +- doc/gotham_restful/attr.delete.html | 4 +- doc/gotham_restful/attr.delete_all.html | 4 +- doc/gotham_restful/attr.endpoint.html | 4 +- doc/gotham_restful/attr.read.html | 4 +- doc/gotham_restful/attr.read_all.html | 4 +- doc/gotham_restful/attr.search.html | 4 +- doc/gotham_restful/attr.update.html | 4 +- doc/gotham_restful/attr.update_all.html | 4 +- doc/gotham_restful/cors/enum.Headers.html | 40 +++++------ doc/gotham_restful/cors/enum.Origin.html | 38 +++++----- doc/gotham_restful/cors/fn.handle_cors.html | 4 +- doc/gotham_restful/cors/index.html | 4 +- .../cors/struct.CorsConfig.html | 48 ++++++------- doc/gotham_restful/cors/trait.CorsRoute.html | 16 ++--- doc/gotham_restful/derive.FromBody.html | 4 +- doc/gotham_restful/derive.RequestBody.html | 4 +- doc/gotham_restful/derive.Resource.html | 4 +- doc/gotham_restful/derive.ResourceError.html | 4 +- doc/gotham_restful/enum.AuthErrorOrOther.html | 50 ++++++------- doc/gotham_restful/enum.AuthSource.html | 40 +++++------ doc/gotham_restful/enum.AuthStatus.html | 42 +++++------ doc/gotham_restful/index.html | 8 +-- doc/gotham_restful/struct.AuthError.html | 36 +++++----- doc/gotham_restful/struct.AuthMiddleware.html | 70 +++++++++---------- doc/gotham_restful/struct.NoContent.html | 43 ++++++------ doc/gotham_restful/struct.NoopExtractor.html | 53 ++++++++------ doc/gotham_restful/struct.OpenapiInfo.html | 40 +++++------ doc/gotham_restful/struct.Raw.html | 67 +++++++++--------- doc/gotham_restful/struct.Redirect.html | 43 ++++++------ doc/gotham_restful/struct.Response.html | 42 +++++------ .../struct.StaticAuthHandler.html | 36 +++++----- doc/gotham_restful/struct.Success.html | 53 +++++++------- doc/gotham_restful/trait.AuthHandler.html | 12 ++-- .../trait.DrawResourceRoutes.html | 14 ++-- .../trait.DrawResourceRoutesWithSchema.html | 14 ++-- doc/gotham_restful/trait.DrawResources.html | 16 ++--- .../trait.DrawResourcesWithSchema.html | 8 +-- doc/gotham_restful/trait.Endpoint.html | 44 ++++++------ .../trait.EndpointWithSchema.html | 56 +++++++-------- doc/gotham_restful/trait.FromBody.html | 18 ++--- doc/gotham_restful/trait.GetOpenapi.html | 12 ++-- doc/gotham_restful/trait.IntoResponse.html | 40 +++++------ .../trait.IntoResponseError.html | 16 ++--- .../trait.IntoResponseWithSchema.html | 4 +- doc/gotham_restful/trait.RequestBody.html | 10 +-- doc/gotham_restful/trait.Resource.html | 4 +- .../trait.ResourceWithSchema.html | 4 +- doc/gotham_restful/trait.ResponseBody.html | 6 +- doc/gotham_restful/trait.ResponseSchema.html | 26 +++---- doc/gotham_restful/trait.WithOpenapi.html | 20 +++--- doc/gotham_restful/type.AuthResult.html | 4 +- doc/gotham_restful/type.AuthSuccess.html | 4 +- doc/gotham_restful/type.AuthValidation.html | 4 +- doc/help.html | 4 +- doc/implementors/core/clone/trait.Clone.js | 2 +- doc/implementors/core/convert/trait.AsMut.js | 2 +- doc/implementors/core/convert/trait.AsRef.js | 2 +- doc/implementors/core/convert/trait.From.js | 2 +- .../core/default/trait.Default.js | 2 +- doc/implementors/core/fmt/trait.Debug.js | 2 +- doc/implementors/core/marker/trait.Copy.js | 2 +- doc/implementors/core/marker/trait.Send.js | 2 +- doc/implementors/core/marker/trait.Sync.js | 2 +- doc/implementors/core/marker/trait.Unpin.js | 2 +- .../panic/unwind_safe/trait.RefUnwindSafe.js | 2 +- .../panic/unwind_safe/trait.UnwindSafe.js | 2 +- .../gotham/middleware/trait.Middleware.js | 2 +- .../gotham/middleware/trait.NewMiddleware.js | 2 +- .../gotham/state/data/trait.StateData.js | 2 +- .../serde/de/trait.Deserialize.js | 2 +- doc/search-index.js | 2 +- doc/settings.html | 4 +- doc/src/gotham_restful/auth.rs.html | 4 +- doc/src/gotham_restful/cors.rs.html | 4 +- doc/src/gotham_restful/endpoint.rs.html | 4 +- doc/src/gotham_restful/lib.rs.html | 4 +- .../gotham_restful/openapi/builder.rs.html | 4 +- .../openapi/handler/mod.rs.html | 4 +- doc/src/gotham_restful/openapi/mod.rs.html | 4 +- .../gotham_restful/openapi/operation.rs.html | 4 +- doc/src/gotham_restful/openapi/router.rs.html | 4 +- .../response/auth_result.rs.html | 4 +- doc/src/gotham_restful/response/mod.rs.html | 4 +- .../response/no_content.rs.html | 4 +- doc/src/gotham_restful/response/raw.rs.html | 4 +- .../gotham_restful/response/redirect.rs.html | 4 +- .../gotham_restful/response/result.rs.html | 4 +- .../gotham_restful/response/success.rs.html | 4 +- doc/src/gotham_restful/routing.rs.html | 4 +- doc/src/gotham_restful/types.rs.html | 4 +- doc/static.files/main-f0540c1d82cde29b.js | 7 ++ doc/static.files/main-f61008743c98d196.js | 7 -- ...a7b69.css => rustdoc-f3501f0f5ae15dfb.css} | 2 +- doc/static.files/search-4926e5fc22a5646a.js | 1 + doc/static.files/search-e077946657036a58.js | 1 - .../settings-7bfb4c59cc6bc502.css | 3 - .../settings-8c76f75bfb6bd192.css | 3 + ...b45b39.js => settings-de11bff964e9d4e5.js} | 2 +- ...a.js => source-script-11255107d0a65077.js} | 2 +- tarpaulin-report.html | 4 +- tarpaulin-report.json | 2 +- 105 files changed, 664 insertions(+), 653 deletions(-) create mode 100644 doc/static.files/main-f0540c1d82cde29b.js delete mode 100644 doc/static.files/main-f61008743c98d196.js rename doc/static.files/{rustdoc-ba5701c5741a7b69.css => rustdoc-f3501f0f5ae15dfb.css} (90%) create mode 100644 doc/static.files/search-4926e5fc22a5646a.js delete mode 100644 doc/static.files/search-e077946657036a58.js delete mode 100644 doc/static.files/settings-7bfb4c59cc6bc502.css create mode 100644 doc/static.files/settings-8c76f75bfb6bd192.css rename doc/static.files/{settings-298e1ea74db45b39.js => settings-de11bff964e9d4e5.js} (67%) rename doc/static.files/{source-script-905937fbbdc8e9ea.js => source-script-11255107d0a65077.js} (92%) diff --git a/coverage.svg b/coverage.svg index 6a97b4cd7..0a64bd0c4 100644 --- a/coverage.svg +++ b/coverage.svg @@ -1 +1 @@ -coverage: 72.27%coverage72.27% \ No newline at end of file +coverage: 73.15%coverage73.15% \ No newline at end of file diff --git a/doc/.timestamp b/doc/.timestamp index 41d6cd2c6..a3bcc7ef4 100644 --- a/doc/.timestamp +++ b/doc/.timestamp @@ -1 +1 @@ -Thu Jun 15 07:36:24 UTC 2023 +Thu Aug 3 13:30:53 UTC 2023 diff --git a/doc/gotham_restful/all.html b/doc/gotham_restful/all.html index f33035a81..e5d5c114b 100644 --- a/doc/gotham_restful/all.html +++ b/doc/gotham_restful/all.html @@ -1,3 +1,3 @@ -List of all items in this crate
\ No newline at end of file +data-use_system_theme="false">
\ No newline at end of file diff --git a/doc/gotham_restful/attr.create.html b/doc/gotham_restful/attr.create.html index 8b0590d9f..11d2029f6 100644 --- a/doc/gotham_restful/attr.create.html +++ b/doc/gotham_restful/attr.create.html @@ -1,3 +1,3 @@ -create in gotham_restful - Rust

Attribute Macro gotham_restful::create

#[create]
\ No newline at end of file +data-use_system_theme="false">

Attribute Macro gotham_restful::create

#[create]
\ No newline at end of file diff --git a/doc/gotham_restful/attr.delete.html b/doc/gotham_restful/attr.delete.html index 9216ff320..c8d98d953 100644 --- a/doc/gotham_restful/attr.delete.html +++ b/doc/gotham_restful/attr.delete.html @@ -1,3 +1,3 @@ -delete in gotham_restful - Rust

Attribute Macro gotham_restful::delete

#[delete]
\ No newline at end of file +data-use_system_theme="false">

Attribute Macro gotham_restful::delete

#[delete]
\ No newline at end of file diff --git a/doc/gotham_restful/attr.delete_all.html b/doc/gotham_restful/attr.delete_all.html index dc70df277..b3b859360 100644 --- a/doc/gotham_restful/attr.delete_all.html +++ b/doc/gotham_restful/attr.delete_all.html @@ -1,3 +1,3 @@ -delete_all in gotham_restful - Rust

Attribute Macro gotham_restful::delete_all

#[delete_all]
\ No newline at end of file +data-use_system_theme="false">

Attribute Macro gotham_restful::delete_all

#[delete_all]
\ No newline at end of file diff --git a/doc/gotham_restful/attr.endpoint.html b/doc/gotham_restful/attr.endpoint.html index c259dff51..61ac11f10 100644 --- a/doc/gotham_restful/attr.endpoint.html +++ b/doc/gotham_restful/attr.endpoint.html @@ -1,3 +1,3 @@ -endpoint in gotham_restful - Rust

Attribute Macro gotham_restful::endpoint

#[endpoint]
\ No newline at end of file +data-use_system_theme="false">

Attribute Macro gotham_restful::endpoint

#[endpoint]
\ No newline at end of file diff --git a/doc/gotham_restful/attr.read.html b/doc/gotham_restful/attr.read.html index a6bf44029..f1fdd0d69 100644 --- a/doc/gotham_restful/attr.read.html +++ b/doc/gotham_restful/attr.read.html @@ -1,3 +1,3 @@ -read in gotham_restful - Rust

Attribute Macro gotham_restful::read

#[read]
\ No newline at end of file +data-use_system_theme="false">

Attribute Macro gotham_restful::read

#[read]
\ No newline at end of file diff --git a/doc/gotham_restful/attr.read_all.html b/doc/gotham_restful/attr.read_all.html index 2e44dd28f..1457811bb 100644 --- a/doc/gotham_restful/attr.read_all.html +++ b/doc/gotham_restful/attr.read_all.html @@ -1,3 +1,3 @@ -read_all in gotham_restful - Rust

Attribute Macro gotham_restful::read_all

#[read_all]
\ No newline at end of file +data-use_system_theme="false">

Attribute Macro gotham_restful::read_all

#[read_all]
\ No newline at end of file diff --git a/doc/gotham_restful/attr.search.html b/doc/gotham_restful/attr.search.html index 56fb99a95..2ebfd6926 100644 --- a/doc/gotham_restful/attr.search.html +++ b/doc/gotham_restful/attr.search.html @@ -1,3 +1,3 @@ -search in gotham_restful - Rust

Attribute Macro gotham_restful::search

#[search]
\ No newline at end of file +data-use_system_theme="false">

Attribute Macro gotham_restful::search

#[search]
\ No newline at end of file diff --git a/doc/gotham_restful/attr.update.html b/doc/gotham_restful/attr.update.html index 422cce769..99047c43e 100644 --- a/doc/gotham_restful/attr.update.html +++ b/doc/gotham_restful/attr.update.html @@ -1,3 +1,3 @@ -update in gotham_restful - Rust

Attribute Macro gotham_restful::update

#[update]
\ No newline at end of file +data-use_system_theme="false">

Attribute Macro gotham_restful::update

#[update]
\ No newline at end of file diff --git a/doc/gotham_restful/attr.update_all.html b/doc/gotham_restful/attr.update_all.html index 66bade717..56da5a9a5 100644 --- a/doc/gotham_restful/attr.update_all.html +++ b/doc/gotham_restful/attr.update_all.html @@ -1,3 +1,3 @@ -update_all in gotham_restful - Rust

Attribute Macro gotham_restful::update_all

#[update_all]
\ No newline at end of file +data-use_system_theme="false">

Attribute Macro gotham_restful::update_all

#[update_all]
\ No newline at end of file diff --git a/doc/gotham_restful/cors/enum.Headers.html b/doc/gotham_restful/cors/enum.Headers.html index bac10c826..52b140a6d 100644 --- a/doc/gotham_restful/cors/enum.Headers.html +++ b/doc/gotham_restful/cors/enum.Headers.html @@ -1,34 +1,34 @@ -Headers in gotham_restful::cors - Rust
pub enum Headers {
+data-use_system_theme="false">
pub enum Headers {
     None,
-    List(Vec<HeaderName>),
+    List(Vec<HeaderName>),
     Copy,
 }
Expand description

Specify the allowed headers of the request. It is up to the browser to check that only the allowed headers are sent with the request.

Variants§

§

None

Do not send any Access-Control-Allow-Headers headers.

-
§

List(Vec<HeaderName>)

Set the Access-Control-Allow-Headers header to the following header list. If empty, this -is treated as if it was None.

+
§

List(Vec<HeaderName>)

Set the Access-Control-Allow-Headers header to the following header list. If empty, this +is treated as if it was None.

§

Copy

Copy the Access-Control-Request-Headers header into the Access-Control-Allow-Header header.

-

Trait Implementations§

source§

impl Clone for Headers

source§

fn clone(&self) -> Headers

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Debug for Headers

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl Default for Headers

source§

fn default() -> Self

Returns the “default value” for a type. Read more

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for Twhere - T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for Twhere - T: ?Sized,

const: unstable · source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for Twhere - T: ?Sized,

const: unstable · source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

const: unstable · source§

fn from(t: T) -> T

Returns the argument unchanged.

+

Trait Implementations§

source§

impl Clone for Headers

source§

fn clone(&self) -> Headers

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Debug for Headers

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl Default for Headers

source§

fn default() -> Self

Returns the “default value” for a type. Read more

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for Twhere + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for Twhere + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for Twhere + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

source§

impl<T> Instrument for T

source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an -Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for Twhere - U: From<T>,

const: unstable · source§

fn into(self) -> U

Calls U::from(self).

+Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for Twhere + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of -From<T> for U chooses to do.

+From<T> for U chooses to do.

§

impl<T> IntoSql for T

§

fn into_sql<T>(self) -> Self::Expressionwhere - Self: AsExpression<T> + Sized, - T: SqlType + TypedExpressionType,

Convert self to an expression for Diesel’s query builder. Read more
§

fn as_sql<'a, T>(&'a self) -> <&'a Self as AsExpression<T>>::Expressionwhere - &'a Self: AsExpression<T>, - T: SqlType + TypedExpressionType,

Convert &self to an expression for Diesel’s query builder. Read more
source§

impl<T> Same<T> for T

§

type Output = T

Should always be Self
source§

impl<T> ToOwned for Twhere - T: Clone,

§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T, U> TryFrom<U> for Twhere - U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
const: unstable · source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for Twhere - U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
const: unstable · source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
source§

impl<T> WithSubscriber for T

source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>where - S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a + Self: AsExpression<T> + Sized, + T: SqlType + TypedExpressionType,
Convert self to an expression for Diesel’s query builder. Read more
§

fn as_sql<'a, T>(&'a self) -> <&'a Self as AsExpression<T>>::Expressionwhere + &'a Self: AsExpression<T>, + T: SqlType + TypedExpressionType,

Convert &self to an expression for Diesel’s query builder. Read more
source§

impl<T> Same<T> for T

§

type Output = T

Should always be Self
source§

impl<T> ToOwned for Twhere + T: Clone,

§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T, U> TryFrom<U> for Twhere + U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for Twhere + U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
source§

impl<T> WithSubscriber for T

source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more
\ No newline at end of file diff --git a/doc/gotham_restful/cors/enum.Origin.html b/doc/gotham_restful/cors/enum.Origin.html index 3cc69f9d2..158fec869 100644 --- a/doc/gotham_restful/cors/enum.Origin.html +++ b/doc/gotham_restful/cors/enum.Origin.html @@ -1,35 +1,35 @@ -Origin in gotham_restful::cors - Rust
pub enum Origin {
+data-use_system_theme="false">
pub enum Origin {
     None,
     Star,
-    Single(String),
+    Single(String),
     Copy,
 }
Expand description

Specify the allowed origins of the request. It is up to the browser to check the validity of the origin. This, when sent to the browser, will indicate whether or not the request’s origin was allowed to make the request.

Variants§

§

None

Do not send any Access-Control-Allow-Origin headers.

§

Star

Send Access-Control-Allow-Origin: *. Note that browser will not send credentials.

-
§

Single(String)

Set the Access-Control-Allow-Origin header to a single origin.

+
§

Single(String)

Set the Access-Control-Allow-Origin header to a single origin.

§

Copy

Copy the Origin header into the Access-Control-Allow-Origin header.

-

Trait Implementations§

source§

impl Clone for Origin

source§

fn clone(&self) -> Origin

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Debug for Origin

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl Default for Origin

source§

fn default() -> Self

Returns the “default value” for a type. Read more

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for Twhere - T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for Twhere - T: ?Sized,

const: unstable · source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for Twhere - T: ?Sized,

const: unstable · source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

const: unstable · source§

fn from(t: T) -> T

Returns the argument unchanged.

+

Trait Implementations§

source§

impl Clone for Origin

source§

fn clone(&self) -> Origin

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Debug for Origin

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl Default for Origin

source§

fn default() -> Self

Returns the “default value” for a type. Read more

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for Twhere + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for Twhere + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for Twhere + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

source§

impl<T> Instrument for T

source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an -Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for Twhere - U: From<T>,

const: unstable · source§

fn into(self) -> U

Calls U::from(self).

+Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for Twhere + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of -From<T> for U chooses to do.

+From<T> for U chooses to do.

§

impl<T> IntoSql for T

§

fn into_sql<T>(self) -> Self::Expressionwhere - Self: AsExpression<T> + Sized, - T: SqlType + TypedExpressionType,

Convert self to an expression for Diesel’s query builder. Read more
§

fn as_sql<'a, T>(&'a self) -> <&'a Self as AsExpression<T>>::Expressionwhere - &'a Self: AsExpression<T>, - T: SqlType + TypedExpressionType,

Convert &self to an expression for Diesel’s query builder. Read more
source§

impl<T> Same<T> for T

§

type Output = T

Should always be Self
source§

impl<T> ToOwned for Twhere - T: Clone,

§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T, U> TryFrom<U> for Twhere - U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
const: unstable · source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for Twhere - U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
const: unstable · source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
source§

impl<T> WithSubscriber for T

source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>where - S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a + Self: AsExpression<T> + Sized, + T: SqlType + TypedExpressionType,
Convert self to an expression for Diesel’s query builder. Read more
§

fn as_sql<'a, T>(&'a self) -> <&'a Self as AsExpression<T>>::Expressionwhere + &'a Self: AsExpression<T>, + T: SqlType + TypedExpressionType,

Convert &self to an expression for Diesel’s query builder. Read more
source§

impl<T> Same<T> for T

§

type Output = T

Should always be Self
source§

impl<T> ToOwned for Twhere + T: Clone,

§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T, U> TryFrom<U> for Twhere + U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for Twhere + U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
source§

impl<T> WithSubscriber for T

source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more
\ No newline at end of file diff --git a/doc/gotham_restful/cors/fn.handle_cors.html b/doc/gotham_restful/cors/fn.handle_cors.html index b019f06af..155f7077f 100644 --- a/doc/gotham_restful/cors/fn.handle_cors.html +++ b/doc/gotham_restful/cors/fn.handle_cors.html @@ -1,6 +1,6 @@ -handle_cors in gotham_restful::cors - Rust
pub fn handle_cors(state: &State, res: &mut Response<Body>)
Expand description

Handle CORS for a non-preflight request. This means manipulating the res HTTP headers so that +data-use_system_theme="false">

pub fn handle_cors(state: &State, res: &mut Response<Body>)
Expand description

Handle CORS for a non-preflight request. This means manipulating the res HTTP headers so that the response is aligned with the state’s CorsConfig.

If you are using the Resource type (which is the recommended way), you’ll never have to call this method. However, if you are writing your own handler method, you might want to diff --git a/doc/gotham_restful/cors/index.html b/doc/gotham_restful/cors/index.html index 9a4075c1d..a7156b8d3 100644 --- a/doc/gotham_restful/cors/index.html +++ b/doc/gotham_restful/cors/index.html @@ -1,6 +1,6 @@ -gotham_restful::cors - Rust

Module gotham_restful::cors

source ·

Structs

Fields§

§origin: Origin

The allowed origins.

§headers: Headers

The allowed headers.

-
§max_age: u64

The amount of seconds that the preflight request can be cached.

-
§credentials: bool

Whether or not the request may be made with supplying credentials.

-

Trait Implementations§

source§

impl Clone for CorsConfig

source§

fn clone(&self) -> CorsConfig

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Debug for CorsConfig

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl Default for CorsConfig

source§

fn default() -> CorsConfig

Returns the “default value” for a type. Read more
source§

impl Middleware for CorsConfig

source§

fn call<Chain>(self, state: State, chain: Chain) -> Pin<Box<HandlerFuture>>where - Chain: FnOnce(State) -> Pin<Box<HandlerFuture>>,

Entry point to the middleware. To pass the request on to the application, the middleware -invokes the chain function with the provided state. Read more
source§

impl NewMiddleware for CorsConfig

§

type Instance = CorsConfig

The type of Middleware created by the NewMiddleware.
source§

fn new_middleware(&self) -> Result<Self>

Create and return a new Middleware value.
source§

impl StateData for CorsConfig

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for Twhere - T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for Twhere - T: ?Sized,

const: unstable · source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for Twhere - T: ?Sized,

const: unstable · source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

const: unstable · source§

fn from(t: T) -> T

Returns the argument unchanged.

+
§max_age: u64

The amount of seconds that the preflight request can be cached.

+
§credentials: bool

Whether or not the request may be made with supplying credentials.

+

Trait Implementations§

source§

impl Clone for CorsConfig

source§

fn clone(&self) -> CorsConfig

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Debug for CorsConfig

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl Default for CorsConfig

source§

fn default() -> CorsConfig

Returns the “default value” for a type. Read more
source§

impl Middleware for CorsConfig

source§

fn call<Chain>(self, state: State, chain: Chain) -> Pin<Box<HandlerFuture>>where + Chain: FnOnce(State) -> Pin<Box<HandlerFuture>>,

Entry point to the middleware. To pass the request on to the application, the middleware +invokes the chain function with the provided state. Read more
source§

impl NewMiddleware for CorsConfig

§

type Instance = CorsConfig

The type of Middleware created by the NewMiddleware.
source§

fn new_middleware(&self) -> Result<Self>

Create and return a new Middleware value.
source§

impl StateData for CorsConfig

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for Twhere + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for Twhere + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for Twhere + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

source§

impl<T> FromState for Twhere - T: StateData,

source§

fn try_borrow_from(state: &State) -> Option<&T>

Tries to borrow a value from the State storage. Read more
source§

fn borrow_from(state: &State) -> &T

Borrows a value from the State storage. Read more
source§

fn try_borrow_mut_from(state: &mut State) -> Option<&mut T>

Tries to mutably borrow a value from the State storage. Read more
source§

fn borrow_mut_from(state: &mut State) -> &mut T

Mutably borrows a value from the State storage. Read more
source§

fn try_take_from(state: &mut State) -> Option<T>

Tries to move a value out of the State storage and return ownership. Read more
source§

fn take_from(state: &mut State) -> T

Moves a value out of the State storage and returns ownership. Read more
source§

impl<T> Instrument for T

source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an + T: StateData,
source§

fn try_borrow_from(state: &State) -> Option<&T>

Tries to borrow a value from the State storage. Read more
source§

fn borrow_from(state: &State) -> &T

Borrows a value from the State storage. Read more
source§

fn try_borrow_mut_from(state: &mut State) -> Option<&mut T>

Tries to mutably borrow a value from the State storage. Read more
source§

fn borrow_mut_from(state: &mut State) -> &mut T

Mutably borrows a value from the State storage. Read more
source§

fn try_take_from(state: &mut State) -> Option<T>

Tries to move a value out of the State storage and return ownership. Read more
source§

fn take_from(state: &mut State) -> T

Moves a value out of the State storage and returns ownership. Read more
source§

impl<T> Instrument for T

source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an -Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for Twhere - U: From<T>,

const: unstable · source§

fn into(self) -> U

Calls U::from(self).

+Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for Twhere + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of -From<T> for U chooses to do.

+From<T> for U chooses to do.

§

impl<T> IntoSql for T

§

fn into_sql<T>(self) -> Self::Expressionwhere - Self: AsExpression<T> + Sized, - T: SqlType + TypedExpressionType,

Convert self to an expression for Diesel’s query builder. Read more
§

fn as_sql<'a, T>(&'a self) -> <&'a Self as AsExpression<T>>::Expressionwhere - &'a Self: AsExpression<T>, - T: SqlType + TypedExpressionType,

Convert &self to an expression for Diesel’s query builder. Read more
source§

impl<T> Same<T> for T

§

type Output = T

Should always be Self
source§

impl<T> ToOwned for Twhere - T: Clone,

§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T, U> TryFrom<U> for Twhere - U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
const: unstable · source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for Twhere - U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
const: unstable · source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
source§

impl<T> WithSubscriber for T

source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>where - S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a + Self: AsExpression<T> + Sized, + T: SqlType + TypedExpressionType,
Convert self to an expression for Diesel’s query builder. Read more
§

fn as_sql<'a, T>(&'a self) -> <&'a Self as AsExpression<T>>::Expressionwhere + &'a Self: AsExpression<T>, + T: SqlType + TypedExpressionType,

Convert &self to an expression for Diesel’s query builder. Read more
source§

impl<T> Same<T> for T

§

type Output = T

Should always be Self
source§

impl<T> ToOwned for Twhere + T: Clone,

§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T, U> TryFrom<U> for Twhere + U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for Twhere + U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
source§

impl<T> WithSubscriber for T

source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more
\ No newline at end of file diff --git a/doc/gotham_restful/cors/trait.CorsRoute.html b/doc/gotham_restful/cors/trait.CorsRoute.html index 149d0f00b..aee46fbe5 100644 --- a/doc/gotham_restful/cors/trait.CorsRoute.html +++ b/doc/gotham_restful/cors/trait.CorsRoute.html @@ -1,10 +1,10 @@ -CorsRoute in gotham_restful::cors - Rust
pub trait CorsRoute<C, P>where
-    C: PipelineHandleChain<P> + Copy + Send + Sync + 'static,
-    P: RefUnwindSafe + Send + Sync + 'static,{
+data-use_system_theme="false">
pub trait CorsRoute<C, P>where
+    C: PipelineHandleChain<P> + Copy + Send + Sync + 'static,
+    P: RefUnwindSafe + Send + Sync + 'static,{
     // Required method
-    fn cors(&mut self, path: &str, method: Method);
+    fn cors(&mut self, path: &str, method: Method);
 }
Expand description

Add CORS routing for your path. This is required for handling preflight requests.

Example:

@@ -18,9 +18,9 @@ // Add preflight handling router.cors("/foo", Method::POST); });
-

Required Methods§

source

fn cors(&mut self, path: &str, method: Method)

Handle a preflight request on path for method. To configure the behaviour, use +

Required Methods§

source

fn cors(&mut self, path: &str, method: Method)

Handle a preflight request on path for method. To configure the behaviour, use CorsConfig.

Implementors§

source§

impl<D, C, P> CorsRoute<C, P> for Dwhere D: DrawRoutes<C, P>, - C: PipelineHandleChain<P> + Copy + Send + Sync + 'static, - P: RefUnwindSafe + Send + Sync + 'static,

\ No newline at end of file + C: PipelineHandleChain<P> + Copy + Send + Sync + 'static, + P: RefUnwindSafe + Send + Sync + 'static, \ No newline at end of file diff --git a/doc/gotham_restful/derive.FromBody.html b/doc/gotham_restful/derive.FromBody.html index 6793a3426..83356e5d4 100644 --- a/doc/gotham_restful/derive.FromBody.html +++ b/doc/gotham_restful/derive.FromBody.html @@ -1,3 +1,3 @@ -FromBody in gotham_restful - Rust

Derive Macro gotham_restful::FromBody

#[derive(FromBody)]
\ No newline at end of file +data-use_system_theme="false">

Derive Macro gotham_restful::FromBody

#[derive(FromBody)]
\ No newline at end of file diff --git a/doc/gotham_restful/derive.RequestBody.html b/doc/gotham_restful/derive.RequestBody.html index 55ece2557..61ea5fd4b 100644 --- a/doc/gotham_restful/derive.RequestBody.html +++ b/doc/gotham_restful/derive.RequestBody.html @@ -1,6 +1,6 @@ -RequestBody in gotham_restful - Rust

Derive Macro gotham_restful::RequestBody

#[derive(RequestBody)]
+data-use_system_theme="false">

Derive Macro gotham_restful::RequestBody

#[derive(RequestBody)]
 {
     // Attributes available to this derive:
     #[supported_types]
diff --git a/doc/gotham_restful/derive.Resource.html b/doc/gotham_restful/derive.Resource.html
index 405155f11..8ca7cc3fb 100644
--- a/doc/gotham_restful/derive.Resource.html
+++ b/doc/gotham_restful/derive.Resource.html
@@ -1,6 +1,6 @@
-Resource in gotham_restful - Rust

Derive Macro gotham_restful::Resource

#[derive(Resource)]
+data-use_system_theme="false">

Derive Macro gotham_restful::Resource

#[derive(Resource)]
 {
     // Attributes available to this derive:
     #[resource]
diff --git a/doc/gotham_restful/derive.ResourceError.html b/doc/gotham_restful/derive.ResourceError.html
index d01bac83c..8c966c1c9 100644
--- a/doc/gotham_restful/derive.ResourceError.html
+++ b/doc/gotham_restful/derive.ResourceError.html
@@ -1,6 +1,6 @@
-ResourceError in gotham_restful - Rust

Derive Macro gotham_restful::ResourceError

#[derive(ResourceError)]
+data-use_system_theme="false">

Derive Macro gotham_restful::ResourceError

#[derive(ResourceError)]
 {
     // Attributes available to this derive:
     #[display]
diff --git a/doc/gotham_restful/enum.AuthErrorOrOther.html b/doc/gotham_restful/enum.AuthErrorOrOther.html
index bb2cb36cd..d3a1c20fb 100644
--- a/doc/gotham_restful/enum.AuthErrorOrOther.html
+++ b/doc/gotham_restful/enum.AuthErrorOrOther.html
@@ -1,37 +1,37 @@
-AuthErrorOrOther in gotham_restful - Rust
pub enum AuthErrorOrOther<E> {
+data-use_system_theme="false">
pub enum AuthErrorOrOther<E> {
     Forbidden(AuthError),
     Other(E),
 }
Expand description

This is an error type that either yields a 403 Forbidden response if produced from an authentication error, or delegates to another error type. This type is best used with AuthResult.

-

Variants§

§

Forbidden(AuthError)

§

Other(E)

Trait Implementations§

source§

impl<E: Clone> Clone for AuthErrorOrOther<E>

source§

fn clone(&self) -> AuthErrorOrOther<E>

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl<E: Debug> Debug for AuthErrorOrOther<E>

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl<E> From<AuthError> for AuthErrorOrOther<E>where - AuthError: IntoResponseError,

source§

fn from(arg0: AuthError) -> Self

Converts to this type from the input type.
source§

impl<E, F> From<F> for AuthErrorOrOther<E>where - F: Sealed + Into<E>,

source§

fn from(err: F) -> Self

Converts to this type from the input type.
source§

impl<E> IntoResponseError for AuthErrorOrOther<E>where - AuthError: IntoResponseError,

Auto Trait Implementations§

§

impl<E> RefUnwindSafe for AuthErrorOrOther<E>where - E: RefUnwindSafe,

§

impl<E> Send for AuthErrorOrOther<E>where - E: Send,

§

impl<E> Sync for AuthErrorOrOther<E>where - E: Sync,

§

impl<E> Unpin for AuthErrorOrOther<E>where - E: Unpin,

§

impl<E> UnwindSafe for AuthErrorOrOther<E>where - E: UnwindSafe,

Blanket Implementations§

source§

impl<T> Any for Twhere - T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for Twhere - T: ?Sized,

const: unstable · source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for Twhere - T: ?Sized,

const: unstable · source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<!> for T

const: unstable · source§

fn from(t: !) -> T

Converts to this type from the input type.
source§

impl<T> From<T> for T

const: unstable · source§

fn from(t: T) -> T

Returns the argument unchanged.

+

Variants§

§

Forbidden(AuthError)

§

Other(E)

Trait Implementations§

source§

impl<E: Clone> Clone for AuthErrorOrOther<E>

source§

fn clone(&self) -> AuthErrorOrOther<E>

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl<E: Debug> Debug for AuthErrorOrOther<E>

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl<E> From<AuthError> for AuthErrorOrOther<E>where + AuthError: IntoResponseError,

source§

fn from(arg0: AuthError) -> Self

Converts to this type from the input type.
source§

impl<E, F> From<F> for AuthErrorOrOther<E>where + F: Sealed + Into<E>,

source§

fn from(err: F) -> Self

Converts to this type from the input type.
source§

impl<E> IntoResponseError for AuthErrorOrOther<E>where + AuthError: IntoResponseError,

Auto Trait Implementations§

§

impl<E> RefUnwindSafe for AuthErrorOrOther<E>where + E: RefUnwindSafe,

§

impl<E> Send for AuthErrorOrOther<E>where + E: Send,

§

impl<E> Sync for AuthErrorOrOther<E>where + E: Sync,

§

impl<E> Unpin for AuthErrorOrOther<E>where + E: Unpin,

§

impl<E> UnwindSafe for AuthErrorOrOther<E>where + E: UnwindSafe,

Blanket Implementations§

source§

impl<T> Any for Twhere + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for Twhere + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for Twhere + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<!> for T

source§

fn from(t: !) -> T

Converts to this type from the input type.
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

source§

impl<T> Instrument for T

source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an -Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for Twhere - U: From<T>,

const: unstable · source§

fn into(self) -> U

Calls U::from(self).

+Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for Twhere + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of -From<T> for U chooses to do.

+From<T> for U chooses to do.

§

impl<T> IntoSql for T

§

fn into_sql<T>(self) -> Self::Expressionwhere - Self: AsExpression<T> + Sized, - T: SqlType + TypedExpressionType,

Convert self to an expression for Diesel’s query builder. Read more
§

fn as_sql<'a, T>(&'a self) -> <&'a Self as AsExpression<T>>::Expressionwhere - &'a Self: AsExpression<T>, - T: SqlType + TypedExpressionType,

Convert &self to an expression for Diesel’s query builder. Read more
source§

impl<T> Same<T> for T

§

type Output = T

Should always be Self
source§

impl<T> ToOwned for Twhere - T: Clone,

§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T, U> TryFrom<U> for Twhere - U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
const: unstable · source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for Twhere - U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
const: unstable · source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
source§

impl<T> WithSubscriber for T

source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>where - S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a + Self: AsExpression<T> + Sized, + T: SqlType + TypedExpressionType,
Convert self to an expression for Diesel’s query builder. Read more
§

fn as_sql<'a, T>(&'a self) -> <&'a Self as AsExpression<T>>::Expressionwhere + &'a Self: AsExpression<T>, + T: SqlType + TypedExpressionType,

Convert &self to an expression for Diesel’s query builder. Read more
source§

impl<T> Same<T> for T

§

type Output = T

Should always be Self
source§

impl<T> ToOwned for Twhere + T: Clone,

§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T, U> TryFrom<U> for Twhere + U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for Twhere + U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
source§

impl<T> WithSubscriber for T

source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more
\ No newline at end of file diff --git a/doc/gotham_restful/enum.AuthSource.html b/doc/gotham_restful/enum.AuthSource.html index f9127eb26..bf5cdc21c 100644 --- a/doc/gotham_restful/enum.AuthSource.html +++ b/doc/gotham_restful/enum.AuthSource.html @@ -1,34 +1,34 @@ -AuthSource in gotham_restful - Rust
pub enum AuthSource {
-    Cookie(String),
+data-use_system_theme="false">
pub enum AuthSource {
+    Cookie(String),
     Header(HeaderName),
     AuthorizationHeader,
 }
Expand description

The source of the authentication token in the request.

-

Variants§

§

Cookie(String)

Take the token from a cookie with the given name.

+

Variants§

§

Cookie(String)

Take the token from a cookie with the given name.

§

Header(HeaderName)

Take the token from a header with the given name.

§

AuthorizationHeader

Take the token from the HTTP Authorization header. This is different from Header("Authorization") as it will follow the scheme param format from the HTTP specification. The scheme will be discarded, so its value doesn’t matter.

-

Trait Implementations§

source§

impl Clone for AuthSource

source§

fn clone(&self) -> AuthSource

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Debug for AuthSource

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl StateData for AuthSource

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for Twhere - T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for Twhere - T: ?Sized,

const: unstable · source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for Twhere - T: ?Sized,

const: unstable · source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

const: unstable · source§

fn from(t: T) -> T

Returns the argument unchanged.

+

Trait Implementations§

source§

impl Clone for AuthSource

source§

fn clone(&self) -> AuthSource

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Debug for AuthSource

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl StateData for AuthSource

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for Twhere + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for Twhere + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for Twhere + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

source§

impl<T> FromState for Twhere - T: StateData,

source§

fn try_borrow_from(state: &State) -> Option<&T>

Tries to borrow a value from the State storage. Read more
source§

fn borrow_from(state: &State) -> &T

Borrows a value from the State storage. Read more
source§

fn try_borrow_mut_from(state: &mut State) -> Option<&mut T>

Tries to mutably borrow a value from the State storage. Read more
source§

fn borrow_mut_from(state: &mut State) -> &mut T

Mutably borrows a value from the State storage. Read more
source§

fn try_take_from(state: &mut State) -> Option<T>

Tries to move a value out of the State storage and return ownership. Read more
source§

fn take_from(state: &mut State) -> T

Moves a value out of the State storage and returns ownership. Read more
source§

impl<T> Instrument for T

source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an + T: StateData,
source§

fn try_borrow_from(state: &State) -> Option<&T>

Tries to borrow a value from the State storage. Read more
source§

fn borrow_from(state: &State) -> &T

Borrows a value from the State storage. Read more
source§

fn try_borrow_mut_from(state: &mut State) -> Option<&mut T>

Tries to mutably borrow a value from the State storage. Read more
source§

fn borrow_mut_from(state: &mut State) -> &mut T

Mutably borrows a value from the State storage. Read more
source§

fn try_take_from(state: &mut State) -> Option<T>

Tries to move a value out of the State storage and return ownership. Read more
source§

fn take_from(state: &mut State) -> T

Moves a value out of the State storage and returns ownership. Read more
source§

impl<T> Instrument for T

source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an -Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for Twhere - U: From<T>,

const: unstable · source§

fn into(self) -> U

Calls U::from(self).

+Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for Twhere + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of -From<T> for U chooses to do.

+From<T> for U chooses to do.

§

impl<T> IntoSql for T

§

fn into_sql<T>(self) -> Self::Expressionwhere - Self: AsExpression<T> + Sized, - T: SqlType + TypedExpressionType,

Convert self to an expression for Diesel’s query builder. Read more
§

fn as_sql<'a, T>(&'a self) -> <&'a Self as AsExpression<T>>::Expressionwhere - &'a Self: AsExpression<T>, - T: SqlType + TypedExpressionType,

Convert &self to an expression for Diesel’s query builder. Read more
source§

impl<T> Same<T> for T

§

type Output = T

Should always be Self
source§

impl<T> ToOwned for Twhere - T: Clone,

§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T, U> TryFrom<U> for Twhere - U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
const: unstable · source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for Twhere - U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
const: unstable · source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
source§

impl<T> WithSubscriber for T

source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>where - S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a + Self: AsExpression<T> + Sized, + T: SqlType + TypedExpressionType,
Convert self to an expression for Diesel’s query builder. Read more
§

fn as_sql<'a, T>(&'a self) -> <&'a Self as AsExpression<T>>::Expressionwhere + &'a Self: AsExpression<T>, + T: SqlType + TypedExpressionType,

Convert &self to an expression for Diesel’s query builder. Read more
source§

impl<T> Same<T> for T

§

type Output = T

Should always be Self
source§

impl<T> ToOwned for Twhere + T: Clone,

§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T, U> TryFrom<U> for Twhere + U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for Twhere + U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
source§

impl<T> WithSubscriber for T

source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more
\ No newline at end of file diff --git a/doc/gotham_restful/enum.AuthStatus.html b/doc/gotham_restful/enum.AuthStatus.html index 27581df9d..087823202 100644 --- a/doc/gotham_restful/enum.AuthStatus.html +++ b/doc/gotham_restful/enum.AuthStatus.html @@ -1,6 +1,6 @@ -AuthStatus in gotham_restful - Rust
pub enum AuthStatus<T: Send + 'static> {
+data-use_system_theme="false">
pub enum AuthStatus<T: Send + 'static> {
     Unknown,
     Unauthenticated,
     Invalid(Error),
@@ -14,28 +14,28 @@
 included error.

§

Authenticated(T)

The request has been performed with a valid authentication. The claims that were decoded from the token are attached.

-

Implementations§

source§

impl<T: Send + 'static> AuthStatus<T>

source

pub fn ok(self) -> Result<T, AuthError>

Trait Implementations§

source§

impl<T> Clone for AuthStatus<T>where - T: Clone + Send + 'static,

source§

fn clone(&self) -> Self

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl<T: Debug + Send + 'static> Debug for AuthStatus<T>

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl<T: Send + 'static> StateData for AuthStatus<T>

Auto Trait Implementations§

§

impl<T> !RefUnwindSafe for AuthStatus<T>

§

impl<T> Send for AuthStatus<T>

§

impl<T> Sync for AuthStatus<T>where - T: Sync,

§

impl<T> Unpin for AuthStatus<T>where - T: Unpin,

§

impl<T> !UnwindSafe for AuthStatus<T>

Blanket Implementations§

source§

impl<T> Any for Twhere - T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for Twhere - T: ?Sized,

const: unstable · source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for Twhere - T: ?Sized,

const: unstable · source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

const: unstable · source§

fn from(t: T) -> T

Returns the argument unchanged.

+

Implementations§

source§

impl<T: Send + 'static> AuthStatus<T>

source

pub fn ok(self) -> Result<T, AuthError>

Trait Implementations§

source§

impl<T> Clone for AuthStatus<T>where + T: Clone + Send + 'static,

source§

fn clone(&self) -> Self

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl<T: Debug + Send + 'static> Debug for AuthStatus<T>

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl<T: Send + 'static> StateData for AuthStatus<T>

Auto Trait Implementations§

§

impl<T> !RefUnwindSafe for AuthStatus<T>

§

impl<T> Send for AuthStatus<T>

§

impl<T> Sync for AuthStatus<T>where + T: Sync,

§

impl<T> Unpin for AuthStatus<T>where + T: Unpin,

§

impl<T> !UnwindSafe for AuthStatus<T>

Blanket Implementations§

source§

impl<T> Any for Twhere + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for Twhere + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for Twhere + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

source§

impl<T> FromState for Twhere - T: StateData,

source§

fn try_borrow_from(state: &State) -> Option<&T>

Tries to borrow a value from the State storage. Read more
source§

fn borrow_from(state: &State) -> &T

Borrows a value from the State storage. Read more
source§

fn try_borrow_mut_from(state: &mut State) -> Option<&mut T>

Tries to mutably borrow a value from the State storage. Read more
source§

fn borrow_mut_from(state: &mut State) -> &mut T

Mutably borrows a value from the State storage. Read more
source§

fn try_take_from(state: &mut State) -> Option<T>

Tries to move a value out of the State storage and return ownership. Read more
source§

fn take_from(state: &mut State) -> T

Moves a value out of the State storage and returns ownership. Read more
source§

impl<T> Instrument for T

source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an + T: StateData,
source§

fn try_borrow_from(state: &State) -> Option<&T>

Tries to borrow a value from the State storage. Read more
source§

fn borrow_from(state: &State) -> &T

Borrows a value from the State storage. Read more
source§

fn try_borrow_mut_from(state: &mut State) -> Option<&mut T>

Tries to mutably borrow a value from the State storage. Read more
source§

fn borrow_mut_from(state: &mut State) -> &mut T

Mutably borrows a value from the State storage. Read more
source§

fn try_take_from(state: &mut State) -> Option<T>

Tries to move a value out of the State storage and return ownership. Read more
source§

fn take_from(state: &mut State) -> T

Moves a value out of the State storage and returns ownership. Read more
source§

impl<T> Instrument for T

source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an -Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for Twhere - U: From<T>,

const: unstable · source§

fn into(self) -> U

Calls U::from(self).

+Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for Twhere + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of -From<T> for U chooses to do.

+From<T> for U chooses to do.

§

impl<T> IntoSql for T

§

fn into_sql<T>(self) -> Self::Expressionwhere - Self: AsExpression<T> + Sized, - T: SqlType + TypedExpressionType,

Convert self to an expression for Diesel’s query builder. Read more
§

fn as_sql<'a, T>(&'a self) -> <&'a Self as AsExpression<T>>::Expressionwhere - &'a Self: AsExpression<T>, - T: SqlType + TypedExpressionType,

Convert &self to an expression for Diesel’s query builder. Read more
source§

impl<T> Same<T> for T

§

type Output = T

Should always be Self
source§

impl<T> ToOwned for Twhere - T: Clone,

§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T, U> TryFrom<U> for Twhere - U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
const: unstable · source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for Twhere - U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
const: unstable · source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
source§

impl<T> WithSubscriber for T

source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>where - S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a + Self: AsExpression<T> + Sized, + T: SqlType + TypedExpressionType,
Convert self to an expression for Diesel’s query builder. Read more
§

fn as_sql<'a, T>(&'a self) -> <&'a Self as AsExpression<T>>::Expressionwhere + &'a Self: AsExpression<T>, + T: SqlType + TypedExpressionType,

Convert &self to an expression for Diesel’s query builder. Read more
source§

impl<T> Same<T> for T

§

type Output = T

Should always be Self
source§

impl<T> ToOwned for Twhere + T: Clone,

§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T, U> TryFrom<U> for Twhere + U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for Twhere + U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
source§

impl<T> WithSubscriber for T

source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more
\ No newline at end of file diff --git a/doc/gotham_restful/index.html b/doc/gotham_restful/index.html index e0968f4ae..b509fcc49 100644 --- a/doc/gotham_restful/index.html +++ b/doc/gotham_restful/index.html @@ -1,6 +1,6 @@ -gotham_restful - Rust

Crate gotham_restful

source ·
Expand description

This crate is an extension to the popular gotham web framework for Rust. It allows you to +data-use_system_theme="false">

Crate gotham_restful

source ·
Expand description

This crate is an extension to the popular gotham web framework for Rust. It allows you to create resources with assigned endpoints that aim to be a more convenient way of creating handlers for requests.

Features

@@ -79,7 +79,7 @@

Custom Endpoints

Arguments

Some endpoints require arguments. Those should be

source§

impl<T> Same<T> for T

§

type Output = T

Should always be Self
source§

impl<T> ToOwned for Twhere + T: Clone,

§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T, U> TryFrom<U> for Twhere + U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for Twhere + U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
source§

impl<T> WithSubscriber for T

source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more
\ No newline at end of file diff --git a/doc/gotham_restful/struct.AuthMiddleware.html b/doc/gotham_restful/struct.AuthMiddleware.html index 092c33243..13bb462d2 100644 --- a/doc/gotham_restful/struct.AuthMiddleware.html +++ b/doc/gotham_restful/struct.AuthMiddleware.html @@ -1,6 +1,6 @@ -AuthMiddleware in gotham_restful - Rust
pub struct AuthMiddleware<Data, Handler> { /* private fields */ }
Expand description

This is the auth middleware. To use it, first make sure you have the auth feature enabled. Then +data-use_system_theme="false">

pub struct AuthMiddleware<Data, Handler> { /* private fields */ }
Expand description

This is the auth middleware. To use it, first make sure you have the auth feature enabled. Then simply add it to your pipeline and request it inside your handler:

#[derive(Resource)]
@@ -33,47 +33,47 @@
 	);
 }

Implementations§

source§

impl<Data, Handler> AuthMiddleware<Data, Handler>where - Data: DeserializeOwned + Send, - Handler: AuthHandler<Data> + Default,

source

pub fn from_source(source: AuthSource) -> Self

source§

impl<Data, Handler> AuthMiddleware<Data, Handler>where - Data: DeserializeOwned + Send, + Data: DeserializeOwned + Send, + Handler: AuthHandler<Data> + Default,

source

pub fn from_source(source: AuthSource) -> Self

source§

impl<Data, Handler> AuthMiddleware<Data, Handler>where + Data: DeserializeOwned + Send, Handler: AuthHandler<Data>,

source

pub fn new( source: AuthSource, validation: AuthValidation, handler: Handler -) -> Self

Trait Implementations§

source§

impl<Data, Handler> Clone for AuthMiddleware<Data, Handler>where - Handler: Clone,

source§

fn clone(&self) -> Self

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl<Data: Debug, Handler: Debug> Debug for AuthMiddleware<Data, Handler>

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl<Data, Handler> Middleware for AuthMiddleware<Data, Handler>where - Data: DeserializeOwned + Send + 'static, - Handler: AuthHandler<Data>,

source§

fn call<Chain>(self, state: State, chain: Chain) -> Pin<Box<HandlerFuture>>where - Chain: FnOnce(State) -> Pin<Box<HandlerFuture>>,

Entry point to the middleware. To pass the request on to the application, the middleware +) -> Self

Trait Implementations§

source§

impl<Data, Handler> Clone for AuthMiddleware<Data, Handler>where + Handler: Clone,

source§

fn clone(&self) -> Self

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl<Data: Debug, Handler: Debug> Debug for AuthMiddleware<Data, Handler>

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl<Data, Handler> Middleware for AuthMiddleware<Data, Handler>where + Data: DeserializeOwned + Send + 'static, + Handler: AuthHandler<Data>,

source§

fn call<Chain>(self, state: State, chain: Chain) -> Pin<Box<HandlerFuture>>where + Chain: FnOnce(State) -> Pin<Box<HandlerFuture>>,

Entry point to the middleware. To pass the request on to the application, the middleware invokes the chain function with the provided state. Read more
source§

impl<Data, Handler> NewMiddleware for AuthMiddleware<Data, Handler>where - Self: Clone + Middleware + Sync + RefUnwindSafe,

§

type Instance = AuthMiddleware<Data, Handler>

The type of Middleware created by the NewMiddleware.
source§

fn new_middleware(&self) -> Result<Self>

Create and return a new Middleware value.

Auto Trait Implementations§

§

impl<Data, Handler> RefUnwindSafe for AuthMiddleware<Data, Handler>where - Data: RefUnwindSafe, - Handler: RefUnwindSafe,

§

impl<Data, Handler> Send for AuthMiddleware<Data, Handler>where - Data: Send, - Handler: Send,

§

impl<Data, Handler> Sync for AuthMiddleware<Data, Handler>where - Data: Sync, - Handler: Sync,

§

impl<Data, Handler> Unpin for AuthMiddleware<Data, Handler>where - Data: Unpin, - Handler: Unpin,

§

impl<Data, Handler> UnwindSafe for AuthMiddleware<Data, Handler>where - Data: UnwindSafe, - Handler: UnwindSafe,

Blanket Implementations§

source§

impl<T> Any for Twhere - T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for Twhere - T: ?Sized,

const: unstable · source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for Twhere - T: ?Sized,

const: unstable · source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

const: unstable · source§

fn from(t: T) -> T

Returns the argument unchanged.

+ Self: Clone + Middleware + Sync + RefUnwindSafe,
§

type Instance = AuthMiddleware<Data, Handler>

The type of Middleware created by the NewMiddleware.
source§

fn new_middleware(&self) -> Result<Self>

Create and return a new Middleware value.

Auto Trait Implementations§

§

impl<Data, Handler> RefUnwindSafe for AuthMiddleware<Data, Handler>where + Data: RefUnwindSafe, + Handler: RefUnwindSafe,

§

impl<Data, Handler> Send for AuthMiddleware<Data, Handler>where + Data: Send, + Handler: Send,

§

impl<Data, Handler> Sync for AuthMiddleware<Data, Handler>where + Data: Sync, + Handler: Sync,

§

impl<Data, Handler> Unpin for AuthMiddleware<Data, Handler>where + Data: Unpin, + Handler: Unpin,

§

impl<Data, Handler> UnwindSafe for AuthMiddleware<Data, Handler>where + Data: UnwindSafe, + Handler: UnwindSafe,

Blanket Implementations§

source§

impl<T> Any for Twhere + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for Twhere + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for Twhere + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

source§

impl<T> Instrument for T

source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an -Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for Twhere - U: From<T>,

const: unstable · source§

fn into(self) -> U

Calls U::from(self).

+Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for Twhere + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of -From<T> for U chooses to do.

+From<T> for U chooses to do.

§

impl<T> IntoSql for T

§

fn into_sql<T>(self) -> Self::Expressionwhere - Self: AsExpression<T> + Sized, - T: SqlType + TypedExpressionType,

Convert self to an expression for Diesel’s query builder. Read more
§

fn as_sql<'a, T>(&'a self) -> <&'a Self as AsExpression<T>>::Expressionwhere - &'a Self: AsExpression<T>, - T: SqlType + TypedExpressionType,

Convert &self to an expression for Diesel’s query builder. Read more
source§

impl<T> Same<T> for T

§

type Output = T

Should always be Self
source§

impl<T> ToOwned for Twhere - T: Clone,

§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T, U> TryFrom<U> for Twhere - U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
const: unstable · source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for Twhere - U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
const: unstable · source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
source§

impl<T> WithSubscriber for T

source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>where - S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a + Self: AsExpression<T> + Sized, + T: SqlType + TypedExpressionType,
Convert self to an expression for Diesel’s query builder. Read more
§

fn as_sql<'a, T>(&'a self) -> <&'a Self as AsExpression<T>>::Expressionwhere + &'a Self: AsExpression<T>, + T: SqlType + TypedExpressionType,

Convert &self to an expression for Diesel’s query builder. Read more
source§

impl<T> Same<T> for T

§

type Output = T

Should always be Self
source§

impl<T> ToOwned for Twhere + T: Clone,

§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T, U> TryFrom<U> for Twhere + U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for Twhere + U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
source§

impl<T> WithSubscriber for T

source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more
\ No newline at end of file diff --git a/doc/gotham_restful/struct.NoContent.html b/doc/gotham_restful/struct.NoContent.html index 0becf1d0a..9dae1b626 100644 --- a/doc/gotham_restful/struct.NoContent.html +++ b/doc/gotham_restful/struct.NoContent.html @@ -1,6 +1,6 @@ -NoContent in gotham_restful - Rust
pub struct NoContent { /* private fields */ }
Expand description

This is the return type of a resource that doesn’t actually return something. It will result +data-use_system_theme="false">

pub struct NoContent { /* private fields */ }
Expand description

This is the return type of a resource that doesn’t actually return something. It will result in a 204 No Content answer by default. You don’t need to use this type directly if using the function attributes:

@@ -10,28 +10,29 @@ }

Implementations§

source§

impl NoContent

source

pub fn header<K: IntoHeaderName>(&mut self, name: K, value: HeaderValue)

Set a custom HTTP header. If a header with this name was set before, its value is being updated.

source

pub fn headers_mut(&mut self) -> &mut HeaderMap

Allow manipulating HTTP headers.

-

Trait Implementations§

source§

impl Clone for NoContent

source§

fn clone(&self) -> NoContent

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Debug for NoContent

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl Default for NoContent

source§

fn default() -> NoContent

Returns the “default value” for a type. Read more
source§

impl From<()> for NoContent

source§

fn from(_: ()) -> Self

Converts to this type from the input type.
source§

impl IntoResponse for NoContent

Trait Implementations§

source§

impl Clone for NoContent

source§

fn clone(&self) -> NoContent

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Debug for NoContent

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl Default for NoContent

source§

fn default() -> NoContent

Returns the “default value” for a type. Read more
source§

impl From<()> for NoContent

source§

fn from(_: ()) -> Self

Converts to this type from the input type.
source§

impl IntoResponse for NoContent

source§

fn into_response( self -) -> Pin<Box<dyn Future<Output = Result<Response, Self::Err>> + Send>>

This will always be a 204 No Content together with an empty string.

-
§

type Err = Error

source§

fn accepted_types() -> Option<Vec<Mime>>

Return a list of supported mime types.
source§

impl ResponseSchema for NoContent

source§

fn schema(code: StatusCode) -> OpenapiSchema

Returns the schema of the () type.

-
source§

fn status_codes() -> Vec<StatusCode>

All status codes returned by this response. Returns [StatusCode::OK] by default.

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for Twhere - T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for Twhere - T: ?Sized,

const: unstable · source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for Twhere - T: ?Sized,

const: unstable · source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

const: unstable · source§

fn from(t: T) -> T

Returns the argument unchanged.

+) -> Pin<Box<dyn Future<Output = Result<Response, Self::Err>> + Send>>

This will always be a 204 No Content together with an empty string.

+
§

type Err = Error

source§

fn accepted_types() -> Option<Vec<Mime>>

Return a list of supported mime types.
source§

impl ResponseSchema for NoContent

source§

fn schema(code: StatusCode) -> OpenapiSchema

Returns the schema of the () type.

+
source§

fn status_codes() -> Vec<StatusCode>

All status codes returned by this response. Returns [StatusCode::OK] by default.

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for Twhere + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for Twhere + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for Twhere + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

source§

impl<T> Instrument for T

source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an -Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for Twhere - U: From<T>,

const: unstable · source§

fn into(self) -> U

Calls U::from(self).

+Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for Twhere + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of -From<T> for U chooses to do.

+From<T> for U chooses to do.

§

impl<T> IntoSql for T

§

fn into_sql<T>(self) -> Self::Expressionwhere - Self: AsExpression<T> + Sized, - T: SqlType + TypedExpressionType,

Convert self to an expression for Diesel’s query builder. Read more
§

fn as_sql<'a, T>(&'a self) -> <&'a Self as AsExpression<T>>::Expressionwhere - &'a Self: AsExpression<T>, - T: SqlType + TypedExpressionType,

Convert &self to an expression for Diesel’s query builder. Read more
source§

impl<T> Same<T> for T

§

type Output = T

Should always be Self
source§

impl<T> ToOwned for Twhere - T: Clone,

§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T, U> TryFrom<U> for Twhere - U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
const: unstable · source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for Twhere - U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
const: unstable · source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
source§

impl<T> WithSubscriber for T

source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>where - S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a + Self: AsExpression<T> + Sized, + T: SqlType + TypedExpressionType,
Convert self to an expression for Diesel’s query builder. Read more
§

fn as_sql<'a, T>(&'a self) -> <&'a Self as AsExpression<T>>::Expressionwhere + &'a Self: AsExpression<T>, + T: SqlType + TypedExpressionType,

Convert &self to an expression for Diesel’s query builder. Read more
source§

impl<T> Same<T> for T

§

type Output = T

Should always be Self
source§

impl<T> ToOwned for Twhere + T: Clone,

§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T, U> TryFrom<U> for Twhere + U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for Twhere + U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
source§

impl<T> WithSubscriber for T

source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a -WithDispatch wrapper. Read more
\ No newline at end of file +WithDispatch wrapper. Read more
source§

impl<R> IntoResponseWithSchema for Rwhere + R: IntoResponse + ResponseSchema,

\ No newline at end of file diff --git a/doc/gotham_restful/struct.NoopExtractor.html b/doc/gotham_restful/struct.NoopExtractor.html index a04af0d91..3ecfb0bf2 100644 --- a/doc/gotham_restful/struct.NoopExtractor.html +++ b/doc/gotham_restful/struct.NoopExtractor.html @@ -1,31 +1,38 @@ -NoopExtractor in gotham_restful - Rust
pub struct NoopExtractor;
Expand description

A no-op extractor that can be used as a default type for Endpoint::Placeholders and +data-use_system_theme="false">

pub struct NoopExtractor;
Expand description

A no-op extractor that can be used as a default type for Endpoint::Placeholders and Endpoint::Params.

-

Trait Implementations§

source§

impl Clone for NoopExtractor

source§

fn clone(&self) -> NoopExtractor

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Debug for NoopExtractor

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl<'de> Deserialize<'de> for NoopExtractor

source§

fn deserialize<D: Deserializer<'de>>(_: D) -> Result<Self, D::Error>

Deserialize this value from the given Serde deserializer. Read more
source§

impl OpenapiType for NoopExtractor

source§

fn visit_type<V: Visitor>(visitor: &mut V)

§

fn schema() -> OpenapiSchema

source§

impl StaticResponseExtender for NoopExtractor

§

type ResBody = Body

The type of the response body. Almost always hyper::Body.
source§

fn extend(_: &mut State, _: &mut Response<Body>)

Extend the response.
source§

impl Copy for NoopExtractor

source§

impl StateData for NoopExtractor

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for Twhere - T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for Twhere - T: ?Sized,

const: unstable · source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for Twhere - T: ?Sized,

const: unstable · source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

const: unstable · source§

fn from(t: T) -> T

Returns the argument unchanged.

-
source§

impl<T> FromState for Twhere - T: StateData,

source§

fn try_borrow_from(state: &State) -> Option<&T>

Tries to borrow a value from the State storage. Read more
source§

fn borrow_from(state: &State) -> &T

Borrows a value from the State storage. Read more
source§

fn try_borrow_mut_from(state: &mut State) -> Option<&mut T>

Tries to mutably borrow a value from the State storage. Read more
source§

fn borrow_mut_from(state: &mut State) -> &mut T

Mutably borrows a value from the State storage. Read more
source§

fn try_take_from(state: &mut State) -> Option<T>

Tries to move a value out of the State storage and return ownership. Read more
source§

fn take_from(state: &mut State) -> T

Moves a value out of the State storage and returns ownership. Read more
source§

impl<T> Instrument for T

source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an +

Trait Implementations§

source§

impl Clone for NoopExtractor

source§

fn clone(&self) -> NoopExtractor

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Debug for NoopExtractor

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl<'de> Deserialize<'de> for NoopExtractor

source§

fn deserialize<D: Deserializer<'de>>(_: D) -> Result<Self, D::Error>

Deserialize this value from the given Serde deserializer. Read more
source§

impl OpenapiType for NoopExtractor

source§

fn visit_type<V: Visitor>(visitor: &mut V)

§

fn schema() -> OpenapiSchema

source§

impl StaticResponseExtender for NoopExtractor

§

type ResBody = Body

The type of the response body. Almost always hyper::Body.
source§

fn extend(_: &mut State, _: &mut Response<Body>)

Extend the response.
source§

impl Copy for NoopExtractor

source§

impl StateData for NoopExtractor

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for Twhere + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for Twhere + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for Twhere + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
source§

impl<T> FromBody for Twhere + T: DeserializeOwned,

§

type Err = Error

The error type returned by the conversion if it was unsuccessfull. When using the derive +macro, there is no way to trigger an error, so std::convert::Infallible is used here. +However, this might change in the future.
source§

fn from_body( + body: Bytes, + _content_type: Mime +) -> Result<T, <T as FromBody>::Err>

Perform the conversion.
source§

impl<T> FromState for Twhere + T: StateData,

source§

fn try_borrow_from(state: &State) -> Option<&T>

Tries to borrow a value from the State storage. Read more
source§

fn borrow_from(state: &State) -> &T

Borrows a value from the State storage. Read more
source§

fn try_borrow_mut_from(state: &mut State) -> Option<&mut T>

Tries to mutably borrow a value from the State storage. Read more
source§

fn borrow_mut_from(state: &mut State) -> &mut T

Mutably borrows a value from the State storage. Read more
source§

fn try_take_from(state: &mut State) -> Option<T>

Tries to move a value out of the State storage and return ownership. Read more
source§

fn take_from(state: &mut State) -> T

Moves a value out of the State storage and returns ownership. Read more
source§

impl<T> Instrument for T

source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an -Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for Twhere - U: From<T>,

const: unstable · source§

fn into(self) -> U

Calls U::from(self).

+Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for Twhere + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of -From<T> for U chooses to do.

+From<T> for U chooses to do.

§

impl<T> IntoSql for T

§

fn into_sql<T>(self) -> Self::Expressionwhere - Self: AsExpression<T> + Sized, - T: SqlType + TypedExpressionType,

Convert self to an expression for Diesel’s query builder. Read more
§

fn as_sql<'a, T>(&'a self) -> <&'a Self as AsExpression<T>>::Expressionwhere - &'a Self: AsExpression<T>, - T: SqlType + TypedExpressionType,

Convert &self to an expression for Diesel’s query builder. Read more
source§

impl<T> Same<T> for T

§

type Output = T

Should always be Self
source§

impl<T> ToOwned for Twhere - T: Clone,

§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T, U> TryFrom<U> for Twhere - U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
const: unstable · source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for Twhere - U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
const: unstable · source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
source§

impl<T> WithSubscriber for T

source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>where - S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a + Self: AsExpression<T> + Sized, + T: SqlType + TypedExpressionType,
Convert self to an expression for Diesel’s query builder. Read more
§

fn as_sql<'a, T>(&'a self) -> <&'a Self as AsExpression<T>>::Expressionwhere + &'a Self: AsExpression<T>, + T: SqlType + TypedExpressionType,

Convert &self to an expression for Diesel’s query builder. Read more
source§

impl<T> RequestBody for Twhere + T: ResourceType + DeserializeOwned,

source§

fn supported_types() -> Option<Vec<Mime, Global>>

Return all types that are supported as content types. Use None if all types are supported.
source§

impl<T> Same<T> for T

§

type Output = T

Should always be Self
source§

impl<T> ToOwned for Twhere + T: Clone,

§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T, U> TryFrom<U> for Twhere + U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for Twhere + U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
source§

impl<T> WithSubscriber for T

source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a -WithDispatch wrapper. Read more
source§

impl<T> DeserializeOwned for Twhere - T: for<'de> Deserialize<'de>,

source§

impl<T, B> PathExtractor<B> for Twhere +WithDispatch wrapper. Read more
source§

impl<T> DeserializeOwned for Twhere + T: for<'de> Deserialize<'de>,

source§

impl<T, B> PathExtractor<B> for Twhere B: Body, - T: for<'de> Deserialize<'de> + StaticResponseExtender<ResBody = B> + StateData,

source§

impl<T, B> QueryStringExtractor<B> for Twhere + T: for<'de> Deserialize<'de> + StaticResponseExtender<ResBody = B> + StateData,

source§

impl<T, B> QueryStringExtractor<B> for Twhere B: Body, - T: for<'de> Deserialize<'de> + StaticResponseExtender<ResBody = B> + StateData,

\ No newline at end of file + T: for<'de> Deserialize<'de> + StaticResponseExtender<ResBody = B> + StateData, \ No newline at end of file diff --git a/doc/gotham_restful/struct.OpenapiInfo.html b/doc/gotham_restful/struct.OpenapiInfo.html index 6e6f9639e..7474b806c 100644 --- a/doc/gotham_restful/struct.OpenapiInfo.html +++ b/doc/gotham_restful/struct.OpenapiInfo.html @@ -1,27 +1,27 @@ -OpenapiInfo in gotham_restful - Rust
pub struct OpenapiInfo {
-    pub title: String,
-    pub version: String,
-    pub urls: Vec<String>,
-}

Fields§

§title: String§version: String§urls: Vec<String>

Trait Implementations§

source§

impl Clone for OpenapiInfo

source§

fn clone(&self) -> OpenapiInfo

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Debug for OpenapiInfo

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for Twhere - T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for Twhere - T: ?Sized,

const: unstable · source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for Twhere - T: ?Sized,

const: unstable · source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

const: unstable · source§

fn from(t: T) -> T

Returns the argument unchanged.

+data-use_system_theme="false">
pub struct OpenapiInfo {
+    pub title: String,
+    pub version: String,
+    pub urls: Vec<String>,
+}

Fields§

§title: String§version: String§urls: Vec<String>

Trait Implementations§

source§

impl Clone for OpenapiInfo

source§

fn clone(&self) -> OpenapiInfo

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Debug for OpenapiInfo

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for Twhere + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for Twhere + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for Twhere + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

source§

impl<T> Instrument for T

source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an -Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for Twhere - U: From<T>,

const: unstable · source§

fn into(self) -> U

Calls U::from(self).

+Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for Twhere + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of -From<T> for U chooses to do.

+From<T> for U chooses to do.

§

impl<T> IntoSql for T

§

fn into_sql<T>(self) -> Self::Expressionwhere - Self: AsExpression<T> + Sized, - T: SqlType + TypedExpressionType,

Convert self to an expression for Diesel’s query builder. Read more
§

fn as_sql<'a, T>(&'a self) -> <&'a Self as AsExpression<T>>::Expressionwhere - &'a Self: AsExpression<T>, - T: SqlType + TypedExpressionType,

Convert &self to an expression for Diesel’s query builder. Read more
source§

impl<T> Same<T> for T

§

type Output = T

Should always be Self
source§

impl<T> ToOwned for Twhere - T: Clone,

§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T, U> TryFrom<U> for Twhere - U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
const: unstable · source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for Twhere - U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
const: unstable · source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
source§

impl<T> WithSubscriber for T

source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>where - S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a + Self: AsExpression<T> + Sized, + T: SqlType + TypedExpressionType,
Convert self to an expression for Diesel’s query builder. Read more
§

fn as_sql<'a, T>(&'a self) -> <&'a Self as AsExpression<T>>::Expressionwhere + &'a Self: AsExpression<T>, + T: SqlType + TypedExpressionType,

Convert &self to an expression for Diesel’s query builder. Read more
source§

impl<T> Same<T> for T

§

type Output = T

Should always be Self
source§

impl<T> ToOwned for Twhere + T: Clone,

§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T, U> TryFrom<U> for Twhere + U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for Twhere + U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
source§

impl<T> WithSubscriber for T

source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more
\ No newline at end of file diff --git a/doc/gotham_restful/struct.Raw.html b/doc/gotham_restful/struct.Raw.html index 1d8ac20fd..1cf3222fd 100644 --- a/doc/gotham_restful/struct.Raw.html +++ b/doc/gotham_restful/struct.Raw.html @@ -1,6 +1,6 @@ -Raw in gotham_restful - Rust

Struct gotham_restful::Raw

source ·
pub struct Raw<T> {
+data-use_system_theme="false">

Struct gotham_restful::Raw

source ·
pub struct Raw<T> {
     pub raw: T,
     pub mime: Mime,
 }
Expand description

This type can be used both as a raw request body, as well as as a raw response. However, all types @@ -16,41 +16,42 @@ fn create(body: Raw<Vec<u8>>) -> Raw<Vec<u8>> { body }

-

Fields§

§raw: T§mime: Mime

Implementations§

source§

impl<T> Raw<T>

source

pub fn new(raw: T, mime: Mime) -> Self

Trait Implementations§

source§

impl<T, U> AsMut<U> for Raw<T>where - T: AsMut<U>,

source§

fn as_mut(&mut self) -> &mut U

Converts this type into a mutable reference of the (usually inferred) input type.
source§

impl<T, U> AsRef<U> for Raw<T>where - T: AsRef<U>,

source§

fn as_ref(&self) -> &U

Converts this type into a shared reference of the (usually inferred) input type.
source§

impl<T: Clone> Clone for Raw<T>

source§

fn clone(&self) -> Self

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl<T: Debug> Debug for Raw<T>

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl<T: for<'a> From<&'a [u8]>> FromBody for Raw<T>

§

type Err = Infallible

The error type returned by the conversion if it was unsuccessfull. When using the derive -macro, there is no way to trigger an error, so std::convert::Infallible is used here. -However, this might change in the future.
source§

fn from_body(body: Bytes, mime: Mime) -> Result<Self, Self::Err>

Perform the conversion.
source§

impl<T: Into<Body>> IntoResponse for Raw<T>where - Self: Send,

Fields§

§raw: T§mime: Mime

Implementations§

source§

impl<T> Raw<T>

source

pub fn new(raw: T, mime: Mime) -> Self

Trait Implementations§

source§

impl<T, U> AsMut<U> for Raw<T>where + T: AsMut<U>,

source§

fn as_mut(&mut self) -> &mut U

Converts this type into a mutable reference of the (usually inferred) input type.
source§

impl<T, U> AsRef<U> for Raw<T>where + T: AsRef<U>,

source§

fn as_ref(&self) -> &U

Converts this type into a shared reference of the (usually inferred) input type.
source§

impl<T: Clone> Clone for Raw<T>

source§

fn clone(&self) -> Self

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl<T: Debug> Debug for Raw<T>

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl<T: for<'a> From<&'a [u8]>> FromBody for Raw<T>

§

type Err = Infallible

The error type returned by the conversion if it was unsuccessfull. When using the derive +macro, there is no way to trigger an error, so std::convert::Infallible is used here. +However, this might change in the future.
source§

fn from_body(body: Bytes, mime: Mime) -> Result<Self, Self::Err>

Perform the conversion.
source§

impl<T: Into<Body>> IntoResponse for Raw<T>where + Self: Send,

§

type Err = Error

source§

fn into_response( self -) -> Pin<Box<dyn Future<Output = Result<Response, SerdeJsonError>> + Send>>

Turn this into a response that can be returned to the browser. This api will likely -change in the future.
source§

fn accepted_types() -> Option<Vec<Mime>>

Return a list of supported mime types.
source§

impl<T> OpenapiType for Raw<T>

source§

fn visit_type<V: Visitor>(visitor: &mut V)

§

fn schema() -> OpenapiSchema

source§

impl<T> RequestBody for Raw<T>where - Raw<T>: FromBody + ResourceType,

source§

fn supported_types() -> Option<Vec<Mime>>

Return all types that are supported as content types. Use None if all types are supported.
source§

impl<T: Into<Body>> ResponseSchema for Raw<T>where - Self: Send,

source§

fn schema(code: StatusCode) -> OpenapiSchema

Return the schema of the response for the given status code. The code may +) -> Pin<Box<dyn Future<Output = Result<Response, SerdeJsonError>> + Send>>
Turn this into a response that can be returned to the browser. This api will likely +change in the future.
source§

fn accepted_types() -> Option<Vec<Mime>>

Return a list of supported mime types.
source§

impl<T> OpenapiType for Raw<T>

source§

fn visit_type<V: Visitor>(visitor: &mut V)

§

fn schema() -> OpenapiSchema

source§

impl<T> RequestBody for Raw<T>where + Raw<T>: FromBody + ResourceType,

source§

fn supported_types() -> Option<Vec<Mime>>

Return all types that are supported as content types. Use None if all types are supported.
source§

impl<T: Into<Body>> ResponseSchema for Raw<T>where + Self: Send,

source§

fn schema(code: StatusCode) -> OpenapiSchema

Return the schema of the response for the given status code. The code may only be one that was previously returned by Self::status_codes. The -implementation should panic if that is not the case.
source§

fn status_codes() -> Vec<StatusCode>

All status codes returned by this response. Returns [StatusCode::OK] by default.

Auto Trait Implementations§

§

impl<T> RefUnwindSafe for Raw<T>where - T: RefUnwindSafe,

§

impl<T> Send for Raw<T>where - T: Send,

§

impl<T> Sync for Raw<T>where - T: Sync,

§

impl<T> Unpin for Raw<T>where - T: Unpin,

§

impl<T> UnwindSafe for Raw<T>where - T: UnwindSafe,

Blanket Implementations§

source§

impl<T> Any for Twhere - T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for Twhere - T: ?Sized,

const: unstable · source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for Twhere - T: ?Sized,

const: unstable · source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

const: unstable · source§

fn from(t: T) -> T

Returns the argument unchanged.

+implementation should panic if that is not the case.
source§

fn status_codes() -> Vec<StatusCode>

All status codes returned by this response. Returns [StatusCode::OK] by default.

Auto Trait Implementations§

§

impl<T> RefUnwindSafe for Raw<T>where + T: RefUnwindSafe,

§

impl<T> Send for Raw<T>where + T: Send,

§

impl<T> Sync for Raw<T>where + T: Sync,

§

impl<T> Unpin for Raw<T>where + T: Unpin,

§

impl<T> UnwindSafe for Raw<T>where + T: UnwindSafe,

Blanket Implementations§

source§

impl<T> Any for Twhere + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for Twhere + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for Twhere + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

source§

impl<T> Instrument for T

source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an -Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for Twhere - U: From<T>,

const: unstable · source§

fn into(self) -> U

Calls U::from(self).

+Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for Twhere + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of -From<T> for U chooses to do.

+From<T> for U chooses to do.

§

impl<T> IntoSql for T

§

fn into_sql<T>(self) -> Self::Expressionwhere - Self: AsExpression<T> + Sized, - T: SqlType + TypedExpressionType,

Convert self to an expression for Diesel’s query builder. Read more
§

fn as_sql<'a, T>(&'a self) -> <&'a Self as AsExpression<T>>::Expressionwhere - &'a Self: AsExpression<T>, - T: SqlType + TypedExpressionType,

Convert &self to an expression for Diesel’s query builder. Read more
source§

impl<T> Same<T> for T

§

type Output = T

Should always be Self
source§

impl<T> ToOwned for Twhere - T: Clone,

§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T, U> TryFrom<U> for Twhere - U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
const: unstable · source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for Twhere - U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
const: unstable · source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
source§

impl<T> WithSubscriber for T

source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>where - S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a + Self: AsExpression<T> + Sized, + T: SqlType + TypedExpressionType,
Convert self to an expression for Diesel’s query builder. Read more
§

fn as_sql<'a, T>(&'a self) -> <&'a Self as AsExpression<T>>::Expressionwhere + &'a Self: AsExpression<T>, + T: SqlType + TypedExpressionType,

Convert &self to an expression for Diesel’s query builder. Read more
source§

impl<T> Same<T> for T

§

type Output = T

Should always be Self
source§

impl<T> ToOwned for Twhere + T: Clone,

§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T, U> TryFrom<U> for Twhere + U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for Twhere + U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
source§

impl<T> WithSubscriber for T

source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a -WithDispatch wrapper. Read more
\ No newline at end of file +WithDispatch wrapper. Read more
source§

impl<R> IntoResponseWithSchema for Rwhere + R: IntoResponse + ResponseSchema,

\ No newline at end of file diff --git a/doc/gotham_restful/struct.Redirect.html b/doc/gotham_restful/struct.Redirect.html index 43c5d33d6..a207680f0 100644 --- a/doc/gotham_restful/struct.Redirect.html +++ b/doc/gotham_restful/struct.Redirect.html @@ -1,7 +1,7 @@ -Redirect in gotham_restful - Rust
pub struct Redirect {
-    pub to: String,
+data-use_system_theme="false">
pub struct Redirect {
+    pub to: String,
 }
Expand description

This is the return type of a resource that only returns a redirect. It will result in a 303 See Other answer, meaning the redirect will always result in a GET request on the target.

@@ -12,27 +12,28 @@ to: "http://localhost:8080/cool/new/location".to_owned() } }
-

Fields§

§to: String

Trait Implementations§

source§

impl Clone for Redirect

source§

fn clone(&self) -> Redirect

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Debug for Redirect

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl Default for Redirect

source§

fn default() -> Redirect

Returns the “default value” for a type. Read more
source§

impl IntoResponse for Redirect

§

type Err = InvalidHeaderValue

source§

fn into_response(self) -> BoxFuture<'static, Result<Response, Self::Err>>

Turn this into a response that can be returned to the browser. This api will likely -change in the future.
source§

fn accepted_types() -> Option<Vec<Mime>>

Return a list of supported mime types.
source§

impl ResponseSchema for Redirect

source§

fn status_codes() -> Vec<StatusCode>

All status codes returned by this response. Returns [StatusCode::OK] by default.
source§

fn schema(code: StatusCode) -> OpenapiSchema

Return the schema of the response for the given status code. The code may +

Fields§

§to: String

Trait Implementations§

source§

impl Clone for Redirect

source§

fn clone(&self) -> Redirect

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Debug for Redirect

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl Default for Redirect

source§

fn default() -> Redirect

Returns the “default value” for a type. Read more
source§

impl IntoResponse for Redirect

§

type Err = InvalidHeaderValue

source§

fn into_response(self) -> BoxFuture<'static, Result<Response, Self::Err>>

Turn this into a response that can be returned to the browser. This api will likely +change in the future.
source§

fn accepted_types() -> Option<Vec<Mime>>

Return a list of supported mime types.
source§

impl ResponseSchema for Redirect

source§

fn status_codes() -> Vec<StatusCode>

All status codes returned by this response. Returns [StatusCode::OK] by default.
source§

fn schema(code: StatusCode) -> OpenapiSchema

Return the schema of the response for the given status code. The code may only be one that was previously returned by Self::status_codes. The -implementation should panic if that is not the case.

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for Twhere - T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for Twhere - T: ?Sized,

const: unstable · source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for Twhere - T: ?Sized,

const: unstable · source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

const: unstable · source§

fn from(t: T) -> T

Returns the argument unchanged.

+implementation should panic if that is not the case.

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for Twhere + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for Twhere + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for Twhere + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

source§

impl<T> Instrument for T

source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an -Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for Twhere - U: From<T>,

const: unstable · source§

fn into(self) -> U

Calls U::from(self).

+Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for Twhere + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of -From<T> for U chooses to do.

+From<T> for U chooses to do.

§

impl<T> IntoSql for T

§

fn into_sql<T>(self) -> Self::Expressionwhere - Self: AsExpression<T> + Sized, - T: SqlType + TypedExpressionType,

Convert self to an expression for Diesel’s query builder. Read more
§

fn as_sql<'a, T>(&'a self) -> <&'a Self as AsExpression<T>>::Expressionwhere - &'a Self: AsExpression<T>, - T: SqlType + TypedExpressionType,

Convert &self to an expression for Diesel’s query builder. Read more
source§

impl<T> Same<T> for T

§

type Output = T

Should always be Self
source§

impl<T> ToOwned for Twhere - T: Clone,

§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T, U> TryFrom<U> for Twhere - U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
const: unstable · source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for Twhere - U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
const: unstable · source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
source§

impl<T> WithSubscriber for T

source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>where - S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a + Self: AsExpression<T> + Sized, + T: SqlType + TypedExpressionType,
Convert self to an expression for Diesel’s query builder. Read more
§

fn as_sql<'a, T>(&'a self) -> <&'a Self as AsExpression<T>>::Expressionwhere + &'a Self: AsExpression<T>, + T: SqlType + TypedExpressionType,

Convert &self to an expression for Diesel’s query builder. Read more
source§

impl<T> Same<T> for T

§

type Output = T

Should always be Self
source§

impl<T> ToOwned for Twhere + T: Clone,

§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T, U> TryFrom<U> for Twhere + U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for Twhere + U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
source§

impl<T> WithSubscriber for T

source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a -WithDispatch wrapper. Read more
\ No newline at end of file +WithDispatch wrapper. Read more
source§

impl<R> IntoResponseWithSchema for Rwhere + R: IntoResponse + ResponseSchema,

\ No newline at end of file diff --git a/doc/gotham_restful/struct.Response.html b/doc/gotham_restful/struct.Response.html index 0cfec3d43..27da30a51 100644 --- a/doc/gotham_restful/struct.Response.html +++ b/doc/gotham_restful/struct.Response.html @@ -1,6 +1,6 @@ -Response in gotham_restful - Rust
pub struct Response { /* private fields */ }
Expand description

A response, used to create the final gotham response from.

+data-use_system_theme="false">
pub struct Response { /* private fields */ }
Expand description

A response, used to create the final gotham response from.

This type is not meant to be used as the return type of endpoint handlers. While it can be freely used without the openapi feature, it is more complicated to use when you enable it, since this type does not store any schema information. You can attach schema information @@ -17,35 +17,35 @@ #[create(schema = "schema", status_codes = "status_codes")] fn create(body: Raw<Vec<u8>>) {}

-

Implementations§

source§

impl Response

source

pub fn new<B: Into<Body>>( +

Implementations§

source§

impl Response

source

pub fn new<B: Into<Body>>( status: StatusCode, body: B, - mime: Option<Mime> + mime: Option<Mime> ) -> Self

Create a new Response from raw data.

-
source

pub fn json<B: Into<Body>>(status: StatusCode, body: B) -> Self

Create a Response with mime type json from already serialized data.

+
source

pub fn json<B: Into<Body>>(status: StatusCode, body: B) -> Self

Create a Response with mime type json from already serialized data.

source

pub fn no_content() -> Self

Create a 204 No Content Response.

source

pub fn forbidden() -> Self

Create an empty 403 Forbidden Response.

source

pub fn status(&self) -> StatusCode

Return the status code of this Response.

-
source

pub fn mime(&self) -> Option<&Mime>

Return the mime type of this Response.

+
source

pub fn mime(&self) -> Option<&Mime>

Return the mime type of this Response.

source

pub fn header(&mut self, name: HeaderName, value: HeaderValue)

Add an HTTP header to the Response.

-

Trait Implementations§

source§

impl Debug for Response

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl IntoResponse for Response

§

type Err = Infallible

source§

fn into_response(self) -> BoxFuture<'static, Result<Response, Self::Err>>

Turn this into a response that can be returned to the browser. This api will likely -change in the future.
source§

fn accepted_types() -> Option<Vec<Mime>>

Return a list of supported mime types.

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for Twhere - T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for Twhere - T: ?Sized,

const: unstable · source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for Twhere - T: ?Sized,

const: unstable · source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

const: unstable · source§

fn from(t: T) -> T

Returns the argument unchanged.

+

Trait Implementations§

source§

impl Debug for Response

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl IntoResponse for Response

§

type Err = Infallible

source§

fn into_response(self) -> BoxFuture<'static, Result<Response, Self::Err>>

Turn this into a response that can be returned to the browser. This api will likely +change in the future.
source§

fn accepted_types() -> Option<Vec<Mime>>

Return a list of supported mime types.

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for Twhere + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for Twhere + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for Twhere + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

source§

impl<T> Instrument for T

source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an -Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for Twhere - U: From<T>,

const: unstable · source§

fn into(self) -> U

Calls U::from(self).

+Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for Twhere + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of -From<T> for U chooses to do.

+From<T> for U chooses to do.

§

impl<T> IntoSql for T

§

fn into_sql<T>(self) -> Self::Expressionwhere - Self: AsExpression<T> + Sized, - T: SqlType + TypedExpressionType,

Convert self to an expression for Diesel’s query builder. Read more
§

fn as_sql<'a, T>(&'a self) -> <&'a Self as AsExpression<T>>::Expressionwhere - &'a Self: AsExpression<T>, - T: SqlType + TypedExpressionType,

Convert &self to an expression for Diesel’s query builder. Read more
source§

impl<T> Same<T> for T

§

type Output = T

Should always be Self
source§

impl<T, U> TryFrom<U> for Twhere - U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
const: unstable · source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for Twhere - U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
const: unstable · source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
source§

impl<T> WithSubscriber for T

source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>where - S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a + Self: AsExpression<T> + Sized, + T: SqlType + TypedExpressionType,
Convert self to an expression for Diesel’s query builder. Read more
§

fn as_sql<'a, T>(&'a self) -> <&'a Self as AsExpression<T>>::Expressionwhere + &'a Self: AsExpression<T>, + T: SqlType + TypedExpressionType,

Convert &self to an expression for Diesel’s query builder. Read more
source§

impl<T> Same<T> for T

§

type Output = T

Should always be Self
source§

impl<T, U> TryFrom<U> for Twhere + U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for Twhere + U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
source§

impl<T> WithSubscriber for T

source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more
\ No newline at end of file diff --git a/doc/gotham_restful/struct.StaticAuthHandler.html b/doc/gotham_restful/struct.StaticAuthHandler.html index 31a9cb3c5..cd051850e 100644 --- a/doc/gotham_restful/struct.StaticAuthHandler.html +++ b/doc/gotham_restful/struct.StaticAuthHandler.html @@ -1,28 +1,28 @@ -StaticAuthHandler in gotham_restful - Rust
pub struct StaticAuthHandler { /* private fields */ }
Expand description

An AuthHandler returning always the same secret. See AuthMiddleware for a usage example.

-

Implementations§

source§

impl StaticAuthHandler

source

pub fn from_vec(secret: Vec<u8>) -> Self

source

pub fn from_array(secret: &[u8]) -> Self

Trait Implementations§

source§

impl<T> AuthHandler<T> for StaticAuthHandler

source§

fn jwt_secret<F: FnOnce() -> Option<T>>( +data-use_system_theme="false">
pub struct StaticAuthHandler { /* private fields */ }
Expand description

An AuthHandler returning always the same secret. See AuthMiddleware for a usage example.

+

Implementations§

source§

impl StaticAuthHandler

source

pub fn from_vec(secret: Vec<u8>) -> Self

source

pub fn from_array(secret: &[u8]) -> Self

Trait Implementations§

source§

impl<T> AuthHandler<T> for StaticAuthHandler

source§

fn jwt_secret<F: FnOnce() -> Option<T>>( &self, _state: &mut State, _decode_data: F -) -> Option<Vec<u8>>

Return the SHA256-HMAC secret used to verify the JWT token.
source§

impl Clone for StaticAuthHandler

source§

fn clone(&self) -> StaticAuthHandler

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Debug for StaticAuthHandler

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for Twhere - T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for Twhere - T: ?Sized,

const: unstable · source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for Twhere - T: ?Sized,

const: unstable · source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

const: unstable · source§

fn from(t: T) -> T

Returns the argument unchanged.

+) -> Option<Vec<u8>>

Return the SHA256-HMAC secret used to verify the JWT token.
source§

impl Clone for StaticAuthHandler

source§

fn clone(&self) -> StaticAuthHandler

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Debug for StaticAuthHandler

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for Twhere + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for Twhere + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for Twhere + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

source§

impl<T> Instrument for T

source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an -Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for Twhere - U: From<T>,

const: unstable · source§

fn into(self) -> U

Calls U::from(self).

+Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for Twhere + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of -From<T> for U chooses to do.

+From<T> for U chooses to do.

§

impl<T> IntoSql for T

§

fn into_sql<T>(self) -> Self::Expressionwhere - Self: AsExpression<T> + Sized, - T: SqlType + TypedExpressionType,

Convert self to an expression for Diesel’s query builder. Read more
§

fn as_sql<'a, T>(&'a self) -> <&'a Self as AsExpression<T>>::Expressionwhere - &'a Self: AsExpression<T>, - T: SqlType + TypedExpressionType,

Convert &self to an expression for Diesel’s query builder. Read more
source§

impl<T> Same<T> for T

§

type Output = T

Should always be Self
source§

impl<T> ToOwned for Twhere - T: Clone,

§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T, U> TryFrom<U> for Twhere - U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
const: unstable · source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for Twhere - U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
const: unstable · source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
source§

impl<T> WithSubscriber for T

source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>where - S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a + Self: AsExpression<T> + Sized, + T: SqlType + TypedExpressionType,
Convert self to an expression for Diesel’s query builder. Read more
§

fn as_sql<'a, T>(&'a self) -> <&'a Self as AsExpression<T>>::Expressionwhere + &'a Self: AsExpression<T>, + T: SqlType + TypedExpressionType,

Convert &self to an expression for Diesel’s query builder. Read more
source§

impl<T> Same<T> for T

§

type Output = T

Should always be Self
source§

impl<T> ToOwned for Twhere + T: Clone,

§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T, U> TryFrom<U> for Twhere + U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for Twhere + U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
source§

impl<T> WithSubscriber for T

source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more
\ No newline at end of file diff --git a/doc/gotham_restful/struct.Success.html b/doc/gotham_restful/struct.Success.html index 2c4fa6eef..fc81fb264 100644 --- a/doc/gotham_restful/struct.Success.html +++ b/doc/gotham_restful/struct.Success.html @@ -1,6 +1,6 @@ -Success in gotham_restful - Rust

Struct gotham_restful::Success

source ·
pub struct Success<T> { /* private fields */ }
Expand description

This can be returned from a resource when there is no cause of an error.

+data-use_system_theme="false">

Struct gotham_restful::Success

source ·
pub struct Success<T> { /* private fields */ }
Expand description

This can be returned from a resource when there is no cause of an error.

Usage example:

#[derive(Deserialize, Serialize)]
@@ -17,34 +17,35 @@
 }

Implementations§

source§

impl<T> Success<T>

source

pub fn header<K: IntoHeaderName>(&mut self, name: K, value: HeaderValue)

Set a custom HTTP header. If a header with this name was set before, its value is being updated.

source

pub fn headers_mut(&mut self) -> &mut HeaderMap

Allow manipulating HTTP headers.

-

Trait Implementations§

source§

impl<T: Clone> Clone for Success<T>

source§

fn clone(&self) -> Success<T>

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl<T: Debug> Debug for Success<T>

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl<T: Default> Default for Success<T>

source§

fn default() -> Success<T>

Returns the “default value” for a type. Read more
source§

impl<T> From<T> for Success<T>

source§

fn from(t: T) -> Self

Converts to this type from the input type.
source§

impl<T: ResponseBody> IntoResponse for Success<T>

Trait Implementations§

source§

impl<T: Clone> Clone for Success<T>

source§

fn clone(&self) -> Success<T>

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl<T: Debug> Debug for Success<T>

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl<T: Default> Default for Success<T>

source§

fn default() -> Success<T>

Returns the “default value” for a type. Read more
source§

impl<T> From<T> for Success<T>

source§

fn from(t: T) -> Self

Converts to this type from the input type.
source§

impl<T: ResponseBody> IntoResponse for Success<T>

§

type Err = Error

source§

fn into_response( self -) -> Pin<Box<dyn Future<Output = Result<Response, Self::Err>> + Send>>

Turn this into a response that can be returned to the browser. This api will likely -change in the future.
source§

fn accepted_types() -> Option<Vec<Mime>>

Return a list of supported mime types.
source§

impl<T: ResponseBody> ResponseSchema for Success<T>

source§

fn schema(code: StatusCode) -> OpenapiSchema

Return the schema of the response for the given status code. The code may +) -> Pin<Box<dyn Future<Output = Result<Response, Self::Err>> + Send>>
Turn this into a response that can be returned to the browser. This api will likely +change in the future.
source§

fn accepted_types() -> Option<Vec<Mime>>

Return a list of supported mime types.
source§

impl<T: ResponseBody> ResponseSchema for Success<T>

source§

fn schema(code: StatusCode) -> OpenapiSchema

Return the schema of the response for the given status code. The code may only be one that was previously returned by Self::status_codes. The -implementation should panic if that is not the case.
source§

fn status_codes() -> Vec<StatusCode>

All status codes returned by this response. Returns [StatusCode::OK] by default.

Auto Trait Implementations§

§

impl<T> RefUnwindSafe for Success<T>where - T: RefUnwindSafe,

§

impl<T> Send for Success<T>where - T: Send,

§

impl<T> Sync for Success<T>where - T: Sync,

§

impl<T> Unpin for Success<T>where - T: Unpin,

§

impl<T> UnwindSafe for Success<T>where - T: UnwindSafe,

Blanket Implementations§

source§

impl<T> Any for Twhere - T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for Twhere - T: ?Sized,

const: unstable · source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for Twhere - T: ?Sized,

const: unstable · source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<!> for T

const: unstable · source§

fn from(t: !) -> T

Converts to this type from the input type.
source§

impl<T> From<T> for T

const: unstable · source§

fn from(t: T) -> T

Returns the argument unchanged.

+implementation should panic if that is not the case.
source§

fn status_codes() -> Vec<StatusCode>

All status codes returned by this response. Returns [StatusCode::OK] by default.

Auto Trait Implementations§

§

impl<T> RefUnwindSafe for Success<T>where + T: RefUnwindSafe,

§

impl<T> Send for Success<T>where + T: Send,

§

impl<T> Sync for Success<T>where + T: Sync,

§

impl<T> Unpin for Success<T>where + T: Unpin,

§

impl<T> UnwindSafe for Success<T>where + T: UnwindSafe,

Blanket Implementations§

source§

impl<T> Any for Twhere + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for Twhere + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for Twhere + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<!> for T

source§

fn from(t: !) -> T

Converts to this type from the input type.
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

source§

impl<T> Instrument for T

source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an -Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for Twhere - U: From<T>,

const: unstable · source§

fn into(self) -> U

Calls U::from(self).

+Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for Twhere + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of -From<T> for U chooses to do.

+From<T> for U chooses to do.

§

impl<T> IntoSql for T

§

fn into_sql<T>(self) -> Self::Expressionwhere - Self: AsExpression<T> + Sized, - T: SqlType + TypedExpressionType,

Convert self to an expression for Diesel’s query builder. Read more
§

fn as_sql<'a, T>(&'a self) -> <&'a Self as AsExpression<T>>::Expressionwhere - &'a Self: AsExpression<T>, - T: SqlType + TypedExpressionType,

Convert &self to an expression for Diesel’s query builder. Read more
source§

impl<T> Same<T> for T

§

type Output = T

Should always be Self
source§

impl<T> ToOwned for Twhere - T: Clone,

§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T, U> TryFrom<U> for Twhere - U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
const: unstable · source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for Twhere - U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
const: unstable · source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
source§

impl<T> WithSubscriber for T

source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>where - S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a + Self: AsExpression<T> + Sized, + T: SqlType + TypedExpressionType,
Convert self to an expression for Diesel’s query builder. Read more
§

fn as_sql<'a, T>(&'a self) -> <&'a Self as AsExpression<T>>::Expressionwhere + &'a Self: AsExpression<T>, + T: SqlType + TypedExpressionType,

Convert &self to an expression for Diesel’s query builder. Read more
source§

impl<T> Same<T> for T

§

type Output = T

Should always be Self
source§

impl<T> ToOwned for Twhere + T: Clone,

§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T, U> TryFrom<U> for Twhere + U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for Twhere + U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
source§

impl<T> WithSubscriber for T

source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>where + S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a -WithDispatch wrapper. Read more
\ No newline at end of file +WithDispatch wrapper. Read more
source§

impl<R> IntoResponseWithSchema for Rwhere + R: IntoResponse + ResponseSchema,

\ No newline at end of file diff --git a/doc/gotham_restful/trait.AuthHandler.html b/doc/gotham_restful/trait.AuthHandler.html index a2f877b2d..4c44ced14 100644 --- a/doc/gotham_restful/trait.AuthHandler.html +++ b/doc/gotham_restful/trait.AuthHandler.html @@ -1,12 +1,12 @@ -AuthHandler in gotham_restful - Rust
pub trait AuthHandler<Data> {
+data-use_system_theme="false">
pub trait AuthHandler<Data> {
     // Required method
-    fn jwt_secret<F: FnOnce() -> Option<Data>>(
+    fn jwt_secret<F: FnOnce() -> Option<Data>>(
         &self,
         state: &mut State,
         decode_data: F
-    ) -> Option<Vec<u8>>;
+    ) -> Option<Vec<u8>>;
 }
Expand description

This trait will help the auth middleware to determine the validity of an authentication token.

A very basic implementation could look like this:

@@ -22,9 +22,9 @@ Some(SECRET.to_vec()) } }
-

Required Methods§

source

fn jwt_secret<F: FnOnce() -> Option<Data>>( +

Required Methods§

source

fn jwt_secret<F: FnOnce() -> Option<Data>>( &self, state: &mut State, decode_data: F -) -> Option<Vec<u8>>

Return the SHA256-HMAC secret used to verify the JWT token.

+) -> Option<Vec<u8>>

Return the SHA256-HMAC secret used to verify the JWT token.

Implementors§

\ No newline at end of file diff --git a/doc/gotham_restful/trait.DrawResourceRoutes.html b/doc/gotham_restful/trait.DrawResourceRoutes.html index 97bcdc789..2e488a521 100644 --- a/doc/gotham_restful/trait.DrawResourceRoutes.html +++ b/doc/gotham_restful/trait.DrawResourceRoutes.html @@ -1,12 +1,12 @@ -DrawResourceRoutes in gotham_restful - Rust
pub trait DrawResourceRoutes {
+data-use_system_theme="false">
pub trait DrawResourceRoutes {
     // Required method
     fn endpoint<E: 'static + Endpoint>(&mut self);
 }
Expand description

This trait allows to draw routes within an resource. Use this only inside the Resource::setup method.

-

Required Methods§

source

fn endpoint<E: 'static + Endpoint>(&mut self)

Implementations on Foreign Types§

source§

impl<'a, C, P> DrawResourceRoutes for (&mut ScopeBuilder<'a, C, P>, &str)where - C: PipelineHandleChain<P> + Copy + Send + Sync + 'static, - P: RefUnwindSafe + Send + Sync + 'static,

source§

fn endpoint<E: Endpoint + 'static>(&mut self)

source§

impl<'a, C, P> DrawResourceRoutes for (&mut RouterBuilder<'a, C, P>, &str)where - C: PipelineHandleChain<P> + Copy + Send + Sync + 'static, - P: RefUnwindSafe + Send + Sync + 'static,

source§

fn endpoint<E: Endpoint + 'static>(&mut self)

Implementors§

\ No newline at end of file +

Required Methods§

source

fn endpoint<E: 'static + Endpoint>(&mut self)

Implementations on Foreign Types§

source§

impl<'a, C, P> DrawResourceRoutes for (&mut ScopeBuilder<'a, C, P>, &str)where + C: PipelineHandleChain<P> + Copy + Send + Sync + 'static, + P: RefUnwindSafe + Send + Sync + 'static,

source§

fn endpoint<E: Endpoint + 'static>(&mut self)

source§

impl<'a, C, P> DrawResourceRoutes for (&mut RouterBuilder<'a, C, P>, &str)where + C: PipelineHandleChain<P> + Copy + Send + Sync + 'static, + P: RefUnwindSafe + Send + Sync + 'static,

source§

fn endpoint<E: Endpoint + 'static>(&mut self)

Implementors§

\ No newline at end of file diff --git a/doc/gotham_restful/trait.DrawResourceRoutesWithSchema.html b/doc/gotham_restful/trait.DrawResourceRoutesWithSchema.html index f15cd02ce..40e95b89d 100644 --- a/doc/gotham_restful/trait.DrawResourceRoutesWithSchema.html +++ b/doc/gotham_restful/trait.DrawResourceRoutesWithSchema.html @@ -1,12 +1,12 @@ -DrawResourceRoutesWithSchema in gotham_restful - Rust
pub trait DrawResourceRoutesWithSchema {
+data-use_system_theme="false">
pub trait DrawResourceRoutesWithSchema {
     // Required method
     fn endpoint<E: 'static + EndpointWithSchema>(&mut self);
 }
Expand description

This trait allows to draw routes within an resource. Use this only inside the Resource::setup method.

-

Required Methods§

source

fn endpoint<E: 'static + EndpointWithSchema>(&mut self)

Implementations on Foreign Types§

source§

impl<'a, 'b, C, P> DrawResourceRoutesWithSchema for (&mut OpenapiRouter<'a, RouterBuilder<'b, C, P>>, &str)where - C: PipelineHandleChain<P> + Copy + Send + Sync + 'static, - P: RefUnwindSafe + Send + Sync + 'static,

source§

fn endpoint<E: EndpointWithSchema + 'static>(&mut self)

source§

impl<'a, 'b, C, P> DrawResourceRoutesWithSchema for (&mut OpenapiRouter<'a, ScopeBuilder<'b, C, P>>, &str)where - C: PipelineHandleChain<P> + Copy + Send + Sync + 'static, - P: RefUnwindSafe + Send + Sync + 'static,

source§

fn endpoint<E: EndpointWithSchema + 'static>(&mut self)

Implementors§

\ No newline at end of file +

Required Methods§

source

fn endpoint<E: 'static + EndpointWithSchema>(&mut self)

Implementations on Foreign Types§

source§

impl<'a, 'b, C, P> DrawResourceRoutesWithSchema for (&mut OpenapiRouter<'a, ScopeBuilder<'b, C, P>>, &str)where + C: PipelineHandleChain<P> + Copy + Send + Sync + 'static, + P: RefUnwindSafe + Send + Sync + 'static,

source§

fn endpoint<E: EndpointWithSchema + 'static>(&mut self)

source§

impl<'a, 'b, C, P> DrawResourceRoutesWithSchema for (&mut OpenapiRouter<'a, RouterBuilder<'b, C, P>>, &str)where + C: PipelineHandleChain<P> + Copy + Send + Sync + 'static, + P: RefUnwindSafe + Send + Sync + 'static,

source§

fn endpoint<E: EndpointWithSchema + 'static>(&mut self)

Implementors§

\ No newline at end of file diff --git a/doc/gotham_restful/trait.DrawResources.html b/doc/gotham_restful/trait.DrawResources.html index 1a63caf39..2a74b3471 100644 --- a/doc/gotham_restful/trait.DrawResources.html +++ b/doc/gotham_restful/trait.DrawResources.html @@ -1,12 +1,12 @@ -DrawResources in gotham_restful - Rust
pub trait DrawResources {
+data-use_system_theme="false">
pub trait DrawResources {
     // Required method
-    fn resource<R: Resource>(&mut self, path: &str);
+    fn resource<R: Resource>(&mut self, path: &str);
 }
Expand description

This trait adds the resource method to gotham’s routing. It allows you to register any RESTful Resource with a path.

-

Required Methods§

source

fn resource<R: Resource>(&mut self, path: &str)

Implementations on Foreign Types§

source§

impl<'a, C, P> DrawResources for RouterBuilder<'a, C, P>where - C: PipelineHandleChain<P> + Copy + Send + Sync + 'static, - P: RefUnwindSafe + Send + Sync + 'static,

source§

fn resource<R: Resource>(&mut self, path: &str)

source§

impl<'a, C, P> DrawResources for ScopeBuilder<'a, C, P>where - C: PipelineHandleChain<P> + Copy + Send + Sync + 'static, - P: RefUnwindSafe + Send + Sync + 'static,

source§

fn resource<R: Resource>(&mut self, path: &str)

Implementors§

\ No newline at end of file +

Required Methods§

source

fn resource<R: Resource>(&mut self, path: &str)

Implementations on Foreign Types§

source§

impl<'a, C, P> DrawResources for RouterBuilder<'a, C, P>where + C: PipelineHandleChain<P> + Copy + Send + Sync + 'static, + P: RefUnwindSafe + Send + Sync + 'static,

source§

fn resource<R: Resource>(&mut self, path: &str)

source§

impl<'a, C, P> DrawResources for ScopeBuilder<'a, C, P>where + C: PipelineHandleChain<P> + Copy + Send + Sync + 'static, + P: RefUnwindSafe + Send + Sync + 'static,

source§

fn resource<R: Resource>(&mut self, path: &str)

Implementors§

\ No newline at end of file diff --git a/doc/gotham_restful/trait.DrawResourcesWithSchema.html b/doc/gotham_restful/trait.DrawResourcesWithSchema.html index 77d89fac0..798b70caa 100644 --- a/doc/gotham_restful/trait.DrawResourcesWithSchema.html +++ b/doc/gotham_restful/trait.DrawResourcesWithSchema.html @@ -1,8 +1,8 @@ -DrawResourcesWithSchema in gotham_restful - Rust
pub trait DrawResourcesWithSchema {
+data-use_system_theme="false">
pub trait DrawResourcesWithSchema {
     // Required method
-    fn resource<R: ResourceWithSchema>(&mut self, path: &str);
+    fn resource<R: ResourceWithSchema>(&mut self, path: &str);
 }
Expand description

This trait adds the resource method to gotham’s routing. It allows you to register any RESTful Resource with a path.

-

Required Methods§

source

fn resource<R: ResourceWithSchema>(&mut self, path: &str)

Implementors§

\ No newline at end of file +

Required Methods§

source

fn resource<R: ResourceWithSchema>(&mut self, path: &str)

Implementors§

\ No newline at end of file diff --git a/doc/gotham_restful/trait.Endpoint.html b/doc/gotham_restful/trait.Endpoint.html index 30a7b82fa..724f42eb6 100644 --- a/doc/gotham_restful/trait.Endpoint.html +++ b/doc/gotham_restful/trait.Endpoint.html @@ -1,42 +1,42 @@ -Endpoint in gotham_restful - Rust
pub trait Endpoint {
-    type Output: IntoResponse + Send;
-    type Placeholders: PathExtractor<Body> + Clone + Sync;
-    type Params: QueryStringExtractor<Body> + Clone + Sync;
-    type Body: RequestBody + Send;
+data-use_system_theme="false">
pub trait Endpoint {
+    type Output: IntoResponse + Send;
+    type Placeholders: PathExtractor<Body> + Clone + Sync;
+    type Params: QueryStringExtractor<Body> + Clone + Sync;
+    type Body: RequestBody + Send;
 
     // Required methods
     fn http_method() -> Method;
-    fn uri() -> Cow<'static, str>;
+    fn uri() -> Cow<'static, str>;
     fn handle(
         state: &mut State,
         placeholders: Self::Placeholders,
         params: Self::Params,
-        body: Option<Self::Body>
+        body: Option<Self::Body>
     ) -> BoxFuture<'_, Self::Output>;
 
     // Provided methods
-    fn has_placeholders() -> bool { ... }
-    fn needs_params() -> bool { ... }
-    fn needs_body() -> bool { ... }
-    fn wants_auth() -> bool { ... }
-}

Required Associated Types§

source

type Output: IntoResponse + Send

The output type that provides the response.

-
source

type Placeholders: PathExtractor<Body> + Clone + Sync

The type that parses the URI placeholders. Use NoopExtractor if has_placeholders() + fn has_placeholders() -> bool { ... } + fn needs_params() -> bool { ... } + fn needs_body() -> bool { ... } + fn wants_auth() -> bool { ... } +}

Required Associated Types§

source

type Output: IntoResponse + Send

The output type that provides the response.

+
source

type Placeholders: PathExtractor<Body> + Clone + Sync

The type that parses the URI placeholders. Use NoopExtractor if has_placeholders() returns false.

-
source

type Params: QueryStringExtractor<Body> + Clone + Sync

The type that parses the request parameters. Use NoopExtractor if needs_params() +

source

type Params: QueryStringExtractor<Body> + Clone + Sync

The type that parses the request parameters. Use NoopExtractor if needs_params() returns false.

-
source

type Body: RequestBody + Send

The type to parse the body into. Use () if needs_body() returns false.

+
source

type Body: RequestBody + Send

The type to parse the body into. Use () if needs_body() returns false.

Required Methods§

source

fn http_method() -> Method

The HTTP Verb of this endpoint.

-
source

fn uri() -> Cow<'static, str>

The URI that this endpoint listens on in gotham’s format.

+
source

fn uri() -> Cow<'static, str>

The URI that this endpoint listens on in gotham’s format.

source

fn handle( state: &mut State, placeholders: Self::Placeholders, params: Self::Params, - body: Option<Self::Body> + body: Option<Self::Body> ) -> BoxFuture<'_, Self::Output>

The handler for this endpoint.

-

Provided Methods§

source

fn has_placeholders() -> bool

Returns true iff the URI contains placeholders. false by default.

-
source

fn needs_params() -> bool

Returns true iff the request parameters should be parsed. false by default.

-
source

fn needs_body() -> bool

Returns true iff the request body should be parsed. false by default.

-
source

fn wants_auth() -> bool

Returns true if the request wants to know the auth status of the client. false by default.

+

Provided Methods§

source

fn has_placeholders() -> bool

Returns true iff the URI contains placeholders. false by default.

+
source

fn needs_params() -> bool

Returns true iff the request parameters should be parsed. false by default.

+
source

fn needs_body() -> bool

Returns true iff the request body should be parsed. false by default.

+
source

fn wants_auth() -> bool

Returns true if the request wants to know the auth status of the client. false by default.

Implementors§

\ No newline at end of file diff --git a/doc/gotham_restful/trait.EndpointWithSchema.html b/doc/gotham_restful/trait.EndpointWithSchema.html index 9e182a0f9..f2d5e7ba1 100644 --- a/doc/gotham_restful/trait.EndpointWithSchema.html +++ b/doc/gotham_restful/trait.EndpointWithSchema.html @@ -1,51 +1,51 @@ -EndpointWithSchema in gotham_restful - Rust
pub trait EndpointWithSchema {
-    type Output: IntoResponse + Send + ResponseSchema;
-    type Placeholders: PathExtractor<Body> + Clone + Sync + OpenapiType;
-    type Params: QueryStringExtractor<Body> + Clone + Sync + OpenapiType;
-    type Body: RequestBody + Send;
+data-use_system_theme="false">
pub trait EndpointWithSchema {
+    type Output: IntoResponse + Send + ResponseSchema;
+    type Placeholders: PathExtractor<Body> + Clone + Sync + OpenapiType;
+    type Params: QueryStringExtractor<Body> + Clone + Sync + OpenapiType;
+    type Body: RequestBody + Send;
 
     // Required methods
     fn http_method() -> Method;
-    fn uri() -> Cow<'static, str>;
-    fn operation_verb() -> Option<&'static str>;
+    fn uri() -> Cow<'static, str>;
+    fn operation_verb() -> Option<&'static str>;
     fn handle(
         state: &mut State,
         placeholders: Self::Placeholders,
         params: Self::Params,
-        body: Option<Self::Body>
+        body: Option<Self::Body>
     ) -> BoxFuture<'_, Self::Output>;
 
     // Provided methods
-    fn has_placeholders() -> bool { ... }
-    fn needs_params() -> bool { ... }
-    fn needs_body() -> bool { ... }
-    fn wants_auth() -> bool { ... }
-    fn operation_id() -> Option<String> { ... }
-    fn description() -> Option<String> { ... }
-}

Required Associated Types§

source

type Output: IntoResponse + Send + ResponseSchema

The output type that provides the response.

-
source

type Placeholders: PathExtractor<Body> + Clone + Sync + OpenapiType

The type that parses the URI placeholders. Use NoopExtractor if has_placeholders() + fn has_placeholders() -> bool { ... } + fn needs_params() -> bool { ... } + fn needs_body() -> bool { ... } + fn wants_auth() -> bool { ... } + fn operation_id() -> Option<String> { ... } + fn description() -> Option<String> { ... } +}

Required Associated Types§

source

type Output: IntoResponse + Send + ResponseSchema

The output type that provides the response.

+
source

type Placeholders: PathExtractor<Body> + Clone + Sync + OpenapiType

The type that parses the URI placeholders. Use NoopExtractor if has_placeholders() returns false.

-
source

type Params: QueryStringExtractor<Body> + Clone + Sync + OpenapiType

The type that parses the request parameters. Use NoopExtractor if needs_params() +

source

type Params: QueryStringExtractor<Body> + Clone + Sync + OpenapiType

The type that parses the request parameters. Use NoopExtractor if needs_params() returns false.

-
source

type Body: RequestBody + Send

The type to parse the body into. Use () if needs_body() returns false.

+
source

type Body: RequestBody + Send

The type to parse the body into. Use () if needs_body() returns false.

Required Methods§

source

fn http_method() -> Method

The HTTP Verb of this endpoint.

-
source

fn uri() -> Cow<'static, str>

The URI that this endpoint listens on in gotham’s format.

-
source

fn operation_verb() -> Option<&'static str>

The verb used for generating an operation id if Self::operation_id returns None. +

source

fn uri() -> Cow<'static, str>

The URI that this endpoint listens on in gotham’s format.

+
source

fn operation_verb() -> Option<&'static str>

The verb used for generating an operation id if Self::operation_id returns None. For example read, read_all, create, update etc.

source

fn handle( state: &mut State, placeholders: Self::Placeholders, params: Self::Params, - body: Option<Self::Body> + body: Option<Self::Body> ) -> BoxFuture<'_, Self::Output>

The handler for this endpoint.

-

Provided Methods§

source

fn has_placeholders() -> bool

Returns true iff the URI contains placeholders. false by default.

-
source

fn needs_params() -> bool

Returns true iff the request parameters should be parsed. false by default.

-
source

fn needs_body() -> bool

Returns true iff the request body should be parsed. false by default.

-
source

fn wants_auth() -> bool

Returns true if the request wants to know the auth status of the client. false by default.

-
source

fn operation_id() -> Option<String>

Replace the automatically generated operation id with a custom one. Only relevant for the +

Provided Methods§

source

fn has_placeholders() -> bool

Returns true iff the URI contains placeholders. false by default.

+
source

fn needs_params() -> bool

Returns true iff the request parameters should be parsed. false by default.

+
source

fn needs_body() -> bool

Returns true iff the request body should be parsed. false by default.

+
source

fn wants_auth() -> bool

Returns true if the request wants to know the auth status of the client. false by default.

+
source

fn operation_id() -> Option<String>

Replace the automatically generated operation id with a custom one. Only relevant for the OpenAPI Specification.

-
source

fn description() -> Option<String>

Add a description to the openapi specification. Usually taken from the rustdoc comment +

source

fn description() -> Option<String>

Add a description to the openapi specification. Usually taken from the rustdoc comment when using the proc macro.

Implementors§

\ No newline at end of file diff --git a/doc/gotham_restful/trait.FromBody.html b/doc/gotham_restful/trait.FromBody.html index 3c3de7290..3725da1a2 100644 --- a/doc/gotham_restful/trait.FromBody.html +++ b/doc/gotham_restful/trait.FromBody.html @@ -1,16 +1,16 @@ -FromBody in gotham_restful - Rust
pub trait FromBody: Sized {
-    type Err: Error;
+data-use_system_theme="false">
pub trait FromBody: Sized {
+    type Err: Error;
 
     // Required method
-    fn from_body(body: Bytes, content_type: Mime) -> Result<Self, Self::Err>;
+    fn from_body(body: Bytes, content_type: Mime) -> Result<Self, Self::Err>;
 }
Expand description

This trait should be implemented for every type that can be built from an HTTP request body plus its media type.

For most use cases it is sufficient to derive this trait, you usually don’t need to manually implement this. Therefore, make sure that the first variable of your struct can be built from [Bytes], and the second one can be build from Mime. If you have any additional variables, they -need to be Default. This is an example of such a struct:

+need to be Default. This is an example of such a struct:

#[derive(FromBody, RequestBody)]
 #[supported_types(mime::IMAGE_GIF, mime::IMAGE_JPEG, mime::IMAGE_PNG)]
@@ -18,8 +18,8 @@
 	content: Vec<u8>,
 	content_type: Mime
 }
-

Required Associated Types§

source

type Err: Error

The error type returned by the conversion if it was unsuccessfull. When using the derive -macro, there is no way to trigger an error, so std::convert::Infallible is used here. +

Required Associated Types§

source

type Err: Error

The error type returned by the conversion if it was unsuccessfull. When using the derive +macro, there is no way to trigger an error, so std::convert::Infallible is used here. However, this might change in the future.

-

Required Methods§

source

fn from_body(body: Bytes, content_type: Mime) -> Result<Self, Self::Err>

Perform the conversion.

-

Implementors§

source§

impl<T: DeserializeOwned> FromBody for T

§

type Err = Error

source§

impl<T: for<'a> From<&'a [u8]>> FromBody for Raw<T>

\ No newline at end of file +

Required Methods§

source

fn from_body(body: Bytes, content_type: Mime) -> Result<Self, Self::Err>

Perform the conversion.

+

Implementors§

source§

impl<T: DeserializeOwned> FromBody for T

§

type Err = Error

source§

impl<T: for<'a> From<&'a [u8]>> FromBody for Raw<T>

\ No newline at end of file diff --git a/doc/gotham_restful/trait.GetOpenapi.html b/doc/gotham_restful/trait.GetOpenapi.html index f94836eff..d5204fb9e 100644 --- a/doc/gotham_restful/trait.GetOpenapi.html +++ b/doc/gotham_restful/trait.GetOpenapi.html @@ -1,10 +1,10 @@ -GetOpenapi in gotham_restful - Rust
pub trait GetOpenapi {
+data-use_system_theme="false">
pub trait GetOpenapi {
     // Required methods
-    fn openapi_spec(&mut self, path: &str);
-    fn openapi_doc(&mut self, path: &str);
+    fn openapi_spec(&mut self, path: &str);
+    fn openapi_doc(&mut self, path: &str);
 }
Expand description

This trait adds the openapi_spec and openapi_doc method to an OpenAPI-aware router.

-

Required Methods§

source

fn openapi_spec(&mut self, path: &str)

Register a GET route to path that returns the OpenAPI specification in JSON format.

-
source

fn openapi_doc(&mut self, path: &str)

Register a GET route to path that returns the OpenAPI documentation in HTML format.

+

Required Methods§

source

fn openapi_spec(&mut self, path: &str)

Register a GET route to path that returns the OpenAPI specification in JSON format.

+
source

fn openapi_doc(&mut self, path: &str)

Register a GET route to path that returns the OpenAPI documentation in HTML format.

Implementors§

\ No newline at end of file diff --git a/doc/gotham_restful/trait.IntoResponse.html b/doc/gotham_restful/trait.IntoResponse.html index 97908521e..a3a54ebbf 100644 --- a/doc/gotham_restful/trait.IntoResponse.html +++ b/doc/gotham_restful/trait.IntoResponse.html @@ -1,33 +1,33 @@ -IntoResponse in gotham_restful - Rust
pub trait IntoResponse {
-    type Err: Into<HandlerError> + Send + Sync + 'static;
+data-use_system_theme="false">
pub trait IntoResponse {
+    type Err: Into<HandlerError> + Send + Sync + 'static;
 
     // Required method
-    fn into_response(self) -> BoxFuture<'static, Result<Response, Self::Err>>;
+    fn into_response(self) -> BoxFuture<'static, Result<Response, Self::Err>>;
 
     // Provided method
-    fn accepted_types() -> Option<Vec<Mime>> { ... }
+    fn accepted_types() -> Option<Vec<Mime>> { ... }
 }
Expand description

This trait needs to be implemented by every type returned from an endpoint to to provide the response.

-

Required Associated Types§

source

type Err: Into<HandlerError> + Send + Sync + 'static

Required Methods§

source

fn into_response(self) -> BoxFuture<'static, Result<Response, Self::Err>>

Turn this into a response that can be returned to the browser. This api will likely +

Required Associated Types§

source

type Err: Into<HandlerError> + Send + Sync + 'static

Required Methods§

source

fn into_response(self) -> BoxFuture<'static, Result<Response, Self::Err>>

Turn this into a response that can be returned to the browser. This api will likely change in the future.

-

Provided Methods§

source

fn accepted_types() -> Option<Vec<Mime>>

Return a list of supported mime types.

-

Implementations on Foreign Types§

source§

impl<Res> IntoResponse for Pin<Box<dyn Future<Output = Res> + Send>>where - Res: IntoResponse + 'static,

Provided Methods§

source

fn accepted_types() -> Option<Vec<Mime>>

Return a list of supported mime types.

+

Implementations on Foreign Types§

source§

impl<R, E> IntoResponse for Result<R, E>where + R: ResponseBody, + E: Debug + IntoResponseError<Err = Error>,

§

type Err = <E as IntoResponseError>::Err

source§

fn into_response( self -) -> Pin<Box<dyn Future<Output = Result<Response, Self::Err>> + Send>>

source§

fn accepted_types() -> Option<Vec<Mime>>

source§

impl<E> IntoResponse for Result<Redirect, E>where - E: Debug + IntoResponseError, - <E as IntoResponseError>::Err: StdError + Sync,

§

type Err = RedirectError<<E as IntoResponseError>::Err>

source§

fn into_response(self) -> BoxFuture<'static, Result<Response, Self::Err>>

source§

impl<T, E> IntoResponse for Result<Raw<T>, E>where +) -> Pin<Box<dyn Future<Output = Result<Response, E::Err>> + Send>>

source§

fn accepted_types() -> Option<Vec<Mime>>

source§

impl<T, E> IntoResponse for Result<Raw<T>, E>where Raw<T>: IntoResponse, - E: Debug + IntoResponseError<Err = <Raw<T> as IntoResponse>::Err>,

§

type Err = <E as IntoResponseError>::Err

source§

fn into_response( + E: Debug + IntoResponseError<Err = <Raw<T> as IntoResponse>::Err>,

§

type Err = <E as IntoResponseError>::Err

source§

fn into_response( self -) -> Pin<Box<dyn Future<Output = Result<Response, E::Err>> + Send>>

source§

impl<E> IntoResponse for Result<NoContent, E>where - E: Debug + IntoResponseError<Err = Error>,

§

type Err = Error

source§

fn into_response( +) -> Pin<Box<dyn Future<Output = Result<Response, E::Err>> + Send>>

source§

impl<E> IntoResponse for Result<Redirect, E>where + E: Debug + IntoResponseError, + <E as IntoResponseError>::Err: StdError + Sync,

§

type Err = RedirectError<<E as IntoResponseError>::Err>

source§

fn into_response(self) -> BoxFuture<'static, Result<Response, Self::Err>>

source§

impl<Res> IntoResponse for Pin<Box<dyn Future<Output = Res> + Send>>where + Res: IntoResponse + 'static,

§

type Err = <Res as IntoResponse>::Err

source§

fn into_response( self -) -> Pin<Box<dyn Future<Output = Result<Response, Error>> + Send>>

source§

fn accepted_types() -> Option<Vec<Mime>>

source§

impl<R, E> IntoResponse for Result<R, E>where - R: ResponseBody, - E: Debug + IntoResponseError<Err = Error>,

source§

impl<E> IntoResponse for Result<NoContent, E>where + E: Debug + IntoResponseError<Err = Error>,

§

type Err = Error

source§

fn into_response( self -) -> Pin<Box<dyn Future<Output = Result<Response, E::Err>> + Send>>

source§

fn accepted_types() -> Option<Vec<Mime>>

Implementors§

\ No newline at end of file +) -> Pin<Box<dyn Future<Output = Result<Response, Error>> + Send>>
source§

fn accepted_types() -> Option<Vec<Mime>>

Implementors§

\ No newline at end of file diff --git a/doc/gotham_restful/trait.IntoResponseError.html b/doc/gotham_restful/trait.IntoResponseError.html index 1efb56729..2c29a6045 100644 --- a/doc/gotham_restful/trait.IntoResponseError.html +++ b/doc/gotham_restful/trait.IntoResponseError.html @@ -1,12 +1,12 @@ -IntoResponseError in gotham_restful - Rust
pub trait IntoResponseError {
-    type Err: Debug + Send + 'static;
+data-use_system_theme="false">
pub trait IntoResponseError {
+    type Err: Debug + Send + 'static;
 
     // Required methods
-    fn into_response_error(self) -> Result<Response, Self::Err>;
-    fn status_codes() -> Vec<StatusCode>;
+    fn into_response_error(self) -> Result<Response, Self::Err>;
+    fn status_codes() -> Vec<StatusCode>;
     fn schema(code: StatusCode) -> OpenapiSchema;
-}

Required Associated Types§

source

type Err: Debug + Send + 'static

Required Methods§

Implementors§

\ No newline at end of file +}

Required Associated Types§

source

type Err: Debug + Send + 'static

Required Methods§

Implementors§

\ No newline at end of file diff --git a/doc/gotham_restful/trait.IntoResponseWithSchema.html b/doc/gotham_restful/trait.IntoResponseWithSchema.html index 29610ae4d..be31b7ef6 100644 --- a/doc/gotham_restful/trait.IntoResponseWithSchema.html +++ b/doc/gotham_restful/trait.IntoResponseWithSchema.html @@ -1,6 +1,6 @@ -IntoResponseWithSchema in gotham_restful - Rust
pub trait IntoResponseWithSchema: IntoResponse + ResponseSchema + Sealed { }
Expand description

A trait provided to convert a resource’s result to json, and provide an OpenAPI schema to the +data-use_system_theme="false">

pub trait IntoResponseWithSchema: IntoResponse + ResponseSchema + Sealed { }
Expand description

A trait provided to convert a resource’s result to json, and provide an OpenAPI schema to the router. This trait is implemented for all types that implement IntoResponse and ResponseSchema.

Implementors§

\ No newline at end of file diff --git a/doc/gotham_restful/trait.RequestBody.html b/doc/gotham_restful/trait.RequestBody.html index e188017e5..8fef10597 100644 --- a/doc/gotham_restful/trait.RequestBody.html +++ b/doc/gotham_restful/trait.RequestBody.html @@ -1,8 +1,8 @@ -RequestBody in gotham_restful - Rust
pub trait RequestBody: ResourceType + FromBody {
+data-use_system_theme="false">
pub trait RequestBody: ResourceType + FromBody {
     // Provided method
-    fn supported_types() -> Option<Vec<Mime>> { ... }
+    fn supported_types() -> Option<Vec<Mime>> { ... }
 }
Expand description

A type that can be used inside a request body. Implemented for every type that is deserializable with serde. If the openapi feature is used, it must also be of type [OpenapiType].

If you want a non-deserializable type to be used as a request body, e.g. because you’d like to @@ -15,6 +15,6 @@ content: Vec<u8>, content_type: Mime }

-

Provided Methods§

source

fn supported_types() -> Option<Vec<Mime>>

Return all types that are supported as content types. Use None if all types are supported.

+

Provided Methods§

source

fn supported_types() -> Option<Vec<Mime>>

Return all types that are supported as content types. Use None if all types are supported.

Implementors§

source§

impl<T> RequestBody for Raw<T>where - Raw<T>: FromBody + ResourceType,

source§

impl<T: ResourceType + DeserializeOwned> RequestBody for T

\ No newline at end of file + Raw<T>: FromBody + ResourceType,
source§

impl<T: ResourceType + DeserializeOwned> RequestBody for T

\ No newline at end of file diff --git a/doc/gotham_restful/trait.Resource.html b/doc/gotham_restful/trait.Resource.html index 2862bcd39..608dff2ae 100644 --- a/doc/gotham_restful/trait.Resource.html +++ b/doc/gotham_restful/trait.Resource.html @@ -1,6 +1,6 @@ -Resource in gotham_restful - Rust
pub trait Resource {
+data-use_system_theme="false">
pub trait Resource {
     // Required method
     fn setup<D: DrawResourceRoutes>(route: D);
 }
Expand description

This trait must be implemented for every resource. It allows you to register the different diff --git a/doc/gotham_restful/trait.ResourceWithSchema.html b/doc/gotham_restful/trait.ResourceWithSchema.html index 0f9fc9334..a367f3a07 100644 --- a/doc/gotham_restful/trait.ResourceWithSchema.html +++ b/doc/gotham_restful/trait.ResourceWithSchema.html @@ -1,6 +1,6 @@ -ResourceWithSchema in gotham_restful - Rust

pub trait ResourceWithSchema {
+data-use_system_theme="false">
pub trait ResourceWithSchema {
     // Required method
     fn setup<D: DrawResourceRoutesWithSchema>(route: D);
 }
Expand description

This trait must be implemented for every resource. It allows you to register the different diff --git a/doc/gotham_restful/trait.ResponseBody.html b/doc/gotham_restful/trait.ResponseBody.html index 75640c46f..ff33d544f 100644 --- a/doc/gotham_restful/trait.ResponseBody.html +++ b/doc/gotham_restful/trait.ResponseBody.html @@ -1,6 +1,6 @@ -ResponseBody in gotham_restful - Rust

pub trait ResponseBody: ResourceType + Serialize { }
Expand description

A type that can be used inside a response body. Implemented for every type that is +data-use_system_theme="false">

pub trait ResponseBody: ResourceType + Serialize { }
Expand description

A type that can be used inside a response body. Implemented for every type that is serializable with serde. If the openapi feature is used, it must also be of type [OpenapiType].

-

Implementors§

source§

impl<T: ResourceType + Serialize> ResponseBody for T

\ No newline at end of file +

Implementors§

source§

impl<T: ResourceType + Serialize> ResponseBody for T

\ No newline at end of file diff --git a/doc/gotham_restful/trait.ResponseSchema.html b/doc/gotham_restful/trait.ResponseSchema.html index 4e5855159..3183111b1 100644 --- a/doc/gotham_restful/trait.ResponseSchema.html +++ b/doc/gotham_restful/trait.ResponseSchema.html @@ -1,23 +1,23 @@ -ResponseSchema in gotham_restful - Rust
pub trait ResponseSchema {
+data-use_system_theme="false">
pub trait ResponseSchema {
     // Required method
     fn schema(code: StatusCode) -> OpenapiSchema;
 
     // Provided method
-    fn status_codes() -> Vec<StatusCode> { ... }
+    fn status_codes() -> Vec<StatusCode> { ... }
 }
Expand description

Additional details for IntoResponse to be used with an OpenAPI-aware router.

Required Methods§

source

fn schema(code: StatusCode) -> OpenapiSchema

Return the schema of the response for the given status code. The code may only be one that was previously returned by Self::status_codes. The implementation should panic if that is not the case.

-

Provided Methods§

source

fn status_codes() -> Vec<StatusCode>

All status codes returned by this response. Returns [StatusCode::OK] by default.

-

Implementations on Foreign Types§

source§

impl<E> ResponseSchema for Result<Redirect, E>where - E: Debug + IntoResponseError, - <E as IntoResponseError>::Err: StdError + Sync,

source§

fn status_codes() -> Vec<StatusCode>

source§

fn schema(code: StatusCode) -> OpenapiSchema

source§

impl<E> ResponseSchema for Result<NoContent, E>where - E: Debug + IntoResponseError<Err = Error>,

source§

fn status_codes() -> Vec<StatusCode>

source§

fn schema(code: StatusCode) -> OpenapiSchema

source§

impl<Res> ResponseSchema for Pin<Box<dyn Future<Output = Res> + Send>>where - Res: ResponseSchema,

source§

fn status_codes() -> Vec<StatusCode>

source§

fn schema(code: StatusCode) -> OpenapiSchema

source§

impl<R, E> ResponseSchema for Result<R, E>where - R: ResponseBody, - E: Debug + IntoResponseError<Err = Error>,

source§

fn status_codes() -> Vec<StatusCode>

source§

fn schema(code: StatusCode) -> OpenapiSchema

source§

impl<T, E> ResponseSchema for Result<Raw<T>, E>where +

Provided Methods§

source

fn status_codes() -> Vec<StatusCode>

All status codes returned by this response. Returns [StatusCode::OK] by default.

+

Implementations on Foreign Types§

source§

impl<Res> ResponseSchema for Pin<Box<dyn Future<Output = Res> + Send>>where + Res: ResponseSchema,

source§

fn status_codes() -> Vec<StatusCode>

source§

fn schema(code: StatusCode) -> OpenapiSchema

source§

impl<T, E> ResponseSchema for Result<Raw<T>, E>where Raw<T>: IntoResponseWithSchema, - E: Debug + IntoResponseError<Err = <Raw<T> as IntoResponse>::Err>,

source§

fn status_codes() -> Vec<StatusCode>

source§

fn schema(code: StatusCode) -> OpenapiSchema

Implementors§

\ No newline at end of file + E: Debug + IntoResponseError<Err = <Raw<T> as IntoResponse>::Err>,
source§

fn status_codes() -> Vec<StatusCode>

source§

fn schema(code: StatusCode) -> OpenapiSchema

source§

impl<E> ResponseSchema for Result<NoContent, E>where + E: Debug + IntoResponseError<Err = Error>,

source§

fn status_codes() -> Vec<StatusCode>

source§

fn schema(code: StatusCode) -> OpenapiSchema

source§

impl<E> ResponseSchema for Result<Redirect, E>where + E: Debug + IntoResponseError, + <E as IntoResponseError>::Err: StdError + Sync,

source§

fn status_codes() -> Vec<StatusCode>

source§

fn schema(code: StatusCode) -> OpenapiSchema

source§

impl<R, E> ResponseSchema for Result<R, E>where + R: ResponseBody, + E: Debug + IntoResponseError<Err = Error>,

source§

fn status_codes() -> Vec<StatusCode>

source§

fn schema(code: StatusCode) -> OpenapiSchema

Implementors§

\ No newline at end of file diff --git a/doc/gotham_restful/trait.WithOpenapi.html b/doc/gotham_restful/trait.WithOpenapi.html index a37f30ecb..2523e757e 100644 --- a/doc/gotham_restful/trait.WithOpenapi.html +++ b/doc/gotham_restful/trait.WithOpenapi.html @@ -1,17 +1,17 @@ -WithOpenapi in gotham_restful - Rust
pub trait WithOpenapi<D> {
+data-use_system_theme="false">
pub trait WithOpenapi<D> {
     // Required method
     fn with_openapi<F>(&mut self, info: OpenapiInfo, block: F)
-       where F: FnOnce(OpenapiRouter<'_, D>);
+       where F: FnOnce(OpenapiRouter<'_, D>);
 }
Expand description

This trait adds the with_openapi method to gotham’s routing. It turns the default router into one that will only allow RESTful resources, but record them and generate an OpenAPI specification on request.

Required Methods§

source

fn with_openapi<F>(&mut self, info: OpenapiInfo, block: F)where - F: FnOnce(OpenapiRouter<'_, D>),

Implementations on Foreign Types§

source§

impl<'a, C, P> WithOpenapi<ScopeBuilder<'a, C, P>> for ScopeBuilder<'a, C, P>where - C: PipelineHandleChain<P> + Copy + Send + Sync + 'static, - P: RefUnwindSafe + Send + Sync + 'static,

source§

fn with_openapi<F>(&mut self, info: OpenapiInfo, block: F)where - F: FnOnce(OpenapiRouter<'_, ScopeBuilder<'a, C, P>>),

source§

impl<'a, C, P> WithOpenapi<RouterBuilder<'a, C, P>> for RouterBuilder<'a, C, P>where - C: PipelineHandleChain<P> + Copy + Send + Sync + 'static, - P: RefUnwindSafe + Send + Sync + 'static,

source§

fn with_openapi<F>(&mut self, info: OpenapiInfo, block: F)where - F: FnOnce(OpenapiRouter<'_, RouterBuilder<'a, C, P>>),

Implementors§

\ No newline at end of file + F: FnOnce(OpenapiRouter<'_, D>),

Implementations on Foreign Types§

source§

impl<'a, C, P> WithOpenapi<RouterBuilder<'a, C, P>> for RouterBuilder<'a, C, P>where + C: PipelineHandleChain<P> + Copy + Send + Sync + 'static, + P: RefUnwindSafe + Send + Sync + 'static,

source§

fn with_openapi<F>(&mut self, info: OpenapiInfo, block: F)where + F: FnOnce(OpenapiRouter<'_, RouterBuilder<'a, C, P>>),

source§

impl<'a, C, P> WithOpenapi<ScopeBuilder<'a, C, P>> for ScopeBuilder<'a, C, P>where + C: PipelineHandleChain<P> + Copy + Send + Sync + 'static, + P: RefUnwindSafe + Send + Sync + 'static,

source§

fn with_openapi<F>(&mut self, info: OpenapiInfo, block: F)where + F: FnOnce(OpenapiRouter<'_, ScopeBuilder<'a, C, P>>),

Implementors§

\ No newline at end of file diff --git a/doc/gotham_restful/type.AuthResult.html b/doc/gotham_restful/type.AuthResult.html index ef6d57701..ae9e4d04f 100644 --- a/doc/gotham_restful/type.AuthResult.html +++ b/doc/gotham_restful/type.AuthResult.html @@ -1,6 +1,6 @@ -AuthResult in gotham_restful - Rust

Type Definition gotham_restful::AuthResult

source ·
pub type AuthResult<T, E> = Result<T, AuthErrorOrOther<E>>;
Expand description

This return type can be used to wrap any type implementing IntoResponse +data-use_system_theme="false">

Type Definition gotham_restful::AuthResult

source ·
pub type AuthResult<T, E> = Result<T, AuthErrorOrOther<E>>;
Expand description

This return type can be used to wrap any type implementing IntoResponse that can only be returned if the client is authenticated. Otherwise, an empty 403 Forbidden response will be issued.

Use can look something like this (assuming the auth feature is enabled):

diff --git a/doc/gotham_restful/type.AuthSuccess.html b/doc/gotham_restful/type.AuthSuccess.html index a34ac10b8..30c5981f4 100644 --- a/doc/gotham_restful/type.AuthSuccess.html +++ b/doc/gotham_restful/type.AuthSuccess.html @@ -1,6 +1,6 @@ -AuthSuccess in gotham_restful - Rust

Type Definition gotham_restful::AuthSuccess

source ·
pub type AuthSuccess<T> = Result<T, AuthError>;
Expand description

This return type can be used to wrap any type implementing IntoResponse +data-use_system_theme="false">

Type Definition gotham_restful::AuthSuccess

source ·
pub type AuthSuccess<T> = Result<T, AuthError>;
Expand description

This return type can be used to wrap any type implementing IntoResponse that can only be returned if the client is authenticated. Otherwise, an empty 403 Forbidden response will be issued.

Use can look something like this (assuming the auth feature is enabled):

diff --git a/doc/gotham_restful/type.AuthValidation.html b/doc/gotham_restful/type.AuthValidation.html index 161dfa399..bf66fac39 100644 --- a/doc/gotham_restful/type.AuthValidation.html +++ b/doc/gotham_restful/type.AuthValidation.html @@ -1,3 +1,3 @@ -AuthValidation in gotham_restful - Rust

Type Definition gotham_restful::AuthValidation

source ·
pub type AuthValidation = Validation;
\ No newline at end of file +data-use_system_theme="false">

Type Definition gotham_restful::AuthValidation

source ·
pub type AuthValidation = Validation;
\ No newline at end of file diff --git a/doc/help.html b/doc/help.html index 05c82ed28..24ab82732 100644 --- a/doc/help.html +++ b/doc/help.html @@ -1,3 +1,3 @@ -Rustdoc help

Rustdoc help

Back
\ No newline at end of file +data-use_system_theme="false">

Rustdoc help

Back
\ No newline at end of file diff --git a/doc/implementors/core/clone/trait.Clone.js b/doc/implementors/core/clone/trait.Clone.js index 15d7d07f4..98a9534a5 100644 --- a/doc/implementors/core/clone/trait.Clone.js +++ b/doc/implementors/core/clone/trait.Clone.js @@ -1,3 +1,3 @@ (function() {var implementors = { -"gotham_restful":[["impl Clone for CorsConfig"],["impl Clone for Origin"],["impl<T> Clone for AuthStatus<T>where\n T: Clone + Send + 'static,"],["impl Clone for NoopExtractor"],["impl<T: Clone> Clone for Success<T>"],["impl Clone for AuthSource"],["impl Clone for Headers"],["impl Clone for AuthError"],["impl<T: Clone> Clone for Raw<T>"],["impl Clone for Redirect"],["impl Clone for StaticAuthHandler"],["impl<E: Clone> Clone for AuthErrorOrOther<E>"],["impl Clone for NoContent"],["impl Clone for OpenapiInfo"],["impl<Data, Handler> Clone for AuthMiddleware<Data, Handler>where\n Handler: Clone,"]] +"gotham_restful":[["impl Clone for NoopExtractor"],["impl Clone for Origin"],["impl<T: Clone> Clone for Success<T>"],["impl Clone for StaticAuthHandler"],["impl Clone for NoContent"],["impl Clone for CorsConfig"],["impl<Data, Handler> Clone for AuthMiddleware<Data, Handler>where\n Handler: Clone,"],["impl<T> Clone for AuthStatus<T>where\n T: Clone + Send + 'static,"],["impl Clone for AuthError"],["impl Clone for OpenapiInfo"],["impl<E: Clone> Clone for AuthErrorOrOther<E>"],["impl Clone for Headers"],["impl Clone for AuthSource"],["impl<T: Clone> Clone for Raw<T>"],["impl Clone for Redirect"]] };if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/doc/implementors/core/convert/trait.AsMut.js b/doc/implementors/core/convert/trait.AsMut.js index a319ca9be..ef1237e0d 100644 --- a/doc/implementors/core/convert/trait.AsMut.js +++ b/doc/implementors/core/convert/trait.AsMut.js @@ -1,3 +1,3 @@ (function() {var implementors = { -"gotham_restful":[["impl<T, U> AsMut<U> for Raw<T>where\n T: AsMut<U>,"]] +"gotham_restful":[["impl<T, U> AsMut<U> for Raw<T>where\n T: AsMut<U>,"]] };if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/doc/implementors/core/convert/trait.AsRef.js b/doc/implementors/core/convert/trait.AsRef.js index f7c8dd0de..44183587b 100644 --- a/doc/implementors/core/convert/trait.AsRef.js +++ b/doc/implementors/core/convert/trait.AsRef.js @@ -1,3 +1,3 @@ (function() {var implementors = { -"gotham_restful":[["impl<T, U> AsRef<U> for Raw<T>where\n T: AsRef<U>,"]] +"gotham_restful":[["impl<T, U> AsRef<U> for Raw<T>where\n T: AsRef<U>,"]] };if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/doc/implementors/core/convert/trait.From.js b/doc/implementors/core/convert/trait.From.js index 2c557647f..634a1bc83 100644 --- a/doc/implementors/core/convert/trait.From.js +++ b/doc/implementors/core/convert/trait.From.js @@ -1,3 +1,3 @@ (function() {var implementors = { -"gotham_restful":[["impl<E, F> From<F> for AuthErrorOrOther<E>where\n F: Sealed + Into<E>,"],["impl<T> From<T> for Success<T>"],["impl<E> From<AuthError> for AuthErrorOrOther<E>where\n AuthError: IntoResponseError,"],["impl From<()> for NoContent"]] +"gotham_restful":[["impl<E> From<AuthError> for AuthErrorOrOther<E>where\n AuthError: IntoResponseError,"],["impl<E, F> From<F> for AuthErrorOrOther<E>where\n F: Sealed + Into<E>,"],["impl From<()> for NoContent"],["impl<T> From<T> for Success<T>"]] };if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/doc/implementors/core/default/trait.Default.js b/doc/implementors/core/default/trait.Default.js index 5d5df04d3..a97c003cb 100644 --- a/doc/implementors/core/default/trait.Default.js +++ b/doc/implementors/core/default/trait.Default.js @@ -1,3 +1,3 @@ (function() {var implementors = { -"gotham_restful":[["impl Default for Redirect"],["impl Default for Headers"],["impl Default for Origin"],["impl Default for CorsConfig"],["impl<T: Default> Default for Success<T>"],["impl Default for NoContent"]] +"gotham_restful":[["impl Default for NoContent"],["impl Default for Headers"],["impl<T: Default> Default for Success<T>"],["impl Default for CorsConfig"],["impl Default for Origin"],["impl Default for Redirect"]] };if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/doc/implementors/core/fmt/trait.Debug.js b/doc/implementors/core/fmt/trait.Debug.js index 86a498417..a02be6a53 100644 --- a/doc/implementors/core/fmt/trait.Debug.js +++ b/doc/implementors/core/fmt/trait.Debug.js @@ -1,3 +1,3 @@ (function() {var implementors = { -"gotham_restful":[["impl Debug for NoContent"],["impl<E: Debug> Debug for AuthErrorOrOther<E>"],["impl Debug for Origin"],["impl Debug for CorsConfig"],["impl Debug for Headers"],["impl Debug for AuthError"],["impl<Data: Debug, Handler: Debug> Debug for AuthMiddleware<Data, Handler>"],["impl Debug for NoopExtractor"],["impl<T: Debug> Debug for Success<T>"],["impl Debug for AuthSource"],["impl Debug for OpenapiInfo"],["impl<T: Debug> Debug for Raw<T>"],["impl Debug for Redirect"],["impl Debug for StaticAuthHandler"],["impl Debug for Response"],["impl<T: Debug + Send + 'static> Debug for AuthStatus<T>"]] +"gotham_restful":[["impl Debug for AuthError"],["impl Debug for AuthSource"],["impl<T: Debug> Debug for Success<T>"],["impl Debug for NoopExtractor"],["impl<Data: Debug, Handler: Debug> Debug for AuthMiddleware<Data, Handler>"],["impl Debug for Response"],["impl Debug for CorsConfig"],["impl Debug for OpenapiInfo"],["impl<T: Debug + Send + 'static> Debug for AuthStatus<T>"],["impl Debug for Headers"],["impl Debug for Origin"],["impl Debug for NoContent"],["impl<T: Debug> Debug for Raw<T>"],["impl Debug for Redirect"],["impl<E: Debug> Debug for AuthErrorOrOther<E>"],["impl Debug for StaticAuthHandler"]] };if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/doc/implementors/core/marker/trait.Copy.js b/doc/implementors/core/marker/trait.Copy.js index d809560f0..f12f5c746 100644 --- a/doc/implementors/core/marker/trait.Copy.js +++ b/doc/implementors/core/marker/trait.Copy.js @@ -1,3 +1,3 @@ (function() {var implementors = { -"gotham_restful":[["impl Copy for NoopExtractor"]] +"gotham_restful":[["impl Copy for NoopExtractor"]] };if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/doc/implementors/core/marker/trait.Send.js b/doc/implementors/core/marker/trait.Send.js index fb7dcccd5..95f3f925e 100644 --- a/doc/implementors/core/marker/trait.Send.js +++ b/doc/implementors/core/marker/trait.Send.js @@ -1,3 +1,3 @@ (function() {var implementors = { -"gotham_restful":[["impl<T> Send for AuthStatus<T>",1,["gotham_restful::auth::AuthStatus"]],["impl Send for AuthSource",1,["gotham_restful::auth::AuthSource"]],["impl Send for StaticAuthHandler",1,["gotham_restful::auth::StaticAuthHandler"]],["impl<Data, Handler> Send for AuthMiddleware<Data, Handler>where\n Data: Send,\n Handler: Send,",1,["gotham_restful::auth::AuthMiddleware"]],["impl Send for Origin",1,["gotham_restful::cors::Origin"]],["impl Send for Headers",1,["gotham_restful::cors::Headers"]],["impl Send for CorsConfig",1,["gotham_restful::cors::CorsConfig"]],["impl Send for OpenapiInfo",1,["gotham_restful::openapi::builder::OpenapiInfo"]],["impl Send for NoopExtractor",1,["gotham_restful::endpoint::NoopExtractor"]],["impl Send for AuthError",1,["gotham_restful::response::auth_result::AuthError"]],["impl<E> Send for AuthErrorOrOther<E>where\n E: Send,",1,["gotham_restful::response::auth_result::AuthErrorOrOther"]],["impl Send for NoContent",1,["gotham_restful::response::no_content::NoContent"]],["impl<T> Send for Raw<T>where\n T: Send,",1,["gotham_restful::response::raw::Raw"]],["impl Send for Redirect",1,["gotham_restful::response::redirect::Redirect"]],["impl<T> Send for Success<T>where\n T: Send,",1,["gotham_restful::response::success::Success"]],["impl Send for Response",1,["gotham_restful::response::Response"]]] +"gotham_restful":[["impl<T> Send for AuthStatus<T>",1,["gotham_restful::auth::AuthStatus"]],["impl Send for AuthSource",1,["gotham_restful::auth::AuthSource"]],["impl Send for StaticAuthHandler",1,["gotham_restful::auth::StaticAuthHandler"]],["impl<Data, Handler> Send for AuthMiddleware<Data, Handler>where\n Data: Send,\n Handler: Send,",1,["gotham_restful::auth::AuthMiddleware"]],["impl Send for Origin",1,["gotham_restful::cors::Origin"]],["impl Send for Headers",1,["gotham_restful::cors::Headers"]],["impl Send for CorsConfig",1,["gotham_restful::cors::CorsConfig"]],["impl Send for OpenapiInfo",1,["gotham_restful::openapi::builder::OpenapiInfo"]],["impl Send for NoopExtractor",1,["gotham_restful::endpoint::NoopExtractor"]],["impl Send for AuthError",1,["gotham_restful::response::auth_result::AuthError"]],["impl<E> Send for AuthErrorOrOther<E>where\n E: Send,",1,["gotham_restful::response::auth_result::AuthErrorOrOther"]],["impl Send for NoContent",1,["gotham_restful::response::no_content::NoContent"]],["impl<T> Send for Raw<T>where\n T: Send,",1,["gotham_restful::response::raw::Raw"]],["impl Send for Redirect",1,["gotham_restful::response::redirect::Redirect"]],["impl<T> Send for Success<T>where\n T: Send,",1,["gotham_restful::response::success::Success"]],["impl Send for Response",1,["gotham_restful::response::Response"]]] };if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/doc/implementors/core/marker/trait.Sync.js b/doc/implementors/core/marker/trait.Sync.js index 688773165..a62c2485e 100644 --- a/doc/implementors/core/marker/trait.Sync.js +++ b/doc/implementors/core/marker/trait.Sync.js @@ -1,3 +1,3 @@ (function() {var implementors = { -"gotham_restful":[["impl<T> Sync for AuthStatus<T>where\n T: Sync,",1,["gotham_restful::auth::AuthStatus"]],["impl Sync for AuthSource",1,["gotham_restful::auth::AuthSource"]],["impl Sync for StaticAuthHandler",1,["gotham_restful::auth::StaticAuthHandler"]],["impl<Data, Handler> Sync for AuthMiddleware<Data, Handler>where\n Data: Sync,\n Handler: Sync,",1,["gotham_restful::auth::AuthMiddleware"]],["impl Sync for Origin",1,["gotham_restful::cors::Origin"]],["impl Sync for Headers",1,["gotham_restful::cors::Headers"]],["impl Sync for CorsConfig",1,["gotham_restful::cors::CorsConfig"]],["impl Sync for OpenapiInfo",1,["gotham_restful::openapi::builder::OpenapiInfo"]],["impl Sync for NoopExtractor",1,["gotham_restful::endpoint::NoopExtractor"]],["impl Sync for AuthError",1,["gotham_restful::response::auth_result::AuthError"]],["impl<E> Sync for AuthErrorOrOther<E>where\n E: Sync,",1,["gotham_restful::response::auth_result::AuthErrorOrOther"]],["impl Sync for NoContent",1,["gotham_restful::response::no_content::NoContent"]],["impl<T> Sync for Raw<T>where\n T: Sync,",1,["gotham_restful::response::raw::Raw"]],["impl Sync for Redirect",1,["gotham_restful::response::redirect::Redirect"]],["impl<T> Sync for Success<T>where\n T: Sync,",1,["gotham_restful::response::success::Success"]],["impl Sync for Response",1,["gotham_restful::response::Response"]]] +"gotham_restful":[["impl<T> Sync for AuthStatus<T>where\n T: Sync,",1,["gotham_restful::auth::AuthStatus"]],["impl Sync for AuthSource",1,["gotham_restful::auth::AuthSource"]],["impl Sync for StaticAuthHandler",1,["gotham_restful::auth::StaticAuthHandler"]],["impl<Data, Handler> Sync for AuthMiddleware<Data, Handler>where\n Data: Sync,\n Handler: Sync,",1,["gotham_restful::auth::AuthMiddleware"]],["impl Sync for Origin",1,["gotham_restful::cors::Origin"]],["impl Sync for Headers",1,["gotham_restful::cors::Headers"]],["impl Sync for CorsConfig",1,["gotham_restful::cors::CorsConfig"]],["impl Sync for OpenapiInfo",1,["gotham_restful::openapi::builder::OpenapiInfo"]],["impl Sync for NoopExtractor",1,["gotham_restful::endpoint::NoopExtractor"]],["impl Sync for AuthError",1,["gotham_restful::response::auth_result::AuthError"]],["impl<E> Sync for AuthErrorOrOther<E>where\n E: Sync,",1,["gotham_restful::response::auth_result::AuthErrorOrOther"]],["impl Sync for NoContent",1,["gotham_restful::response::no_content::NoContent"]],["impl<T> Sync for Raw<T>where\n T: Sync,",1,["gotham_restful::response::raw::Raw"]],["impl Sync for Redirect",1,["gotham_restful::response::redirect::Redirect"]],["impl<T> Sync for Success<T>where\n T: Sync,",1,["gotham_restful::response::success::Success"]],["impl Sync for Response",1,["gotham_restful::response::Response"]]] };if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/doc/implementors/core/marker/trait.Unpin.js b/doc/implementors/core/marker/trait.Unpin.js index f8612148f..381b80372 100644 --- a/doc/implementors/core/marker/trait.Unpin.js +++ b/doc/implementors/core/marker/trait.Unpin.js @@ -1,3 +1,3 @@ (function() {var implementors = { -"gotham_restful":[["impl<T> Unpin for AuthStatus<T>where\n T: Unpin,",1,["gotham_restful::auth::AuthStatus"]],["impl Unpin for AuthSource",1,["gotham_restful::auth::AuthSource"]],["impl Unpin for StaticAuthHandler",1,["gotham_restful::auth::StaticAuthHandler"]],["impl<Data, Handler> Unpin for AuthMiddleware<Data, Handler>where\n Data: Unpin,\n Handler: Unpin,",1,["gotham_restful::auth::AuthMiddleware"]],["impl Unpin for Origin",1,["gotham_restful::cors::Origin"]],["impl Unpin for Headers",1,["gotham_restful::cors::Headers"]],["impl Unpin for CorsConfig",1,["gotham_restful::cors::CorsConfig"]],["impl Unpin for OpenapiInfo",1,["gotham_restful::openapi::builder::OpenapiInfo"]],["impl Unpin for NoopExtractor",1,["gotham_restful::endpoint::NoopExtractor"]],["impl Unpin for AuthError",1,["gotham_restful::response::auth_result::AuthError"]],["impl<E> Unpin for AuthErrorOrOther<E>where\n E: Unpin,",1,["gotham_restful::response::auth_result::AuthErrorOrOther"]],["impl Unpin for NoContent",1,["gotham_restful::response::no_content::NoContent"]],["impl<T> Unpin for Raw<T>where\n T: Unpin,",1,["gotham_restful::response::raw::Raw"]],["impl Unpin for Redirect",1,["gotham_restful::response::redirect::Redirect"]],["impl<T> Unpin for Success<T>where\n T: Unpin,",1,["gotham_restful::response::success::Success"]],["impl Unpin for Response",1,["gotham_restful::response::Response"]]] +"gotham_restful":[["impl<T> Unpin for AuthStatus<T>where\n T: Unpin,",1,["gotham_restful::auth::AuthStatus"]],["impl Unpin for AuthSource",1,["gotham_restful::auth::AuthSource"]],["impl Unpin for StaticAuthHandler",1,["gotham_restful::auth::StaticAuthHandler"]],["impl<Data, Handler> Unpin for AuthMiddleware<Data, Handler>where\n Data: Unpin,\n Handler: Unpin,",1,["gotham_restful::auth::AuthMiddleware"]],["impl Unpin for Origin",1,["gotham_restful::cors::Origin"]],["impl Unpin for Headers",1,["gotham_restful::cors::Headers"]],["impl Unpin for CorsConfig",1,["gotham_restful::cors::CorsConfig"]],["impl Unpin for OpenapiInfo",1,["gotham_restful::openapi::builder::OpenapiInfo"]],["impl Unpin for NoopExtractor",1,["gotham_restful::endpoint::NoopExtractor"]],["impl Unpin for AuthError",1,["gotham_restful::response::auth_result::AuthError"]],["impl<E> Unpin for AuthErrorOrOther<E>where\n E: Unpin,",1,["gotham_restful::response::auth_result::AuthErrorOrOther"]],["impl Unpin for NoContent",1,["gotham_restful::response::no_content::NoContent"]],["impl<T> Unpin for Raw<T>where\n T: Unpin,",1,["gotham_restful::response::raw::Raw"]],["impl Unpin for Redirect",1,["gotham_restful::response::redirect::Redirect"]],["impl<T> Unpin for Success<T>where\n T: Unpin,",1,["gotham_restful::response::success::Success"]],["impl Unpin for Response",1,["gotham_restful::response::Response"]]] };if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/doc/implementors/core/panic/unwind_safe/trait.RefUnwindSafe.js b/doc/implementors/core/panic/unwind_safe/trait.RefUnwindSafe.js index 01bb64cb2..808bcc8dc 100644 --- a/doc/implementors/core/panic/unwind_safe/trait.RefUnwindSafe.js +++ b/doc/implementors/core/panic/unwind_safe/trait.RefUnwindSafe.js @@ -1,3 +1,3 @@ (function() {var implementors = { -"gotham_restful":[["impl<T> !RefUnwindSafe for AuthStatus<T>",1,["gotham_restful::auth::AuthStatus"]],["impl RefUnwindSafe for AuthSource",1,["gotham_restful::auth::AuthSource"]],["impl RefUnwindSafe for StaticAuthHandler",1,["gotham_restful::auth::StaticAuthHandler"]],["impl<Data, Handler> RefUnwindSafe for AuthMiddleware<Data, Handler>where\n Data: RefUnwindSafe,\n Handler: RefUnwindSafe,",1,["gotham_restful::auth::AuthMiddleware"]],["impl RefUnwindSafe for Origin",1,["gotham_restful::cors::Origin"]],["impl RefUnwindSafe for Headers",1,["gotham_restful::cors::Headers"]],["impl RefUnwindSafe for CorsConfig",1,["gotham_restful::cors::CorsConfig"]],["impl RefUnwindSafe for OpenapiInfo",1,["gotham_restful::openapi::builder::OpenapiInfo"]],["impl RefUnwindSafe for NoopExtractor",1,["gotham_restful::endpoint::NoopExtractor"]],["impl RefUnwindSafe for AuthError",1,["gotham_restful::response::auth_result::AuthError"]],["impl<E> RefUnwindSafe for AuthErrorOrOther<E>where\n E: RefUnwindSafe,",1,["gotham_restful::response::auth_result::AuthErrorOrOther"]],["impl RefUnwindSafe for NoContent",1,["gotham_restful::response::no_content::NoContent"]],["impl<T> RefUnwindSafe for Raw<T>where\n T: RefUnwindSafe,",1,["gotham_restful::response::raw::Raw"]],["impl RefUnwindSafe for Redirect",1,["gotham_restful::response::redirect::Redirect"]],["impl<T> RefUnwindSafe for Success<T>where\n T: RefUnwindSafe,",1,["gotham_restful::response::success::Success"]],["impl !RefUnwindSafe for Response",1,["gotham_restful::response::Response"]]] +"gotham_restful":[["impl<T> !RefUnwindSafe for AuthStatus<T>",1,["gotham_restful::auth::AuthStatus"]],["impl RefUnwindSafe for AuthSource",1,["gotham_restful::auth::AuthSource"]],["impl RefUnwindSafe for StaticAuthHandler",1,["gotham_restful::auth::StaticAuthHandler"]],["impl<Data, Handler> RefUnwindSafe for AuthMiddleware<Data, Handler>where\n Data: RefUnwindSafe,\n Handler: RefUnwindSafe,",1,["gotham_restful::auth::AuthMiddleware"]],["impl RefUnwindSafe for Origin",1,["gotham_restful::cors::Origin"]],["impl RefUnwindSafe for Headers",1,["gotham_restful::cors::Headers"]],["impl RefUnwindSafe for CorsConfig",1,["gotham_restful::cors::CorsConfig"]],["impl RefUnwindSafe for OpenapiInfo",1,["gotham_restful::openapi::builder::OpenapiInfo"]],["impl RefUnwindSafe for NoopExtractor",1,["gotham_restful::endpoint::NoopExtractor"]],["impl RefUnwindSafe for AuthError",1,["gotham_restful::response::auth_result::AuthError"]],["impl<E> RefUnwindSafe for AuthErrorOrOther<E>where\n E: RefUnwindSafe,",1,["gotham_restful::response::auth_result::AuthErrorOrOther"]],["impl RefUnwindSafe for NoContent",1,["gotham_restful::response::no_content::NoContent"]],["impl<T> RefUnwindSafe for Raw<T>where\n T: RefUnwindSafe,",1,["gotham_restful::response::raw::Raw"]],["impl RefUnwindSafe for Redirect",1,["gotham_restful::response::redirect::Redirect"]],["impl<T> RefUnwindSafe for Success<T>where\n T: RefUnwindSafe,",1,["gotham_restful::response::success::Success"]],["impl !RefUnwindSafe for Response",1,["gotham_restful::response::Response"]]] };if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/doc/implementors/core/panic/unwind_safe/trait.UnwindSafe.js b/doc/implementors/core/panic/unwind_safe/trait.UnwindSafe.js index 262a9e2f7..90f9564a9 100644 --- a/doc/implementors/core/panic/unwind_safe/trait.UnwindSafe.js +++ b/doc/implementors/core/panic/unwind_safe/trait.UnwindSafe.js @@ -1,3 +1,3 @@ (function() {var implementors = { -"gotham_restful":[["impl<T> !UnwindSafe for AuthStatus<T>",1,["gotham_restful::auth::AuthStatus"]],["impl UnwindSafe for AuthSource",1,["gotham_restful::auth::AuthSource"]],["impl UnwindSafe for StaticAuthHandler",1,["gotham_restful::auth::StaticAuthHandler"]],["impl<Data, Handler> UnwindSafe for AuthMiddleware<Data, Handler>where\n Data: UnwindSafe,\n Handler: UnwindSafe,",1,["gotham_restful::auth::AuthMiddleware"]],["impl UnwindSafe for Origin",1,["gotham_restful::cors::Origin"]],["impl UnwindSafe for Headers",1,["gotham_restful::cors::Headers"]],["impl UnwindSafe for CorsConfig",1,["gotham_restful::cors::CorsConfig"]],["impl UnwindSafe for OpenapiInfo",1,["gotham_restful::openapi::builder::OpenapiInfo"]],["impl UnwindSafe for NoopExtractor",1,["gotham_restful::endpoint::NoopExtractor"]],["impl UnwindSafe for AuthError",1,["gotham_restful::response::auth_result::AuthError"]],["impl<E> UnwindSafe for AuthErrorOrOther<E>where\n E: UnwindSafe,",1,["gotham_restful::response::auth_result::AuthErrorOrOther"]],["impl UnwindSafe for NoContent",1,["gotham_restful::response::no_content::NoContent"]],["impl<T> UnwindSafe for Raw<T>where\n T: UnwindSafe,",1,["gotham_restful::response::raw::Raw"]],["impl UnwindSafe for Redirect",1,["gotham_restful::response::redirect::Redirect"]],["impl<T> UnwindSafe for Success<T>where\n T: UnwindSafe,",1,["gotham_restful::response::success::Success"]],["impl !UnwindSafe for Response",1,["gotham_restful::response::Response"]]] +"gotham_restful":[["impl<T> !UnwindSafe for AuthStatus<T>",1,["gotham_restful::auth::AuthStatus"]],["impl UnwindSafe for AuthSource",1,["gotham_restful::auth::AuthSource"]],["impl UnwindSafe for StaticAuthHandler",1,["gotham_restful::auth::StaticAuthHandler"]],["impl<Data, Handler> UnwindSafe for AuthMiddleware<Data, Handler>where\n Data: UnwindSafe,\n Handler: UnwindSafe,",1,["gotham_restful::auth::AuthMiddleware"]],["impl UnwindSafe for Origin",1,["gotham_restful::cors::Origin"]],["impl UnwindSafe for Headers",1,["gotham_restful::cors::Headers"]],["impl UnwindSafe for CorsConfig",1,["gotham_restful::cors::CorsConfig"]],["impl UnwindSafe for OpenapiInfo",1,["gotham_restful::openapi::builder::OpenapiInfo"]],["impl UnwindSafe for NoopExtractor",1,["gotham_restful::endpoint::NoopExtractor"]],["impl UnwindSafe for AuthError",1,["gotham_restful::response::auth_result::AuthError"]],["impl<E> UnwindSafe for AuthErrorOrOther<E>where\n E: UnwindSafe,",1,["gotham_restful::response::auth_result::AuthErrorOrOther"]],["impl UnwindSafe for NoContent",1,["gotham_restful::response::no_content::NoContent"]],["impl<T> UnwindSafe for Raw<T>where\n T: UnwindSafe,",1,["gotham_restful::response::raw::Raw"]],["impl UnwindSafe for Redirect",1,["gotham_restful::response::redirect::Redirect"]],["impl<T> UnwindSafe for Success<T>where\n T: UnwindSafe,",1,["gotham_restful::response::success::Success"]],["impl !UnwindSafe for Response",1,["gotham_restful::response::Response"]]] };if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/doc/implementors/gotham/middleware/trait.Middleware.js b/doc/implementors/gotham/middleware/trait.Middleware.js index ad579ca2d..75cd3fe1d 100644 --- a/doc/implementors/gotham/middleware/trait.Middleware.js +++ b/doc/implementors/gotham/middleware/trait.Middleware.js @@ -1,3 +1,3 @@ (function() {var implementors = { -"gotham_restful":[["impl Middleware for CorsConfig"],["impl<Data, Handler> Middleware for AuthMiddleware<Data, Handler>where\n Data: DeserializeOwned + Send + 'static,\n Handler: AuthHandler<Data>,"]] +"gotham_restful":[["impl<Data, Handler> Middleware for AuthMiddleware<Data, Handler>where\n Data: DeserializeOwned + Send + 'static,\n Handler: AuthHandler<Data>,"],["impl Middleware for CorsConfig"]] };if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/doc/implementors/gotham/middleware/trait.NewMiddleware.js b/doc/implementors/gotham/middleware/trait.NewMiddleware.js index 6d6211c14..3f166b7a0 100644 --- a/doc/implementors/gotham/middleware/trait.NewMiddleware.js +++ b/doc/implementors/gotham/middleware/trait.NewMiddleware.js @@ -1,3 +1,3 @@ (function() {var implementors = { -"gotham_restful":[["impl NewMiddleware for CorsConfig"],["impl<Data, Handler> NewMiddleware for AuthMiddleware<Data, Handler>where\n Self: Clone + Middleware + Sync + RefUnwindSafe,"]] +"gotham_restful":[["impl<Data, Handler> NewMiddleware for AuthMiddleware<Data, Handler>where\n Self: Clone + Middleware + Sync + RefUnwindSafe,"],["impl NewMiddleware for CorsConfig"]] };if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/doc/implementors/gotham/state/data/trait.StateData.js b/doc/implementors/gotham/state/data/trait.StateData.js index bade57b1a..4be554eed 100644 --- a/doc/implementors/gotham/state/data/trait.StateData.js +++ b/doc/implementors/gotham/state/data/trait.StateData.js @@ -1,3 +1,3 @@ (function() {var implementors = { -"gotham_restful":[["impl StateData for CorsConfig"],["impl StateData for NoopExtractor"],["impl StateData for AuthSource"],["impl<T: Send + 'static> StateData for AuthStatus<T>"]] +"gotham_restful":[["impl<T: Send + 'static> StateData for AuthStatus<T>"],["impl StateData for AuthSource"],["impl StateData for NoopExtractor"],["impl StateData for CorsConfig"]] };if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/doc/implementors/serde/de/trait.Deserialize.js b/doc/implementors/serde/de/trait.Deserialize.js index 962e85294..d7b74540d 100644 --- a/doc/implementors/serde/de/trait.Deserialize.js +++ b/doc/implementors/serde/de/trait.Deserialize.js @@ -1,3 +1,3 @@ (function() {var implementors = { -"gotham_restful":[["impl<'de> Deserialize<'de> for NoopExtractor"]] +"gotham_restful":[["impl<'de> Deserialize<'de> for NoopExtractor"]] };if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/doc/search-index.js b/doc/search-index.js index 77468a089..224057863 100644 --- a/doc/search-index.js +++ b/doc/search-index.js @@ -1,5 +1,5 @@ var searchIndex = JSON.parse('{\ -"gotham_restful":{"doc":"This crate is an extension to the popular gotham web …","t":"DEIDGEEGGNNQQNCCIIIIIIQQQNIYINIIINDDDNQQQQQQDDIYIYYIDIIDDNNILLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLAXLLLXXLLLKKXLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLKLLLCKKCLLLLLLLLLKKLLLLLLLLLLLLLKLLLLLKLLLKLLMLLLLLLLLLLLLLLLKKLLKMXXKKKKLLLLLLXKKLKLLLLLLLLLLLMMLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLXXKKMMLLLLLLKNNDIENNNENNLLLLLLLLLLLLLLLKMLLLLLLLLLFMLLLMLMLLLLLLLLLLLLLLLL","n":["AuthError","AuthErrorOrOther","AuthHandler","AuthMiddleware","AuthResult","AuthSource","AuthStatus","AuthSuccess","AuthValidation","Authenticated","AuthorizationHeader","Body","Body","Cookie","CorsConfig","CorsRoute","DrawResourceRoutes","DrawResourceRoutesWithSchema","DrawResources","DrawResourcesWithSchema","Endpoint","EndpointWithSchema","Err","Err","Err","Forbidden","FromBody","FromBody","GetOpenapi","Header","IntoResponse","IntoResponseError","IntoResponseWithSchema","Invalid","NoContent","NoopExtractor","OpenapiInfo","Other","Output","Output","Params","Params","Placeholders","Placeholders","Raw","Redirect","RequestBody","RequestBody","Resource","Resource","ResourceError","ResourceWithSchema","Response","ResponseBody","ResponseSchema","StaticAuthHandler","Success","Unauthenticated","Unknown","WithOpenapi","accepted_types","accepted_types","accepted_types","accepted_types","as_mut","as_ref","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow_from","borrow_from","borrow_from","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut_from","borrow_mut_from","borrow_mut_from","call","clone","clone","clone","clone","clone","clone","clone","clone","clone","clone","clone","clone","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","cors","create","default","default","default","delete","delete_all","description","description","deserialize","endpoint","endpoint","endpoint","extend","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","forbidden","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from_array","from_body","from_body","from_source","from_vec","gotham","handle","handle","handle_cors","has_placeholders","has_placeholders","has_placeholders","has_placeholders","header","header","header","headers_mut","headers_mut","http_method","http_method","into","into","into","into","into","into","into","into","into","into","into","into","into","into_response","into_response","into_response","into_response","into_response","into_response","into_response_error","into_response_error","into_response_error","json","jwt_secret","jwt_secret","mime","mime","needs_body","needs_body","needs_body","needs_body","needs_params","needs_params","needs_params","needs_params","new","new","new","new","new_middleware","no_content","ok","openapi_doc","openapi_spec","operation_id","operation_id","operation_verb","raw","read","read_all","resource","resource","schema","schema","schema","schema","schema","schema","schema","schema","search","setup","setup","status","status_codes","status_codes","status_codes","status_codes","status_codes","status_codes","status_codes","supported_types","supported_types","take_from","take_from","take_from","title","to","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","try_borrow_from","try_borrow_from","try_borrow_from","try_borrow_mut_from","try_borrow_mut_from","try_borrow_mut_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_take_from","try_take_from","try_take_from","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","update","update_all","uri","uri","urls","version","visit_type","visit_type","wants_auth","wants_auth","wants_auth","wants_auth","with_openapi","Copy","Copy","CorsConfig","CorsRoute","Headers","List","None","None","Origin","Single","Star","borrow","borrow","borrow","borrow_from","borrow_mut","borrow_mut","borrow_mut","borrow_mut_from","call","clone","clone","clone","clone_into","clone_into","clone_into","cors","credentials","default","default","default","fmt","fmt","fmt","from","from","from","handle_cors","headers","into","into","into","max_age","new_middleware","origin","take_from","to_owned","to_owned","to_owned","try_borrow_from","try_borrow_mut_from","try_from","try_from","try_from","try_into","try_into","try_into","try_take_from","type_id","type_id","type_id"],"q":[[0,"gotham_restful"],[341,"gotham_restful::cors"]],"d":["This is an error type that always yields a 403 Forbidden …","This is an error type that either yields a 403 Forbidden …","This trait will help the auth middleware to determine the …","This is the auth middleware. To use it, first make sure …","This return type can be used to wrap any type implementing …","The source of the authentication token in the request.","The authentication status returned by the auth middleware …","This return type can be used to wrap any type implementing …","","The request has been performed with a valid …","Take the token from the HTTP Authorization header. This is …","The type to parse the body into. Use () if needs_body() …","The type to parse the body into. Use () if needs_body() …","Take the token from a cookie with the given name.","","","This trait allows to draw routes within an resource. Use …","This trait allows to draw routes within an resource. Use …","This trait adds the resource method to gotham’s routing. …","This trait adds the resource method to gotham’s routing. …","","","","","The error type returned by the conversion if it was …","","This trait should be implemented for every type that can …","","This trait adds the openapi_spec and openapi_doc method to …","Take the token from a header with the given name.","This trait needs to be implemented by every type returned …","","A trait provided to convert a resource’s result to json, …","The request has been performed with an invalid …","This is the return type of a resource that doesn’t …","A no-op extractor that can be used as a default type for …","","","The output type that provides the response.","The output type that provides the response.","The type that parses the request parameters. Use …","The type that parses the request parameters. Use …","The type that parses the URI placeholders. Use …","The type that parses the URI placeholders. Use …","This type can be used both as a raw request body, as well …","This is the return type of a resource that only returns a …","A type that can be used inside a request body. Implemented …","","This trait must be implemented for every resource. It …","","","This trait must be implemented for every resource. It …","A response, used to create the final gotham response from.","A type that can be used inside a response body. …","Additional details for IntoResponse to be used with an …","An AuthHandler returning always the same secret. See …","This can be returned from a resource when there is no …","The request has been performed without any kind of …","The auth status is unknown. This is likely because no …","This trait adds the with_openapi method to gotham’s …","Return a list of supported mime types.","Return a list of supported mime types.","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","Add a description to the openapi specification. Usually …","Add a description to the openapi specification. Usually …","","","","","","","","","","","","","","","","","","","Create an empty 403 Forbidden Response.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","","","","Returns the argument unchanged.","","Returns the argument unchanged.","Returns the argument unchanged.","","Returns the argument unchanged.","","Returns the argument unchanged.","","Perform the conversion.","","","","","The handler for this endpoint.","The handler for this endpoint.","","Returns true iff the URI contains placeholders. false by …","Returns true iff the URI contains placeholders. false by …","Returns true iff the URI contains placeholders. false by …","Returns true iff the URI contains placeholders. false by …","Set a custom HTTP header. If a header with this name was …","Set a custom HTTP header. If a header with this name was …","Add an HTTP header to the Response.","Allow manipulating HTTP headers.","Allow manipulating HTTP headers.","The HTTP Verb of this endpoint.","The HTTP Verb of this endpoint.","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Turn this into a response that can be returned to the …","This will always be a 204 No Content together with an …","","","","","","","","Create a Response with mime type json from already …","Return the SHA256-HMAC secret used to verify the JWT token.","","Return the mime type of this Response.","","Returns true iff the request body should be parsed. false …","Returns true iff the request body should be parsed. false …","Returns true iff the request body should be parsed. false …","Returns true iff the request body should be parsed. false …","Returns true iff the request parameters should be parsed. …","Returns true iff the request parameters should be parsed. …","Returns true iff the request parameters should be parsed. …","Returns true iff the request parameters should be parsed. …","","","","Create a new Response from raw data.","","Create a 204 No Content Response.","","Register a GET route to path that returns the OpenAPI …","Register a GET route to path that returns the OpenAPI …","Replace the automatically generated operation id with a …","Replace the automatically generated operation id with a …","The verb used for generating an operation id if …","","","","","","","Return the schema of the response for the given status …","","","Returns the schema of the () type.","","","","","Register all methods handled by this resource with the …","Register all methods handled by this resource with the …","Return the status code of this Response.","","All status codes returned by this response. Returns …","All status codes returned by this response. Returns …","","","","","Return all types that are supported as content types. Use …","Return all types that are supported as content types. Use …","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","The URI that this endpoint listens on in gotham’s format.","The URI that this endpoint listens on in gotham’s format.","","","","","Returns true if the request wants to know the auth status …","Returns true if the request wants to know the auth status …","Returns true if the request wants to know the auth status …","Returns true if the request wants to know the auth status …","","Copy the Origin header into the Access-Control-Allow-Origin…","Copy the Access-Control-Request-Headers header into the …","This is the configuration that the CORS handler will …","Add CORS routing for your path. This is required for …","Specify the allowed headers of the request. It is up to …","Set the Access-Control-Allow-Headers header to the …","Do not send any Access-Control-Allow-Origin headers.","Do not send any Access-Control-Allow-Headers headers.","Specify the allowed origins of the request. It is up to …","Set the Access-Control-Allow-Origin header to a single …","Send Access-Control-Allow-Origin: *. Note that browser …","","","","","","","","","","","","","","","","Handle a preflight request on path for method. To …","Whether or not the request may be made with supplying …","","","","","","","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Handle CORS for a non-preflight request. This means …","The allowed headers.","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","The amount of seconds that the preflight request can be …","","The allowed origins.","","","","","","","","","","","","","","","",""],"i":[0,0,0,0,0,0,0,0,0,17,18,64,65,18,0,0,0,0,0,0,0,0,66,67,68,23,0,0,0,18,0,0,0,17,0,0,0,23,64,65,64,65,64,65,0,0,0,0,0,0,0,0,0,0,0,0,0,17,17,0,67,67,24,26,5,5,17,18,19,11,20,21,22,23,24,5,25,26,36,17,18,21,17,18,19,11,20,21,22,23,24,5,25,26,36,17,18,21,11,17,18,19,11,20,21,22,23,24,5,25,26,17,18,19,11,20,21,22,23,24,5,25,26,0,0,24,25,26,0,0,65,65,21,56,57,0,21,17,18,19,11,20,21,22,23,24,5,25,26,36,36,17,18,19,11,20,21,22,23,23,23,23,24,24,5,25,26,26,26,36,19,68,5,11,19,0,64,65,0,64,64,65,65,24,26,36,24,26,64,65,17,18,19,11,20,21,22,23,24,5,25,26,36,67,24,5,25,26,36,66,22,23,36,10,19,36,5,64,64,65,65,64,64,65,65,11,22,5,36,11,36,17,69,69,65,65,65,5,0,0,70,71,66,72,22,23,24,5,25,26,0,73,74,36,66,72,72,22,23,24,25,75,75,17,18,21,20,25,17,18,19,11,20,21,22,23,24,5,25,26,17,18,21,17,18,21,17,18,19,11,20,21,22,23,24,5,25,26,36,17,18,19,11,20,21,22,23,24,5,25,26,36,17,18,21,17,18,19,11,20,21,22,23,24,5,25,26,36,0,0,64,65,20,20,21,5,64,64,65,65,76,62,63,0,0,0,63,62,63,0,62,62,62,63,61,61,62,63,61,61,61,62,63,61,62,63,61,77,61,62,63,61,62,63,61,62,63,61,0,61,62,63,61,61,61,61,61,62,63,61,61,61,62,63,61,62,63,61,61,62,63,61],"f":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,[[],[[3,[[2,[1]]]]]],[[],[[3,[[2,[1]]]]]],[[],[[3,[[2,[1]]]]]],[[],[[3,[[2,[1]]]]]],[[[5,[4]]]],[[[5,[6]]]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[7],[7],[7],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[7],[7],[7],[[[11,[[0,[8,9]],[10,[[0,[8,9]]]]]],7,12],[[15,[[14,[13]]]]]],[[[17,[[0,[16,9]]]]],[[17,[[0,[16,9]]]]]],[18,18],[19,19],[[[11,[16]]],[[11,[16]]]],[20,20],[21,21],[22,22],[[[23,[16]]],[[23,[16]]]],[24,24],[[[5,[16]]],[[5,[16]]]],[25,25],[[[26,[16]]],[[26,[16]]]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],0,0,[[],24],[[],25],[[],[[26,[27]]]],0,0,[[],[[3,[28]]]],[[],[[3,[28]]]],[29,[[30,[21]]]],[[]],[[]],0,[[7,[32,[31]]]],[[[17,[[0,[33,9]]]],34],35],[[18,34],35],[[19,34],35],[[[11,[33,33]],34],35],[[20,34],35],[[21,34],35],[[22,34],35],[[[23,[33]],34],35],[[24,34],35],[[[5,[33]],34],35],[[25,34],35],[[[26,[33]],34],35],[[36,34],35],[[],36],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[37],[[[0,[0,38]]],23],[22,23],[[]],[[],24],[[]],[[]],[[],26],[[]],[37],[[]],[[],19],[[39,1],30],[[39,1],[[30,[[5,[40]]]]]],[18,[[11,[[0,[8,9]],[0,[[10,[[0,[8,9]]]],27]]]]]],[[[2,[41]]],19],0,[[7,3],42],[[7,3],42],0,[[],43],[[],43],[[],43],[[],43],[[24,44,45]],[[26,44,45]],[[36,46,45]],[24,47],[26,47],[[],48],[[],48],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[],[[42,[[30,[36]]]]]],[24,[[15,[[14,[49]]]]]],[[[5,[[38,[31]]]]],[[15,[[14,[49]]]]]],[25,[[42,[[30,[36]]]]]],[[[26,[50]]],[[15,[[14,[49]]]]]],[36,[[42,[[30,[36]]]]]],[[],[[30,[36]]]],[22,[[30,[36]]]],[23,[[30,[36]]]],[[51,[38,[31]]],36],[[7,12],[[3,[[2,[41]]]]]],[[19,7,12],[[3,[[2,[41]]]]]],[36,[[3,[1]]]],0,[[],43],[[],43],[[],43],[[],43],[[],43],[[],43],[[],43],[[],43],[[18,52,[10,[[0,[8,9]]]]],[[11,[[0,[8,9]],[10,[[0,[8,9]]]]]]]],[[[38,[28]]],22],[1,5],[[51,[38,[31]],[3,[1]]],36],[11,[[53,[11]]]],[[],36],[[[17,[9]]],[[30,[9,22]]]],[54],[54],[[],[[3,[28]]]],[[],[[3,[28]]]],[[],[[3,[54]]]],0,0,0,[54],[54],[51,55],[51,55],[51,55],[51,55],[51,55],[51,55],[51,55],[51,55],0,[56],[57],[36,51],[[],[[2,[51]]]],[[],[[2,[51]]]],[[],[[2,[51]]]],[[],[[2,[51]]]],[[],[[2,[51]]]],[[],[[2,[51]]]],[[],[[2,[51]]]],[[],[[3,[[2,[1]]]]]],[[],[[3,[[2,[1]]]]]],[7],[7],[7],0,0,[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[7,3],[7,3],[7,3],[7,3],[7,3],[7,3],[[],30],[[],30],[[],30],[[],30],[[],30],[[],30],[[],30],[[],30],[[],30],[[],30],[[],30],[[],30],[[],30],[[],30],[[],30],[[],30],[[],30],[[],30],[[],30],[[],30],[[],30],[[],30],[[],30],[[],30],[[],30],[[],30],[7,3],[7,3],[7,3],[[],58],[[],58],[[],58],[[],58],[[],58],[[],58],[[],58],[[],58],[[],58],[[],58],[[],58],[[],58],[[],58],0,0,[[],[[59,[54]]]],[[],[[59,[54]]]],0,0,[60],[60],[[],43],[[],43],[[],43],[[],43],[[20,12]],0,0,0,0,0,0,0,0,0,0,0,[[]],[[]],[[]],[7],[[]],[[]],[[]],[7],[[61,7,12],[[15,[[14,[13]]]]]],[62,62],[63,63],[61,61],[[]],[[]],[[]],[[54,48]],0,[[],62],[[],63],[[],61],[[62,34],35],[[63,34],35],[[61,34],35],[[]],[[]],[[]],[[7,[32,[31]]]],0,[[]],[[]],[[]],0,[61,[[53,[61]]]],0,[7],[[]],[[]],[[]],[7,3],[7,3],[[],30],[[],30],[[],30],[[],30],[[],30],[[],30],[7,3],[[],58],[[],58],[[],58]],"c":[],"p":[[3,"Mime"],[3,"Vec"],[4,"Option"],[8,"AsMut"],[3,"Raw"],[8,"AsRef"],[3,"State"],[8,"DeserializeOwned"],[8,"Send"],[8,"AuthHandler"],[3,"AuthMiddleware"],[8,"FnOnce"],[6,"HandlerFuture"],[3,"Box"],[3,"Pin"],[8,"Clone"],[4,"AuthStatus"],[4,"AuthSource"],[3,"StaticAuthHandler"],[3,"OpenapiInfo"],[3,"NoopExtractor"],[3,"AuthError"],[4,"AuthErrorOrOther"],[3,"NoContent"],[3,"Redirect"],[3,"Success"],[8,"Default"],[3,"String"],[8,"Deserializer"],[4,"Result"],[3,"Body"],[3,"Response"],[8,"Debug"],[3,"Formatter"],[6,"Result"],[3,"Response"],[15,"never"],[8,"Into"],[3,"Bytes"],[8,"From"],[15,"u8"],[6,"BoxFuture"],[15,"bool"],[8,"IntoHeaderName"],[3,"HeaderValue"],[3,"HeaderName"],[3,"HeaderMap"],[3,"Method"],[8,"Future"],[8,"ResponseBody"],[3,"StatusCode"],[6,"AuthValidation"],[6,"Result"],[15,"str"],[3,"OpenapiSchema"],[8,"DrawResourceRoutes"],[8,"DrawResourceRoutesWithSchema"],[3,"TypeId"],[4,"Cow"],[8,"Visitor"],[3,"CorsConfig"],[4,"Origin"],[4,"Headers"],[8,"Endpoint"],[8,"EndpointWithSchema"],[8,"IntoResponseError"],[8,"IntoResponse"],[8,"FromBody"],[8,"GetOpenapi"],[8,"DrawResources"],[8,"DrawResourcesWithSchema"],[8,"ResponseSchema"],[8,"Resource"],[8,"ResourceWithSchema"],[8,"RequestBody"],[8,"WithOpenapi"],[8,"CorsRoute"]]}\ +"gotham_restful":{"doc":"This crate is an extension to the popular gotham web …","t":"DEIDGEEGGNNQQNCCIIIIIIQQQNIYINIIINDDDNQQQQQQDDIYIYYIDIIDDNNILLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLAXLLLXXLLLKKXLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLKLLLLCKKCLLLLLLLLLKKLLLLLLLLLLLLLKLLLLLKLLLKLLMLLLLLLLLLLLLLLLKKLLKMXXKKKKLLLLLLXKKLKLLLLLLLLLLLLMMLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLXXKKMMLLLLLLKNNDIENNNENNLLLLLLLLLLLLLLLKMLLLLLLLLLFMLLLMLMLLLLLLLLLLLLLLLL","n":["AuthError","AuthErrorOrOther","AuthHandler","AuthMiddleware","AuthResult","AuthSource","AuthStatus","AuthSuccess","AuthValidation","Authenticated","AuthorizationHeader","Body","Body","Cookie","CorsConfig","CorsRoute","DrawResourceRoutes","DrawResourceRoutesWithSchema","DrawResources","DrawResourcesWithSchema","Endpoint","EndpointWithSchema","Err","Err","Err","Forbidden","FromBody","FromBody","GetOpenapi","Header","IntoResponse","IntoResponseError","IntoResponseWithSchema","Invalid","NoContent","NoopExtractor","OpenapiInfo","Other","Output","Output","Params","Params","Placeholders","Placeholders","Raw","Redirect","RequestBody","RequestBody","Resource","Resource","ResourceError","ResourceWithSchema","Response","ResponseBody","ResponseSchema","StaticAuthHandler","Success","Unauthenticated","Unknown","WithOpenapi","accepted_types","accepted_types","accepted_types","accepted_types","as_mut","as_ref","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow_from","borrow_from","borrow_from","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut_from","borrow_mut_from","borrow_mut_from","call","clone","clone","clone","clone","clone","clone","clone","clone","clone","clone","clone","clone","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","cors","create","default","default","default","delete","delete_all","description","description","deserialize","endpoint","endpoint","endpoint","extend","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","forbidden","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from_array","from_body","from_body","from_body","from_source","from_vec","gotham","handle","handle","handle_cors","has_placeholders","has_placeholders","has_placeholders","has_placeholders","header","header","header","headers_mut","headers_mut","http_method","http_method","into","into","into","into","into","into","into","into","into","into","into","into","into","into_response","into_response","into_response","into_response","into_response","into_response","into_response_error","into_response_error","into_response_error","json","jwt_secret","jwt_secret","mime","mime","needs_body","needs_body","needs_body","needs_body","needs_params","needs_params","needs_params","needs_params","new","new","new","new","new_middleware","no_content","ok","openapi_doc","openapi_spec","operation_id","operation_id","operation_verb","raw","read","read_all","resource","resource","schema","schema","schema","schema","schema","schema","schema","schema","search","setup","setup","status","status_codes","status_codes","status_codes","status_codes","status_codes","status_codes","status_codes","supported_types","supported_types","supported_types","take_from","take_from","take_from","title","to","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","try_borrow_from","try_borrow_from","try_borrow_from","try_borrow_mut_from","try_borrow_mut_from","try_borrow_mut_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_take_from","try_take_from","try_take_from","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","update","update_all","uri","uri","urls","version","visit_type","visit_type","wants_auth","wants_auth","wants_auth","wants_auth","with_openapi","Copy","Copy","CorsConfig","CorsRoute","Headers","List","None","None","Origin","Single","Star","borrow","borrow","borrow","borrow_from","borrow_mut","borrow_mut","borrow_mut","borrow_mut_from","call","clone","clone","clone","clone_into","clone_into","clone_into","cors","credentials","default","default","default","fmt","fmt","fmt","from","from","from","handle_cors","headers","into","into","into","max_age","new_middleware","origin","take_from","to_owned","to_owned","to_owned","try_borrow_from","try_borrow_mut_from","try_from","try_from","try_from","try_into","try_into","try_into","try_take_from","type_id","type_id","type_id"],"q":[[0,"gotham_restful"],[343,"gotham_restful::cors"]],"d":["This is an error type that always yields a 403 Forbidden …","This is an error type that either yields a 403 Forbidden …","This trait will help the auth middleware to determine the …","This is the auth middleware. To use it, first make sure …","This return type can be used to wrap any type implementing …","The source of the authentication token in the request.","The authentication status returned by the auth middleware …","This return type can be used to wrap any type implementing …","","The request has been performed with a valid …","Take the token from the HTTP Authorization header. This is …","The type to parse the body into. Use () if needs_body() …","The type to parse the body into. Use () if needs_body() …","Take the token from a cookie with the given name.","","","This trait allows to draw routes within an resource. Use …","This trait allows to draw routes within an resource. Use …","This trait adds the resource method to gotham’s routing. …","This trait adds the resource method to gotham’s routing. …","","","","","The error type returned by the conversion if it was …","","This trait should be implemented for every type that can …","","This trait adds the openapi_spec and openapi_doc method to …","Take the token from a header with the given name.","This trait needs to be implemented by every type returned …","","A trait provided to convert a resource’s result to json, …","The request has been performed with an invalid …","This is the return type of a resource that doesn’t …","A no-op extractor that can be used as a default type for …","","","The output type that provides the response.","The output type that provides the response.","The type that parses the request parameters. Use …","The type that parses the request parameters. Use …","The type that parses the URI placeholders. Use …","The type that parses the URI placeholders. Use …","This type can be used both as a raw request body, as well …","This is the return type of a resource that only returns a …","A type that can be used inside a request body. Implemented …","","This trait must be implemented for every resource. It …","","","This trait must be implemented for every resource. It …","A response, used to create the final gotham response from.","A type that can be used inside a response body. …","Additional details for IntoResponse to be used with an …","An AuthHandler returning always the same secret. See …","This can be returned from a resource when there is no …","The request has been performed without any kind of …","The auth status is unknown. This is likely because no …","This trait adds the with_openapi method to gotham’s …","Return a list of supported mime types.","Return a list of supported mime types.","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","Add a description to the openapi specification. Usually …","Add a description to the openapi specification. Usually …","","","","","","","","","","","","","","","","","","","Create an empty 403 Forbidden Response.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","","","","Returns the argument unchanged.","","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","","","Returns the argument unchanged.","","Perform the conversion.","","","","","","The handler for this endpoint.","The handler for this endpoint.","","Returns true iff the URI contains placeholders. false by …","Returns true iff the URI contains placeholders. false by …","Returns true iff the URI contains placeholders. false by …","Returns true iff the URI contains placeholders. false by …","Set a custom HTTP header. If a header with this name was …","Set a custom HTTP header. If a header with this name was …","Add an HTTP header to the Response.","Allow manipulating HTTP headers.","Allow manipulating HTTP headers.","The HTTP Verb of this endpoint.","The HTTP Verb of this endpoint.","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Turn this into a response that can be returned to the …","This will always be a 204 No Content together with an …","","","","","","","","Create a Response with mime type json from already …","Return the SHA256-HMAC secret used to verify the JWT token.","","Return the mime type of this Response.","","Returns true iff the request body should be parsed. false …","Returns true iff the request body should be parsed. false …","Returns true iff the request body should be parsed. false …","Returns true iff the request body should be parsed. false …","Returns true iff the request parameters should be parsed. …","Returns true iff the request parameters should be parsed. …","Returns true iff the request parameters should be parsed. …","Returns true iff the request parameters should be parsed. …","","","","Create a new Response from raw data.","","Create a 204 No Content Response.","","Register a GET route to path that returns the OpenAPI …","Register a GET route to path that returns the OpenAPI …","Replace the automatically generated operation id with a …","Replace the automatically generated operation id with a …","The verb used for generating an operation id if …","","","","","","","Return the schema of the response for the given status …","","","Returns the schema of the () type.","","","","","Register all methods handled by this resource with the …","Register all methods handled by this resource with the …","Return the status code of this Response.","","All status codes returned by this response. Returns …","All status codes returned by this response. Returns …","","","","","Return all types that are supported as content types. Use …","Return all types that are supported as content types. Use …","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","The URI that this endpoint listens on in gotham’s format.","The URI that this endpoint listens on in gotham’s format.","","","","","Returns true if the request wants to know the auth status …","Returns true if the request wants to know the auth status …","Returns true if the request wants to know the auth status …","Returns true if the request wants to know the auth status …","","Copy the Origin header into the Access-Control-Allow-Origin…","Copy the Access-Control-Request-Headers header into the …","This is the configuration that the CORS handler will …","Add CORS routing for your path. This is required for …","Specify the allowed headers of the request. It is up to …","Set the Access-Control-Allow-Headers header to the …","Do not send any Access-Control-Allow-Origin headers.","Do not send any Access-Control-Allow-Headers headers.","Specify the allowed origins of the request. It is up to …","Set the Access-Control-Allow-Origin header to a single …","Send Access-Control-Allow-Origin: *. Note that browser …","","","","","","","","","","","","","","","","Handle a preflight request on path for method. To …","Whether or not the request may be made with supplying …","","","","","","","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Handle CORS for a non-preflight request. This means …","The allowed headers.","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","The amount of seconds that the preflight request can be …","","The allowed origins.","","","","","","","","","","","","","","","",""],"i":[0,0,0,0,0,0,0,0,0,17,18,66,67,18,0,0,0,0,0,0,0,0,68,69,70,23,0,0,0,18,0,0,0,17,0,0,0,23,66,67,66,67,66,67,0,0,0,0,0,0,0,0,0,0,0,0,0,17,17,0,69,69,24,26,5,5,17,18,19,11,20,21,22,23,24,5,25,26,36,17,18,21,17,18,19,11,20,21,22,23,24,5,25,26,36,17,18,21,11,17,18,19,11,20,21,22,23,24,5,25,26,17,18,19,11,20,21,22,23,24,5,25,26,0,0,24,25,26,0,0,67,67,21,57,58,0,21,17,18,19,11,20,21,22,23,24,5,25,26,36,36,17,18,19,11,20,21,22,23,23,23,23,24,24,5,25,26,26,26,36,19,70,21,5,11,19,0,66,67,0,66,66,67,67,24,26,36,24,26,66,67,17,18,19,11,20,21,22,23,24,5,25,26,36,69,24,5,25,26,36,68,22,23,36,10,19,36,5,66,66,67,67,66,66,67,67,11,22,5,36,11,36,17,71,71,67,67,67,5,0,0,72,73,68,74,22,23,24,5,25,26,0,75,76,36,68,74,74,22,23,24,25,77,77,21,17,18,21,20,25,17,18,19,11,20,21,22,23,24,5,25,26,17,18,21,17,18,21,17,18,19,11,20,21,22,23,24,5,25,26,36,17,18,19,11,20,21,22,23,24,5,25,26,36,17,18,21,17,18,19,11,20,21,22,23,24,5,25,26,36,0,0,66,67,20,20,21,5,66,66,67,67,78,64,65,0,0,0,65,64,65,0,64,64,64,65,63,63,64,65,63,63,63,64,65,63,64,65,63,79,63,64,65,63,64,65,63,64,65,63,0,63,64,65,63,63,63,63,63,64,65,63,63,63,64,65,63,64,65,63,63,64,65,63],"f":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,[[],[[3,[[2,[1]]]]]],[[],[[3,[[2,[1]]]]]],[[],[[3,[[2,[1]]]]]],[[],[[3,[[2,[1]]]]]],[[[5,[4]]]],[[[5,[6]]]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[7],[7],[7],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[7],[7],[7],[[[11,[[0,[8,9]],[10,[[0,[8,9]]]]]],7,12],[[15,[[14,[13]]]]]],[[[17,[[0,[16,9]]]]],[[17,[[0,[16,9]]]]]],[18,18],[19,19],[[[11,[16]]],[[11,[16]]]],[20,20],[21,21],[22,22],[[[23,[16]]],[[23,[16]]]],[24,24],[[[5,[16]]],[[5,[16]]]],[25,25],[[[26,[16]]],[[26,[16]]]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],0,0,[[],24],[[],25],[[],[[26,[27]]]],0,0,[[],[[3,[28]]]],[[],[[3,[28]]]],[29,[[30,[21]]]],[[]],[[]],0,[[7,[32,[31]]]],[[[17,[[0,[33,9]]]],34],35],[[18,34],35],[[19,34],35],[[[11,[33,33]],34],35],[[20,34],35],[[21,34],35],[[22,34],35],[[[23,[33]],34],35],[[24,34],35],[[[5,[33]],34],35],[[25,34],35],[[[26,[33]],34],35],[[36,34],35],[[],36],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[22,23],[[[0,[0,37]]],23],[38],[[]],[[],24],[[]],[[]],[[]],[[]],[38],[[],26],[[]],[[[40,[39]]],19],[[41,1],30],[[41,1],30],[[41,1],[[30,[[5,[[42,[[40,[39]]]]]]]]]],[18,[[11,[[0,[8,9]],[0,[[10,[[0,[8,9]]]],27]]]]]],[[[2,[39]]],19],0,[[7,3],43],[[7,3],43],0,[[],44],[[],44],[[],44],[[],44],[[24,45,46]],[[26,45,46]],[[36,47,46]],[24,48],[26,48],[[],49],[[],49],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[],[[43,[[30,[36]]]]]],[24,[[15,[[14,[50]]]]]],[[[5,[[37,[31]]]]],[[15,[[14,[50]]]]]],[25,[[43,[[30,[36]]]]]],[[[26,[51]]],[[15,[[14,[50]]]]]],[36,[[43,[[30,[36]]]]]],[[],[[30,[36]]]],[22,[[30,[36]]]],[23,[[30,[36]]]],[[52,[37,[31]]],36],[[7,12],[[3,[[2,[39]]]]]],[[19,7,12],[[3,[[2,[39]]]]]],[36,[[3,[1]]]],0,[[],44],[[],44],[[],44],[[],44],[[],44],[[],44],[[],44],[[],44],[[18,53,[10,[[0,[8,9]]]]],[[11,[[0,[8,9]],[10,[[0,[8,9]]]]]]]],[[[37,[28]]],22],[1,5],[[52,[37,[31]],[3,[1]]],36],[11,[[54,[11]]]],[[],36],[[[17,[9]]],[[30,[9,22]]]],[55],[55],[[],[[3,[28]]]],[[],[[3,[28]]]],[[],[[3,[55]]]],0,0,0,[55],[55],[52,56],[52,56],[52,56],[52,56],[52,56],[52,56],[52,56],[52,56],0,[57],[58],[36,52],[[],[[2,[52]]]],[[],[[2,[52]]]],[[],[[2,[52]]]],[[],[[2,[52]]]],[[],[[2,[52]]]],[[],[[2,[52]]]],[[],[[2,[52]]]],[[],[[3,[[2,[1]]]]]],[[],[[3,[[2,[1]]]]]],[[],[[3,[[2,[1,59]]]]]],[7],[7],[7],0,0,[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[7,3],[7,3],[7,3],[7,3],[7,3],[7,3],[[],30],[[],30],[[],30],[[],30],[[],30],[[],30],[[],30],[[],30],[[],30],[[],30],[[],30],[[],30],[[],30],[[],30],[[],30],[[],30],[[],30],[[],30],[[],30],[[],30],[[],30],[[],30],[[],30],[[],30],[[],30],[[],30],[7,3],[7,3],[7,3],[[],60],[[],60],[[],60],[[],60],[[],60],[[],60],[[],60],[[],60],[[],60],[[],60],[[],60],[[],60],[[],60],0,0,[[],[[61,[55]]]],[[],[[61,[55]]]],0,0,[62],[62],[[],44],[[],44],[[],44],[[],44],[[20,12]],0,0,0,0,0,0,0,0,0,0,0,[[]],[[]],[[]],[7],[[]],[[]],[[]],[7],[[63,7,12],[[15,[[14,[13]]]]]],[64,64],[65,65],[63,63],[[]],[[]],[[]],[[55,49]],0,[[],64],[[],65],[[],63],[[64,34],35],[[65,34],35],[[63,34],35],[[]],[[]],[[]],[[7,[32,[31]]]],0,[[]],[[]],[[]],0,[63,[[54,[63]]]],0,[7],[[]],[[]],[[]],[7,3],[7,3],[[],30],[[],30],[[],30],[[],30],[[],30],[[],30],[7,3],[[],60],[[],60],[[],60]],"c":[],"p":[[3,"Mime"],[3,"Vec"],[4,"Option"],[8,"AsMut"],[3,"Raw"],[8,"AsRef"],[3,"State"],[8,"DeserializeOwned"],[8,"Send"],[8,"AuthHandler"],[3,"AuthMiddleware"],[8,"FnOnce"],[6,"HandlerFuture"],[3,"Box"],[3,"Pin"],[8,"Clone"],[4,"AuthStatus"],[4,"AuthSource"],[3,"StaticAuthHandler"],[3,"OpenapiInfo"],[3,"NoopExtractor"],[3,"AuthError"],[4,"AuthErrorOrOther"],[3,"NoContent"],[3,"Redirect"],[3,"Success"],[8,"Default"],[3,"String"],[8,"Deserializer"],[4,"Result"],[3,"Body"],[3,"Response"],[8,"Debug"],[3,"Formatter"],[6,"Result"],[3,"Response"],[8,"Into"],[15,"never"],[15,"u8"],[15,"slice"],[3,"Bytes"],[8,"From"],[6,"BoxFuture"],[15,"bool"],[8,"IntoHeaderName"],[3,"HeaderValue"],[3,"HeaderName"],[3,"HeaderMap"],[3,"Method"],[8,"Future"],[8,"ResponseBody"],[3,"StatusCode"],[6,"AuthValidation"],[6,"Result"],[15,"str"],[3,"OpenapiSchema"],[8,"DrawResourceRoutes"],[8,"DrawResourceRoutesWithSchema"],[3,"Global"],[3,"TypeId"],[4,"Cow"],[8,"Visitor"],[3,"CorsConfig"],[4,"Origin"],[4,"Headers"],[8,"Endpoint"],[8,"EndpointWithSchema"],[8,"IntoResponseError"],[8,"IntoResponse"],[8,"FromBody"],[8,"GetOpenapi"],[8,"DrawResources"],[8,"DrawResourcesWithSchema"],[8,"ResponseSchema"],[8,"Resource"],[8,"ResourceWithSchema"],[8,"RequestBody"],[8,"WithOpenapi"],[8,"CorsRoute"]]}\ }'); if (typeof window !== 'undefined' && window.initSearch) {window.initSearch(searchIndex)}; if (typeof exports !== 'undefined') {exports.searchIndex = searchIndex}; diff --git a/doc/settings.html b/doc/settings.html index cccbdffef..de5489bd3 100644 --- a/doc/settings.html +++ b/doc/settings.html @@ -1,3 +1,3 @@ -Rustdoc settings

Rustdoc settings

Back
\ No newline at end of file +data-use_system_theme="false">

Rustdoc settings

Back
\ No newline at end of file diff --git a/doc/src/gotham_restful/auth.rs.html b/doc/src/gotham_restful/auth.rs.html index 0a1da4464..5304112e3 100644 --- a/doc/src/gotham_restful/auth.rs.html +++ b/doc/src/gotham_restful/auth.rs.html @@ -1,6 +1,6 @@ -auth.rs - source
1
+data-use_system_theme="false">
1
 2
 3
 4
diff --git a/doc/src/gotham_restful/cors.rs.html b/doc/src/gotham_restful/cors.rs.html
index 006701478..8f215d084 100644
--- a/doc/src/gotham_restful/cors.rs.html
+++ b/doc/src/gotham_restful/cors.rs.html
@@ -1,6 +1,6 @@
-cors.rs - source
1
+data-use_system_theme="false">
1
 2
 3
 4
diff --git a/doc/src/gotham_restful/endpoint.rs.html b/doc/src/gotham_restful/endpoint.rs.html
index a0ac8912c..99bb8e4e3 100644
--- a/doc/src/gotham_restful/endpoint.rs.html
+++ b/doc/src/gotham_restful/endpoint.rs.html
@@ -1,6 +1,6 @@
-endpoint.rs - source
1
+data-use_system_theme="false">
1
 2
 3
 4
diff --git a/doc/src/gotham_restful/lib.rs.html b/doc/src/gotham_restful/lib.rs.html
index 2b58ed4da..6453baa34 100644
--- a/doc/src/gotham_restful/lib.rs.html
+++ b/doc/src/gotham_restful/lib.rs.html
@@ -1,6 +1,6 @@
-lib.rs - source
1
+data-use_system_theme="false">
1
 2
 3
 4
diff --git a/doc/src/gotham_restful/openapi/builder.rs.html b/doc/src/gotham_restful/openapi/builder.rs.html
index 1e1cfbabe..af6ff5a12 100644
--- a/doc/src/gotham_restful/openapi/builder.rs.html
+++ b/doc/src/gotham_restful/openapi/builder.rs.html
@@ -1,6 +1,6 @@
-builder.rs - source
1
+data-use_system_theme="false">
1
 2
 3
 4
diff --git a/doc/src/gotham_restful/openapi/handler/mod.rs.html b/doc/src/gotham_restful/openapi/handler/mod.rs.html
index af1a92fbb..1d606df18 100644
--- a/doc/src/gotham_restful/openapi/handler/mod.rs.html
+++ b/doc/src/gotham_restful/openapi/handler/mod.rs.html
@@ -1,6 +1,6 @@
-mod.rs - source
1
+data-use_system_theme="false">
1
 2
 3
 4
diff --git a/doc/src/gotham_restful/openapi/mod.rs.html b/doc/src/gotham_restful/openapi/mod.rs.html
index cafb55917..396c0ae73 100644
--- a/doc/src/gotham_restful/openapi/mod.rs.html
+++ b/doc/src/gotham_restful/openapi/mod.rs.html
@@ -1,6 +1,6 @@
-mod.rs - source
1
+data-use_system_theme="false">
1
 2
 3
 4
diff --git a/doc/src/gotham_restful/openapi/operation.rs.html b/doc/src/gotham_restful/openapi/operation.rs.html
index bc35db7c7..5039617ca 100644
--- a/doc/src/gotham_restful/openapi/operation.rs.html
+++ b/doc/src/gotham_restful/openapi/operation.rs.html
@@ -1,6 +1,6 @@
-operation.rs - source
1
+data-use_system_theme="false">
1
 2
 3
 4
diff --git a/doc/src/gotham_restful/openapi/router.rs.html b/doc/src/gotham_restful/openapi/router.rs.html
index 2042c81e4..0df6e74a2 100644
--- a/doc/src/gotham_restful/openapi/router.rs.html
+++ b/doc/src/gotham_restful/openapi/router.rs.html
@@ -1,6 +1,6 @@
-router.rs - source
1
+data-use_system_theme="false">
1
 2
 3
 4
diff --git a/doc/src/gotham_restful/response/auth_result.rs.html b/doc/src/gotham_restful/response/auth_result.rs.html
index 67c389988..45902a449 100644
--- a/doc/src/gotham_restful/response/auth_result.rs.html
+++ b/doc/src/gotham_restful/response/auth_result.rs.html
@@ -1,6 +1,6 @@
-auth_result.rs - source
1
+data-use_system_theme="false">
1
 2
 3
 4
diff --git a/doc/src/gotham_restful/response/mod.rs.html b/doc/src/gotham_restful/response/mod.rs.html
index 0f4485968..6beff93e3 100644
--- a/doc/src/gotham_restful/response/mod.rs.html
+++ b/doc/src/gotham_restful/response/mod.rs.html
@@ -1,6 +1,6 @@
-mod.rs - source
1
+data-use_system_theme="false">
1
 2
 3
 4
diff --git a/doc/src/gotham_restful/response/no_content.rs.html b/doc/src/gotham_restful/response/no_content.rs.html
index b43bdb8af..a701afe47 100644
--- a/doc/src/gotham_restful/response/no_content.rs.html
+++ b/doc/src/gotham_restful/response/no_content.rs.html
@@ -1,6 +1,6 @@
-no_content.rs - source
1
+data-use_system_theme="false">
1
 2
 3
 4
diff --git a/doc/src/gotham_restful/response/raw.rs.html b/doc/src/gotham_restful/response/raw.rs.html
index 91149f6fd..6e44d5070 100644
--- a/doc/src/gotham_restful/response/raw.rs.html
+++ b/doc/src/gotham_restful/response/raw.rs.html
@@ -1,6 +1,6 @@
-raw.rs - source
1
+data-use_system_theme="false">
1
 2
 3
 4
diff --git a/doc/src/gotham_restful/response/redirect.rs.html b/doc/src/gotham_restful/response/redirect.rs.html
index 505f1c05b..9830aa93f 100644
--- a/doc/src/gotham_restful/response/redirect.rs.html
+++ b/doc/src/gotham_restful/response/redirect.rs.html
@@ -1,6 +1,6 @@
-redirect.rs - source
1
+data-use_system_theme="false">
1
 2
 3
 4
diff --git a/doc/src/gotham_restful/response/result.rs.html b/doc/src/gotham_restful/response/result.rs.html
index beaa6dda5..147781b81 100644
--- a/doc/src/gotham_restful/response/result.rs.html
+++ b/doc/src/gotham_restful/response/result.rs.html
@@ -1,6 +1,6 @@
-result.rs - source
1
+data-use_system_theme="false">
1
 2
 3
 4
diff --git a/doc/src/gotham_restful/response/success.rs.html b/doc/src/gotham_restful/response/success.rs.html
index a1a542846..2561a89af 100644
--- a/doc/src/gotham_restful/response/success.rs.html
+++ b/doc/src/gotham_restful/response/success.rs.html
@@ -1,6 +1,6 @@
-success.rs - source
1
+data-use_system_theme="false">
1
 2
 3
 4
diff --git a/doc/src/gotham_restful/routing.rs.html b/doc/src/gotham_restful/routing.rs.html
index b3765f97a..99faa5129 100644
--- a/doc/src/gotham_restful/routing.rs.html
+++ b/doc/src/gotham_restful/routing.rs.html
@@ -1,6 +1,6 @@
-routing.rs - source
1
+data-use_system_theme="false">
1
 2
 3
 4
diff --git a/doc/src/gotham_restful/types.rs.html b/doc/src/gotham_restful/types.rs.html
index c1d81e8de..f8061dff1 100644
--- a/doc/src/gotham_restful/types.rs.html
+++ b/doc/src/gotham_restful/types.rs.html
@@ -1,6 +1,6 @@
-types.rs - source
1
+data-use_system_theme="false">
1
 2
 3
 4
diff --git a/doc/static.files/main-f0540c1d82cde29b.js b/doc/static.files/main-f0540c1d82cde29b.js
new file mode 100644
index 000000000..2fa290256
--- /dev/null
+++ b/doc/static.files/main-f0540c1d82cde29b.js
@@ -0,0 +1,7 @@
+"use strict";function resourcePath(basename,extension){return getVar("root-path")+basename+getVar("resource-suffix")+extension}function hideMain(){addClass(document.getElementById(MAIN_ID),"hidden")}function showMain(){removeClass(document.getElementById(MAIN_ID),"hidden")}function elemIsInParent(elem,parent){while(elem&&elem!==document.body){if(elem===parent){return true}elem=elem.parentElement}return false}function blurHandler(event,parentElem,hideCallback){if(!elemIsInParent(document.activeElement,parentElem)&&!elemIsInParent(event.relatedTarget,parentElem)){hideCallback()}}window.rootPath=getVar("root-path");window.currentCrate=getVar("current-crate");function setMobileTopbar(){const mobileLocationTitle=document.querySelector(".mobile-topbar h2");const locationTitle=document.querySelector(".sidebar h2.location");if(mobileLocationTitle&&locationTitle){mobileLocationTitle.innerHTML=locationTitle.innerHTML}}function getVirtualKey(ev){if("key"in ev&&typeof ev.key!=="undefined"){return ev.key}const c=ev.charCode||ev.keyCode;if(c===27){return"Escape"}return String.fromCharCode(c)}const MAIN_ID="main-content";const SETTINGS_BUTTON_ID="settings-menu";const ALTERNATIVE_DISPLAY_ID="alternative-display";const NOT_DISPLAYED_ID="not-displayed";const HELP_BUTTON_ID="help-button";function getSettingsButton(){return document.getElementById(SETTINGS_BUTTON_ID)}function getHelpButton(){return document.getElementById(HELP_BUTTON_ID)}function getNakedUrl(){return window.location.href.split("?")[0].split("#")[0]}function insertAfter(newNode,referenceNode){referenceNode.parentNode.insertBefore(newNode,referenceNode.nextSibling)}function getOrCreateSection(id,classes){let el=document.getElementById(id);if(!el){el=document.createElement("section");el.id=id;el.className=classes;insertAfter(el,document.getElementById(MAIN_ID))}return el}function getAlternativeDisplayElem(){return getOrCreateSection(ALTERNATIVE_DISPLAY_ID,"content hidden")}function getNotDisplayedElem(){return getOrCreateSection(NOT_DISPLAYED_ID,"hidden")}function switchDisplayedElement(elemToDisplay){const el=getAlternativeDisplayElem();if(el.children.length>0){getNotDisplayedElem().appendChild(el.firstElementChild)}if(elemToDisplay===null){addClass(el,"hidden");showMain();return}el.appendChild(elemToDisplay);hideMain();removeClass(el,"hidden")}function browserSupportsHistoryApi(){return window.history&&typeof window.history.pushState==="function"}function loadCss(cssUrl){const link=document.createElement("link");link.href=cssUrl;link.rel="stylesheet";document.getElementsByTagName("head")[0].appendChild(link)}function preLoadCss(cssUrl){const link=document.createElement("link");link.href=cssUrl;link.rel="preload";link.as="style";document.getElementsByTagName("head")[0].appendChild(link)}(function(){const isHelpPage=window.location.pathname.endsWith("/help.html");function loadScript(url){const script=document.createElement("script");script.src=url;document.head.append(script)}getSettingsButton().onclick=event=>{if(event.ctrlKey||event.altKey||event.metaKey){return}window.hideAllModals(false);addClass(getSettingsButton(),"rotate");event.preventDefault();loadCss(getVar("static-root-path")+getVar("settings-css"));loadScript(getVar("static-root-path")+getVar("settings-js"));preLoadCss(getVar("static-root-path")+getVar("theme-light-css"));preLoadCss(getVar("static-root-path")+getVar("theme-dark-css"));preLoadCss(getVar("static-root-path")+getVar("theme-ayu-css"));setTimeout(()=>{const themes=getVar("themes").split(",");for(const theme of themes){if(theme!==""){preLoadCss(getVar("root-path")+theme+".css")}}},0)};window.searchState={loadingText:"Loading search results...",input:document.getElementsByClassName("search-input")[0],outputElement:()=>{let el=document.getElementById("search");if(!el){el=document.createElement("section");el.id="search";getNotDisplayedElem().appendChild(el)}return el},title:document.title,titleBeforeSearch:document.title,timeout:null,currentTab:0,focusedByTab:[null,null,null],clearInputTimeout:()=>{if(searchState.timeout!==null){clearTimeout(searchState.timeout);searchState.timeout=null}},isDisplayed:()=>searchState.outputElement().parentElement.id===ALTERNATIVE_DISPLAY_ID,focus:()=>{searchState.input.focus()},defocus:()=>{searchState.input.blur()},showResults:search=>{if(search===null||typeof search==="undefined"){search=searchState.outputElement()}switchDisplayedElement(search);searchState.mouseMovedAfterSearch=false;document.title=searchState.title},hideResults:()=>{switchDisplayedElement(null);document.title=searchState.titleBeforeSearch;if(browserSupportsHistoryApi()){history.replaceState(null,"",getNakedUrl()+window.location.hash)}},getQueryStringParams:()=>{const params={};window.location.search.substring(1).split("&").map(s=>{const pair=s.split("=");params[decodeURIComponent(pair[0])]=typeof pair[1]==="undefined"?null:decodeURIComponent(pair[1])});return params},setup:()=>{const search_input=searchState.input;if(!searchState.input){return}let searchLoaded=false;function loadSearch(){if(!searchLoaded){searchLoaded=true;loadScript(getVar("static-root-path")+getVar("search-js"));loadScript(resourcePath("search-index",".js"))}}search_input.addEventListener("focus",()=>{search_input.origPlaceholder=search_input.placeholder;search_input.placeholder="Type your search here.";loadSearch()});if(search_input.value!==""){loadSearch()}const params=searchState.getQueryStringParams();if(params.search!==undefined){searchState.setLoadingSearch();loadSearch()}},setLoadingSearch:()=>{const search=searchState.outputElement();search.innerHTML="

"+searchState.loadingText+"

";searchState.showResults(search)},};const toggleAllDocsId="toggle-all-docs";let savedHash="";function handleHashes(ev){if(ev!==null&&searchState.isDisplayed()&&ev.newURL){switchDisplayedElement(null);const hash=ev.newURL.slice(ev.newURL.indexOf("#")+1);if(browserSupportsHistoryApi()){history.replaceState(null,"",getNakedUrl()+window.location.search+"#"+hash)}const elem=document.getElementById(hash);if(elem){elem.scrollIntoView()}}const pageId=window.location.hash.replace(/^#/,"");if(savedHash!==pageId){savedHash=pageId;if(pageId!==""){expandSection(pageId)}}}function onHashChange(ev){hideSidebar();handleHashes(ev)}function openParentDetails(elem){while(elem){if(elem.tagName==="DETAILS"){elem.open=true}elem=elem.parentNode}}function expandSection(id){openParentDetails(document.getElementById(id))}function handleEscape(ev){searchState.clearInputTimeout();searchState.hideResults();ev.preventDefault();searchState.defocus();window.hideAllModals(true)}function handleShortcut(ev){const disableShortcuts=getSettingValue("disable-shortcuts")==="true";if(ev.ctrlKey||ev.altKey||ev.metaKey||disableShortcuts){return}if(document.activeElement.tagName==="INPUT"&&document.activeElement.type!=="checkbox"&&document.activeElement.type!=="radio"){switch(getVirtualKey(ev)){case"Escape":handleEscape(ev);break}}else{switch(getVirtualKey(ev)){case"Escape":handleEscape(ev);break;case"s":case"S":ev.preventDefault();searchState.focus();break;case"+":ev.preventDefault();expandAllDocs();break;case"-":ev.preventDefault();collapseAllDocs();break;case"?":showHelp();break;default:break}}}document.addEventListener("keypress",handleShortcut);document.addEventListener("keydown",handleShortcut);function addSidebarItems(){if(!window.SIDEBAR_ITEMS){return}const sidebar=document.getElementsByClassName("sidebar-elems")[0];function block(shortty,id,longty){const filtered=window.SIDEBAR_ITEMS[shortty];if(!filtered){return}const h3=document.createElement("h3");h3.innerHTML=`${longty}`;const ul=document.createElement("ul");ul.className="block "+shortty;for(const name of filtered){let path;if(shortty==="mod"){path=name+"/index.html"}else{path=shortty+"."+name+".html"}const current_page=document.location.href.split("/").pop();const link=document.createElement("a");link.href=path;if(path===current_page){link.className="current"}link.textContent=name;const li=document.createElement("li");li.appendChild(link);ul.appendChild(li)}sidebar.appendChild(h3);sidebar.appendChild(ul)}if(sidebar){block("primitive","primitives","Primitive Types");block("mod","modules","Modules");block("macro","macros","Macros");block("struct","structs","Structs");block("enum","enums","Enums");block("union","unions","Unions");block("constant","constants","Constants");block("static","static","Statics");block("trait","traits","Traits");block("fn","functions","Functions");block("type","types","Type Definitions");block("foreigntype","foreign-types","Foreign Types");block("keyword","keywords","Keywords");block("traitalias","trait-aliases","Trait Aliases")}}window.register_implementors=imp=>{const implementors=document.getElementById("implementors-list");const synthetic_implementors=document.getElementById("synthetic-implementors-list");const inlined_types=new Set();const TEXT_IDX=0;const SYNTHETIC_IDX=1;const TYPES_IDX=2;if(synthetic_implementors){onEachLazy(synthetic_implementors.getElementsByClassName("impl"),el=>{const aliases=el.getAttribute("data-aliases");if(!aliases){return}aliases.split(",").forEach(alias=>{inlined_types.add(alias)})})}let currentNbImpls=implementors.getElementsByClassName("impl").length;const traitName=document.querySelector(".main-heading h1 > .trait").textContent;const baseIdName="impl-"+traitName+"-";const libs=Object.getOwnPropertyNames(imp);const script=document.querySelector("script[data-ignore-extern-crates]");const ignoreExternCrates=new Set((script?script.getAttribute("data-ignore-extern-crates"):"").split(","));for(const lib of libs){if(lib===window.currentCrate||ignoreExternCrates.has(lib)){continue}const structs=imp[lib];struct_loop:for(const struct of structs){const list=struct[SYNTHETIC_IDX]?synthetic_implementors:implementors;if(struct[SYNTHETIC_IDX]){for(const struct_type of struct[TYPES_IDX]){if(inlined_types.has(struct_type)){continue struct_loop}inlined_types.add(struct_type)}}const code=document.createElement("h3");code.innerHTML=struct[TEXT_IDX];addClass(code,"code-header");onEachLazy(code.getElementsByTagName("a"),elem=>{const href=elem.getAttribute("href");if(href&&!/^(?:[a-z+]+:)?\/\//.test(href)){elem.setAttribute("href",window.rootPath+href)}});const currentId=baseIdName+currentNbImpls;const anchor=document.createElement("a");anchor.href="#"+currentId;addClass(anchor,"anchor");const display=document.createElement("div");display.id=currentId;addClass(display,"impl");display.appendChild(anchor);display.appendChild(code);list.appendChild(display);currentNbImpls+=1}}};if(window.pending_implementors){window.register_implementors(window.pending_implementors)}function addSidebarCrates(){if(!window.ALL_CRATES){return}const sidebarElems=document.getElementsByClassName("sidebar-elems")[0];if(!sidebarElems){return}const h3=document.createElement("h3");h3.innerHTML="Crates";const ul=document.createElement("ul");ul.className="block crate";for(const crate of window.ALL_CRATES){const link=document.createElement("a");link.href=window.rootPath+crate+"/index.html";if(window.rootPath!=="./"&&crate===window.currentCrate){link.className="current"}link.textContent=crate;const li=document.createElement("li");li.appendChild(link);ul.appendChild(li)}sidebarElems.appendChild(h3);sidebarElems.appendChild(ul)}function expandAllDocs(){const innerToggle=document.getElementById(toggleAllDocsId);removeClass(innerToggle,"will-expand");onEachLazy(document.getElementsByClassName("toggle"),e=>{if(!hasClass(e,"type-contents-toggle")&&!hasClass(e,"more-examples-toggle")){e.open=true}});innerToggle.title="collapse all docs";innerToggle.children[0].innerText="\u2212"}function collapseAllDocs(){const innerToggle=document.getElementById(toggleAllDocsId);addClass(innerToggle,"will-expand");onEachLazy(document.getElementsByClassName("toggle"),e=>{if(e.parentNode.id!=="implementations-list"||(!hasClass(e,"implementors-toggle")&&!hasClass(e,"type-contents-toggle"))){e.open=false}});innerToggle.title="expand all docs";innerToggle.children[0].innerText="+"}function toggleAllDocs(){const innerToggle=document.getElementById(toggleAllDocsId);if(!innerToggle){return}if(hasClass(innerToggle,"will-expand")){expandAllDocs()}else{collapseAllDocs()}}(function(){const toggles=document.getElementById(toggleAllDocsId);if(toggles){toggles.onclick=toggleAllDocs}const hideMethodDocs=getSettingValue("auto-hide-method-docs")==="true";const hideImplementations=getSettingValue("auto-hide-trait-implementations")==="true";const hideLargeItemContents=getSettingValue("auto-hide-large-items")!=="false";function setImplementorsTogglesOpen(id,open){const list=document.getElementById(id);if(list!==null){onEachLazy(list.getElementsByClassName("implementors-toggle"),e=>{e.open=open})}}if(hideImplementations){setImplementorsTogglesOpen("trait-implementations-list",false);setImplementorsTogglesOpen("blanket-implementations-list",false)}onEachLazy(document.getElementsByClassName("toggle"),e=>{if(!hideLargeItemContents&&hasClass(e,"type-contents-toggle")){e.open=true}if(hideMethodDocs&&hasClass(e,"method-toggle")){e.open=false}})}());window.rustdoc_add_line_numbers_to_examples=()=>{onEachLazy(document.getElementsByClassName("rust-example-rendered"),x=>{const parent=x.parentNode;const line_numbers=parent.querySelectorAll(".example-line-numbers");if(line_numbers.length>0){return}const count=x.textContent.split("\n").length;const elems=[];for(let i=0;i{onEachLazy(document.getElementsByClassName("rust-example-rendered"),x=>{const parent=x.parentNode;const line_numbers=parent.querySelectorAll(".example-line-numbers");for(const node of line_numbers){parent.removeChild(node)}})};if(getSettingValue("line-numbers")==="true"){window.rustdoc_add_line_numbers_to_examples()}function showSidebar(){window.hideAllModals(false);const sidebar=document.getElementsByClassName("sidebar")[0];addClass(sidebar,"shown")}function hideSidebar(){const sidebar=document.getElementsByClassName("sidebar")[0];removeClass(sidebar,"shown")}window.addEventListener("resize",()=>{if(window.CURRENT_TOOLTIP_ELEMENT){const base=window.CURRENT_TOOLTIP_ELEMENT.TOOLTIP_BASE;const force_visible=base.TOOLTIP_FORCE_VISIBLE;hideTooltip(false);if(force_visible){showTooltip(base);base.TOOLTIP_FORCE_VISIBLE=true}}});const mainElem=document.getElementById(MAIN_ID);if(mainElem){mainElem.addEventListener("click",hideSidebar)}onEachLazy(document.querySelectorAll("a[href^='#']"),el=>{el.addEventListener("click",()=>{expandSection(el.hash.slice(1));hideSidebar()})});onEachLazy(document.querySelectorAll(".toggle > summary:not(.hideme)"),el=>{el.addEventListener("click",e=>{if(e.target.tagName!=="SUMMARY"&&e.target.tagName!=="A"){e.preventDefault()}})});function showTooltip(e){const notable_ty=e.getAttribute("data-notable-ty");if(!window.NOTABLE_TRAITS&¬able_ty){const data=document.getElementById("notable-traits-data");if(data){window.NOTABLE_TRAITS=JSON.parse(data.innerText)}else{throw new Error("showTooltip() called with notable without any notable traits!")}}if(window.CURRENT_TOOLTIP_ELEMENT&&window.CURRENT_TOOLTIP_ELEMENT.TOOLTIP_BASE===e){return}window.hideAllModals(false);const wrapper=document.createElement("div");if(notable_ty){wrapper.innerHTML="
"+window.NOTABLE_TRAITS[notable_ty]+"
"}else if(e.getAttribute("title")!==undefined){const titleContent=document.createElement("div");titleContent.className="content";titleContent.appendChild(document.createTextNode(e.getAttribute("title")));wrapper.appendChild(titleContent)}wrapper.className="tooltip popover";const focusCatcher=document.createElement("div");focusCatcher.setAttribute("tabindex","0");focusCatcher.onfocus=hideTooltip;wrapper.appendChild(focusCatcher);const pos=e.getBoundingClientRect();wrapper.style.top=(pos.top+window.scrollY+pos.height)+"px";wrapper.style.left=0;wrapper.style.right="auto";wrapper.style.visibility="hidden";const body=document.getElementsByTagName("body")[0];body.appendChild(wrapper);const wrapperPos=wrapper.getBoundingClientRect();const finalPos=pos.left+window.scrollX-wrapperPos.width+24;if(finalPos>0){wrapper.style.left=finalPos+"px"}else{wrapper.style.setProperty("--popover-arrow-offset",(wrapperPos.right-pos.right+4)+"px")}wrapper.style.visibility="";window.CURRENT_TOOLTIP_ELEMENT=wrapper;window.CURRENT_TOOLTIP_ELEMENT.TOOLTIP_BASE=e;wrapper.onpointerleave=function(ev){if(ev.pointerType!=="mouse"){return}if(!e.TOOLTIP_FORCE_VISIBLE&&!elemIsInParent(event.relatedTarget,e)){hideTooltip(true)}}}function tooltipBlurHandler(event){if(window.CURRENT_TOOLTIP_ELEMENT&&!elemIsInParent(document.activeElement,window.CURRENT_TOOLTIP_ELEMENT)&&!elemIsInParent(event.relatedTarget,window.CURRENT_TOOLTIP_ELEMENT)&&!elemIsInParent(document.activeElement,window.CURRENT_TOOLTIP_ELEMENT.TOOLTIP_BASE)&&!elemIsInParent(event.relatedTarget,window.CURRENT_TOOLTIP_ELEMENT.TOOLTIP_BASE)){setTimeout(()=>hideTooltip(false),0)}}function hideTooltip(focus){if(window.CURRENT_TOOLTIP_ELEMENT){if(window.CURRENT_TOOLTIP_ELEMENT.TOOLTIP_BASE.TOOLTIP_FORCE_VISIBLE){if(focus){window.CURRENT_TOOLTIP_ELEMENT.TOOLTIP_BASE.focus()}window.CURRENT_TOOLTIP_ELEMENT.TOOLTIP_BASE.TOOLTIP_FORCE_VISIBLE=false}const body=document.getElementsByTagName("body")[0];body.removeChild(window.CURRENT_TOOLTIP_ELEMENT);window.CURRENT_TOOLTIP_ELEMENT=null}}onEachLazy(document.getElementsByClassName("tooltip"),e=>{e.onclick=function(){this.TOOLTIP_FORCE_VISIBLE=this.TOOLTIP_FORCE_VISIBLE?false:true;if(window.CURRENT_TOOLTIP_ELEMENT&&!this.TOOLTIP_FORCE_VISIBLE){hideTooltip(true)}else{showTooltip(this);window.CURRENT_TOOLTIP_ELEMENT.setAttribute("tabindex","0");window.CURRENT_TOOLTIP_ELEMENT.focus();window.CURRENT_TOOLTIP_ELEMENT.onblur=tooltipBlurHandler}return false};e.onpointerenter=function(ev){if(ev.pointerType!=="mouse"){return}showTooltip(this)};e.onpointerleave=function(ev){if(ev.pointerType!=="mouse"){return}if(!this.TOOLTIP_FORCE_VISIBLE&&!elemIsInParent(ev.relatedTarget,window.CURRENT_TOOLTIP_ELEMENT)){hideTooltip(true)}}});const sidebar_menu_toggle=document.getElementsByClassName("sidebar-menu-toggle")[0];if(sidebar_menu_toggle){sidebar_menu_toggle.addEventListener("click",()=>{const sidebar=document.getElementsByClassName("sidebar")[0];if(!hasClass(sidebar,"shown")){showSidebar()}else{hideSidebar()}})}function helpBlurHandler(event){blurHandler(event,getHelpButton(),window.hidePopoverMenus)}function buildHelpMenu(){const book_info=document.createElement("span");book_info.className="top";book_info.innerHTML="You can find more information in \ + the rustdoc book.";const shortcuts=[["?","Show this help dialog"],["S","Focus the search field"],["↑","Move up in search results"],["↓","Move down in search results"],["← / →","Switch result tab (when results focused)"],["⏎","Go to active search result"],["+","Expand all sections"],["-","Collapse all sections"],].map(x=>"
"+x[0].split(" ").map((y,index)=>((index&1)===0?""+y+"":" "+y+" ")).join("")+"
"+x[1]+"
").join("");const div_shortcuts=document.createElement("div");addClass(div_shortcuts,"shortcuts");div_shortcuts.innerHTML="

Keyboard Shortcuts

"+shortcuts+"
";const infos=["Prefix searches with a type followed by a colon (e.g., fn:) to \ + restrict the search to a given item kind.","Accepted kinds are: fn, mod, struct, \ + enum, trait, type, macro, \ + and const.","Search functions by type signature (e.g., vec -> usize or \ + -> vec or String, enum:Cow -> bool)","You can look for items with an exact name by putting double quotes around \ + your request: \"string\"","Look for items inside another one by searching for a path: vec::Vec",].map(x=>"

"+x+"

").join("");const div_infos=document.createElement("div");addClass(div_infos,"infos");div_infos.innerHTML="

Search Tricks

"+infos;const rustdoc_version=document.createElement("span");rustdoc_version.className="bottom";const rustdoc_version_code=document.createElement("code");rustdoc_version_code.innerText="rustdoc "+getVar("rustdoc-version");rustdoc_version.appendChild(rustdoc_version_code);const container=document.createElement("div");if(!isHelpPage){container.className="popover"}container.id="help";container.style.display="none";const side_by_side=document.createElement("div");side_by_side.className="side-by-side";side_by_side.appendChild(div_shortcuts);side_by_side.appendChild(div_infos);container.appendChild(book_info);container.appendChild(side_by_side);container.appendChild(rustdoc_version);if(isHelpPage){const help_section=document.createElement("section");help_section.appendChild(container);document.getElementById("main-content").appendChild(help_section);container.style.display="block"}else{const help_button=getHelpButton();help_button.appendChild(container);container.onblur=helpBlurHandler;help_button.onblur=helpBlurHandler;help_button.children[0].onblur=helpBlurHandler}return container}window.hideAllModals=function(switchFocus){hideSidebar();window.hidePopoverMenus();hideTooltip(switchFocus)};window.hidePopoverMenus=function(){onEachLazy(document.querySelectorAll(".search-form .popover"),elem=>{elem.style.display="none"})};function getHelpMenu(buildNeeded){let menu=getHelpButton().querySelector(".popover");if(!menu&&buildNeeded){menu=buildHelpMenu()}return menu}function showHelp(){getHelpButton().querySelector("a").focus();const menu=getHelpMenu(true);if(menu.style.display==="none"){window.hideAllModals();menu.style.display=""}}if(isHelpPage){showHelp();document.querySelector(`#${HELP_BUTTON_ID} > a`).addEventListener("click",event=>{const target=event.target;if(target.tagName!=="A"||target.parentElement.id!==HELP_BUTTON_ID||event.ctrlKey||event.altKey||event.metaKey){return}event.preventDefault()})}else{document.querySelector(`#${HELP_BUTTON_ID} > a`).addEventListener("click",event=>{const target=event.target;if(target.tagName!=="A"||target.parentElement.id!==HELP_BUTTON_ID||event.ctrlKey||event.altKey||event.metaKey){return}event.preventDefault();const menu=getHelpMenu(true);const shouldShowHelp=menu.style.display==="none";if(shouldShowHelp){showHelp()}else{window.hidePopoverMenus()}})}setMobileTopbar();addSidebarItems();addSidebarCrates();onHashChange(null);window.addEventListener("hashchange",onHashChange);searchState.setup()}());(function(){let reset_button_timeout=null;const but=document.getElementById("copy-path");if(!but){return}but.onclick=()=>{const parent=but.parentElement;const path=[];onEach(parent.childNodes,child=>{if(child.tagName==="A"){path.push(child.textContent)}});const el=document.createElement("textarea");el.value=path.join("::");el.setAttribute("readonly","");el.style.position="absolute";el.style.left="-9999px";document.body.appendChild(el);el.select();document.execCommand("copy");document.body.removeChild(el);but.children[0].style.display="none";let tmp;if(but.childNodes.length<2){tmp=document.createTextNode("✓");but.appendChild(tmp)}else{onEachLazy(but.childNodes,e=>{if(e.nodeType===Node.TEXT_NODE){tmp=e;return true}});tmp.textContent="✓"}if(reset_button_timeout!==null){window.clearTimeout(reset_button_timeout)}function reset_button(){tmp.textContent="";reset_button_timeout=null;but.children[0].style.display=""}reset_button_timeout=window.setTimeout(reset_button,1000)}}()) \ No newline at end of file diff --git a/doc/static.files/main-f61008743c98d196.js b/doc/static.files/main-f61008743c98d196.js deleted file mode 100644 index 18fb9381c..000000000 --- a/doc/static.files/main-f61008743c98d196.js +++ /dev/null @@ -1,7 +0,0 @@ -"use strict";function resourcePath(basename,extension){return getVar("root-path")+basename+getVar("resource-suffix")+extension}function hideMain(){addClass(document.getElementById(MAIN_ID),"hidden")}function showMain(){removeClass(document.getElementById(MAIN_ID),"hidden")}function elemIsInParent(elem,parent){while(elem&&elem!==document.body){if(elem===parent){return true}elem=elem.parentElement}return false}function blurHandler(event,parentElem,hideCallback){if(!elemIsInParent(document.activeElement,parentElem)&&!elemIsInParent(event.relatedTarget,parentElem)){hideCallback()}}window.rootPath=getVar("root-path");window.currentCrate=getVar("current-crate");function setMobileTopbar(){const mobileLocationTitle=document.querySelector(".mobile-topbar h2");const locationTitle=document.querySelector(".sidebar h2.location");if(mobileLocationTitle&&locationTitle){mobileLocationTitle.innerHTML=locationTitle.innerHTML}}function getVirtualKey(ev){if("key"in ev&&typeof ev.key!=="undefined"){return ev.key}const c=ev.charCode||ev.keyCode;if(c===27){return"Escape"}return String.fromCharCode(c)}const MAIN_ID="main-content";const SETTINGS_BUTTON_ID="settings-menu";const ALTERNATIVE_DISPLAY_ID="alternative-display";const NOT_DISPLAYED_ID="not-displayed";const HELP_BUTTON_ID="help-button";function getSettingsButton(){return document.getElementById(SETTINGS_BUTTON_ID)}function getHelpButton(){return document.getElementById(HELP_BUTTON_ID)}function getNakedUrl(){return window.location.href.split("?")[0].split("#")[0]}function insertAfter(newNode,referenceNode){referenceNode.parentNode.insertBefore(newNode,referenceNode.nextSibling)}function getOrCreateSection(id,classes){let el=document.getElementById(id);if(!el){el=document.createElement("section");el.id=id;el.className=classes;insertAfter(el,document.getElementById(MAIN_ID))}return el}function getAlternativeDisplayElem(){return getOrCreateSection(ALTERNATIVE_DISPLAY_ID,"content hidden")}function getNotDisplayedElem(){return getOrCreateSection(NOT_DISPLAYED_ID,"hidden")}function switchDisplayedElement(elemToDisplay){const el=getAlternativeDisplayElem();if(el.children.length>0){getNotDisplayedElem().appendChild(el.firstElementChild)}if(elemToDisplay===null){addClass(el,"hidden");showMain();return}el.appendChild(elemToDisplay);hideMain();removeClass(el,"hidden")}function browserSupportsHistoryApi(){return window.history&&typeof window.history.pushState==="function"}function loadCss(cssUrl){const link=document.createElement("link");link.href=cssUrl;link.rel="stylesheet";document.getElementsByTagName("head")[0].appendChild(link)}function preLoadCss(cssUrl){const link=document.createElement("link");link.href=cssUrl;link.rel="preload";link.as="style";document.getElementsByTagName("head")[0].appendChild(link)}(function(){const isHelpPage=window.location.pathname.endsWith("/help.html");function loadScript(url){const script=document.createElement("script");script.src=url;document.head.append(script)}getSettingsButton().onclick=event=>{if(event.ctrlKey||event.altKey||event.metaKey){return}window.hideAllModals(false);addClass(getSettingsButton(),"rotate");event.preventDefault();loadCss(getVar("static-root-path")+getVar("settings-css"));loadScript(getVar("static-root-path")+getVar("settings-js"));preLoadCss(getVar("static-root-path")+getVar("theme-light-css"));preLoadCss(getVar("static-root-path")+getVar("theme-dark-css"));preLoadCss(getVar("static-root-path")+getVar("theme-ayu-css"));setTimeout(()=>{const themes=getVar("themes").split(",");for(const theme of themes){if(theme!==""){preLoadCss(getVar("root-path")+theme+".css")}}},0)};window.searchState={loadingText:"Loading search results...",input:document.getElementsByClassName("search-input")[0],outputElement:()=>{let el=document.getElementById("search");if(!el){el=document.createElement("section");el.id="search";getNotDisplayedElem().appendChild(el)}return el},title:document.title,titleBeforeSearch:document.title,timeout:null,currentTab:0,focusedByTab:[null,null,null],clearInputTimeout:()=>{if(searchState.timeout!==null){clearTimeout(searchState.timeout);searchState.timeout=null}},isDisplayed:()=>searchState.outputElement().parentElement.id===ALTERNATIVE_DISPLAY_ID,focus:()=>{searchState.input.focus()},defocus:()=>{searchState.input.blur()},showResults:search=>{if(search===null||typeof search==="undefined"){search=searchState.outputElement()}switchDisplayedElement(search);searchState.mouseMovedAfterSearch=false;document.title=searchState.title},hideResults:()=>{switchDisplayedElement(null);document.title=searchState.titleBeforeSearch;if(browserSupportsHistoryApi()){history.replaceState(null,window.currentCrate+" - Rust",getNakedUrl()+window.location.hash)}},getQueryStringParams:()=>{const params={};window.location.search.substring(1).split("&").map(s=>{const pair=s.split("=");params[decodeURIComponent(pair[0])]=typeof pair[1]==="undefined"?null:decodeURIComponent(pair[1])});return params},setup:()=>{const search_input=searchState.input;if(!searchState.input){return}let searchLoaded=false;function loadSearch(){if(!searchLoaded){searchLoaded=true;loadScript(getVar("static-root-path")+getVar("search-js"));loadScript(resourcePath("search-index",".js"))}}search_input.addEventListener("focus",()=>{search_input.origPlaceholder=search_input.placeholder;search_input.placeholder="Type your search here.";loadSearch()});if(search_input.value!==""){loadSearch()}const params=searchState.getQueryStringParams();if(params.search!==undefined){searchState.setLoadingSearch();loadSearch()}},setLoadingSearch:()=>{const search=searchState.outputElement();search.innerHTML="

"+searchState.loadingText+"

";searchState.showResults(search)},};const toggleAllDocsId="toggle-all-docs";let savedHash="";function handleHashes(ev){if(ev!==null&&searchState.isDisplayed()&&ev.newURL){switchDisplayedElement(null);const hash=ev.newURL.slice(ev.newURL.indexOf("#")+1);if(browserSupportsHistoryApi()){history.replaceState(null,"",getNakedUrl()+window.location.search+"#"+hash)}const elem=document.getElementById(hash);if(elem){elem.scrollIntoView()}}const pageId=window.location.hash.replace(/^#/,"");if(savedHash!==pageId){savedHash=pageId;if(pageId!==""){expandSection(pageId)}}}function onHashChange(ev){hideSidebar();handleHashes(ev)}function openParentDetails(elem){while(elem){if(elem.tagName==="DETAILS"){elem.open=true}elem=elem.parentNode}}function expandSection(id){openParentDetails(document.getElementById(id))}function handleEscape(ev){searchState.clearInputTimeout();switchDisplayedElement(null);if(browserSupportsHistoryApi()){history.replaceState(null,window.currentCrate+" - Rust",getNakedUrl()+window.location.hash)}ev.preventDefault();searchState.defocus();window.hideAllModals(true)}function handleShortcut(ev){const disableShortcuts=getSettingValue("disable-shortcuts")==="true";if(ev.ctrlKey||ev.altKey||ev.metaKey||disableShortcuts){return}if(document.activeElement.tagName==="INPUT"&&document.activeElement.type!=="checkbox"&&document.activeElement.type!=="radio"){switch(getVirtualKey(ev)){case"Escape":handleEscape(ev);break}}else{switch(getVirtualKey(ev)){case"Escape":handleEscape(ev);break;case"s":case"S":ev.preventDefault();searchState.focus();break;case"+":ev.preventDefault();expandAllDocs();break;case"-":ev.preventDefault();collapseAllDocs();break;case"?":showHelp();break;default:break}}}document.addEventListener("keypress",handleShortcut);document.addEventListener("keydown",handleShortcut);function addSidebarItems(){if(!window.SIDEBAR_ITEMS){return}const sidebar=document.getElementsByClassName("sidebar-elems")[0];function block(shortty,id,longty){const filtered=window.SIDEBAR_ITEMS[shortty];if(!filtered){return}const h3=document.createElement("h3");h3.innerHTML=`${longty}`;const ul=document.createElement("ul");ul.className="block "+shortty;for(const name of filtered){let path;if(shortty==="mod"){path=name+"/index.html"}else{path=shortty+"."+name+".html"}const current_page=document.location.href.split("/").pop();const link=document.createElement("a");link.href=path;if(path===current_page){link.className="current"}link.textContent=name;const li=document.createElement("li");li.appendChild(link);ul.appendChild(li)}sidebar.appendChild(h3);sidebar.appendChild(ul)}if(sidebar){block("primitive","primitives","Primitive Types");block("mod","modules","Modules");block("macro","macros","Macros");block("struct","structs","Structs");block("enum","enums","Enums");block("union","unions","Unions");block("constant","constants","Constants");block("static","static","Statics");block("trait","traits","Traits");block("fn","functions","Functions");block("type","types","Type Definitions");block("foreigntype","foreign-types","Foreign Types");block("keyword","keywords","Keywords");block("traitalias","trait-aliases","Trait Aliases")}}window.register_implementors=imp=>{const implementors=document.getElementById("implementors-list");const synthetic_implementors=document.getElementById("synthetic-implementors-list");const inlined_types=new Set();const TEXT_IDX=0;const SYNTHETIC_IDX=1;const TYPES_IDX=2;if(synthetic_implementors){onEachLazy(synthetic_implementors.getElementsByClassName("impl"),el=>{const aliases=el.getAttribute("data-aliases");if(!aliases){return}aliases.split(",").forEach(alias=>{inlined_types.add(alias)})})}let currentNbImpls=implementors.getElementsByClassName("impl").length;const traitName=document.querySelector(".main-heading h1 > .trait").textContent;const baseIdName="impl-"+traitName+"-";const libs=Object.getOwnPropertyNames(imp);const script=document.querySelector("script[data-ignore-extern-crates]");const ignoreExternCrates=script?script.getAttribute("data-ignore-extern-crates"):"";for(const lib of libs){if(lib===window.currentCrate||ignoreExternCrates.indexOf(lib)!==-1){continue}const structs=imp[lib];struct_loop:for(const struct of structs){const list=struct[SYNTHETIC_IDX]?synthetic_implementors:implementors;if(struct[SYNTHETIC_IDX]){for(const struct_type of struct[TYPES_IDX]){if(inlined_types.has(struct_type)){continue struct_loop}inlined_types.add(struct_type)}}const code=document.createElement("h3");code.innerHTML=struct[TEXT_IDX];addClass(code,"code-header");onEachLazy(code.getElementsByTagName("a"),elem=>{const href=elem.getAttribute("href");if(href&&!/^(?:[a-z+]+:)?\/\//.test(href)){elem.setAttribute("href",window.rootPath+href)}});const currentId=baseIdName+currentNbImpls;const anchor=document.createElement("a");anchor.href="#"+currentId;addClass(anchor,"anchor");const display=document.createElement("div");display.id=currentId;addClass(display,"impl");display.appendChild(anchor);display.appendChild(code);list.appendChild(display);currentNbImpls+=1}}};if(window.pending_implementors){window.register_implementors(window.pending_implementors)}function addSidebarCrates(){if(!window.ALL_CRATES){return}const sidebarElems=document.getElementsByClassName("sidebar-elems")[0];if(!sidebarElems){return}const h3=document.createElement("h3");h3.innerHTML="Crates";const ul=document.createElement("ul");ul.className="block crate";for(const crate of window.ALL_CRATES){const link=document.createElement("a");link.href=window.rootPath+crate+"/index.html";if(window.rootPath!=="./"&&crate===window.currentCrate){link.className="current"}link.textContent=crate;const li=document.createElement("li");li.appendChild(link);ul.appendChild(li)}sidebarElems.appendChild(h3);sidebarElems.appendChild(ul)}function expandAllDocs(){const innerToggle=document.getElementById(toggleAllDocsId);removeClass(innerToggle,"will-expand");onEachLazy(document.getElementsByClassName("toggle"),e=>{if(!hasClass(e,"type-contents-toggle")&&!hasClass(e,"more-examples-toggle")){e.open=true}});innerToggle.title="collapse all docs";innerToggle.children[0].innerText="\u2212"}function collapseAllDocs(){const innerToggle=document.getElementById(toggleAllDocsId);addClass(innerToggle,"will-expand");onEachLazy(document.getElementsByClassName("toggle"),e=>{if(e.parentNode.id!=="implementations-list"||(!hasClass(e,"implementors-toggle")&&!hasClass(e,"type-contents-toggle"))){e.open=false}});innerToggle.title="expand all docs";innerToggle.children[0].innerText="+"}function toggleAllDocs(){const innerToggle=document.getElementById(toggleAllDocsId);if(!innerToggle){return}if(hasClass(innerToggle,"will-expand")){expandAllDocs()}else{collapseAllDocs()}}(function(){const toggles=document.getElementById(toggleAllDocsId);if(toggles){toggles.onclick=toggleAllDocs}const hideMethodDocs=getSettingValue("auto-hide-method-docs")==="true";const hideImplementations=getSettingValue("auto-hide-trait-implementations")==="true";const hideLargeItemContents=getSettingValue("auto-hide-large-items")!=="false";function setImplementorsTogglesOpen(id,open){const list=document.getElementById(id);if(list!==null){onEachLazy(list.getElementsByClassName("implementors-toggle"),e=>{e.open=open})}}if(hideImplementations){setImplementorsTogglesOpen("trait-implementations-list",false);setImplementorsTogglesOpen("blanket-implementations-list",false)}onEachLazy(document.getElementsByClassName("toggle"),e=>{if(!hideLargeItemContents&&hasClass(e,"type-contents-toggle")){e.open=true}if(hideMethodDocs&&hasClass(e,"method-toggle")){e.open=false}})}());window.rustdoc_add_line_numbers_to_examples=()=>{onEachLazy(document.getElementsByClassName("rust-example-rendered"),x=>{const parent=x.parentNode;const line_numbers=parent.querySelectorAll(".example-line-numbers");if(line_numbers.length>0){return}const count=x.textContent.split("\n").length;const elems=[];for(let i=0;i{onEachLazy(document.getElementsByClassName("rust-example-rendered"),x=>{const parent=x.parentNode;const line_numbers=parent.querySelectorAll(".example-line-numbers");for(const node of line_numbers){parent.removeChild(node)}})};if(getSettingValue("line-numbers")==="true"){window.rustdoc_add_line_numbers_to_examples()}function showSidebar(){window.hideAllModals(false);const sidebar=document.getElementsByClassName("sidebar")[0];addClass(sidebar,"shown")}function hideSidebar(){const sidebar=document.getElementsByClassName("sidebar")[0];removeClass(sidebar,"shown")}window.addEventListener("resize",()=>{if(window.CURRENT_TOOLTIP_ELEMENT){const base=window.CURRENT_TOOLTIP_ELEMENT.TOOLTIP_BASE;const force_visible=base.TOOLTIP_FORCE_VISIBLE;hideTooltip(false);if(force_visible){showTooltip(base);base.TOOLTIP_FORCE_VISIBLE=true}}});const mainElem=document.getElementById(MAIN_ID);if(mainElem){mainElem.addEventListener("click",hideSidebar)}onEachLazy(document.querySelectorAll("a[href^='#']"),el=>{el.addEventListener("click",()=>{expandSection(el.hash.slice(1));hideSidebar()})});onEachLazy(document.querySelectorAll(".toggle > summary:not(.hideme)"),el=>{el.addEventListener("click",e=>{if(e.target.tagName!=="SUMMARY"&&e.target.tagName!=="A"){e.preventDefault()}})});function showTooltip(e){const notable_ty=e.getAttribute("data-notable-ty");if(!window.NOTABLE_TRAITS&¬able_ty){const data=document.getElementById("notable-traits-data");if(data){window.NOTABLE_TRAITS=JSON.parse(data.innerText)}else{throw new Error("showTooltip() called with notable without any notable traits!")}}if(window.CURRENT_TOOLTIP_ELEMENT&&window.CURRENT_TOOLTIP_ELEMENT.TOOLTIP_BASE===e){return}window.hideAllModals(false);const wrapper=document.createElement("div");if(notable_ty){wrapper.innerHTML="
"+window.NOTABLE_TRAITS[notable_ty]+"
"}else if(e.getAttribute("title")!==undefined){const titleContent=document.createElement("div");titleContent.className="content";titleContent.appendChild(document.createTextNode(e.getAttribute("title")));wrapper.appendChild(titleContent)}wrapper.className="tooltip popover";const focusCatcher=document.createElement("div");focusCatcher.setAttribute("tabindex","0");focusCatcher.onfocus=hideTooltip;wrapper.appendChild(focusCatcher);const pos=e.getBoundingClientRect();wrapper.style.top=(pos.top+window.scrollY+pos.height)+"px";wrapper.style.left=0;wrapper.style.right="auto";wrapper.style.visibility="hidden";const body=document.getElementsByTagName("body")[0];body.appendChild(wrapper);const wrapperPos=wrapper.getBoundingClientRect();const finalPos=pos.left+window.scrollX-wrapperPos.width+24;if(finalPos>0){wrapper.style.left=finalPos+"px"}else{wrapper.style.setProperty("--popover-arrow-offset",(wrapperPos.right-pos.right+4)+"px")}wrapper.style.visibility="";window.CURRENT_TOOLTIP_ELEMENT=wrapper;window.CURRENT_TOOLTIP_ELEMENT.TOOLTIP_BASE=e;wrapper.onpointerleave=function(ev){if(ev.pointerType!=="mouse"){return}if(!e.TOOLTIP_FORCE_VISIBLE&&!elemIsInParent(event.relatedTarget,e)){hideTooltip(true)}}}function tooltipBlurHandler(event){if(window.CURRENT_TOOLTIP_ELEMENT&&!elemIsInParent(document.activeElement,window.CURRENT_TOOLTIP_ELEMENT)&&!elemIsInParent(event.relatedTarget,window.CURRENT_TOOLTIP_ELEMENT)&&!elemIsInParent(document.activeElement,window.CURRENT_TOOLTIP_ELEMENT.TOOLTIP_BASE)&&!elemIsInParent(event.relatedTarget,window.CURRENT_TOOLTIP_ELEMENT.TOOLTIP_BASE)){setTimeout(()=>hideTooltip(false),0)}}function hideTooltip(focus){if(window.CURRENT_TOOLTIP_ELEMENT){if(window.CURRENT_TOOLTIP_ELEMENT.TOOLTIP_BASE.TOOLTIP_FORCE_VISIBLE){if(focus){window.CURRENT_TOOLTIP_ELEMENT.TOOLTIP_BASE.focus()}window.CURRENT_TOOLTIP_ELEMENT.TOOLTIP_BASE.TOOLTIP_FORCE_VISIBLE=false}const body=document.getElementsByTagName("body")[0];body.removeChild(window.CURRENT_TOOLTIP_ELEMENT);window.CURRENT_TOOLTIP_ELEMENT=null}}onEachLazy(document.getElementsByClassName("tooltip"),e=>{e.onclick=function(){this.TOOLTIP_FORCE_VISIBLE=this.TOOLTIP_FORCE_VISIBLE?false:true;if(window.CURRENT_TOOLTIP_ELEMENT&&!this.TOOLTIP_FORCE_VISIBLE){hideTooltip(true)}else{showTooltip(this);window.CURRENT_TOOLTIP_ELEMENT.setAttribute("tabindex","0");window.CURRENT_TOOLTIP_ELEMENT.focus();window.CURRENT_TOOLTIP_ELEMENT.onblur=tooltipBlurHandler}return false};e.onpointerenter=function(ev){if(ev.pointerType!=="mouse"){return}showTooltip(this)};e.onpointerleave=function(ev){if(ev.pointerType!=="mouse"){return}if(!this.TOOLTIP_FORCE_VISIBLE&&!elemIsInParent(ev.relatedTarget,window.CURRENT_TOOLTIP_ELEMENT)){hideTooltip(true)}}});const sidebar_menu_toggle=document.getElementsByClassName("sidebar-menu-toggle")[0];if(sidebar_menu_toggle){sidebar_menu_toggle.addEventListener("click",()=>{const sidebar=document.getElementsByClassName("sidebar")[0];if(!hasClass(sidebar,"shown")){showSidebar()}else{hideSidebar()}})}function helpBlurHandler(event){blurHandler(event,getHelpButton(),window.hidePopoverMenus)}function buildHelpMenu(){const book_info=document.createElement("span");book_info.className="top";book_info.innerHTML="You can find more information in \ - the rustdoc book.";const shortcuts=[["?","Show this help dialog"],["S","Focus the search field"],["↑","Move up in search results"],["↓","Move down in search results"],["← / →","Switch result tab (when results focused)"],["⏎","Go to active search result"],["+","Expand all sections"],["-","Collapse all sections"],].map(x=>"
"+x[0].split(" ").map((y,index)=>((index&1)===0?""+y+"":" "+y+" ")).join("")+"
"+x[1]+"
").join("");const div_shortcuts=document.createElement("div");addClass(div_shortcuts,"shortcuts");div_shortcuts.innerHTML="

Keyboard Shortcuts

"+shortcuts+"
";const infos=["Prefix searches with a type followed by a colon (e.g., fn:) to \ - restrict the search to a given item kind.","Accepted kinds are: fn, mod, struct, \ - enum, trait, type, macro, \ - and const.","Search functions by type signature (e.g., vec -> usize or \ - -> vec or String, enum:Cow -> bool)","You can look for items with an exact name by putting double quotes around \ - your request: \"string\"","Look for items inside another one by searching for a path: vec::Vec",].map(x=>"

"+x+"

").join("");const div_infos=document.createElement("div");addClass(div_infos,"infos");div_infos.innerHTML="

Search Tricks

"+infos;const rustdoc_version=document.createElement("span");rustdoc_version.className="bottom";const rustdoc_version_code=document.createElement("code");rustdoc_version_code.innerText="rustdoc "+getVar("rustdoc-version");rustdoc_version.appendChild(rustdoc_version_code);const container=document.createElement("div");if(!isHelpPage){container.className="popover"}container.id="help";container.style.display="none";const side_by_side=document.createElement("div");side_by_side.className="side-by-side";side_by_side.appendChild(div_shortcuts);side_by_side.appendChild(div_infos);container.appendChild(book_info);container.appendChild(side_by_side);container.appendChild(rustdoc_version);if(isHelpPage){const help_section=document.createElement("section");help_section.appendChild(container);document.getElementById("main-content").appendChild(help_section);container.style.display="block"}else{const help_button=getHelpButton();help_button.appendChild(container);container.onblur=helpBlurHandler;help_button.onblur=helpBlurHandler;help_button.children[0].onblur=helpBlurHandler}return container}window.hideAllModals=function(switchFocus){hideSidebar();window.hidePopoverMenus();hideTooltip(switchFocus)};window.hidePopoverMenus=function(){onEachLazy(document.querySelectorAll(".search-form .popover"),elem=>{elem.style.display="none"})};function getHelpMenu(buildNeeded){let menu=getHelpButton().querySelector(".popover");if(!menu&&buildNeeded){menu=buildHelpMenu()}return menu}function showHelp(){getHelpButton().querySelector("a").focus();const menu=getHelpMenu(true);if(menu.style.display==="none"){window.hideAllModals();menu.style.display=""}}if(isHelpPage){showHelp();document.querySelector(`#${HELP_BUTTON_ID} > a`).addEventListener("click",event=>{const target=event.target;if(target.tagName!=="A"||target.parentElement.id!==HELP_BUTTON_ID||event.ctrlKey||event.altKey||event.metaKey){return}event.preventDefault()})}else{document.querySelector(`#${HELP_BUTTON_ID} > a`).addEventListener("click",event=>{const target=event.target;if(target.tagName!=="A"||target.parentElement.id!==HELP_BUTTON_ID||event.ctrlKey||event.altKey||event.metaKey){return}event.preventDefault();const menu=getHelpMenu(true);const shouldShowHelp=menu.style.display==="none";if(shouldShowHelp){showHelp()}else{window.hidePopoverMenus()}})}setMobileTopbar();addSidebarItems();addSidebarCrates();onHashChange(null);window.addEventListener("hashchange",onHashChange);searchState.setup()}());(function(){let reset_button_timeout=null;const but=document.getElementById("copy-path");if(!but){return}but.onclick=()=>{const parent=but.parentElement;const path=[];onEach(parent.childNodes,child=>{if(child.tagName==="A"){path.push(child.textContent)}});const el=document.createElement("textarea");el.value=path.join("::");el.setAttribute("readonly","");el.style.position="absolute";el.style.left="-9999px";document.body.appendChild(el);el.select();document.execCommand("copy");document.body.removeChild(el);but.children[0].style.display="none";let tmp;if(but.childNodes.length<2){tmp=document.createTextNode("✓");but.appendChild(tmp)}else{onEachLazy(but.childNodes,e=>{if(e.nodeType===Node.TEXT_NODE){tmp=e;return true}});tmp.textContent="✓"}if(reset_button_timeout!==null){window.clearTimeout(reset_button_timeout)}function reset_button(){tmp.textContent="";reset_button_timeout=null;but.children[0].style.display=""}reset_button_timeout=window.setTimeout(reset_button,1000)}}()) \ No newline at end of file diff --git a/doc/static.files/rustdoc-ba5701c5741a7b69.css b/doc/static.files/rustdoc-f3501f0f5ae15dfb.css similarity index 90% rename from doc/static.files/rustdoc-ba5701c5741a7b69.css rename to doc/static.files/rustdoc-f3501f0f5ae15dfb.css index 55584a76d..3681b049e 100644 --- a/doc/static.files/rustdoc-ba5701c5741a7b69.css +++ b/doc/static.files/rustdoc-f3501f0f5ae15dfb.css @@ -1,7 +1,7 @@ :root{--nav-sub-mobile-padding:8px;}@font-face {font-family:'Fira Sans';font-style:normal;font-weight:400;src:local('Fira Sans'),url("FiraSans-Regular-018c141bf0843ffd.woff2") format("woff2");font-display:swap;}@font-face {font-family:'Fira Sans';font-style:normal;font-weight:500;src:local('Fira Sans Medium'),url("FiraSans-Medium-8f9a781e4970d388.woff2") format("woff2");font-display:swap;}@font-face {font-family:'Source Serif 4';font-style:normal;font-weight:400;src:local('Source Serif 4'),url("SourceSerif4-Regular-46f98efaafac5295.ttf.woff2") format("woff2");font-display:swap;}@font-face {font-family:'Source Serif 4';font-style:italic;font-weight:400;src:local('Source Serif 4 Italic'),url("SourceSerif4-It-acdfaf1a8af734b1.ttf.woff2") format("woff2");font-display:swap;}@font-face {font-family:'Source Serif 4';font-style:normal;font-weight:700;src:local('Source Serif 4 Bold'),url("SourceSerif4-Bold-a2c9cd1067f8b328.ttf.woff2") format("woff2");font-display:swap;}@font-face {font-family:'Source Code Pro';font-style:normal;font-weight:400;src:url("SourceCodePro-Regular-562dcc5011b6de7d.ttf.woff2") format("woff2");font-display:swap;}@font-face {font-family:'Source Code Pro';font-style:italic;font-weight:400;src:url("SourceCodePro-It-1cc31594bf4f1f79.ttf.woff2") format("woff2");font-display:swap;}@font-face {font-family:'Source Code Pro';font-style:normal;font-weight:600;src:url("SourceCodePro-Semibold-d899c5a5c4aeb14a.ttf.woff2") format("woff2");font-display:swap;}@font-face {font-family:'NanumBarunGothic';src:url("NanumBarunGothic-0f09457c7a19b7c6.ttf.woff2") format("woff2");font-display:swap;unicode-range:U+AC00-D7AF,U+1100-11FF,U+3130-318F,U+A960-A97F,U+D7B0-D7FF;}*{box-sizing:border-box;}body{font:1rem/1.5 "Source Serif 4",NanumBarunGothic,serif;margin:0;position:relative;overflow-wrap:break-word;overflow-wrap:anywhere;font-feature-settings:"kern","liga";background-color:var(--main-background-color);color:var(--main-color);}h1{font-size:1.5rem;}h2{font-size:1.375rem;}h3{font-size:1.25rem;}h1,h2,h3,h4,h5,h6{font-weight:500;}h1,h2,h3,h4{margin:25px 0 15px 0;padding-bottom:6px;}.docblock h3,.docblock h4,h5,h6{margin:15px 0 5px 0;}.docblock>h2:first-child,.docblock>h3:first-child,.docblock>h4:first-child,.docblock>h5:first-child,.docblock>h6:first-child{margin-top:0;}.main-heading h1{margin:0;padding:0;flex-grow:1;overflow-wrap:break-word;overflow-wrap:anywhere;}.main-heading{display:flex;flex-wrap:wrap;padding-bottom:6px;margin-bottom:15px;}.content h2,.top-doc .docblock>h3,.top-doc .docblock>h4{border-bottom:1px solid var(--headings-border-bottom-color);}h1,h2{line-height:1.25;padding-top:3px;padding-bottom:9px;}h3.code-header{font-size:1.125rem;}h4.code-header{font-size:1rem;}.code-header{font-weight:600;margin:0;padding:0;white-space:pre-wrap;}#crate-search,h1,h2,h3,h4,h5,h6,.sidebar,.mobile-topbar,.search-input,.search-results .result-name,.item-name>a,.out-of-band,span.since,a.srclink,#help-button>a,summary.hideme,.scraped-example-list,ul.all-items{font-family:"Fira Sans",Arial,NanumBarunGothic,sans-serif;}#toggle-all-docs,a.anchor,.small-section-header a,#source-sidebar a,.rust a,.sidebar h2 a,.sidebar h3 a,.mobile-topbar h2 a,h1 a,.search-results a,.stab,.result-name .primitive>i,.result-name .keyword>i{color:var(--main-color);}span.enum,a.enum,span.struct,a.struct,span.union,a.union,span.primitive,a.primitive,span.type,a.type,span.foreigntype,a.foreigntype{color:var(--type-link-color);}span.trait,a.trait,span.traitalias,a.traitalias{color:var(--trait-link-color);}span.associatedtype,a.associatedtype,span.constant,a.constant,span.static,a.static{color:var(--assoc-item-link-color);}span.fn,a.fn,span.method,a.method,span.tymethod,a.tymethod{color:var(--function-link-color);}span.attr,a.attr,span.derive,a.derive,span.macro,a.macro{color:var(--macro-link-color);}span.mod,a.mod{color:var(--mod-link-color);}span.keyword,a.keyword{color:var(--keyword-link-color);}a{color:var(--link-color);text-decoration:none;}ol,ul{padding-left:24px;}ul ul,ol ul,ul ol,ol ol{margin-bottom:.625em;}p{margin:0 0 .75em 0;}p:last-child{margin:0;}button{padding:1px 6px;cursor:pointer;}button#toggle-all-docs{padding:0;background:none;border:none;-webkit-appearance:none;opacity:1;}.rustdoc{display:flex;flex-direction:row;flex-wrap:nowrap;}main{position:relative;flex-grow:1;padding:10px 15px 40px 45px;min-width:0;}.source main{padding:15px;}.width-limiter{max-width:960px;margin-right:auto;}details:not(.toggle) summary{margin-bottom:.6em;}code,pre,a.test-arrow,.code-header{font-family:"Source Code Pro",monospace;}.docblock code,.docblock-short code{border-radius:3px;padding:0 0.125em;}.docblock pre code,.docblock-short pre code{padding:0;}pre{padding:14px;line-height:1.5;}pre.item-decl{overflow-x:auto;}.item-decl .type-contents-toggle{contain:initial;}.source .content pre{padding:20px;}.rustdoc.source .example-wrap pre.src-line-numbers{padding:20px 0 20px 4px;}img{max-width:100%;}.sub-logo-container,.logo-container{line-height:0;display:block;}.sub-logo-container{margin-right:32px;}.sub-logo-container>img{height:60px;width:60px;object-fit:contain;}.rust-logo{filter:var(--rust-logo-filter);}.sidebar{font-size:0.875rem;flex:0 0 200px;overflow-y:scroll;overscroll-behavior:contain;position:sticky;height:100vh;top:0;left:0;}.rustdoc.source .sidebar{flex-basis:50px;border-right:1px solid;overflow-x:hidden;overflow-y:hidden;z-index:1;}.sidebar,.mobile-topbar,.sidebar-menu-toggle,#src-sidebar-toggle,#source-sidebar{background-color:var(--sidebar-background-color);}#src-sidebar-toggle>button:hover,#src-sidebar-toggle>button:focus{background-color:var(--sidebar-background-color-hover);}.source .sidebar>*:not(#src-sidebar-toggle){visibility:hidden;}.source-sidebar-expanded .source .sidebar{overflow-y:auto;flex-basis:300px;}.source-sidebar-expanded .source .sidebar>*:not(#src-sidebar-toggle){visibility:visible;}#all-types{margin-top:1em;}*{scrollbar-width:initial;scrollbar-color:var(--scrollbar-color);}.sidebar{scrollbar-width:thin;scrollbar-color:var(--scrollbar-color);}::-webkit-scrollbar{width:12px;}.sidebar::-webkit-scrollbar{width:8px;}::-webkit-scrollbar-track{-webkit-box-shadow:inset 0;background-color:var(--scrollbar-track-background-color);}.sidebar::-webkit-scrollbar-track{background-color:var(--scrollbar-track-background-color);}::-webkit-scrollbar-thumb,.sidebar::-webkit-scrollbar-thumb{background-color:var(--scrollbar-thumb-background-color);}.hidden{display:none !important;}.sidebar .logo-container{margin-top:10px;margin-bottom:10px;text-align:center;}.version{overflow-wrap:break-word;}.logo-container>img{height:100px;width:100px;}ul.block,.block li{padding:0;margin:0;list-style:none;}.sidebar-elems a,.sidebar>h2 a{display:block;padding:0.25rem;margin-left:-0.25rem;}.sidebar h2{overflow-wrap:anywhere;padding:0;margin:0.7rem 0;}.sidebar h3{font-size:1.125rem;padding:0;margin:0;}.sidebar-elems,.sidebar>h2{padding-left:24px;}.sidebar a{color:var(--sidebar-link-color);}.sidebar .current,.sidebar a:hover:not(.logo-container){background-color:var(--sidebar-current-link-background-color);}.sidebar-elems .block{margin-bottom:2em;}.sidebar-elems .block li a{white-space:nowrap;text-overflow:ellipsis;overflow:hidden;}.mobile-topbar{display:none;}.rustdoc .example-wrap{display:flex;position:relative;margin-bottom:10px;}.rustdoc .example-wrap:last-child{margin-bottom:0px;}.rustdoc .example-wrap pre{margin:0;flex-grow:1;}.rustdoc:not(.source) .example-wrap pre{overflow:auto hidden;}.rustdoc .example-wrap pre.example-line-numbers,.rustdoc .example-wrap pre.src-line-numbers{flex-grow:0;min-width:fit-content;overflow:initial;text-align:right;-webkit-user-select:none;user-select:none;padding:14px 8px;color:var(--src-line-numbers-span-color);}.rustdoc .example-wrap pre.src-line-numbers{padding:14px 0;}.src-line-numbers a,.src-line-numbers span{color:var(--src-line-numbers-span-color);padding:0 8px;}.src-line-numbers :target{background-color:transparent;border-right:none;padding:0 8px;}.src-line-numbers .line-highlighted{background-color:var(--src-line-number-highlighted-background-color);}.search-loading{text-align:center;}.docblock-short{overflow-wrap:break-word;overflow-wrap:anywhere;}.docblock :not(pre)>code,.docblock-short code{white-space:pre-wrap;}.top-doc .docblock h2{font-size:1.375rem;}.top-doc .docblock h3{font-size:1.25rem;}.top-doc .docblock h4,.top-doc .docblock h5{font-size:1.125rem;}.top-doc .docblock h6{font-size:1rem;}.docblock h5{font-size:1rem;}.docblock h6{font-size:0.875rem;}.docblock{margin-left:24px;position:relative;}.docblock>:not(.more-examples-toggle):not(.example-wrap){max-width:100%;overflow-x:auto;}.out-of-band{flex-grow:0;font-size:1.125rem;}.docblock code,.docblock-short code,pre,.rustdoc.source .example-wrap{background-color:var(--code-block-background-color);}#main-content{position:relative;}.docblock table{margin:.5em 0;border-collapse:collapse;}.docblock table td,.docblock table th{padding:.5em;border:1px solid var(--border-color);}.docblock table tbody tr:nth-child(2n){background:var(--table-alt-row-background-color);}.method .where,.fn .where,.where.fmt-newline{display:block;white-space:pre-wrap;font-size:0.875rem;}.item-info{display:block;margin-left:24px;}.item-info code{font-size:0.875rem;}#main-content>.item-info{margin-left:0;}nav.sub{flex-grow:1;flex-flow:row nowrap;margin:4px 0 25px 0;display:flex;align-items:center;}.search-form{position:relative;display:flex;height:34px;flex-grow:1;}.source nav.sub{margin:0 0 15px 0;}.small-section-header{display:block;position:relative;}.small-section-header:hover>.anchor,.impl:hover>.anchor,.trait-impl:hover>.anchor,.variant:hover>.anchor{display:initial;}.anchor{display:none;position:absolute;left:-0.5em;background:none !important;}.anchor.field{left:-5px;}.small-section-header>.anchor{left:-15px;padding-right:8px;}h2.small-section-header>.anchor{padding-right:6px;}.main-heading a:hover,.example-wrap .rust a:hover,.all-items a:hover,.docblock a:not(.test-arrow):not(.scrape-help):not(.tooltip):hover,.docblock-short a:not(.test-arrow):not(.scrape-help):not(.tooltip):hover,.item-info a{text-decoration:underline;}.crate.block a.current{font-weight:500;}table,.item-table{overflow-wrap:break-word;}.item-table{display:table;padding:0;margin:0;}.item-table>li{display:table-row;}.item-table>li>div{display:table-cell;}.item-table>li>.item-name{padding-right:1.25rem;}.search-results-title{margin-top:0;white-space:nowrap;display:flex;align-items:baseline;}#crate-search-div{position:relative;min-width:5em;}#crate-search{min-width:115px;padding:0 23px 0 4px;max-width:100%;text-overflow:ellipsis;border:1px solid var(--border-color);border-radius:4px;outline:none;cursor:pointer;-moz-appearance:none;-webkit-appearance:none;text-indent:0.01px;background-color:var(--main-background-color);color:inherit;line-height:1.5;font-weight:500;}#crate-search:hover,#crate-search:focus{border-color:var(--crate-search-hover-border);}@-moz-document url-prefix(){#crate-search{padding-left:0px;padding-right:19px;}}#crate-search-div::after{pointer-events:none;width:100%;height:100%;position:absolute;top:0;left:0;content:"";background-repeat:no-repeat;background-size:20px;background-position:calc(100% - 2px) 56%;background-image:url('data:image/svg+xml, \ - ');filter:var(--crate-search-div-filter);}#crate-search-div:hover::after,#crate-search-div:focus-within::after{filter:var(--crate-search-div-hover-filter);}#crate-search>option{font-size:1rem;}.search-input{-webkit-appearance:none;outline:none;border:1px solid var(--border-color);border-radius:2px;padding:8px;font-size:1rem;flex-grow:1;background-color:var(--button-background-color);color:var(--search-color);}.search-input:focus{border-color:var(--search-input-focused-border-color);}.search-results{display:none;}.search-results.active{display:block;}.search-results>a{display:flex;margin-left:2px;margin-right:2px;border-bottom:1px solid var(--search-result-border-color);gap:1em;}.search-results>a>div{flex:1;}.search-results>a>div.desc{white-space:nowrap;text-overflow:ellipsis;overflow:hidden;}.search-results a:hover,.search-results a:focus{background-color:var(--search-result-link-focus-background-color);}.search-results .result-name span.alias{color:var(--search-results-alias-color);}.search-results .result-name span.grey{color:var(--search-results-grey-color);}.popover{position:absolute;top:100%;right:0;z-index:2;margin-top:7px;border-radius:3px;border:1px solid var(--border-color);background-color:var(--main-background-color);color:var(--main-color);--popover-arrow-offset:11px;}.popover::before{content:'';position:absolute;right:var(--popover-arrow-offset);border:solid var(--border-color);border-width:1px 1px 0 0;background-color:var(--main-background-color);padding:4px;transform:rotate(-45deg);top:-5px;}#help.popover{max-width:600px;--popover-arrow-offset:48px;}#help dt{float:left;clear:left;margin-right:0.5rem;}#help span.top,#help span.bottom{text-align:center;display:block;font-size:1.125rem;}#help span.top{margin:10px 0;border-bottom:1px solid var(--border-color);padding-bottom:4px;margin-bottom:6px;}#help span.bottom{clear:both;border-top:1px solid var(--border-color);}.side-by-side>div{width:50%;float:left;padding:0 20px 20px 17px;}.item-info .stab{min-height:36px;display:flex;padding:3px;margin-bottom:5px;}.item-name .stab{margin-left:0.3125em;}.stab{padding:0 2px;font-size:0.875rem;font-weight:normal;color:var(--main-color);background-color:var(--stab-background-color);width:fit-content;align-items:center;white-space:pre-wrap;border-radius:3px;display:inline-flex;vertical-align:text-bottom;}.stab.portability>code{background:none;color:var(--stab-code-color);}.stab .emoji{font-size:1.25rem;margin-right:0.3rem;}.emoji{text-shadow:1px 0 0 black,-1px 0 0 black,0 1px 0 black,0 -1px 0 black;}.since{font-weight:normal;font-size:initial;}.rightside{padding-left:12px;float:right;}.rightside:not(a),.out-of-band{color:var(--right-side-color);}pre.rust{tab-size:4;-moz-tab-size:4;}pre.rust .kw{color:var(--code-highlight-kw-color);}pre.rust .kw-2{color:var(--code-highlight-kw-2-color);}pre.rust .lifetime{color:var(--code-highlight-lifetime-color);}pre.rust .prelude-ty{color:var(--code-highlight-prelude-color);}pre.rust .prelude-val{color:var(--code-highlight-prelude-val-color);}pre.rust .string{color:var(--code-highlight-string-color);}pre.rust .number{color:var(--code-highlight-number-color);}pre.rust .bool-val{color:var(--code-highlight-literal-color);}pre.rust .self{color:var(--code-highlight-self-color);}pre.rust .attr{color:var(--code-highlight-attribute-color);}pre.rust .macro,pre.rust .macro-nonterminal{color:var(--code-highlight-macro-color);}pre.rust .question-mark{font-weight:bold;color:var(--code-highlight-question-mark-color);}pre.rust .comment{color:var(--code-highlight-comment-color);}pre.rust .doccomment{color:var(--code-highlight-doc-comment-color);}.rustdoc.source .example-wrap pre.rust a{background:var(--codeblock-link-background);}.example-wrap.compile_fail,.example-wrap.should_panic{border-left:2px solid var(--codeblock-error-color);}.ignore.example-wrap{border-left:2px solid var(--codeblock-ignore-color);}.example-wrap.compile_fail:hover,.example-wrap.should_panic:hover{border-left:2px solid var(--codeblock-error-hover-color);}.example-wrap.ignore:hover{border-left:2px solid var(--codeblock-ignore-hover-color);}.example-wrap.compile_fail .tooltip,.example-wrap.should_panic .tooltip{color:var(--codeblock-error-color);}.example-wrap.ignore .tooltip{color:var(--codeblock-ignore-color);}.example-wrap.compile_fail:hover .tooltip,.example-wrap.should_panic:hover .tooltip{color:var(--codeblock-error-hover-color);}.example-wrap.ignore:hover .tooltip{color:var(--codeblock-ignore-hover-color);}.example-wrap .tooltip{position:absolute;display:block;left:-25px;top:5px;margin:0;line-height:1;}.example-wrap.compile_fail .tooltip,.example-wrap.should_panic .tooltip,.example-wrap.ignore .tooltip{font-weight:bold;font-size:1.25rem;}a.test-arrow{visibility:hidden;position:absolute;padding:5px 10px 5px 10px;border-radius:5px;font-size:1.375rem;top:5px;right:5px;z-index:1;color:var(--test-arrow-color);background-color:var(--test-arrow-background-color);}a.test-arrow:hover{color:var(--test-arrow-hover-color);background-color:var(--test-arrow-hover-background-color);}.example-wrap:hover .test-arrow{visibility:visible;}.code-attribute{font-weight:300;color:var(--code-attribute-color);}.item-spacer{width:100%;height:12px;display:block;}.out-of-band>span.since{font-size:1.25rem;}.sub-variant h4{font-size:1rem;font-weight:400;margin-top:0;margin-bottom:0;}.sub-variant{margin-left:24px;margin-bottom:40px;}.sub-variant>.sub-variant-field{margin-left:24px;}:target{padding-right:3px;background-color:var(--target-background-color);border-right:3px solid var(--target-border-color);}.code-header a.tooltip{color:inherit;margin-right:15px;position:relative;}a.tooltip:hover::after{position:absolute;top:calc(100% - 10px);left:-15px;right:-15px;height:20px;content:"\00a0";}.popover.tooltip .content{margin:0.25em 0.5em;}.popover.tooltip .content pre,.popover.tooltip .content code{background:transparent;margin:0;padding:0;font-size:1.25rem;white-space:pre-wrap;}.popover.tooltip .content>h3:first-child{margin:0 0 5px 0;}.search-failed{text-align:center;margin-top:20px;display:none;}.search-failed.active{display:block;}.search-failed>ul{text-align:left;max-width:570px;margin-left:auto;margin-right:auto;}#search-tabs{display:flex;flex-direction:row;gap:1px;margin-bottom:4px;}#search-tabs button{text-align:center;font-size:1.125rem;border:0;border-top:2px solid;flex:1;line-height:1.5;color:inherit;}#search-tabs button:not(.selected){background-color:var(--search-tab-button-not-selected-background);border-top-color:var(--search-tab-button-not-selected-border-top-color);}#search-tabs button:hover,#search-tabs button.selected{background-color:var(--search-tab-button-selected-background);border-top-color:var(--search-tab-button-selected-border-top-color);}#search-tabs .count{font-size:1rem;color:var(--search-tab-title-count-color);}#search .error code{border-radius:3px;background-color:var(--search-error-code-background-color);}#src-sidebar-toggle{position:sticky;top:0;left:0;font-size:1.25rem;border-bottom:1px solid;display:flex;height:40px;justify-content:stretch;align-items:stretch;z-index:10;}#source-sidebar{width:100%;overflow:auto;}#source-sidebar>.title{font-size:1.5rem;text-align:center;border-bottom:1px solid var(--border-color);margin-bottom:6px;}#source-sidebar div.files>a:hover,details.dir-entry summary:hover,#source-sidebar div.files>a:focus,details.dir-entry summary:focus{background-color:var(--source-sidebar-background-hover);}#source-sidebar div.files>a.selected{background-color:var(--source-sidebar-background-selected);}#src-sidebar-toggle>button{font-size:inherit;font-weight:bold;background:none;color:inherit;text-align:center;border:none;outline:none;flex:1 1;-webkit-appearance:none;opacity:1;}#settings-menu,#help-button{margin-left:4px;display:flex;}#settings-menu>a,#help-button>a{display:flex;align-items:center;justify-content:center;background-color:var(--button-background-color);border:1px solid var(--border-color);border-radius:2px;color:var(--settings-button-color);font-size:20px;width:33px;}#settings-menu>a:hover,#settings-menu>a:focus,#help-button>a:hover,#help-button>a:focus{border-color:var(--settings-button-border-focus);}#copy-path{color:var(--copy-path-button-color);background:var(--main-background-color);height:34px;margin-left:10px;padding:0;padding-left:2px;border:0;width:33px;}#copy-path>img{filter:var(--copy-path-img-filter);}#copy-path:hover>img{filter:var(--copy-path-img-hover-filter);}@keyframes rotating{from{transform:rotate(0deg);}to{transform:rotate(360deg);}}#settings-menu.rotate>a img{animation:rotating 2s linear infinite;}kbd{display:inline-block;padding:3px 5px;font:15px monospace;line-height:10px;vertical-align:middle;border:solid 1px var(--border-color);border-radius:3px;color:var(--kbd-color);background-color:var(--kbd-background);box-shadow:inset 0 -1px 0 var(--kbd-box-shadow-color);}ul.all-items>li{list-style:none;}details.dir-entry{padding-left:4px;}details.dir-entry>summary{margin:0 0 0 -4px;padding:0 0 0 4px;cursor:pointer;}details.dir-entry div.folders,details.dir-entry div.files{padding-left:23px;}details.dir-entry a{display:block;}details.toggle{contain:layout;position:relative;}details.toggle>summary.hideme{cursor:pointer;font-size:1rem;}details.toggle>summary{list-style:none;outline:none;}details.toggle>summary::-webkit-details-marker,details.toggle>summary::marker{display:none;}details.toggle>summary.hideme>span{margin-left:9px;}details.toggle>summary::before{background:url('data:image/svg+xml,');filter:var(--crate-search-div-filter);}#crate-search-div:hover::after,#crate-search-div:focus-within::after{filter:var(--crate-search-div-hover-filter);}#crate-search>option{font-size:1rem;}.search-input{-webkit-appearance:none;outline:none;border:1px solid var(--border-color);border-radius:2px;padding:8px;font-size:1rem;flex-grow:1;background-color:var(--button-background-color);color:var(--search-color);}.search-input:focus{border-color:var(--search-input-focused-border-color);}.search-results{display:none;}.search-results.active{display:block;}.search-results>a{display:flex;margin-left:2px;margin-right:2px;border-bottom:1px solid var(--search-result-border-color);gap:1em;}.search-results>a>div{flex:1;}.search-results>a>div.desc{white-space:nowrap;text-overflow:ellipsis;overflow:hidden;}.search-results a:hover,.search-results a:focus{background-color:var(--search-result-link-focus-background-color);}.search-results .result-name span.alias{color:var(--search-results-alias-color);}.search-results .result-name span.grey{color:var(--search-results-grey-color);}.popover{position:absolute;top:100%;right:0;z-index:2;margin-top:7px;border-radius:3px;border:1px solid var(--border-color);background-color:var(--main-background-color);color:var(--main-color);--popover-arrow-offset:11px;}.popover::before{content:'';position:absolute;right:var(--popover-arrow-offset);border:solid var(--border-color);border-width:1px 1px 0 0;background-color:var(--main-background-color);padding:4px;transform:rotate(-45deg);top:-5px;}#help.popover{max-width:600px;--popover-arrow-offset:48px;}#help dt{float:left;clear:left;margin-right:0.5rem;}#help span.top,#help span.bottom{text-align:center;display:block;font-size:1.125rem;}#help span.top{margin:10px 0;border-bottom:1px solid var(--border-color);padding-bottom:4px;margin-bottom:6px;}#help span.bottom{clear:both;border-top:1px solid var(--border-color);}.side-by-side>div{width:50%;float:left;padding:0 20px 20px 17px;}.item-info .stab{min-height:36px;display:flex;padding:3px;margin-bottom:5px;}.item-name .stab{margin-left:0.3125em;}.stab{padding:0 2px;font-size:0.875rem;font-weight:normal;color:var(--main-color);background-color:var(--stab-background-color);width:fit-content;align-items:center;white-space:pre-wrap;border-radius:3px;display:inline-flex;vertical-align:text-bottom;}.stab.portability>code{background:none;color:var(--stab-code-color);}.stab .emoji{font-size:1.25rem;margin-right:0.3rem;}.emoji{text-shadow:1px 0 0 black,-1px 0 0 black,0 1px 0 black,0 -1px 0 black;}.since{font-weight:normal;font-size:initial;}.rightside{padding-left:12px;float:right;}.rightside:not(a),.out-of-band{color:var(--right-side-color);}pre.rust{tab-size:4;-moz-tab-size:4;}pre.rust .kw{color:var(--code-highlight-kw-color);}pre.rust .kw-2{color:var(--code-highlight-kw-2-color);}pre.rust .lifetime{color:var(--code-highlight-lifetime-color);}pre.rust .prelude-ty{color:var(--code-highlight-prelude-color);}pre.rust .prelude-val{color:var(--code-highlight-prelude-val-color);}pre.rust .string{color:var(--code-highlight-string-color);}pre.rust .number{color:var(--code-highlight-number-color);}pre.rust .bool-val{color:var(--code-highlight-literal-color);}pre.rust .self{color:var(--code-highlight-self-color);}pre.rust .attr{color:var(--code-highlight-attribute-color);}pre.rust .macro,pre.rust .macro-nonterminal{color:var(--code-highlight-macro-color);}pre.rust .question-mark{font-weight:bold;color:var(--code-highlight-question-mark-color);}pre.rust .comment{color:var(--code-highlight-comment-color);}pre.rust .doccomment{color:var(--code-highlight-doc-comment-color);}.rustdoc.source .example-wrap pre.rust a{background:var(--codeblock-link-background);}.example-wrap.compile_fail,.example-wrap.should_panic{border-left:2px solid var(--codeblock-error-color);}.ignore.example-wrap{border-left:2px solid var(--codeblock-ignore-color);}.example-wrap.compile_fail:hover,.example-wrap.should_panic:hover{border-left:2px solid var(--codeblock-error-hover-color);}.example-wrap.ignore:hover{border-left:2px solid var(--codeblock-ignore-hover-color);}.example-wrap.compile_fail .tooltip,.example-wrap.should_panic .tooltip{color:var(--codeblock-error-color);}.example-wrap.ignore .tooltip{color:var(--codeblock-ignore-color);}.example-wrap.compile_fail:hover .tooltip,.example-wrap.should_panic:hover .tooltip{color:var(--codeblock-error-hover-color);}.example-wrap.ignore:hover .tooltip{color:var(--codeblock-ignore-hover-color);}.example-wrap .tooltip{position:absolute;display:block;left:-25px;top:5px;margin:0;line-height:1;}.example-wrap.compile_fail .tooltip,.example-wrap.should_panic .tooltip,.example-wrap.ignore .tooltip{font-weight:bold;font-size:1.25rem;}a.test-arrow{visibility:hidden;position:absolute;padding:5px 10px 5px 10px;border-radius:5px;font-size:1.375rem;top:5px;right:5px;z-index:1;color:var(--test-arrow-color);background-color:var(--test-arrow-background-color);}a.test-arrow:hover{color:var(--test-arrow-hover-color);background-color:var(--test-arrow-hover-background-color);}.example-wrap:hover .test-arrow{visibility:visible;}.code-attribute{font-weight:300;color:var(--code-attribute-color);}.item-spacer{width:100%;height:12px;display:block;}.out-of-band>span.since{font-size:1.25rem;}.sub-variant h4{font-size:1rem;font-weight:400;margin-top:0;margin-bottom:0;}.sub-variant{margin-left:24px;margin-bottom:40px;}.sub-variant>.sub-variant-field{margin-left:24px;}:target{padding-right:3px;background-color:var(--target-background-color);border-right:3px solid var(--target-border-color);}.code-header a.tooltip{color:inherit;margin-right:15px;position:relative;}a.tooltip:hover::after{position:absolute;top:calc(100% - 10px);left:-15px;right:-15px;height:20px;content:"\00a0";}.popover.tooltip .content{margin:0.25em 0.5em;}.popover.tooltip .content pre,.popover.tooltip .content code{background:transparent;margin:0;padding:0;font-size:1.25rem;white-space:pre-wrap;}.popover.tooltip .content>h3:first-child{margin:0 0 5px 0;}.search-failed{text-align:center;margin-top:20px;display:none;}.search-failed.active{display:block;}.search-failed>ul{text-align:left;max-width:570px;margin-left:auto;margin-right:auto;}#search-tabs{display:flex;flex-direction:row;gap:1px;margin-bottom:4px;}#search-tabs button{text-align:center;font-size:1.125rem;border:0;border-top:2px solid;flex:1;line-height:1.5;color:inherit;}#search-tabs button:not(.selected){background-color:var(--search-tab-button-not-selected-background);border-top-color:var(--search-tab-button-not-selected-border-top-color);}#search-tabs button:hover,#search-tabs button.selected{background-color:var(--search-tab-button-selected-background);border-top-color:var(--search-tab-button-selected-border-top-color);}#search-tabs .count{font-size:1rem;color:var(--search-tab-title-count-color);}#search .error code{border-radius:3px;background-color:var(--search-error-code-background-color);}.search-corrections{font-weight:normal;}#src-sidebar-toggle{position:sticky;top:0;left:0;font-size:1.25rem;border-bottom:1px solid;display:flex;height:40px;justify-content:stretch;align-items:stretch;z-index:10;}#source-sidebar{width:100%;overflow:auto;}#source-sidebar>.title{font-size:1.5rem;text-align:center;border-bottom:1px solid var(--border-color);margin-bottom:6px;}#source-sidebar div.files>a:hover,details.dir-entry summary:hover,#source-sidebar div.files>a:focus,details.dir-entry summary:focus{background-color:var(--source-sidebar-background-hover);}#source-sidebar div.files>a.selected{background-color:var(--source-sidebar-background-selected);}#src-sidebar-toggle>button{font-size:inherit;font-weight:bold;background:none;color:inherit;text-align:center;border:none;outline:none;flex:1 1;-webkit-appearance:none;opacity:1;}#settings-menu,#help-button{margin-left:4px;display:flex;}#settings-menu>a,#help-button>a{display:flex;align-items:center;justify-content:center;background-color:var(--button-background-color);border:1px solid var(--border-color);border-radius:2px;color:var(--settings-button-color);font-size:20px;width:33px;}#settings-menu>a:hover,#settings-menu>a:focus,#help-button>a:hover,#help-button>a:focus{border-color:var(--settings-button-border-focus);}#copy-path{color:var(--copy-path-button-color);background:var(--main-background-color);height:34px;margin-left:10px;padding:0;padding-left:2px;border:0;width:33px;}#copy-path>img{filter:var(--copy-path-img-filter);}#copy-path:hover>img{filter:var(--copy-path-img-hover-filter);}@keyframes rotating{from{transform:rotate(0deg);}to{transform:rotate(360deg);}}#settings-menu.rotate>a img{animation:rotating 2s linear infinite;}kbd{display:inline-block;padding:3px 5px;font:15px monospace;line-height:10px;vertical-align:middle;border:solid 1px var(--border-color);border-radius:3px;color:var(--kbd-color);background-color:var(--kbd-background);box-shadow:inset 0 -1px 0 var(--kbd-box-shadow-color);}ul.all-items>li{list-style:none;}details.dir-entry{padding-left:4px;}details.dir-entry>summary{margin:0 0 0 -4px;padding:0 0 0 4px;cursor:pointer;}details.dir-entry div.folders,details.dir-entry div.files{padding-left:23px;}details.dir-entry a{display:block;}details.toggle{contain:layout;position:relative;}details.toggle>summary.hideme{cursor:pointer;font-size:1rem;}details.toggle>summary{list-style:none;outline:none;}details.toggle>summary::-webkit-details-marker,details.toggle>summary::marker{display:none;}details.toggle>summary.hideme>span{margin-left:9px;}details.toggle>summary::before{background:url('data:image/svg+xml,') no-repeat top left;content:"";cursor:pointer;width:16px;height:16px;display:inline-block;vertical-align:middle;opacity:.5;filter:var(--toggle-filter);}details.toggle>summary.hideme>span,.more-examples-toggle summary,.more-examples-toggle .hide-more{color:var(--toggles-color);}details.toggle>summary::after{content:"Expand";overflow:hidden;width:0;height:0;position:absolute;}details.toggle>summary.hideme::after{content:"";}details.toggle>summary:focus::before,details.toggle>summary:hover::before{opacity:1;}details.toggle>summary:focus-visible::before{outline:1px dotted #000;outline-offset:1px;}details.non-exhaustive{margin-bottom:8px;}details.toggle>summary.hideme::before{position:relative;}details.toggle>summary:not(.hideme)::before{position:absolute;left:-24px;top:4px;}.impl-items>details.toggle>summary:not(.hideme)::before{position:absolute;left:-24px;}details.toggle[open] >summary.hideme{position:absolute;}details.toggle[open] >summary.hideme>span{display:none;}details.toggle[open] >summary::before{background:url('data:image/svg+xml,{if(nb===iter){addClass(elem,"selected");foundCurrentTab=true}else{removeClass(elem,"selected")}iter+=1});const isTypeSearch=(nb>0||iter===1);iter=0;onEachLazy(document.getElementById("results").childNodes,elem=>{if(nb===iter){addClass(elem,"active");foundCurrentResultSet=true}else{removeClass(elem,"active")}iter+=1});if(foundCurrentTab&&foundCurrentResultSet){searchState.currentTab=nb;const correctionsElem=document.getElementsByClassName("search-corrections");if(isTypeSearch){removeClass(correctionsElem[0],"hidden")}else{addClass(correctionsElem[0],"hidden")}}else if(nb!==0){printTab(0)}}const editDistanceState={current:[],prev:[],prevPrev:[],calculate:function calculate(a,b,limit){if(a.lengthlimit){return limit+1}while(b.length>0&&b[0]===a[0]){a=a.substring(1);b=b.substring(1)}while(b.length>0&&b[b.length-1]===a[a.length-1]){a=a.substring(0,a.length-1);b=b.substring(0,b.length-1)}if(b.length===0){return minDist}const aLength=a.length;const bLength=b.length;for(let i=0;i<=bLength;++i){this.current[i]=0;this.prev[i]=i;this.prevPrev[i]=Number.MAX_VALUE}for(let i=1;i<=aLength;++i){this.current[0]=i;const aIdx=i-1;for(let j=1;j<=bLength;++j){const bIdx=j-1;const substitutionCost=a[aIdx]===b[bIdx]?0:1;this.current[j]=Math.min(this.prev[j]+1,this.current[j-1]+1,this.prev[j-1]+substitutionCost);if((i>1)&&(j>1)&&(a[aIdx]===b[bIdx-1])&&(a[aIdx-1]===b[bIdx])){this.current[j]=Math.min(this.current[j],this.prevPrev[j-2]+1)}}const prevPrevTmp=this.prevPrev;this.prevPrev=this.prev;this.prev=this.current;this.current=prevPrevTmp}const distance=this.prev[bLength];return distance<=limit?distance:(limit+1)},};function editDistance(a,b,limit){return editDistanceState.calculate(a,b,limit)}function initSearch(rawSearchIndex){const MAX_RESULTS=200;const NO_TYPE_FILTER=-1;let searchIndex;let currentResults;let typeNameIdMap;const ALIASES=new Map();function isWhitespace(c){return" \t\n\r".indexOf(c)!==-1}function isSpecialStartCharacter(c){return"<\"".indexOf(c)!==-1}function isEndCharacter(c){return",>-".indexOf(c)!==-1}function isStopCharacter(c){return isWhitespace(c)||isEndCharacter(c)}function isErrorCharacter(c){return"()".indexOf(c)!==-1}function itemTypeFromName(typename){const index=itemTypes.findIndex(i=>i===typename);if(index<0){throw["Unknown type filter ",typename]}return index}function getStringElem(query,parserState,isInGenerics){if(isInGenerics){throw["Unexpected ","\""," in generics"]}else if(query.literalSearch){throw["Cannot have more than one literal search element"]}else if(parserState.totalElems-parserState.genericsElems>0){throw["Cannot use literal search when there is more than one element"]}parserState.pos+=1;const start=parserState.pos;const end=getIdentEndPosition(parserState);if(parserState.pos>=parserState.length){throw["Unclosed ","\""]}else if(parserState.userQuery[end]!=="\""){throw["Unexpected ",parserState.userQuery[end]," in a string element"]}else if(start===end){throw["Cannot have empty string element"]}parserState.pos+=1;query.literalSearch=true}function isPathStart(parserState){return parserState.userQuery.slice(parserState.pos,parserState.pos+2)==="::"}function isReturnArrow(parserState){return parserState.userQuery.slice(parserState.pos,parserState.pos+2)==="->"}function isIdentCharacter(c){return(c==="_"||(c>="0"&&c<="9")||(c>="a"&&c<="z")||(c>="A"&&c<="Z"))}function isSeparatorCharacter(c){return c===","||isWhitespaceCharacter(c)}function isWhitespaceCharacter(c){return c===" "||c==="\t"}function createQueryElement(query,parserState,name,generics,isInGenerics){if(name==="*"||(name.length===0&&generics.length===0)){return}if(query.literalSearch&&parserState.totalElems-parserState.genericsElems>0){throw["You cannot have more than one element if you use quotes"]}const pathSegments=name.split("::");if(pathSegments.length>1){for(let i=0,len=pathSegments.length;i=end){throw["Found generics without a path"]}parserState.pos+=1;getItemsBefore(query,parserState,generics,">")}if(start>=end&&generics.length===0){return}elems.push(createQueryElement(query,parserState,parserState.userQuery.slice(start,end),generics,isInGenerics))}function getItemsBefore(query,parserState,elems,endChar){let foundStopChar=true;let start=parserState.pos;const oldTypeFilter=parserState.typeFilter;parserState.typeFilter=null;while(parserState.pos"){extra="<"}else if(endChar===""){extra="->"}else{extra=endChar}throw["Unexpected ",c," after ",extra]}if(!foundStopChar){if(endChar!==""){throw["Expected ",",",", "," "," or ",endChar,", found ",c,]}throw["Expected ",","," or "," ",", found ",c,]}const posBefore=parserState.pos;start=parserState.pos;getNextElem(query,parserState,elems,endChar===">");if(endChar!==""&&parserState.pos>=parserState.length){throw["Unclosed ","<"]}if(posBefore===parserState.pos){parserState.pos+=1}foundStopChar=false}if(parserState.pos>=parserState.length&&endChar!==""){throw["Unclosed ","<"]}parserState.pos+=1;parserState.typeFilter=oldTypeFilter}function checkExtraTypeFilterCharacters(start,parserState){const query=parserState.userQuery;for(let pos=start;pos"){if(isReturnArrow(parserState)){break}throw["Unexpected ",c," (did you mean ","->","?)"]}throw["Unexpected ",c]}else if(c===":"&&!isPathStart(parserState)){if(parserState.typeFilter!==null){throw["Unexpected ",":"]}if(query.elems.length===0){throw["Expected type filter before ",":"]}else if(query.literalSearch){throw["You cannot use quotes on type filter"]}const typeFilterElem=query.elems.pop();checkExtraTypeFilterCharacters(start,parserState);parserState.typeFilter=typeFilterElem.name;parserState.pos+=1;parserState.totalElems-=1;query.literalSearch=false;foundStopChar=true;continue}if(!foundStopChar){if(parserState.typeFilter!==null){throw["Expected ",",",", "," "," or ","->",", found ",c,]}throw["Expected ",",",", "," ",", ",":"," or ","->",", found ",c,]}const before=query.elems.length;start=parserState.pos;getNextElem(query,parserState,query.elems,false);if(query.elems.length===before){parserState.pos+=1}foundStopChar=false}if(parserState.typeFilter!==null){throw["Unexpected ",":"," (expected path after type filter)"]}while(parserState.pos"]}break}else{parserState.pos+=1}}}function newParsedQuery(userQuery){return{original:userQuery,userQuery:userQuery.toLowerCase(),elems:[],returned:[],foundElems:0,literalSearch:false,error:null,correction:null,}}function buildUrl(search,filterCrates){let extra="?search="+encodeURIComponent(search);if(filterCrates!==null){extra+="&filter-crate="+encodeURIComponent(filterCrates)}return getNakedUrl()+extra+window.location.hash}function getFilterCrates(){const elem=document.getElementById("crate-search");if(elem&&elem.value!=="all crates"&&hasOwnPropertyRustdoc(rawSearchIndex,elem.value)){return elem.value}return null}function parseQuery(userQuery){function convertTypeFilterOnElem(elem){if(elem.typeFilter!==null){let typeFilter=elem.typeFilter;if(typeFilter==="const"){typeFilter="constant"}elem.typeFilter=itemTypeFromName(typeFilter)}else{elem.typeFilter=NO_TYPE_FILTER}for(const elem2 of elem.generics){convertTypeFilterOnElem(elem2)}}userQuery=userQuery.trim();const parserState={length:userQuery.length,pos:0,totalElems:0,genericsElems:0,typeFilter:null,userQuery:userQuery.toLowerCase(),};let query=newParsedQuery(userQuery);try{parseInput(query,parserState);for(const elem of query.elems){convertTypeFilterOnElem(elem)}for(const elem of query.returned){convertTypeFilterOnElem(elem)}}catch(err){query=newParsedQuery(userQuery);query.error=err;return query}if(!query.literalSearch){query.literalSearch=parserState.totalElems>1}query.foundElems=query.elems.length+query.returned.length;return query}function createQueryResults(results_in_args,results_returned,results_others,parsedQuery){return{"in_args":results_in_args,"returned":results_returned,"others":results_others,"query":parsedQuery,}}function execQuery(parsedQuery,searchWords,filterCrates,currentCrate){const results_others=new Map(),results_in_args=new Map(),results_returned=new Map();function transformResults(results){const duplicates=new Set();const out=[];for(const result of results){if(result.id>-1){const obj=searchIndex[result.id];obj.dist=result.dist;const res=buildHrefAndPath(obj);obj.displayPath=pathSplitter(res[0]);obj.fullPath=obj.displayPath+obj.name;obj.fullPath+="|"+obj.ty;if(duplicates.has(obj.fullPath)){continue}duplicates.add(obj.fullPath);obj.href=res[1];out.push(obj);if(out.length>=MAX_RESULTS){break}}}return out}function sortResults(results,isType,preferredCrate){if(results.size===0){return[]}const userQuery=parsedQuery.userQuery;const result_list=[];for(const result of results.values()){result.word=searchWords[result.id];result.item=searchIndex[result.id]||{};result_list.push(result)}result_list.sort((aaa,bbb)=>{let a,b;a=(aaa.word!==userQuery);b=(bbb.word!==userQuery);if(a!==b){return a-b}a=(aaa.index<0);b=(bbb.index<0);if(a!==b){return a-b}a=aaa.path_dist;b=bbb.path_dist;if(a!==b){return a-b}a=aaa.index;b=bbb.index;if(a!==b){return a-b}a=(aaa.dist);b=(bbb.dist);if(a!==b){return a-b}a=aaa.item.deprecated;b=bbb.item.deprecated;if(a!==b){return a-b}a=(aaa.item.crate!==preferredCrate);b=(bbb.item.crate!==preferredCrate);if(a!==b){return a-b}a=aaa.word.length;b=bbb.word.length;if(a!==b){return a-b}a=aaa.word;b=bbb.word;if(a!==b){return(a>b?+1:-1)}if((aaa.item.ty===TY_PRIMITIVE&&bbb.item.ty!==TY_KEYWORD)||(aaa.item.ty===TY_KEYWORD&&bbb.item.ty!==TY_PRIMITIVE)){return-1}if((bbb.item.ty===TY_PRIMITIVE&&aaa.item.ty!==TY_PRIMITIVE)||(bbb.item.ty===TY_KEYWORD&&aaa.item.ty!==TY_KEYWORD)){return 1}a=(aaa.item.desc==="");b=(bbb.item.desc==="");if(a!==b){return a-b}a=aaa.item.ty;b=bbb.item.ty;if(a!==b){return a-b}a=aaa.item.path;b=bbb.item.path;if(a!==b){return(a>b?+1:-1)}return 0});let nameSplit=null;if(parsedQuery.elems.length===1){const hasPath=typeof parsedQuery.elems[0].path==="undefined";nameSplit=hasPath?null:parsedQuery.elems[0].path}for(const result of result_list){if(result.dontValidate){continue}const name=result.item.name.toLowerCase(),path=result.item.path.toLowerCase(),parent=result.item.parent;if(!isType&&!validateResult(name,path,nameSplit,parent)){result.id=-1}}return transformResults(result_list)}function checkGenerics(row,elem){if(row.generics.length===0||elem.generics.length===0){return false}if(elem.generics.length>0&&row.generics.length>=elem.generics.length){const elems=new Map();const addEntryToElems=function addEntryToElems(entry){if(entry.id===-1){for(const inner_entry of entry.generics){addEntryToElems(inner_entry)}return}let currentEntryElems;if(elems.has(entry.id)){currentEntryElems=elems.get(entry.id)}else{currentEntryElems=[];elems.set(entry.id,currentEntryElems)}currentEntryElems.push(entry)};for(const entry of row.generics){addEntryToElems(entry)}const handleGeneric=generic=>{if(!elems.has(generic.id)){return false}const matchElems=elems.get(generic.id);const matchIdx=matchElems.findIndex(tmp_elem=>{if(generic.generics.length>0&&!checkGenerics(tmp_elem,generic)){return false}return typePassesFilter(generic.typeFilter,tmp_elem.ty)});if(matchIdx===-1){return false}matchElems.splice(matchIdx,1);if(matchElems.length===0){elems.delete(generic.id)}return true};for(const generic of elem.generics){if(generic.typeFilter!==-1&&!handleGeneric(generic)){return false}}for(const generic of elem.generics){if(generic.typeFilter===-1&&!handleGeneric(generic)){return false}}return true}return false}function checkIfInGenerics(row,elem){for(const entry of row.generics){if(checkType(entry,elem)){return true}}return false}function checkType(row,elem){if(row.id===-1){return row.generics.length>0?checkIfInGenerics(row,elem):false}if(row.id===elem.id&&typePassesFilter(elem.typeFilter,row.ty)){if(elem.generics.length>0){return checkGenerics(row,elem)}return true}return checkIfInGenerics(row,elem)}function findArg(row,elem,skipPositions){if(row&&row.type&&row.type.inputs&&row.type.inputs.length>0){let i=0;for(const input of row.type.inputs){if(skipPositions.indexOf(i)!==-1){i+=1;continue}if(checkType(input,elem)){return i}i+=1}}return-1}function checkReturned(row,elem,skipPositions){if(row&&row.type&&row.type.output.length>0){let i=0;for(const ret_ty of row.type.output){if(skipPositions.indexOf(i)!==-1){i+=1;continue}if(checkType(ret_ty,elem)){return i}i+=1}}return-1}function checkPath(contains,ty,maxEditDistance){if(contains.length===0){return 0}let ret_dist=maxEditDistance+1;const path=ty.path.split("::");if(ty.parent&&ty.parent.name){path.push(ty.parent.name.toLowerCase())}const length=path.length;const clength=contains.length;if(clength>length){return maxEditDistance+1}for(let i=0;ilength){break}let dist_total=0;let aborted=false;for(let x=0;xmaxEditDistance){aborted=true;break}dist_total+=dist}if(!aborted){ret_dist=Math.min(ret_dist,Math.round(dist_total/clength))}}return ret_dist}function typePassesFilter(filter,type){if(filter<=NO_TYPE_FILTER||filter===type)return true;const name=itemTypes[type];switch(itemTypes[filter]){case"constant":return name==="associatedconstant";case"fn":return name==="method"||name==="tymethod";case"type":return name==="primitive"||name==="associatedtype";case"trait":return name==="traitalias"}return false}function createAliasFromItem(item){return{crate:item.crate,name:item.name,path:item.path,desc:item.desc,ty:item.ty,parent:item.parent,type:item.type,is_alias:true,deprecated:item.deprecated,}}function handleAliases(ret,query,filterCrates,currentCrate){const lowerQuery=query.toLowerCase();const aliases=[];const crateAliases=[];if(filterCrates!==null){if(ALIASES.has(filterCrates)&&ALIASES.get(filterCrates).has(lowerQuery)){const query_aliases=ALIASES.get(filterCrates).get(lowerQuery);for(const alias of query_aliases){aliases.push(createAliasFromItem(searchIndex[alias]))}}}else{for(const[crate,crateAliasesIndex]of ALIASES){if(crateAliasesIndex.has(lowerQuery)){const pushTo=crate===currentCrate?crateAliases:aliases;const query_aliases=crateAliasesIndex.get(lowerQuery);for(const alias of query_aliases){pushTo.push(createAliasFromItem(searchIndex[alias]))}}}}const sortFunc=(aaa,bbb)=>{if(aaa.path{alias.alias=query;const res=buildHrefAndPath(alias);alias.displayPath=pathSplitter(res[0]);alias.fullPath=alias.displayPath+alias.name;alias.href=res[1];ret.others.unshift(alias);if(ret.others.length>MAX_RESULTS){ret.others.pop()}};aliases.forEach(pushFunc);crateAliases.forEach(pushFunc)}function addIntoResults(results,fullId,id,index,dist,path_dist,maxEditDistance){const inBounds=dist<=maxEditDistance||index!==-1;if(dist===0||(!parsedQuery.literalSearch&&inBounds)){if(results.has(fullId)){const result=results.get(fullId);if(result.dontValidate||result.dist<=dist){return}}results.set(fullId,{id:id,index:index,dontValidate:parsedQuery.literalSearch,dist:dist,path_dist:path_dist,})}}function handleSingleArg(row,pos,elem,results_others,results_in_args,results_returned,maxEditDistance){if(!row||(filterCrates!==null&&row.crate!==filterCrates)){return}let index=-1,path_dist=0;const fullId=row.id;const searchWord=searchWords[pos];const in_args=findArg(row,elem,[]);if(in_args!==-1){addIntoResults(results_in_args,fullId,pos,-1,0,0,maxEditDistance)}const returned=checkReturned(row,elem,[]);if(returned!==-1){addIntoResults(results_returned,fullId,pos,-1,0,0,maxEditDistance)}if(!typePassesFilter(elem.typeFilter,row.ty)){return}const row_index=row.normalizedName.indexOf(elem.pathLast);const word_index=searchWord.indexOf(elem.pathLast);if(row_index===-1){index=word_index}else if(word_index===-1){index=row_index}else if(word_index1){path_dist=checkPath(elem.pathWithoutLast,row,maxEditDistance);if(path_dist>maxEditDistance){return}}if(parsedQuery.literalSearch){if(searchWord===elem.name){addIntoResults(results_others,fullId,pos,index,0,path_dist)}return}const dist=editDistance(searchWord,elem.pathLast,maxEditDistance);if(index===-1&&dist+path_dist>maxEditDistance){return}addIntoResults(results_others,fullId,pos,index,dist,path_dist,maxEditDistance)}function handleArgs(row,pos,results){if(!row||(filterCrates!==null&&row.crate!==filterCrates)){return}function checkArgs(elems,callback){const skipPositions=[];for(const elem of elems){const position=callback(row,elem,skipPositions);if(position!==-1){skipPositions.push(position)}else{return false}}return true}if(!checkArgs(parsedQuery.elems,findArg)){return}if(!checkArgs(parsedQuery.returned,checkReturned)){return}addIntoResults(results,row.id,pos,0,0,0,Number.MAX_VALUE)}function innerRunQuery(){let elem,i,nSearchWords,in_returned,row;let queryLen=0;for(const elem of parsedQuery.elems){queryLen+=elem.name.length}for(const elem of parsedQuery.returned){queryLen+=elem.name.length}const maxEditDistance=Math.floor(queryLen/3);function convertNameToId(elem){if(typeNameIdMap.has(elem.name)){elem.id=typeNameIdMap.get(elem.name)}else if(!parsedQuery.literalSearch){let match=-1;let matchDist=maxEditDistance+1;let matchName="";for(const[name,id]of typeNameIdMap){const dist=editDistance(name,elem.name,maxEditDistance);if(dist<=matchDist&&dist<=maxEditDistance){if(dist===matchDist&&matchName>name){continue}match=id;matchDist=dist;matchName=name}}if(match!==-1){parsedQuery.correction=matchName}elem.id=match}for(const elem2 of elem.generics){convertNameToId(elem2)}}for(const elem of parsedQuery.elems){convertNameToId(elem)}for(const elem of parsedQuery.returned){convertNameToId(elem)}if(parsedQuery.foundElems===1){if(parsedQuery.elems.length===1){elem=parsedQuery.elems[0];for(i=0,nSearchWords=searchWords.length;i0){for(i=0,nSearchWords=searchWords.length;i-1||path.indexOf(key)>-1||(parent!==undefined&&parent.name!==undefined&&parent.name.toLowerCase().indexOf(key)>-1)||editDistance(name,key,maxEditDistance)<=maxEditDistance)){return false}}return true}function nextTab(direction){const next=(searchState.currentTab+direction+3)%searchState.focusedByTab.length;searchState.focusedByTab[searchState.currentTab]=document.activeElement;printTab(next);focusSearchResult()}function focusSearchResult(){const target=searchState.focusedByTab[searchState.currentTab]||document.querySelectorAll(".search-results.active a").item(0)||document.querySelectorAll("#search-tabs button").item(searchState.currentTab);searchState.focusedByTab[searchState.currentTab]=null;if(target){target.focus()}}function buildHrefAndPath(item){let displayPath;let href;const type=itemTypes[item.ty];const name=item.name;let path=item.path;if(type==="mod"){displayPath=path+"::";href=ROOT_PATH+path.replace(/::/g,"/")+"/"+name+"/index.html"}else if(type==="import"){displayPath=item.path+"::";href=ROOT_PATH+item.path.replace(/::/g,"/")+"/index.html#reexport."+name}else if(type==="primitive"||type==="keyword"){displayPath="";href=ROOT_PATH+path.replace(/::/g,"/")+"/"+type+"."+name+".html"}else if(type==="externcrate"){displayPath="";href=ROOT_PATH+name+"/index.html"}else if(item.parent!==undefined){const myparent=item.parent;let anchor="#"+type+"."+name;const parentType=itemTypes[myparent.ty];let pageType=parentType;let pageName=myparent.name;if(parentType==="primitive"){displayPath=myparent.name+"::"}else if(type==="structfield"&&parentType==="variant"){const enumNameIdx=item.path.lastIndexOf("::");const enumName=item.path.substr(enumNameIdx+2);path=item.path.substr(0,enumNameIdx);displayPath=path+"::"+enumName+"::"+myparent.name+"::";anchor="#variant."+myparent.name+".field."+name;pageType="enum";pageName=enumName}else{displayPath=path+"::"+myparent.name+"::"}href=ROOT_PATH+path.replace(/::/g,"/")+"/"+pageType+"."+pageName+".html"+anchor}else{displayPath=item.path+"::";href=ROOT_PATH+item.path.replace(/::/g,"/")+"/"+type+"."+name+".html"}return[displayPath,href]}function pathSplitter(path){const tmp=""+path.replace(/::/g,"::");if(tmp.endsWith("")){return tmp.slice(0,tmp.length-6)}return tmp}function addTab(array,query,display){let extraClass="";if(display===true){extraClass=" active"}const output=document.createElement("div");let length=0;if(array.length>0){output.className="search-results "+extraClass;array.forEach(item=>{const name=item.name;const type=itemTypes[item.ty];length+=1;let extra="";if(type==="primitive"){extra=" (primitive type)"}else if(type==="keyword"){extra=" (keyword)"}const link=document.createElement("a");link.className="result-"+type;link.href=item.href;const resultName=document.createElement("div");resultName.className="result-name";if(item.is_alias){const alias=document.createElement("span");alias.className="alias";const bold=document.createElement("b");bold.innerText=item.alias;alias.appendChild(bold);alias.insertAdjacentHTML("beforeend"," - see ");resultName.appendChild(alias)}resultName.insertAdjacentHTML("beforeend",item.displayPath+""+name+extra+"");link.appendChild(resultName);const description=document.createElement("div");description.className="desc";description.insertAdjacentHTML("beforeend",item.desc);link.appendChild(description);output.appendChild(link)})}else if(query.error===null){output.className="search-failed"+extraClass;output.innerHTML="No results :(
"+"Try on DuckDuckGo?

"+"Or try looking in one of these:"}return[output,length]}function makeTabHeader(tabNb,text,nbElems){if(searchState.currentTab===tabNb){return""}return""}function showResults(results,go_to_first,filterCrates){const search=searchState.outputElement();if(go_to_first||(results.others.length===1&&getSettingValue("go-to-only-result")==="true")){const elem=document.createElement("a");elem.href=results.others[0].href;removeClass(elem,"active");document.body.appendChild(elem);elem.click();return}if(results.query===undefined){results.query=parseQuery(searchState.input.value)}currentResults=results.query.userQuery;const ret_others=addTab(results.others,results.query,true);const ret_in_args=addTab(results.in_args,results.query,false);const ret_returned=addTab(results.returned,results.query,false);let currentTab=searchState.currentTab;if((currentTab===0&&ret_others[1]===0)||(currentTab===1&&ret_in_args[1]===0)||(currentTab===2&&ret_returned[1]===0)){if(ret_others[1]!==0){currentTab=0}else if(ret_in_args[1]!==0){currentTab=1}else if(ret_returned[1]!==0){currentTab=2}}let crates="";const crates_list=Object.keys(rawSearchIndex);if(crates_list.length>1){crates=" in 
"}let output=`

Results${crates}

`;if(results.query.error!==null){const error=results.query.error;error.forEach((value,index)=>{value=value.split("<").join("<").split(">").join(">");if(index%2!==0){error[index]=`${value}`}else{error[index]=value}});output+=`

Query parser error: "${error.join("")}".

`;output+="
"+makeTabHeader(0,"In Names",ret_others[1])+"
";currentTab=0}else if(results.query.foundElems<=1&&results.query.returned.length===0){output+="
"+makeTabHeader(0,"In Names",ret_others[1])+makeTabHeader(1,"In Parameters",ret_in_args[1])+makeTabHeader(2,"In Return Types",ret_returned[1])+"
"}else{const signatureTabTitle=results.query.elems.length===0?"In Function Return Types":results.query.returned.length===0?"In Function Parameters":"In Function Signatures";output+="
"+makeTabHeader(0,signatureTabTitle,ret_others[1])+"
";currentTab=0}if(results.query.correction!==null){const orig=results.query.returned.length>0?results.query.returned[0].name:results.query.elems[0].name;output+="

"+`Type "${orig}" not found. `+"Showing results for closest type name "+`"${results.query.correction}" instead.

`}const resultsElem=document.createElement("div");resultsElem.id="results";resultsElem.appendChild(ret_others[0]);resultsElem.appendChild(ret_in_args[0]);resultsElem.appendChild(ret_returned[0]);search.innerHTML=output;const crateSearch=document.getElementById("crate-search");if(crateSearch){crateSearch.addEventListener("input",updateCrate)}search.appendChild(resultsElem);searchState.showResults(search);const elems=document.getElementById("search-tabs").childNodes;searchState.focusedByTab=[];let i=0;for(const elem of elems){const j=i;elem.onclick=()=>printTab(j);searchState.focusedByTab.push(null);i+=1}printTab(currentTab)}function search(e,forced){if(e){e.preventDefault()}const query=parseQuery(searchState.input.value.trim());let filterCrates=getFilterCrates();if(!forced&&query.userQuery===currentResults){if(query.userQuery.length>0){putBackSearch()}return}searchState.setLoadingSearch();const params=searchState.getQueryStringParams();if(filterCrates===null&¶ms["filter-crate"]!==undefined){filterCrates=params["filter-crate"]}searchState.title="Results for "+query.original+" - Rust";if(browserSupportsHistoryApi()){const newURL=buildUrl(query.original,filterCrates);if(!history.state&&!params.search){history.pushState(null,"",newURL)}else{history.replaceState(null,"",newURL)}}showResults(execQuery(query,searchWords,filterCrates,window.currentCrate),params.go_to_first,filterCrates)}function buildTypeMapIndex(typeNameIdMap,name){if(name===""||name===null){return-1}if(typeNameIdMap.has(name)){return typeNameIdMap.get(name)}else{const id=typeNameIdMap.size;typeNameIdMap.set(name,id);return id}}function buildItemSearchTypeAll(types,lowercasePaths,typeNameIdMap){const PATH_INDEX_DATA=0;const GENERICS_DATA=1;return types.map(type=>{let pathIndex,generics;if(typeof type==="number"){pathIndex=type;generics=[]}else{pathIndex=type[PATH_INDEX_DATA];generics=buildItemSearchTypeAll(type[GENERICS_DATA],lowercasePaths,typeNameIdMap)}return{id:pathIndex===0?-1:buildTypeMapIndex(typeNameIdMap,lowercasePaths[pathIndex-1].name),ty:pathIndex===0?null:lowercasePaths[pathIndex-1].ty,generics:generics,}})}function buildFunctionSearchType(functionSearchType,lowercasePaths,typeNameIdMap){const INPUTS_DATA=0;const OUTPUT_DATA=1;if(functionSearchType===0){return null}let inputs,output;if(typeof functionSearchType[INPUTS_DATA]==="number"){const pathIndex=functionSearchType[INPUTS_DATA];inputs=[{id:pathIndex===0?-1:buildTypeMapIndex(typeNameIdMap,lowercasePaths[pathIndex-1].name),ty:pathIndex===0?null:lowercasePaths[pathIndex-1].ty,generics:[],}]}else{inputs=buildItemSearchTypeAll(functionSearchType[INPUTS_DATA],lowercasePaths,typeNameIdMap)}if(functionSearchType.length>1){if(typeof functionSearchType[OUTPUT_DATA]==="number"){const pathIndex=functionSearchType[OUTPUT_DATA];output=[{id:pathIndex===0?-1:buildTypeMapIndex(typeNameIdMap,lowercasePaths[pathIndex-1].name),ty:pathIndex===0?null:lowercasePaths[pathIndex-1].ty,generics:[],}]}else{output=buildItemSearchTypeAll(functionSearchType[OUTPUT_DATA],lowercasePaths,typeNameIdMap)}}else{output=[]}return{inputs,output,}}function buildIndex(rawSearchIndex){searchIndex=[];const searchWords=[];typeNameIdMap=new Map();const charA="A".charCodeAt(0);let currentIndex=0;let id=0;for(const crate in rawSearchIndex){if(!hasOwnPropertyRustdoc(rawSearchIndex,crate)){continue}let crateSize=0;const crateCorpus=rawSearchIndex[crate];searchWords.push(crate);const crateRow={crate:crate,ty:1,name:crate,path:"",desc:crateCorpus.doc,parent:undefined,type:null,id:id,normalizedName:crate.indexOf("_")===-1?crate:crate.replace(/_/g,""),deprecated:null,};id+=1;searchIndex.push(crateRow);currentIndex+=1;const itemTypes=crateCorpus.t;const itemNames=crateCorpus.n;const itemPaths=new Map(crateCorpus.q);const itemDescs=crateCorpus.d;const itemParentIdxs=crateCorpus.i;const itemFunctionSearchTypes=crateCorpus.f;const deprecatedItems=new Set(crateCorpus.c);const paths=crateCorpus.p;const aliases=crateCorpus.a;const lowercasePaths=[];let len=paths.length;for(let i=0;i0?paths[itemParentIdxs[i]-1]:undefined,type:buildFunctionSearchType(itemFunctionSearchTypes[i],lowercasePaths,typeNameIdMap),id:id,normalizedName:word.indexOf("_")===-1?word:word.replace(/_/g,""),deprecated:deprecatedItems.has(i),};id+=1;searchIndex.push(row);lastPath=row.path;crateSize+=1}if(aliases){const currentCrateAliases=new Map();ALIASES.set(crate,currentCrateAliases);for(const alias_name in aliases){if(!hasOwnPropertyRustdoc(aliases,alias_name)){continue}let currentNameAliases;if(currentCrateAliases.has(alias_name)){currentNameAliases=currentCrateAliases.get(alias_name)}else{currentNameAliases=[];currentCrateAliases.set(alias_name,currentNameAliases)}for(const local_alias of aliases[alias_name]){currentNameAliases.push(local_alias+currentIndex)}}}currentIndex+=crateSize}return searchWords}function onSearchSubmit(e){e.preventDefault();searchState.clearInputTimeout();search()}function putBackSearch(){const search_input=searchState.input;if(!searchState.input){return}if(search_input.value!==""&&!searchState.isDisplayed()){searchState.showResults();if(browserSupportsHistoryApi()){history.replaceState(null,"",buildUrl(search_input.value,getFilterCrates()))}document.title=searchState.title}}function registerSearchEvents(){const params=searchState.getQueryStringParams();if(searchState.input.value===""){searchState.input.value=params.search||""}const searchAfter500ms=()=>{searchState.clearInputTimeout();if(searchState.input.value.length===0){searchState.hideResults()}else{searchState.timeout=setTimeout(search,500)}};searchState.input.onkeyup=searchAfter500ms;searchState.input.oninput=searchAfter500ms;document.getElementsByClassName("search-form")[0].onsubmit=onSearchSubmit;searchState.input.onchange=e=>{if(e.target!==document.activeElement){return}searchState.clearInputTimeout();setTimeout(search,0)};searchState.input.onpaste=searchState.input.onchange;searchState.outputElement().addEventListener("keydown",e=>{if(e.altKey||e.ctrlKey||e.shiftKey||e.metaKey){return}if(e.which===38){const previous=document.activeElement.previousElementSibling;if(previous){previous.focus()}else{searchState.focus()}e.preventDefault()}else if(e.which===40){const next=document.activeElement.nextElementSibling;if(next){next.focus()}const rect=document.activeElement.getBoundingClientRect();if(window.innerHeight-rect.bottom{if(e.which===40){focusSearchResult();e.preventDefault()}});searchState.input.addEventListener("focus",()=>{putBackSearch()});searchState.input.addEventListener("blur",()=>{searchState.input.placeholder=searchState.input.origPlaceholder});if(browserSupportsHistoryApi()){const previousTitle=document.title;window.addEventListener("popstate",e=>{const params=searchState.getQueryStringParams();document.title=previousTitle;currentResults=null;if(params.search&¶ms.search.length>0){searchState.input.value=params.search;search(e)}else{searchState.input.value="";searchState.hideResults()}})}window.onpageshow=()=>{const qSearch=searchState.getQueryStringParams().search;if(searchState.input.value===""&&qSearch){searchState.input.value=qSearch}search()}}function updateCrate(ev){if(ev.target.value==="all crates"){const params=searchState.getQueryStringParams();const query=searchState.input.value.trim();if(!history.state&&!params.search){history.pushState(null,"",buildUrl(query,null))}else{history.replaceState(null,"",buildUrl(query,null))}}currentResults=null;search(undefined,true)}const searchWords=buildIndex(rawSearchIndex);if(typeof window!=="undefined"){registerSearchEvents();if(window.searchState.getQueryStringParams().search){search()}}if(typeof exports!=="undefined"){exports.initSearch=initSearch;exports.execQuery=execQuery;exports.parseQuery=parseQuery}return searchWords}if(typeof window!=="undefined"){window.initSearch=initSearch;if(window.searchIndex!==undefined){initSearch(window.searchIndex)}}else{initSearch({})}})() \ No newline at end of file diff --git a/doc/static.files/search-e077946657036a58.js b/doc/static.files/search-e077946657036a58.js deleted file mode 100644 index 3b21179bf..000000000 --- a/doc/static.files/search-e077946657036a58.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(function(){const itemTypes=["mod","externcrate","import","struct","enum","fn","type","static","trait","impl","tymethod","method","structfield","variant","macro","primitive","associatedtype","constant","associatedconstant","union","foreigntype","keyword","existential","attr","derive","traitalias",];const TY_PRIMITIVE=itemTypes.indexOf("primitive");const TY_KEYWORD=itemTypes.indexOf("keyword");const ROOT_PATH=typeof window!=="undefined"?window.rootPath:"../";function hasOwnPropertyRustdoc(obj,property){return Object.prototype.hasOwnProperty.call(obj,property)}function printTab(nb){let iter=0;let foundCurrentTab=false;let foundCurrentResultSet=false;onEachLazy(document.getElementById("search-tabs").childNodes,elem=>{if(nb===iter){addClass(elem,"selected");foundCurrentTab=true}else{removeClass(elem,"selected")}iter+=1});iter=0;onEachLazy(document.getElementById("results").childNodes,elem=>{if(nb===iter){addClass(elem,"active");foundCurrentResultSet=true}else{removeClass(elem,"active")}iter+=1});if(foundCurrentTab&&foundCurrentResultSet){searchState.currentTab=nb}else if(nb!==0){printTab(0)}}const editDistanceState={current:[],prev:[],prevPrev:[],calculate:function calculate(a,b,limit){if(a.lengthlimit){return limit+1}while(b.length>0&&b[0]===a[0]){a=a.substring(1);b=b.substring(1)}while(b.length>0&&b[b.length-1]===a[a.length-1]){a=a.substring(0,a.length-1);b=b.substring(0,b.length-1)}if(b.length===0){return minDist}const aLength=a.length;const bLength=b.length;for(let i=0;i<=bLength;++i){this.current[i]=0;this.prev[i]=i;this.prevPrev[i]=Number.MAX_VALUE}for(let i=1;i<=aLength;++i){this.current[0]=i;const aIdx=i-1;for(let j=1;j<=bLength;++j){const bIdx=j-1;const substitutionCost=a[aIdx]===b[bIdx]?0:1;this.current[j]=Math.min(this.prev[j]+1,this.current[j-1]+1,this.prev[j-1]+substitutionCost);if((i>1)&&(j>1)&&(a[aIdx]===b[bIdx-1])&&(a[aIdx-1]===b[bIdx])){this.current[j]=Math.min(this.current[j],this.prevPrev[j-2]+1)}}const prevPrevTmp=this.prevPrev;this.prevPrev=this.prev;this.prev=this.current;this.current=prevPrevTmp}const distance=this.prev[bLength];return distance<=limit?distance:(limit+1)},};function editDistance(a,b,limit){return editDistanceState.calculate(a,b,limit)}function initSearch(rawSearchIndex){const MAX_RESULTS=200;const NO_TYPE_FILTER=-1;let searchIndex;let currentResults;const ALIASES=new Map();function isWhitespace(c){return" \t\n\r".indexOf(c)!==-1}function isSpecialStartCharacter(c){return"<\"".indexOf(c)!==-1}function isEndCharacter(c){return",>-".indexOf(c)!==-1}function isStopCharacter(c){return isWhitespace(c)||isEndCharacter(c)}function isErrorCharacter(c){return"()".indexOf(c)!==-1}function itemTypeFromName(typename){const index=itemTypes.findIndex(i=>i===typename);if(index<0){throw["Unknown type filter ",typename]}return index}function getStringElem(query,parserState,isInGenerics){if(isInGenerics){throw["Unexpected ","\""," in generics"]}else if(query.literalSearch){throw["Cannot have more than one literal search element"]}else if(parserState.totalElems-parserState.genericsElems>0){throw["Cannot use literal search when there is more than one element"]}parserState.pos+=1;const start=parserState.pos;const end=getIdentEndPosition(parserState);if(parserState.pos>=parserState.length){throw["Unclosed ","\""]}else if(parserState.userQuery[end]!=="\""){throw["Unexpected ",parserState.userQuery[end]," in a string element"]}else if(start===end){throw["Cannot have empty string element"]}parserState.pos+=1;query.literalSearch=true}function isPathStart(parserState){return parserState.userQuery.slice(parserState.pos,parserState.pos+2)==="::"}function isReturnArrow(parserState){return parserState.userQuery.slice(parserState.pos,parserState.pos+2)==="->"}function isIdentCharacter(c){return(c==="_"||(c>="0"&&c<="9")||(c>="a"&&c<="z")||(c>="A"&&c<="Z"))}function isSeparatorCharacter(c){return c===","||isWhitespaceCharacter(c)}function isWhitespaceCharacter(c){return c===" "||c==="\t"}function createQueryElement(query,parserState,name,generics,isInGenerics){if(name==="*"||(name.length===0&&generics.length===0)){return}if(query.literalSearch&&parserState.totalElems-parserState.genericsElems>0){throw["You cannot have more than one element if you use quotes"]}const pathSegments=name.split("::");if(pathSegments.length>1){for(let i=0,len=pathSegments.length;i=end){throw["Found generics without a path"]}parserState.pos+=1;getItemsBefore(query,parserState,generics,">")}if(start>=end&&generics.length===0){return}elems.push(createQueryElement(query,parserState,parserState.userQuery.slice(start,end),generics,isInGenerics))}function getItemsBefore(query,parserState,elems,endChar){let foundStopChar=true;let start=parserState.pos;const oldTypeFilter=parserState.typeFilter;parserState.typeFilter=null;while(parserState.pos"){extra="<"}else if(endChar===""){extra="->"}else{extra=endChar}throw["Unexpected ",c," after ",extra]}if(!foundStopChar){if(endChar!==""){throw["Expected ",",",", "," "," or ",endChar,", found ",c,]}throw["Expected ",","," or "," ",", found ",c,]}const posBefore=parserState.pos;start=parserState.pos;getNextElem(query,parserState,elems,endChar===">");if(endChar!==""&&parserState.pos>=parserState.length){throw["Unclosed ","<"]}if(posBefore===parserState.pos){parserState.pos+=1}foundStopChar=false}if(parserState.pos>=parserState.length&&endChar!==""){throw["Unclosed ","<"]}parserState.pos+=1;parserState.typeFilter=oldTypeFilter}function checkExtraTypeFilterCharacters(start,parserState){const query=parserState.userQuery;for(let pos=start;pos"){if(isReturnArrow(parserState)){break}throw["Unexpected ",c," (did you mean ","->","?)"]}throw["Unexpected ",c]}else if(c===":"&&!isPathStart(parserState)){if(parserState.typeFilter!==null){throw["Unexpected ",":"]}if(query.elems.length===0){throw["Expected type filter before ",":"]}else if(query.literalSearch){throw["You cannot use quotes on type filter"]}const typeFilterElem=query.elems.pop();checkExtraTypeFilterCharacters(start,parserState);parserState.typeFilter=typeFilterElem.name;parserState.pos+=1;parserState.totalElems-=1;query.literalSearch=false;foundStopChar=true;continue}if(!foundStopChar){if(parserState.typeFilter!==null){throw["Expected ",",",", "," "," or ","->",", found ",c,]}throw["Expected ",",",", "," ",", ",":"," or ","->",", found ",c,]}const before=query.elems.length;start=parserState.pos;getNextElem(query,parserState,query.elems,false);if(query.elems.length===before){parserState.pos+=1}foundStopChar=false}if(parserState.typeFilter!==null){throw["Unexpected ",":"," (expected path after type filter)"]}while(parserState.pos"]}break}else{parserState.pos+=1}}}function newParsedQuery(userQuery){return{original:userQuery,userQuery:userQuery.toLowerCase(),elems:[],returned:[],foundElems:0,literalSearch:false,error:null,}}function buildUrl(search,filterCrates){let extra="?search="+encodeURIComponent(search);if(filterCrates!==null){extra+="&filter-crate="+encodeURIComponent(filterCrates)}return getNakedUrl()+extra+window.location.hash}function getFilterCrates(){const elem=document.getElementById("crate-search");if(elem&&elem.value!=="all crates"&&hasOwnPropertyRustdoc(rawSearchIndex,elem.value)){return elem.value}return null}function parseQuery(userQuery){function convertTypeFilterOnElem(elem){if(elem.typeFilter!==null){let typeFilter=elem.typeFilter;if(typeFilter==="const"){typeFilter="constant"}elem.typeFilter=itemTypeFromName(typeFilter)}else{elem.typeFilter=NO_TYPE_FILTER}for(const elem2 of elem.generics){convertTypeFilterOnElem(elem2)}}userQuery=userQuery.trim();const parserState={length:userQuery.length,pos:0,totalElems:0,genericsElems:0,typeFilter:null,userQuery:userQuery.toLowerCase(),};let query=newParsedQuery(userQuery);try{parseInput(query,parserState);for(const elem of query.elems){convertTypeFilterOnElem(elem)}for(const elem of query.returned){convertTypeFilterOnElem(elem)}}catch(err){query=newParsedQuery(userQuery);query.error=err;return query}if(!query.literalSearch){query.literalSearch=parserState.totalElems>1}query.foundElems=query.elems.length+query.returned.length;return query}function createQueryResults(results_in_args,results_returned,results_others,parsedQuery){return{"in_args":results_in_args,"returned":results_returned,"others":results_others,"query":parsedQuery,}}function execQuery(parsedQuery,searchWords,filterCrates,currentCrate){const results_others=new Map(),results_in_args=new Map(),results_returned=new Map();function transformResults(results){const duplicates=new Set();const out=[];for(const result of results){if(result.id>-1){const obj=searchIndex[result.id];obj.dist=result.dist;const res=buildHrefAndPath(obj);obj.displayPath=pathSplitter(res[0]);obj.fullPath=obj.displayPath+obj.name;obj.fullPath+="|"+obj.ty;if(duplicates.has(obj.fullPath)){continue}duplicates.add(obj.fullPath);obj.href=res[1];out.push(obj);if(out.length>=MAX_RESULTS){break}}}return out}function sortResults(results,isType,preferredCrate){if(results.size===0){return[]}const userQuery=parsedQuery.userQuery;const result_list=[];for(const result of results.values()){result.word=searchWords[result.id];result.item=searchIndex[result.id]||{};result_list.push(result)}result_list.sort((aaa,bbb)=>{let a,b;a=(aaa.word!==userQuery);b=(bbb.word!==userQuery);if(a!==b){return a-b}a=(aaa.index<0);b=(bbb.index<0);if(a!==b){return a-b}a=aaa.path_dist;b=bbb.path_dist;if(a!==b){return a-b}a=aaa.index;b=bbb.index;if(a!==b){return a-b}a=(aaa.dist);b=(bbb.dist);if(a!==b){return a-b}a=aaa.item.deprecated;b=bbb.item.deprecated;if(a!==b){return a-b}a=(aaa.item.crate!==preferredCrate);b=(bbb.item.crate!==preferredCrate);if(a!==b){return a-b}a=aaa.word.length;b=bbb.word.length;if(a!==b){return a-b}a=aaa.word;b=bbb.word;if(a!==b){return(a>b?+1:-1)}if((aaa.item.ty===TY_PRIMITIVE&&bbb.item.ty!==TY_KEYWORD)||(aaa.item.ty===TY_KEYWORD&&bbb.item.ty!==TY_PRIMITIVE)){return-1}if((bbb.item.ty===TY_PRIMITIVE&&aaa.item.ty!==TY_PRIMITIVE)||(bbb.item.ty===TY_KEYWORD&&aaa.item.ty!==TY_KEYWORD)){return 1}a=(aaa.item.desc==="");b=(bbb.item.desc==="");if(a!==b){return a-b}a=aaa.item.ty;b=bbb.item.ty;if(a!==b){return a-b}a=aaa.item.path;b=bbb.item.path;if(a!==b){return(a>b?+1:-1)}return 0});let nameSplit=null;if(parsedQuery.elems.length===1){const hasPath=typeof parsedQuery.elems[0].path==="undefined";nameSplit=hasPath?null:parsedQuery.elems[0].path}for(const result of result_list){if(result.dontValidate){continue}const name=result.item.name.toLowerCase(),path=result.item.path.toLowerCase(),parent=result.item.parent;if(!isType&&!validateResult(name,path,nameSplit,parent)){result.id=-1}}return transformResults(result_list)}function checkGenerics(row,elem,defaultDistance,maxEditDistance){if(row.generics.length===0){return elem.generics.length===0?defaultDistance:maxEditDistance+1}else if(row.generics.length>0&&row.generics[0].name===null){return checkGenerics(row.generics[0],elem,defaultDistance,maxEditDistance)}if(elem.generics.length>0&&row.generics.length>=elem.generics.length){const elems=new Map();for(const entry of row.generics){if(entry.name===""){if(checkGenerics(entry,elem,maxEditDistance+1,maxEditDistance)!==0){return maxEditDistance+1}continue}let currentEntryElems;if(elems.has(entry.name)){currentEntryElems=elems.get(entry.name)}else{currentEntryElems=[];elems.set(entry.name,currentEntryElems)}currentEntryElems.push(entry)}const handleGeneric=generic=>{if(!elems.has(generic.name)){return false}const matchElems=elems.get(generic.name);const matchIdx=matchElems.findIndex(tmp_elem=>{if(checkGenerics(tmp_elem,generic,0,maxEditDistance)!==0){return false}return typePassesFilter(generic.typeFilter,tmp_elem.ty)});if(matchIdx===-1){return false}matchElems.splice(matchIdx,1);if(matchElems.length===0){elems.delete(generic.name)}return true};for(const generic of elem.generics){if(generic.typeFilter!==-1&&!handleGeneric(generic)){return maxEditDistance+1}}for(const generic of elem.generics){if(generic.typeFilter===-1&&!handleGeneric(generic)){return maxEditDistance+1}}return 0}return maxEditDistance+1}function checkIfInGenerics(row,elem,maxEditDistance){let dist=maxEditDistance+1;for(const entry of row.generics){dist=Math.min(checkType(entry,elem,true,maxEditDistance),dist);if(dist===0){break}}return dist}function checkType(row,elem,literalSearch,maxEditDistance){if(row.name===null){if(row.generics.length>0){return checkIfInGenerics(row,elem,maxEditDistance)}return maxEditDistance+1}let dist;if(typePassesFilter(elem.typeFilter,row.ty)){dist=editDistance(row.name,elem.name,maxEditDistance)}else{dist=maxEditDistance+1}if(literalSearch){if(dist!==0){if(elem.generics.length===0){const checkGeneric=row.generics.length>0;if(checkGeneric&&row.generics.findIndex(tmp_elem=>tmp_elem.name===elem.name&&typePassesFilter(elem.typeFilter,tmp_elem.ty))!==-1){return 0}}return maxEditDistance+1}else if(elem.generics.length>0){return checkGenerics(row,elem,maxEditDistance+1,maxEditDistance)}return 0}else if(row.generics.length>0){if(elem.generics.length===0){if(dist===0){return 0}dist=Math.min(dist,checkIfInGenerics(row,elem,maxEditDistance));return dist}else if(dist>maxEditDistance){return checkIfInGenerics(row,elem,maxEditDistance)}else{const tmp_dist=checkGenerics(row,elem,dist,maxEditDistance);if(tmp_dist>maxEditDistance){return maxEditDistance+1}return(tmp_dist+dist)/2}}else if(elem.generics.length>0){return maxEditDistance+1}return dist}function findArg(row,elem,maxEditDistance,skipPositions){let dist=maxEditDistance+1;let position=-1;if(row&&row.type&&row.type.inputs&&row.type.inputs.length>0){let i=0;for(const input of row.type.inputs){if(skipPositions.indexOf(i)!==-1){i+=1;continue}const typeDist=checkType(input,elem,parsedQuery.literalSearch,maxEditDistance);if(typeDist===0){return{dist:0,position:i}}if(typeDist0){const ret=row.type.output;let i=0;for(const ret_ty of ret){if(skipPositions.indexOf(i)!==-1){i+=1;continue}const typeDist=checkType(ret_ty,elem,parsedQuery.literalSearch,maxEditDistance);if(typeDist===0){return{dist:0,position:i}}if(typeDistlength){return maxEditDistance+1}for(let i=0;ilength){break}let dist_total=0;let aborted=false;for(let x=0;xmaxEditDistance){aborted=true;break}dist_total+=dist}if(!aborted){ret_dist=Math.min(ret_dist,Math.round(dist_total/clength))}}return ret_dist}function typePassesFilter(filter,type){if(filter<=NO_TYPE_FILTER||filter===type)return true;const name=itemTypes[type];switch(itemTypes[filter]){case"constant":return name==="associatedconstant";case"fn":return name==="method"||name==="tymethod";case"type":return name==="primitive"||name==="associatedtype";case"trait":return name==="traitalias"}return false}function createAliasFromItem(item){return{crate:item.crate,name:item.name,path:item.path,desc:item.desc,ty:item.ty,parent:item.parent,type:item.type,is_alias:true,deprecated:item.deprecated,}}function handleAliases(ret,query,filterCrates,currentCrate){const lowerQuery=query.toLowerCase();const aliases=[];const crateAliases=[];if(filterCrates!==null){if(ALIASES.has(filterCrates)&&ALIASES.get(filterCrates).has(lowerQuery)){const query_aliases=ALIASES.get(filterCrates).get(lowerQuery);for(const alias of query_aliases){aliases.push(createAliasFromItem(searchIndex[alias]))}}}else{for(const[crate,crateAliasesIndex]of ALIASES){if(crateAliasesIndex.has(lowerQuery)){const pushTo=crate===currentCrate?crateAliases:aliases;const query_aliases=crateAliasesIndex.get(lowerQuery);for(const alias of query_aliases){pushTo.push(createAliasFromItem(searchIndex[alias]))}}}}const sortFunc=(aaa,bbb)=>{if(aaa.path{alias.alias=query;const res=buildHrefAndPath(alias);alias.displayPath=pathSplitter(res[0]);alias.fullPath=alias.displayPath+alias.name;alias.href=res[1];ret.others.unshift(alias);if(ret.others.length>MAX_RESULTS){ret.others.pop()}};aliases.forEach(pushFunc);crateAliases.forEach(pushFunc)}function addIntoResults(results,fullId,id,index,dist,path_dist,maxEditDistance){const inBounds=dist<=maxEditDistance||index!==-1;if(dist===0||(!parsedQuery.literalSearch&&inBounds)){if(results.has(fullId)){const result=results.get(fullId);if(result.dontValidate||result.dist<=dist){return}}results.set(fullId,{id:id,index:index,dontValidate:parsedQuery.literalSearch,dist:dist,path_dist:path_dist,})}}function handleSingleArg(row,pos,elem,results_others,results_in_args,results_returned,maxEditDistance){if(!row||(filterCrates!==null&&row.crate!==filterCrates)){return}let dist,index=-1,path_dist=0;const fullId=row.id;const searchWord=searchWords[pos];const in_args=findArg(row,elem,maxEditDistance,[]);const returned=checkReturned(row,elem,maxEditDistance,[]);addIntoResults(results_in_args,fullId,pos,-1,in_args.dist,0,maxEditDistance);addIntoResults(results_returned,fullId,pos,-1,returned.dist,0,maxEditDistance);if(!typePassesFilter(elem.typeFilter,row.ty)){return}const row_index=row.normalizedName.indexOf(elem.pathLast);const word_index=searchWord.indexOf(elem.pathLast);if(row_index===-1){index=word_index}else if(word_index===-1){index=row_index}else if(word_index1){path_dist=checkPath(elem.pathWithoutLast,row,maxEditDistance);if(path_dist>maxEditDistance){return}}if(parsedQuery.literalSearch){if(searchWord===elem.name){addIntoResults(results_others,fullId,pos,index,0,path_dist)}return}dist=editDistance(searchWord,elem.pathLast,maxEditDistance);if(index===-1&&dist+path_dist>maxEditDistance){return}addIntoResults(results_others,fullId,pos,index,dist,path_dist,maxEditDistance)}function handleArgs(row,pos,results,maxEditDistance){if(!row||(filterCrates!==null&&row.crate!==filterCrates)){return}let totalDist=0;let nbDist=0;function checkArgs(elems,callback){const skipPositions=[];for(const elem of elems){const{dist,position}=callback(row,elem,maxEditDistance,skipPositions);if(dist<=1){nbDist+=1;totalDist+=dist;skipPositions.push(position)}else{return false}}return true}if(!checkArgs(parsedQuery.elems,findArg)){return}if(!checkArgs(parsedQuery.returned,checkReturned)){return}if(nbDist===0){return}const dist=Math.round(totalDist/nbDist);addIntoResults(results,row.id,pos,0,dist,0,maxEditDistance)}function innerRunQuery(){let elem,i,nSearchWords,in_returned,row;let queryLen=0;for(const elem of parsedQuery.elems){queryLen+=elem.name.length}for(const elem of parsedQuery.returned){queryLen+=elem.name.length}const maxEditDistance=Math.floor(queryLen/3);if(parsedQuery.foundElems===1){if(parsedQuery.elems.length===1){elem=parsedQuery.elems[0];for(i=0,nSearchWords=searchWords.length;i0){for(i=0,nSearchWords=searchWords.length;i-1||path.indexOf(key)>-1||(parent!==undefined&&parent.name!==undefined&&parent.name.toLowerCase().indexOf(key)>-1)||editDistance(name,key,maxEditDistance)<=maxEditDistance)){return false}}return true}function nextTab(direction){const next=(searchState.currentTab+direction+3)%searchState.focusedByTab.length;searchState.focusedByTab[searchState.currentTab]=document.activeElement;printTab(next);focusSearchResult()}function focusSearchResult(){const target=searchState.focusedByTab[searchState.currentTab]||document.querySelectorAll(".search-results.active a").item(0)||document.querySelectorAll("#search-tabs button").item(searchState.currentTab);searchState.focusedByTab[searchState.currentTab]=null;if(target){target.focus()}}function buildHrefAndPath(item){let displayPath;let href;const type=itemTypes[item.ty];const name=item.name;let path=item.path;if(type==="mod"){displayPath=path+"::";href=ROOT_PATH+path.replace(/::/g,"/")+"/"+name+"/index.html"}else if(type==="import"){displayPath=item.path+"::";href=ROOT_PATH+item.path.replace(/::/g,"/")+"/index.html#reexport."+name}else if(type==="primitive"||type==="keyword"){displayPath="";href=ROOT_PATH+path.replace(/::/g,"/")+"/"+type+"."+name+".html"}else if(type==="externcrate"){displayPath="";href=ROOT_PATH+name+"/index.html"}else if(item.parent!==undefined){const myparent=item.parent;let anchor="#"+type+"."+name;const parentType=itemTypes[myparent.ty];let pageType=parentType;let pageName=myparent.name;if(parentType==="primitive"){displayPath=myparent.name+"::"}else if(type==="structfield"&&parentType==="variant"){const enumNameIdx=item.path.lastIndexOf("::");const enumName=item.path.substr(enumNameIdx+2);path=item.path.substr(0,enumNameIdx);displayPath=path+"::"+enumName+"::"+myparent.name+"::";anchor="#variant."+myparent.name+".field."+name;pageType="enum";pageName=enumName}else{displayPath=path+"::"+myparent.name+"::"}href=ROOT_PATH+path.replace(/::/g,"/")+"/"+pageType+"."+pageName+".html"+anchor}else{displayPath=item.path+"::";href=ROOT_PATH+item.path.replace(/::/g,"/")+"/"+type+"."+name+".html"}return[displayPath,href]}function pathSplitter(path){const tmp=""+path.replace(/::/g,"::");if(tmp.endsWith("")){return tmp.slice(0,tmp.length-6)}return tmp}function addTab(array,query,display){let extraClass="";if(display===true){extraClass=" active"}const output=document.createElement("div");let length=0;if(array.length>0){output.className="search-results "+extraClass;array.forEach(item=>{const name=item.name;const type=itemTypes[item.ty];length+=1;let extra="";if(type==="primitive"){extra=" (primitive type)"}else if(type==="keyword"){extra=" (keyword)"}const link=document.createElement("a");link.className="result-"+type;link.href=item.href;const resultName=document.createElement("div");resultName.className="result-name";if(item.is_alias){const alias=document.createElement("span");alias.className="alias";const bold=document.createElement("b");bold.innerText=item.alias;alias.appendChild(bold);alias.insertAdjacentHTML("beforeend"," - see ");resultName.appendChild(alias)}resultName.insertAdjacentHTML("beforeend",item.displayPath+""+name+extra+"");link.appendChild(resultName);const description=document.createElement("div");description.className="desc";description.insertAdjacentHTML("beforeend",item.desc);link.appendChild(description);output.appendChild(link)})}else if(query.error===null){output.className="search-failed"+extraClass;output.innerHTML="No results :(
"+"Try on DuckDuckGo?

"+"Or try looking in one of these:"}return[output,length]}function makeTabHeader(tabNb,text,nbElems){if(searchState.currentTab===tabNb){return""}return""}function showResults(results,go_to_first,filterCrates){const search=searchState.outputElement();if(go_to_first||(results.others.length===1&&getSettingValue("go-to-only-result")==="true")){const elem=document.createElement("a");elem.href=results.others[0].href;removeClass(elem,"active");document.body.appendChild(elem);elem.click();return}if(results.query===undefined){results.query=parseQuery(searchState.input.value)}currentResults=results.query.userQuery;const ret_others=addTab(results.others,results.query,true);const ret_in_args=addTab(results.in_args,results.query,false);const ret_returned=addTab(results.returned,results.query,false);let currentTab=searchState.currentTab;if((currentTab===0&&ret_others[1]===0)||(currentTab===1&&ret_in_args[1]===0)||(currentTab===2&&ret_returned[1]===0)){if(ret_others[1]!==0){currentTab=0}else if(ret_in_args[1]!==0){currentTab=1}else if(ret_returned[1]!==0){currentTab=2}}let crates="";const crates_list=Object.keys(rawSearchIndex);if(crates_list.length>1){crates=" in 
"}let output=`

Results${crates}

`;if(results.query.error!==null){const error=results.query.error;error.forEach((value,index)=>{value=value.split("<").join("<").split(">").join(">");if(index%2!==0){error[index]=`${value}`}else{error[index]=value}});output+=`

Query parser error: "${error.join("")}".

`;output+="
"+makeTabHeader(0,"In Names",ret_others[1])+"
";currentTab=0}else if(results.query.foundElems<=1&&results.query.returned.length===0){output+="
"+makeTabHeader(0,"In Names",ret_others[1])+makeTabHeader(1,"In Parameters",ret_in_args[1])+makeTabHeader(2,"In Return Types",ret_returned[1])+"
"}else{const signatureTabTitle=results.query.elems.length===0?"In Function Return Types":results.query.returned.length===0?"In Function Parameters":"In Function Signatures";output+="
"+makeTabHeader(0,signatureTabTitle,ret_others[1])+"
";currentTab=0}const resultsElem=document.createElement("div");resultsElem.id="results";resultsElem.appendChild(ret_others[0]);resultsElem.appendChild(ret_in_args[0]);resultsElem.appendChild(ret_returned[0]);search.innerHTML=output;const crateSearch=document.getElementById("crate-search");if(crateSearch){crateSearch.addEventListener("input",updateCrate)}search.appendChild(resultsElem);searchState.showResults(search);const elems=document.getElementById("search-tabs").childNodes;searchState.focusedByTab=[];let i=0;for(const elem of elems){const j=i;elem.onclick=()=>printTab(j);searchState.focusedByTab.push(null);i+=1}printTab(currentTab)}function search(e,forced){if(e){e.preventDefault()}const query=parseQuery(searchState.input.value.trim());let filterCrates=getFilterCrates();if(!forced&&query.userQuery===currentResults){if(query.userQuery.length>0){putBackSearch()}return}searchState.setLoadingSearch();const params=searchState.getQueryStringParams();if(filterCrates===null&¶ms["filter-crate"]!==undefined){filterCrates=params["filter-crate"]}searchState.title="Results for "+query.original+" - Rust";if(browserSupportsHistoryApi()){const newURL=buildUrl(query.original,filterCrates);if(!history.state&&!params.search){history.pushState(null,"",newURL)}else{history.replaceState(null,"",newURL)}}showResults(execQuery(query,searchWords,filterCrates,window.currentCrate),params.go_to_first,filterCrates)}function buildItemSearchTypeAll(types,lowercasePaths){const PATH_INDEX_DATA=0;const GENERICS_DATA=1;return types.map(type=>{let pathIndex,generics;if(typeof type==="number"){pathIndex=type;generics=[]}else{pathIndex=type[PATH_INDEX_DATA];generics=buildItemSearchTypeAll(type[GENERICS_DATA],lowercasePaths)}return{name:pathIndex===0?null:lowercasePaths[pathIndex-1].name,ty:pathIndex===0?null:lowercasePaths[pathIndex-1].ty,generics:generics,}})}function buildFunctionSearchType(functionSearchType,lowercasePaths){const INPUTS_DATA=0;const OUTPUT_DATA=1;if(functionSearchType===0){return null}let inputs,output;if(typeof functionSearchType[INPUTS_DATA]==="number"){const pathIndex=functionSearchType[INPUTS_DATA];inputs=[{name:pathIndex===0?null:lowercasePaths[pathIndex-1].name,ty:pathIndex===0?null:lowercasePaths[pathIndex-1].ty,generics:[],}]}else{inputs=buildItemSearchTypeAll(functionSearchType[INPUTS_DATA],lowercasePaths)}if(functionSearchType.length>1){if(typeof functionSearchType[OUTPUT_DATA]==="number"){const pathIndex=functionSearchType[OUTPUT_DATA];output=[{name:pathIndex===0?null:lowercasePaths[pathIndex-1].name,ty:pathIndex===0?null:lowercasePaths[pathIndex-1].ty,generics:[],}]}else{output=buildItemSearchTypeAll(functionSearchType[OUTPUT_DATA],lowercasePaths)}}else{output=[]}return{inputs,output,}}function buildIndex(rawSearchIndex){searchIndex=[];const searchWords=[];const charA="A".charCodeAt(0);let currentIndex=0;let id=0;for(const crate in rawSearchIndex){if(!hasOwnPropertyRustdoc(rawSearchIndex,crate)){continue}let crateSize=0;const crateCorpus=rawSearchIndex[crate];searchWords.push(crate);const crateRow={crate:crate,ty:1,name:crate,path:"",desc:crateCorpus.doc,parent:undefined,type:null,id:id,normalizedName:crate.indexOf("_")===-1?crate:crate.replace(/_/g,""),deprecated:null,};id+=1;searchIndex.push(crateRow);currentIndex+=1;const itemTypes=crateCorpus.t;const itemNames=crateCorpus.n;const itemPaths=new Map(crateCorpus.q);const itemDescs=crateCorpus.d;const itemParentIdxs=crateCorpus.i;const itemFunctionSearchTypes=crateCorpus.f;const deprecatedItems=new Set(crateCorpus.c);const paths=crateCorpus.p;const aliases=crateCorpus.a;const lowercasePaths=[];let len=paths.length;for(let i=0;i0?paths[itemParentIdxs[i]-1]:undefined,type:buildFunctionSearchType(itemFunctionSearchTypes[i],lowercasePaths),id:id,normalizedName:word.indexOf("_")===-1?word:word.replace(/_/g,""),deprecated:deprecatedItems.has(i),};id+=1;searchIndex.push(row);lastPath=row.path;crateSize+=1}if(aliases){const currentCrateAliases=new Map();ALIASES.set(crate,currentCrateAliases);for(const alias_name in aliases){if(!hasOwnPropertyRustdoc(aliases,alias_name)){continue}let currentNameAliases;if(currentCrateAliases.has(alias_name)){currentNameAliases=currentCrateAliases.get(alias_name)}else{currentNameAliases=[];currentCrateAliases.set(alias_name,currentNameAliases)}for(const local_alias of aliases[alias_name]){currentNameAliases.push(local_alias+currentIndex)}}}currentIndex+=crateSize}return searchWords}function onSearchSubmit(e){e.preventDefault();searchState.clearInputTimeout();search()}function putBackSearch(){const search_input=searchState.input;if(!searchState.input){return}if(search_input.value!==""&&!searchState.isDisplayed()){searchState.showResults();if(browserSupportsHistoryApi()){history.replaceState(null,"",buildUrl(search_input.value,getFilterCrates()))}document.title=searchState.title}}function registerSearchEvents(){const params=searchState.getQueryStringParams();if(searchState.input.value===""){searchState.input.value=params.search||""}const searchAfter500ms=()=>{searchState.clearInputTimeout();if(searchState.input.value.length===0){if(browserSupportsHistoryApi()){history.replaceState(null,window.currentCrate+" - Rust",getNakedUrl()+window.location.hash)}searchState.hideResults()}else{searchState.timeout=setTimeout(search,500)}};searchState.input.onkeyup=searchAfter500ms;searchState.input.oninput=searchAfter500ms;document.getElementsByClassName("search-form")[0].onsubmit=onSearchSubmit;searchState.input.onchange=e=>{if(e.target!==document.activeElement){return}searchState.clearInputTimeout();setTimeout(search,0)};searchState.input.onpaste=searchState.input.onchange;searchState.outputElement().addEventListener("keydown",e=>{if(e.altKey||e.ctrlKey||e.shiftKey||e.metaKey){return}if(e.which===38){const previous=document.activeElement.previousElementSibling;if(previous){previous.focus()}else{searchState.focus()}e.preventDefault()}else if(e.which===40){const next=document.activeElement.nextElementSibling;if(next){next.focus()}const rect=document.activeElement.getBoundingClientRect();if(window.innerHeight-rect.bottom{if(e.which===40){focusSearchResult();e.preventDefault()}});searchState.input.addEventListener("focus",()=>{putBackSearch()});searchState.input.addEventListener("blur",()=>{searchState.input.placeholder=searchState.input.origPlaceholder});if(browserSupportsHistoryApi()){const previousTitle=document.title;window.addEventListener("popstate",e=>{const params=searchState.getQueryStringParams();document.title=previousTitle;currentResults=null;if(params.search&¶ms.search.length>0){searchState.input.value=params.search;search(e)}else{searchState.input.value="";searchState.hideResults()}})}window.onpageshow=()=>{const qSearch=searchState.getQueryStringParams().search;if(searchState.input.value===""&&qSearch){searchState.input.value=qSearch}search()}}function updateCrate(ev){if(ev.target.value==="all crates"){const params=searchState.getQueryStringParams();const query=searchState.input.value.trim();if(!history.state&&!params.search){history.pushState(null,"",buildUrl(query,null))}else{history.replaceState(null,"",buildUrl(query,null))}}currentResults=null;search(undefined,true)}const searchWords=buildIndex(rawSearchIndex);if(typeof window!=="undefined"){registerSearchEvents();if(window.searchState.getQueryStringParams().search){search()}}if(typeof exports!=="undefined"){exports.initSearch=initSearch;exports.execQuery=execQuery;exports.parseQuery=parseQuery}return searchWords}if(typeof window!=="undefined"){window.initSearch=initSearch;if(window.searchIndex!==undefined){initSearch(window.searchIndex)}}else{initSearch({})}})() \ No newline at end of file diff --git a/doc/static.files/settings-7bfb4c59cc6bc502.css b/doc/static.files/settings-7bfb4c59cc6bc502.css deleted file mode 100644 index 79ad21581..000000000 --- a/doc/static.files/settings-7bfb4c59cc6bc502.css +++ /dev/null @@ -1,3 +0,0 @@ -.setting-line{margin:1.2em 0.6em;position:relative;}.setting-radio input,.setting-check input{margin-right:0.3em;height:1.2rem;width:1.2rem;color:inherit;border:2px solid var(--settings-input-border-color);outline:none;-webkit-appearance:none;cursor:pointer;}.setting-radio input{border-radius:50%;}.setting-check input:checked{content:url('data:image/svg+xml,\ - \ - ');}.setting-radio span,.setting-check span{padding-bottom:1px;}.setting-radio{margin-top:0.1em;margin-bottom:0.1em;min-width:3.8em;padding:0.3em;display:inline-flex;align-items:center;cursor:pointer;}.setting-radio+.setting-radio{margin-left:0.5em;}.setting-check{margin-right:20px;display:flex;align-items:center;cursor:pointer;}.setting-radio input:checked{box-shadow:inset 0 0 0 3px var(--main-background-color);background-color:var(--settings-input-color);}.setting-check input:checked{background-color:var(--settings-input-color);border-width:1px;}.setting-radio input:focus,.setting-check input:focus{box-shadow:0 0 1px 1px var(--settings-input-color);}.setting-radio input:checked:focus{box-shadow:inset 0 0 0 3px var(--main-background-color),0 0 2px 2px var(--settings-input-color);}.setting-radio input:hover,.setting-check input:hover{border-color:var(--settings-input-color) !important;} \ No newline at end of file diff --git a/doc/static.files/settings-8c76f75bfb6bd192.css b/doc/static.files/settings-8c76f75bfb6bd192.css new file mode 100644 index 000000000..5241bb861 --- /dev/null +++ b/doc/static.files/settings-8c76f75bfb6bd192.css @@ -0,0 +1,3 @@ +.setting-line{margin:1.2em 0.6em;}.setting-radio input,.setting-check input{margin-right:0.3em;height:1.2rem;width:1.2rem;border:2px solid var(--settings-input-border-color);outline:none;-webkit-appearance:none;cursor:pointer;}.setting-radio input{border-radius:50%;}.setting-radio span,.setting-check span{padding-bottom:1px;}.setting-radio{margin-top:0.1em;margin-bottom:0.1em;min-width:3.8em;padding:0.3em;display:inline-flex;align-items:center;cursor:pointer;}.setting-radio+.setting-radio{margin-left:0.5em;}.setting-check{margin-right:20px;display:flex;align-items:center;cursor:pointer;}.setting-radio input:checked{box-shadow:inset 0 0 0 3px var(--main-background-color);background-color:var(--settings-input-color);}.setting-check input:checked{background-color:var(--settings-input-color);border-width:1px;content:url('data:image/svg+xml,\ + \ + ');}.setting-radio input:focus,.setting-check input:focus{box-shadow:0 0 1px 1px var(--settings-input-color);}.setting-radio input:checked:focus{box-shadow:inset 0 0 0 3px var(--main-background-color),0 0 2px 2px var(--settings-input-color);}.setting-radio input:hover,.setting-check input:hover{border-color:var(--settings-input-color) !important;} \ No newline at end of file diff --git a/doc/static.files/settings-298e1ea74db45b39.js b/doc/static.files/settings-de11bff964e9d4e5.js similarity index 67% rename from doc/static.files/settings-298e1ea74db45b39.js rename to doc/static.files/settings-de11bff964e9d4e5.js index a426aef32..cc508a861 100644 --- a/doc/static.files/settings-298e1ea74db45b39.js +++ b/doc/static.files/settings-de11bff964e9d4e5.js @@ -1,4 +1,4 @@ -"use strict";(function(){const isSettingsPage=window.location.pathname.endsWith("/settings.html");function changeSetting(settingName,value){if(settingName==="theme"){const useSystem=value==="system preference"?"true":"false";updateLocalStorage("use-system-theme",useSystem)}updateLocalStorage(settingName,value);switch(settingName){case"theme":case"preferred-dark-theme":case"preferred-light-theme":updateTheme();updateLightAndDark();break;case"line-numbers":if(value===true){window.rustdoc_add_line_numbers_to_examples()}else{window.rustdoc_remove_line_numbers_from_examples()}break}}function handleKey(ev){if(ev.ctrlKey||ev.altKey||ev.metaKey){return}switch(getVirtualKey(ev)){case"Enter":case"Return":case"Space":ev.target.checked=!ev.target.checked;ev.preventDefault();break}}function showLightAndDark(){removeClass(document.getElementById("preferred-light-theme"),"hidden");removeClass(document.getElementById("preferred-dark-theme"),"hidden")}function hideLightAndDark(){addClass(document.getElementById("preferred-light-theme"),"hidden");addClass(document.getElementById("preferred-dark-theme"),"hidden")}function updateLightAndDark(){const useSystem=getSettingValue("use-system-theme");if(useSystem==="true"||(useSystem===null&&getSettingValue("theme")===null)){showLightAndDark()}else{hideLightAndDark()}}function setEvents(settingsElement){updateLightAndDark();onEachLazy(settingsElement.querySelectorAll("input[type=\"checkbox\"]"),toggle=>{const settingId=toggle.id;const settingValue=getSettingValue(settingId);if(settingValue!==null){toggle.checked=settingValue==="true"}toggle.onchange=function(){changeSetting(this.id,this.checked)};toggle.onkeyup=handleKey;toggle.onkeyrelease=handleKey});onEachLazy(settingsElement.querySelectorAll("input[type=\"radio\"]"),elem=>{const settingId=elem.name;let settingValue=getSettingValue(settingId);if(settingId==="theme"){const useSystem=getSettingValue("use-system-theme");if(useSystem==="true"||settingValue===null){settingValue=useSystem==="false"?"light":"system preference"}}if(settingValue!==null&&settingValue!=="null"){elem.checked=settingValue===elem.value}elem.addEventListener("change",ev=>{changeSetting(ev.target.name,ev.target.value)})})}function buildSettingsPageSections(settings){let output="";for(const setting of settings){const js_data_name=setting["js_name"];const setting_name=setting["name"];if(setting["options"]!==undefined){output+=`\ +"use strict";(function(){const isSettingsPage=window.location.pathname.endsWith("/settings.html");function changeSetting(settingName,value){if(settingName==="theme"){const useSystem=value==="system preference"?"true":"false";updateLocalStorage("use-system-theme",useSystem)}updateLocalStorage(settingName,value);switch(settingName){case"theme":case"preferred-dark-theme":case"preferred-light-theme":updateTheme();updateLightAndDark();break;case"line-numbers":if(value===true){window.rustdoc_add_line_numbers_to_examples()}else{window.rustdoc_remove_line_numbers_from_examples()}break}}function showLightAndDark(){removeClass(document.getElementById("preferred-light-theme"),"hidden");removeClass(document.getElementById("preferred-dark-theme"),"hidden")}function hideLightAndDark(){addClass(document.getElementById("preferred-light-theme"),"hidden");addClass(document.getElementById("preferred-dark-theme"),"hidden")}function updateLightAndDark(){const useSystem=getSettingValue("use-system-theme");if(useSystem==="true"||(useSystem===null&&getSettingValue("theme")===null)){showLightAndDark()}else{hideLightAndDark()}}function setEvents(settingsElement){updateLightAndDark();onEachLazy(settingsElement.querySelectorAll("input[type=\"checkbox\"]"),toggle=>{const settingId=toggle.id;const settingValue=getSettingValue(settingId);if(settingValue!==null){toggle.checked=settingValue==="true"}toggle.onchange=function(){changeSetting(this.id,this.checked)}});onEachLazy(settingsElement.querySelectorAll("input[type=\"radio\"]"),elem=>{const settingId=elem.name;let settingValue=getSettingValue(settingId);if(settingId==="theme"){const useSystem=getSettingValue("use-system-theme");if(useSystem==="true"||settingValue===null){settingValue=useSystem==="false"?"light":"system preference"}}if(settingValue!==null&&settingValue!=="null"){elem.checked=settingValue===elem.value}elem.addEventListener("change",ev=>{changeSetting(ev.target.name,ev.target.value)})})}function buildSettingsPageSections(settings){let output="";for(const setting of settings){const js_data_name=setting["js_name"];const setting_name=setting["name"];if(setting["options"]!==undefined){output+=`\
${setting_name}
`;onEach(setting["options"],option=>{const checked=option===setting["default"]?" checked":"";const full=`${js_data_name}-${option.replace(/ /g,"-")}`;output+=`\ diff --git a/doc/static.files/source-script-905937fbbdc8e9ea.js b/doc/static.files/source-script-11255107d0a65077.js similarity index 92% rename from doc/static.files/source-script-905937fbbdc8e9ea.js rename to doc/static.files/source-script-11255107d0a65077.js index fc5080998..6afbb5a26 100644 --- a/doc/static.files/source-script-905937fbbdc8e9ea.js +++ b/doc/static.files/source-script-11255107d0a65077.js @@ -1 +1 @@ -"use strict";(function(){const rootPath=document.getElementById("rustdoc-vars").attributes["data-root-path"].value;const NAME_OFFSET=0;const DIRS_OFFSET=1;const FILES_OFFSET=2;const RUSTDOC_MOBILE_BREAKPOINT=700;function closeSidebarIfMobile(){if(window.innerWidth"){addClass(document.documentElement,"source-sidebar-expanded");child.innerText="<";updateLocalStorage("source-sidebar-show","true")}else{removeClass(document.documentElement,"source-sidebar-expanded");child.innerText=">";updateLocalStorage("source-sidebar-show","false")}}function createSidebarToggle(){const sidebarToggle=document.createElement("div");sidebarToggle.id="src-sidebar-toggle";const inner=document.createElement("button");if(getCurrentValue("source-sidebar-show")==="true"){inner.innerText="<"}else{inner.innerText=">"}inner.onclick=toggleSidebar;sidebarToggle.appendChild(inner);return sidebarToggle}function createSourceSidebar(){const container=document.querySelector("nav.sidebar");const sidebarToggle=createSidebarToggle();container.insertBefore(sidebarToggle,container.firstChild);const sidebar=document.createElement("div");sidebar.id="source-sidebar";let hasFoundFile=false;const title=document.createElement("div");title.className="title";title.innerText="Files";sidebar.appendChild(title);Object.keys(sourcesIndex).forEach(key=>{sourcesIndex[key][NAME_OFFSET]=key;hasFoundFile=createDirEntry(sourcesIndex[key],sidebar,"",hasFoundFile)});container.appendChild(sidebar);const selected_elem=sidebar.getElementsByClassName("selected")[0];if(typeof selected_elem!=="undefined"){selected_elem.focus()}}const lineNumbersRegex=/^#?(\d+)(?:-(\d+))?$/;function highlightSourceLines(match){if(typeof match==="undefined"){match=window.location.hash.match(lineNumbersRegex)}if(!match){return}let from=parseInt(match[1],10);let to=from;if(typeof match[2]!=="undefined"){to=parseInt(match[2],10)}if(to{onEachLazy(e.getElementsByTagName("a"),i_e=>{removeClass(i_e,"line-highlighted")})});for(let i=from;i<=to;++i){elem=document.getElementById(i);if(!elem){break}addClass(elem,"line-highlighted")}}const handleSourceHighlight=(function(){let prev_line_id=0;const set_fragment=name=>{const x=window.scrollX,y=window.scrollY;if(browserSupportsHistoryApi()){history.replaceState(null,null,"#"+name);highlightSourceLines()}else{location.replace("#"+name)}window.scrollTo(x,y)};return ev=>{let cur_line_id=parseInt(ev.target.id,10);if(isNaN(cur_line_id)||ev.ctrlKey||ev.altKey||ev.metaKey){return}ev.preventDefault();if(ev.shiftKey&&prev_line_id){if(prev_line_id>cur_line_id){const tmp=prev_line_id;prev_line_id=cur_line_id;cur_line_id=tmp}set_fragment(prev_line_id+"-"+cur_line_id)}else{prev_line_id=cur_line_id;set_fragment(cur_line_id)}}}());window.addEventListener("hashchange",()=>{const match=window.location.hash.match(lineNumbersRegex);if(match){return highlightSourceLines(match)}});onEachLazy(document.getElementsByClassName("src-line-numbers"),el=>{el.addEventListener("click",handleSourceHighlight)});highlightSourceLines();window.createSourceSidebar=createSourceSidebar})() \ No newline at end of file +"use strict";(function(){const rootPath=document.getElementById("rustdoc-vars").attributes["data-root-path"].value;const NAME_OFFSET=0;const DIRS_OFFSET=1;const FILES_OFFSET=2;const RUSTDOC_MOBILE_BREAKPOINT=700;function closeSidebarIfMobile(){if(window.innerWidth"){addClass(document.documentElement,"source-sidebar-expanded");child.innerText="<";updateLocalStorage("source-sidebar-show","true")}else{removeClass(document.documentElement,"source-sidebar-expanded");child.innerText=">";updateLocalStorage("source-sidebar-show","false")}}function createSidebarToggle(){const sidebarToggle=document.createElement("div");sidebarToggle.id="src-sidebar-toggle";const inner=document.createElement("button");if(getCurrentValue("source-sidebar-show")==="true"){inner.innerText="<"}else{inner.innerText=">"}inner.onclick=toggleSidebar;sidebarToggle.appendChild(inner);return sidebarToggle}function createSourceSidebar(){const container=document.querySelector("nav.sidebar");const sidebarToggle=createSidebarToggle();container.insertBefore(sidebarToggle,container.firstChild);const sidebar=document.createElement("div");sidebar.id="source-sidebar";let hasFoundFile=false;const title=document.createElement("div");title.className="title";title.innerText="Files";sidebar.appendChild(title);Object.keys(sourcesIndex).forEach(key=>{sourcesIndex[key][NAME_OFFSET]=key;hasFoundFile=createDirEntry(sourcesIndex[key],sidebar,"",hasFoundFile)});container.appendChild(sidebar);const selected_elem=sidebar.getElementsByClassName("selected")[0];if(typeof selected_elem!=="undefined"){selected_elem.focus()}}const lineNumbersRegex=/^#?(\d+)(?:-(\d+))?$/;function highlightSourceLines(match){if(typeof match==="undefined"){match=window.location.hash.match(lineNumbersRegex)}if(!match){return}let from=parseInt(match[1],10);let to=from;if(typeof match[2]!=="undefined"){to=parseInt(match[2],10)}if(to{onEachLazy(e.getElementsByTagName("a"),i_e=>{removeClass(i_e,"line-highlighted")})});for(let i=from;i<=to;++i){elem=document.getElementById(i);if(!elem){break}addClass(elem,"line-highlighted")}}const handleSourceHighlight=(function(){let prev_line_id=0;const set_fragment=name=>{const x=window.scrollX,y=window.scrollY;if(browserSupportsHistoryApi()){history.replaceState(null,null,"#"+name);highlightSourceLines()}else{location.replace("#"+name)}window.scrollTo(x,y)};return ev=>{let cur_line_id=parseInt(ev.target.id,10);if(isNaN(cur_line_id)||ev.ctrlKey||ev.altKey||ev.metaKey){return}ev.preventDefault();if(ev.shiftKey&&prev_line_id){if(prev_line_id>cur_line_id){const tmp=prev_line_id;prev_line_id=cur_line_id;cur_line_id=tmp}set_fragment(prev_line_id+"-"+cur_line_id)}else{prev_line_id=cur_line_id;set_fragment(cur_line_id)}}}());window.addEventListener("hashchange",()=>{const match=window.location.hash.match(lineNumbersRegex);if(match){return highlightSourceLines(match)}});onEachLazy(document.getElementsByClassName("src-line-numbers"),el=>{el.addEventListener("click",handleSourceHighlight)});highlightSourceLines();window.createSourceSidebar=createSourceSidebar})() \ No newline at end of file diff --git a/tarpaulin-report.html b/tarpaulin-report.html index bd039b4c7..cb8577f7d 100644 --- a/tarpaulin-report.html +++ b/tarpaulin-report.html @@ -107,8 +107,8 @@
\"#,\n\t\t\t\"\",\n\t\t\t\"\"\n\t\t),\n\t\tencoded_spec, script\n\t)\n\t.unwrap();\n\n\tRedoc { html, script_hash }\n}\n","traces":[{"line":20,"address":[6763584,6764539,6764504],"length":1,"stats":{"Line":0},"fn_name":"html"},{"line":21,"address":[6763614,6763682],"length":1,"stats":{"Line":0},"fn_name":null},{"line":23,"address":[7829355,7829328],"length":1,"stats":{"Line":0},"fn_name":"{closure#0}"},{"line":24,"address":[6764645],"length":1,"stats":{"Line":0},"fn_name":null},{"line":25,"address":[7829447],"length":1,"stats":{"Line":0},"fn_name":null},{"line":26,"address":[7829481],"length":1,"stats":{"Line":0},"fn_name":null},{"line":27,"address":[7829388],"length":1,"stats":{"Line":0},"fn_name":null},{"line":31,"address":[6763752],"length":1,"stats":{"Line":0},"fn_name":null},{"line":32,"address":[7828547],"length":1,"stats":{"Line":0},"fn_name":null},{"line":33,"address":[8454047],"length":1,"stats":{"Line":0},"fn_name":null},{"line":34,"address":[6763874],"length":1,"stats":{"Line":0},"fn_name":null},{"line":36,"address":[6764047],"length":1,"stats":{"Line":0},"fn_name":null},{"line":37,"address":[6764197,6764110],"length":1,"stats":{"Line":0},"fn_name":null}],"covered":0,"coverable":13},{"path":["/","home","runner","work","gotham_restful","gotham_restful","src","auth.rs"],"content":"use crate::AuthError;\n\nuse base64::prelude::*;\nuse cookie::CookieJar;\nuse futures_util::{\n\tfuture,\n\tfuture::{FutureExt, TryFutureExt}\n};\nuse gotham::{\n\tanyhow,\n\thandler::HandlerFuture,\n\thyper::header::{HeaderMap, HeaderName, AUTHORIZATION},\n\tmiddleware::{cookie::CookieParser, Middleware, NewMiddleware},\n\tprelude::*,\n\tstate::State\n};\nuse jsonwebtoken::DecodingKey;\nuse serde::de::DeserializeOwned;\nuse std::{marker::PhantomData, panic::RefUnwindSafe, pin::Pin};\n\npub type AuthValidation = jsonwebtoken::Validation;\n\n/// The authentication status returned by the auth middleware for each request.\n#[derive(Debug, StateData)]\npub enum AuthStatus {\n\t/// The auth status is unknown. This is likely because no secret was provided\n\t/// that could be used to verify the token of the client.\n\tUnknown,\n\n\t/// The request has been performed without any kind of authentication.\n\tUnauthenticated,\n\n\t/// The request has been performed with an invalid authentication. This\n\t/// includes expired tokens. Further details can be obtained from the\n\t/// included error.\n\tInvalid(jsonwebtoken::errors::Error),\n\n\t/// The request has been performed with a valid authentication. The claims\n\t/// that were decoded from the token are attached.\n\tAuthenticated(T)\n}\n\nimpl Clone for AuthStatus\nwhere\n\tT: Clone + Send + 'static\n{\n\tfn clone(&self) -> Self {\n\t\t// TODO why is this manually implemented?\n\t\tmatch self {\n\t\t\tSelf::Unknown => Self::Unknown,\n\t\t\tSelf::Unauthenticated => Self::Unauthenticated,\n\t\t\tSelf::Invalid(err) => Self::Invalid(err.clone()),\n\t\t\tSelf::Authenticated(data) => Self::Authenticated(data.clone())\n\t\t}\n\t}\n}\n\nimpl AuthStatus {\n\tpub fn ok(self) -> Result {\n\t\tmatch self {\n\t\t\tSelf::Unknown => Err(AuthError::new(\"The authentication could not be determined\")),\n\t\t\tSelf::Unauthenticated => Err(AuthError::new(\"Missing token\")),\n\t\t\tSelf::Invalid(err) => Err(AuthError::new(format!(\"Invalid token: {err}\"))),\n\t\t\tSelf::Authenticated(data) => Ok(data)\n\t\t}\n\t}\n}\n\n/// The source of the authentication token in the request.\n#[derive(Clone, Debug, StateData)]\npub enum AuthSource {\n\t/// Take the token from a cookie with the given name.\n\tCookie(String),\n\t/// Take the token from a header with the given name.\n\tHeader(HeaderName),\n\t/// Take the token from the HTTP Authorization header. This is different from `Header(\"Authorization\")`\n\t/// as it will follow the `scheme param` format from the HTTP specification. The `scheme` will\n\t/// be discarded, so its value doesn't matter.\n\tAuthorizationHeader\n}\n\n/// This trait will help the auth middleware to determine the validity of an authentication token.\n///\n/// A very basic implementation could look like this:\n///\n/// ```\n/// # use gotham_restful::{AuthHandler, gotham::state::State};\n/// #\n/// const SECRET: &'static [u8; 32] = b\"zlBsA2QXnkmpe0QTh8uCvtAEa4j33YAc\";\n///\n/// struct CustomAuthHandler;\n/// impl AuthHandler for CustomAuthHandler {\n/// \tfn jwt_secret Option>(\n/// \t\t&self,\n/// \t\t_state: &mut State,\n/// \t\t_decode_data: F\n/// \t) -> Option> {\n/// \t\tSome(SECRET.to_vec())\n/// \t}\n/// }\n/// ```\npub trait AuthHandler {\n\t/// Return the SHA256-HMAC secret used to verify the JWT token.\n\tfn jwt_secret Option>(\n\t\t&self,\n\t\tstate: &mut State,\n\t\tdecode_data: F\n\t) -> Option>;\n}\n\n/// An [AuthHandler] returning always the same secret. See [AuthMiddleware] for a usage example.\n#[derive(Clone, Debug)]\npub struct StaticAuthHandler {\n\tsecret: Vec\n}\n\nimpl StaticAuthHandler {\n\tpub fn from_vec(secret: Vec) -> Self {\n\t\tSelf { secret }\n\t}\n\n\tpub fn from_array(secret: &[u8]) -> Self {\n\t\tSelf::from_vec(secret.to_vec())\n\t}\n}\n\nimpl AuthHandler for StaticAuthHandler {\n\tfn jwt_secret Option>(\n\t\t&self,\n\t\t_state: &mut State,\n\t\t_decode_data: F\n\t) -> Option> {\n\t\tSome(self.secret.clone())\n\t}\n}\n\n/// This is the auth middleware. To use it, first make sure you have the `auth` feature enabled. Then\n/// simply add it to your pipeline and request it inside your handler:\n///\n/// ```rust,no_run\n/// # #[macro_use] extern crate gotham_restful_derive;\n/// # use gotham::{router::builder::*, pipeline::*, state::State};\n/// # use gotham_restful::*;\n/// # use serde::{Deserialize, Serialize};\n/// #\n/// #[derive(Resource)]\n/// #[resource(read_all)]\n/// struct AuthResource;\n///\n/// #[derive(Debug, Deserialize, Clone)]\n/// struct AuthData {\n/// \tsub: String,\n/// \texp: u64\n/// }\n///\n/// #[read_all]\n/// fn read_all(auth: &AuthStatus) -> Success {\n/// \tformat!(\"{auth:?}\").into()\n/// }\n///\n/// fn main() {\n/// \tlet auth: AuthMiddleware = AuthMiddleware::new(\n/// \t\tAuthSource::AuthorizationHeader,\n/// \t\tAuthValidation::default(),\n/// \t\tStaticAuthHandler::from_array(b\"zlBsA2QXnkmpe0QTh8uCvtAEa4j33YAc\")\n/// \t);\n/// \tlet (chain, pipelines) = single_pipeline(new_pipeline().add(auth).build());\n/// \tgotham::start(\n/// \t\t\"127.0.0.1:8080\",\n/// \t\tbuild_router(chain, pipelines, |route| {\n/// \t\t\troute.resource::(\"auth\");\n/// \t\t})\n/// \t);\n/// }\n/// ```\n#[derive(Debug)]\npub struct AuthMiddleware {\n\tsource: AuthSource,\n\tvalidation: AuthValidation,\n\thandler: Handler,\n\t_data: PhantomData\n}\n\nimpl Clone for AuthMiddleware\nwhere\n\tHandler: Clone\n{\n\tfn clone(&self) -> Self {\n\t\tSelf {\n\t\t\tsource: self.source.clone(),\n\t\t\tvalidation: self.validation.clone(),\n\t\t\thandler: self.handler.clone(),\n\t\t\t_data: self._data\n\t\t}\n\t}\n}\n\nimpl AuthMiddleware\nwhere\n\tData: DeserializeOwned + Send,\n\tHandler: AuthHandler + Default\n{\n\tpub fn from_source(source: AuthSource) -> Self {\n\t\tSelf {\n\t\t\tsource,\n\t\t\tvalidation: Default::default(),\n\t\t\thandler: Default::default(),\n\t\t\t_data: Default::default()\n\t\t}\n\t}\n}\n\nimpl AuthMiddleware\nwhere\n\tData: DeserializeOwned + Send,\n\tHandler: AuthHandler\n{\n\tpub fn new(source: AuthSource, validation: AuthValidation, handler: Handler) -> Self {\n\t\tSelf {\n\t\t\tsource,\n\t\t\tvalidation,\n\t\t\thandler,\n\t\t\t_data: Default::default()\n\t\t}\n\t}\n\n\tfn auth_status(&self, state: &mut State) -> AuthStatus {\n\t\t// extract the provided token, if any\n\t\tlet token = match &self.source {\n\t\t\tAuthSource::Cookie(name) => CookieJar::try_borrow_from(&state)\n\t\t\t\t.map(|jar| jar.get(&name).map(|cookie| cookie.value().to_owned()))\n\t\t\t\t.unwrap_or_else(|| {\n\t\t\t\t\tCookieParser::from_state(&state)\n\t\t\t\t\t\t.get(&name)\n\t\t\t\t\t\t.map(|cookie| cookie.value().to_owned())\n\t\t\t\t}),\n\t\t\tAuthSource::Header(name) => HeaderMap::try_borrow_from(&state)\n\t\t\t\t.and_then(|map| map.get(name))\n\t\t\t\t.and_then(|header| header.to_str().ok())\n\t\t\t\t.map(|value| value.to_owned()),\n\t\t\tAuthSource::AuthorizationHeader => HeaderMap::try_borrow_from(&state)\n\t\t\t\t.and_then(|map| map.get(AUTHORIZATION))\n\t\t\t\t.and_then(|header| header.to_str().ok())\n\t\t\t\t.and_then(|value| value.split_whitespace().nth(1))\n\t\t\t\t.map(|value| value.to_owned())\n\t\t};\n\n\t\t// unauthed if no token\n\t\tlet token = match token {\n\t\t\tSome(token) => token,\n\t\t\tNone => return AuthStatus::Unauthenticated\n\t\t};\n\n\t\t// get the secret from the handler, possibly decoding claims ourselves\n\t\tlet secret = self.handler.jwt_secret(state, || {\n\t\t\tlet b64 = token.split('.').nth(1)?;\n\t\t\tlet raw = BASE64_URL_SAFE_NO_PAD.decode(b64).ok()?;\n\t\t\tserde_json::from_slice(&raw).ok()?\n\t\t});\n\n\t\t// unknown if no secret\n\t\tlet secret = match secret {\n\t\t\tSome(secret) => secret,\n\t\t\tNone => return AuthStatus::Unknown\n\t\t};\n\n\t\t// validate the token\n\t\tlet data: Data = match jsonwebtoken::decode(\n\t\t\t&token,\n\t\t\t&DecodingKey::from_secret(&secret),\n\t\t\t&self.validation\n\t\t) {\n\t\t\tOk(data) => data.claims,\n\t\t\tErr(e) => return AuthStatus::Invalid(e)\n\t\t};\n\n\t\t// we found a valid token\n\t\tAuthStatus::Authenticated(data)\n\t}\n}\n\nimpl Middleware for AuthMiddleware\nwhere\n\tData: DeserializeOwned + Send + 'static,\n\tHandler: AuthHandler\n{\n\tfn call(self, mut state: State, chain: Chain) -> Pin>\n\twhere\n\t\tChain: FnOnce(State) -> Pin>\n\t{\n\t\t// put the source in our state, required for e.g. openapi\n\t\tstate.put(self.source.clone());\n\n\t\t// put the status in our state\n\t\tlet status = self.auth_status(&mut state);\n\t\tstate.put(status);\n\n\t\t// call the rest of the chain\n\t\tchain(state)\n\t\t\t.and_then(|(state, res)| future::ok((state, res)))\n\t\t\t.boxed()\n\t}\n}\n\nimpl NewMiddleware for AuthMiddleware\nwhere\n\tSelf: Clone + Middleware + Sync + RefUnwindSafe\n{\n\ttype Instance = Self;\n\n\tfn new_middleware(&self) -> anyhow::Result {\n\t\tlet c: Self = self.clone();\n\t\tOk(c)\n\t}\n}\n\n#[cfg(test)]\nmod test {\n\tuse super::*;\n\tuse cookie::Cookie;\n\tuse gotham::hyper::header::COOKIE;\n\tuse jsonwebtoken::errors::ErrorKind;\n\tuse std::fmt::Debug;\n\n\t// 256-bit random string\n\tconst JWT_SECRET: &'static [u8; 32] = b\"Lyzsfnta0cdxyF0T9y6VGxp3jpgoMUuW\";\n\n\t// some known tokens\n\tconst VALID_TOKEN: &'static str = \"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJtc3JkMCIsInN1YiI6ImdvdGhhbS1yZXN0ZnVsIiwiaWF0IjoxNTc3ODM2ODAwLCJleHAiOjQxMDI0NDQ4MDB9.8h8Ax-nnykqEQ62t7CxmM3ja6NzUQ4L0MLOOzddjLKk\";\n\tconst EXPIRED_TOKEN: &'static str = \"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJtc3JkMCIsInN1YiI6ImdvdGhhbS1yZXN0ZnVsIiwiaWF0IjoxNTc3ODM2ODAwLCJleHAiOjE1Nzc4MzcxMDB9.eV1snaGLYrJ7qUoMk74OvBY3WUU9M0Je5HTU2xtX1v0\";\n\tconst INVALID_TOKEN: &'static str = \"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJtc3JkMCIsInN1YiI6ImdvdGhhbS1yZXN0ZnVsIiwiaWF0IjoxNTc3ODM2ODAwLCJleHAiOjQxMDI0NDQ4MDB9\";\n\n\t#[derive(Debug, Deserialize, PartialEq)]\n\tstruct TestData {\n\t\tiss: String,\n\t\tsub: String,\n\t\tiat: u64,\n\t\texp: u64\n\t}\n\n\timpl Default for TestData {\n\t\tfn default() -> Self {\n\t\t\tSelf {\n\t\t\t\tiss: \"msrd0\".to_owned(),\n\t\t\t\tsub: \"gotham-restful\".to_owned(),\n\t\t\t\tiat: 1577836800,\n\t\t\t\texp: 4102444800\n\t\t\t}\n\t\t}\n\t}\n\n\t#[derive(Default)]\n\tstruct NoneAuthHandler;\n\timpl AuthHandler for NoneAuthHandler {\n\t\tfn jwt_secret Option>(\n\t\t\t&self,\n\t\t\t_state: &mut State,\n\t\t\t_decode_data: F\n\t\t) -> Option> {\n\t\t\tNone\n\t\t}\n\t}\n\n\t#[test]\n\tfn test_auth_middleware_none_secret() {\n\t\tlet middleware = >::from_source(\n\t\t\tAuthSource::AuthorizationHeader\n\t\t);\n\t\tState::with_new(|mut state| {\n\t\t\tlet mut headers = HeaderMap::new();\n\t\t\theaders.insert(\n\t\t\t\tAUTHORIZATION,\n\t\t\t\tformat!(\"Bearer {VALID_TOKEN}\").parse().unwrap()\n\t\t\t);\n\t\t\tstate.put(headers);\n\t\t\tmiddleware.auth_status(&mut state);\n\t\t});\n\t}\n\n\t#[derive(Default)]\n\tstruct TestAssertingHandler;\n\timpl AuthHandler for TestAssertingHandler\n\twhere\n\t\tT: Debug + Default + PartialEq\n\t{\n\t\tfn jwt_secret Option>(\n\t\t\t&self,\n\t\t\t_state: &mut State,\n\t\t\tdecode_data: F\n\t\t) -> Option> {\n\t\t\tassert_eq!(decode_data(), Some(T::default()));\n\t\t\tSome(JWT_SECRET.to_vec())\n\t\t}\n\t}\n\n\t#[test]\n\tfn test_auth_middleware_decode_data() {\n\t\tlet middleware = >::from_source(\n\t\t\tAuthSource::AuthorizationHeader\n\t\t);\n\t\tState::with_new(|mut state| {\n\t\t\tlet mut headers = HeaderMap::new();\n\t\t\theaders.insert(\n\t\t\t\tAUTHORIZATION,\n\t\t\t\tformat!(\"Bearer {VALID_TOKEN}\").parse().unwrap()\n\t\t\t);\n\t\t\tstate.put(headers);\n\t\t\tmiddleware.auth_status(&mut state);\n\t\t});\n\t}\n\n\tfn new_middleware(source: AuthSource) -> AuthMiddleware\n\twhere\n\t\tT: DeserializeOwned + Send\n\t{\n\t\tAuthMiddleware::new(\n\t\t\tsource,\n\t\t\tDefault::default(),\n\t\t\tStaticAuthHandler::from_array(JWT_SECRET)\n\t\t)\n\t}\n\n\t#[test]\n\tfn test_auth_middleware_no_token() {\n\t\tlet middleware = new_middleware::(AuthSource::AuthorizationHeader);\n\t\tState::with_new(|mut state| {\n\t\t\tlet status = middleware.auth_status(&mut state);\n\t\t\tmatch status {\n\t\t\t\tAuthStatus::Unauthenticated => {},\n\t\t\t\t_ => panic!(\"Expected AuthStatus::Unauthenticated, got {status:?}\")\n\t\t\t};\n\t\t});\n\t}\n\n\t#[test]\n\tfn test_auth_middleware_expired_token() {\n\t\tlet middleware = new_middleware::(AuthSource::AuthorizationHeader);\n\t\tState::with_new(|mut state| {\n\t\t\tlet mut headers = HeaderMap::new();\n\t\t\theaders.insert(\n\t\t\t\tAUTHORIZATION,\n\t\t\t\tformat!(\"Bearer {EXPIRED_TOKEN}\").parse().unwrap()\n\t\t\t);\n\t\t\tstate.put(headers);\n\t\t\tlet status = middleware.auth_status(&mut state);\n\t\t\tmatch status {\n\t\t\t\tAuthStatus::Invalid(err) if *err.kind() == ErrorKind::ExpiredSignature => {},\n\t\t\t\t_ => panic!(\n\t\t\t\t\t\"Expected AuthStatus::Invalid(..) with ErrorKind::ExpiredSignature, got {status:?}\"\n\t\t\t\t)\n\t\t\t};\n\t\t});\n\t}\n\n\t#[test]\n\tfn test_auth_middleware_invalid_token() {\n\t\tlet middleware = new_middleware::(AuthSource::AuthorizationHeader);\n\t\tState::with_new(|mut state| {\n\t\t\tlet mut headers = HeaderMap::new();\n\t\t\theaders.insert(\n\t\t\t\tAUTHORIZATION,\n\t\t\t\tformat!(\"Bearer {INVALID_TOKEN}\").parse().unwrap()\n\t\t\t);\n\t\t\tstate.put(headers);\n\t\t\tlet status = middleware.auth_status(&mut state);\n\t\t\tmatch status {\n\t\t\t\tAuthStatus::Invalid(err) if *err.kind() == ErrorKind::InvalidToken => {},\n\t\t\t\t_ => panic!(\n\t\t\t\t\t\"Expected AuthStatus::Invalid(..) with ErrorKind::InvalidToken, got {status:?}\"\n\t\t\t\t)\n\t\t\t};\n\t\t});\n\t}\n\n\t#[test]\n\tfn test_auth_middleware_auth_header_token() {\n\t\tlet middleware = new_middleware::(AuthSource::AuthorizationHeader);\n\t\tState::with_new(|mut state| {\n\t\t\tlet mut headers = HeaderMap::new();\n\t\t\theaders.insert(\n\t\t\t\tAUTHORIZATION,\n\t\t\t\tformat!(\"Bearer {VALID_TOKEN}\").parse().unwrap()\n\t\t\t);\n\t\t\tstate.put(headers);\n\t\t\tlet status = middleware.auth_status(&mut state);\n\t\t\tmatch status {\n\t\t\t\tAuthStatus::Authenticated(data) => assert_eq!(data, TestData::default()),\n\t\t\t\t_ => panic!(\"Expected AuthStatus::Authenticated, got {status:?}\")\n\t\t\t};\n\t\t})\n\t}\n\n\t#[test]\n\tfn test_auth_middleware_header_token() {\n\t\tlet header_name = \"x-znoiprwmvfexju\";\n\t\tlet middleware =\n\t\t\tnew_middleware::(AuthSource::Header(HeaderName::from_static(header_name)));\n\t\tState::with_new(|mut state| {\n\t\t\tlet mut headers = HeaderMap::new();\n\t\t\theaders.insert(header_name, VALID_TOKEN.parse().unwrap());\n\t\t\tstate.put(headers);\n\t\t\tlet status = middleware.auth_status(&mut state);\n\t\t\tmatch status {\n\t\t\t\tAuthStatus::Authenticated(data) => assert_eq!(data, TestData::default()),\n\t\t\t\t_ => panic!(\"Expected AuthStatus::Authenticated, got {status:?}\")\n\t\t\t};\n\t\t})\n\t}\n\n\t#[test]\n\tfn test_auth_middleware_cookie_token() {\n\t\tlet cookie_name = \"znoiprwmvfexju\";\n\t\tlet middleware = new_middleware::(AuthSource::Cookie(cookie_name.to_owned()));\n\t\tState::with_new(|mut state| {\n\t\t\tlet mut jar = CookieJar::new();\n\t\t\tjar.add_original(Cookie::new(cookie_name, VALID_TOKEN));\n\t\t\tstate.put(jar);\n\t\t\tlet status = middleware.auth_status(&mut state);\n\t\t\tmatch status {\n\t\t\t\tAuthStatus::Authenticated(data) => assert_eq!(data, TestData::default()),\n\t\t\t\t_ => panic!(\"Expected AuthStatus::Authenticated, got {status:?}\")\n\t\t\t};\n\t\t})\n\t}\n\n\t#[test]\n\tfn test_auth_middleware_cookie_no_jar() {\n\t\tlet cookie_name = \"znoiprwmvfexju\";\n\t\tlet middleware = new_middleware::(AuthSource::Cookie(cookie_name.to_owned()));\n\t\tState::with_new(|mut state| {\n\t\t\tlet mut headers = HeaderMap::new();\n\t\t\theaders.insert(\n\t\t\t\tCOOKIE,\n\t\t\t\tformat!(\"{cookie_name}={VALID_TOKEN}\").parse().unwrap()\n\t\t\t);\n\t\t\tstate.put(headers);\n\t\t\tlet status = middleware.auth_status(&mut state);\n\t\t\tmatch status {\n\t\t\t\tAuthStatus::Authenticated(data) => assert_eq!(data, TestData::default()),\n\t\t\t\t_ => panic!(\"Expected AuthStatus::Authenticated, got {status:?}\")\n\t\t\t};\n\t\t})\n\t}\n}\n","traces":[{"line":47,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":49,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":50,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":51,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":52,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":53,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":59,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":60,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":61,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":62,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":63,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":64,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":118,"address":[5899120],"length":1,"stats":{"Line":2},"fn_name":null},{"line":122,"address":[5899152],"length":1,"stats":{"Line":2},"fn_name":null},{"line":123,"address":[5899175],"length":1,"stats":{"Line":2},"fn_name":null},{"line":128,"address":[5899216,5899261],"length":1,"stats":{"Line":1},"fn_name":"jwt_secret>"},{"line":133,"address":[5899299,5899245],"length":1,"stats":{"Line":2},"fn_name":null},{"line":188,"address":[],"length":0,"stats":{"Line":1},"fn_name":null},{"line":190,"address":[],"length":0,"stats":{"Line":1},"fn_name":null},{"line":191,"address":[],"length":0,"stats":{"Line":1},"fn_name":null},{"line":192,"address":[],"length":0,"stats":{"Line":1},"fn_name":null},{"line":193,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":203,"address":[5899600,5899829,5899344,5899573],"length":1,"stats":{"Line":2},"fn_name":null},{"line":206,"address":[5899386,5899642],"length":1,"stats":{"Line":2},"fn_name":null},{"line":207,"address":[5899439,5899695],"length":1,"stats":{"Line":2},"fn_name":null},{"line":208,"address":[5899740,5899484],"length":1,"stats":{"Line":2},"fn_name":null},{"line":218,"address":[5900119,5899856,5900158],"length":1,"stats":{"Line":2},"fn_name":null},{"line":223,"address":[5899962],"length":1,"stats":{"Line":2},"fn_name":null},{"line":227,"address":[5901315,5901568,5904106,5900176,5904316,5902917,5902707,5902960,5901525],"length":1,"stats":{"Line":4},"fn_name":null},{"line":229,"address":[5900211,5901603,5902995],"length":1,"stats":{"Line":4},"fn_name":null},{"line":230,"address":[5900314,5901706,5901665,5903148,5903057,5901756,5903098,5900273,5900364],"length":1,"stats":{"Line":3},"fn_name":null},{"line":231,"address":[5903082,5904432,5904380,5904592,5904352,5904720,5904686,5904460,5904656,5904622,5904750,5901690,5900298,5904512,5904540],"length":1,"stats":{"Line":5},"fn_name":"{closure#0}"},{"line":232,"address":[5904966,5904784,5900335,5901727,5903119,5904992,5905200,5905174,5905382],"length":1,"stats":{"Line":2},"fn_name":"{closure#1}"},{"line":233,"address":[5904811,5905114,5905322,5904906,5905019,5905227],"length":1,"stats":{"Line":2},"fn_name":null},{"line":234,"address":[5905249,5904833,5905041],"length":1,"stats":{"Line":1},"fn_name":null},{"line":235,"address":[5905438,5905472,5905536,5905502,5905408,5905566],"length":1,"stats":{"Line":2},"fn_name":"{closure#0}"},{"line":237,"address":[5903192,5901800,5900449,5900408,5901841,5903233],"length":1,"stats":{"Line":2},"fn_name":null},{"line":238,"address":[5900433,5905648,5905625,5905600,5905721,5905696,5905673,5901825,5903217],"length":1,"stats":{"Line":3},"fn_name":"{closure#2}"},{"line":239,"address":[5905744,5905801,5905792,5905753,5905840,5905849],"length":1,"stats":{"Line":2},"fn_name":"{closure#3}"},{"line":240,"address":[5905984,5905936,5906006,5905888,5905910,5905958],"length":1,"stats":{"Line":2},"fn_name":"{closure#4}"},{"line":241,"address":[5900485,5901877,5903269],"length":1,"stats":{"Line":4},"fn_name":null},{"line":242,"address":[5906032,5906112,5906041,5906121,5906192,5906201],"length":1,"stats":{"Line":8},"fn_name":"{closure#5}"},{"line":243,"address":[5906320,5906368,5906281,5906272,5906329,5906377],"length":1,"stats":{"Line":6},"fn_name":"{closure#6}"},{"line":244,"address":[5906574,5906480,5906416,5906510,5906544,5906446],"length":1,"stats":{"Line":6},"fn_name":"{closure#7}"},{"line":245,"address":[5906726,5906704,5906656,5906630,5906608,5906678],"length":1,"stats":{"Line":6},"fn_name":"{closure#8}"},{"line":249,"address":[5903319,5901927,5900535],"length":1,"stats":{"Line":4},"fn_name":null},{"line":250,"address":[5900583,5901975,5903367],"length":1,"stats":{"Line":3},"fn_name":null},{"line":251,"address":[5903350,5900566,5901958],"length":1,"stats":{"Line":2},"fn_name":null},{"line":255,"address":[5902041,5903425,5907252,5900649,5906752],"length":1,"stats":{"Line":4},"fn_name":"{closure#9}"},{"line":256,"address":[5906774,5907006],"length":1,"stats":{"Line":1},"fn_name":null},{"line":257,"address":[5906907,5907121,5907024],"length":1,"stats":{"Line":2},"fn_name":null},{"line":258,"address":[5907186,5907278,5907355,5907088],"length":1,"stats":{"Line":3},"fn_name":null},{"line":262,"address":[5900729,5902121,5903520],"length":1,"stats":{"Line":4},"fn_name":null},{"line":263,"address":[5900775,5902167,5903566],"length":1,"stats":{"Line":3},"fn_name":null},{"line":264,"address":[5900763,5903554,5902155],"length":1,"stats":{"Line":1},"fn_name":null},{"line":268,"address":[5902460,5902409,5903808,5901068,5903859,5901017],"length":1,"stats":{"Line":6},"fn_name":null},{"line":269,"address":[5900847,5902239,5903638],"length":1,"stats":{"Line":3},"fn_name":null},{"line":270,"address":[5902320,5903719,5900928],"length":1,"stats":{"Line":3},"fn_name":null},{"line":271,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":273,"address":[5903913,5901122,5902514],"length":1,"stats":{"Line":3},"fn_name":null},{"line":274,"address":[5901212,5902604,5904003],"length":1,"stats":{"Line":1},"fn_name":null},{"line":278,"address":[5902763,5904162,5901371],"length":1,"stats":{"Line":3},"fn_name":null},{"line":287,"address":[7217376,7216421,7215488,7214997,7216448,7216912,7215024,7217840,7217813,7214096,7214533,7216885,7215461,7215984,7217349,7214560,7215915,7218277,7215954],"length":1,"stats":{"Line":1},"fn_name":"call, gotham_restful::routing::MaybeMatchAcceptHeader>, (borrow_bag::handle::Handle, ())>, borrow_bag::handle::Take>, ()), (gotham::pipeline::Pipeline<(gotham_restful::auth::AuthMiddleware, ())>, ()), gotham_restful::routing::PathExtractor, gotham_restful::endpoint::NoopExtractor, fn(&mut gotham::state::State) -> gotham_restful::routing::endpoint_handler::{async_fn_env#0}>, (borrow_bag::handle::Handle, ())>, borrow_bag::handle::Take>, ()), (gotham::pipeline::Pipeline<(gotham_restful::auth::AuthMiddleware, ())>, ())>>"},{"line":292,"address":[],"length":0,"stats":{"Line":2},"fn_name":null},{"line":295,"address":[],"length":0,"stats":{"Line":1},"fn_name":null},{"line":296,"address":[],"length":0,"stats":{"Line":1},"fn_name":null},{"line":299,"address":[],"length":0,"stats":{"Line":2},"fn_name":null},{"line":300,"address":[],"length":0,"stats":{"Line":2},"fn_name":null},{"line":311,"address":[],"length":0,"stats":{"Line":1},"fn_name":null},{"line":312,"address":[],"length":0,"stats":{"Line":1},"fn_name":null},{"line":313,"address":[],"length":0,"stats":{"Line":1},"fn_name":null}],"covered":57,"coverable":71},{"path":["/","home","runner","work","gotham_restful","gotham_restful","src","cors.rs"],"content":"use gotham::{\n\thandler::HandlerFuture,\n\thelpers::http::response::create_empty_response,\n\thyper::{\n\t\theader::{\n\t\t\tHeaderMap, HeaderName, HeaderValue, ACCESS_CONTROL_ALLOW_CREDENTIALS,\n\t\t\tACCESS_CONTROL_ALLOW_HEADERS, ACCESS_CONTROL_ALLOW_METHODS,\n\t\t\tACCESS_CONTROL_ALLOW_ORIGIN, ACCESS_CONTROL_MAX_AGE, ACCESS_CONTROL_REQUEST_HEADERS,\n\t\t\tACCESS_CONTROL_REQUEST_METHOD, ORIGIN, VARY\n\t\t},\n\t\tBody, Method, Response, StatusCode\n\t},\n\tmiddleware::Middleware,\n\tpipeline::PipelineHandleChain,\n\tprelude::*,\n\trouter::{builder::ExtendRouteMatcher, route::matcher::AccessControlRequestMethodMatcher},\n\tstate::State\n};\nuse std::{panic::RefUnwindSafe, pin::Pin};\n\n/// Specify the allowed origins of the request. It is up to the browser to check the validity of the\n/// origin. This, when sent to the browser, will indicate whether or not the request's origin was\n/// allowed to make the request.\n#[derive(Clone, Debug)]\npub enum Origin {\n\t/// Do not send any `Access-Control-Allow-Origin` headers.\n\tNone,\n\t/// Send `Access-Control-Allow-Origin: *`. Note that browser will not send credentials.\n\tStar,\n\t/// Set the `Access-Control-Allow-Origin` header to a single origin.\n\tSingle(String),\n\t/// Copy the `Origin` header into the `Access-Control-Allow-Origin` header.\n\tCopy\n}\n\nimpl Default for Origin {\n\tfn default() -> Self {\n\t\tSelf::None\n\t}\n}\n\nimpl Origin {\n\t/// Get the header value for the `Access-Control-Allow-Origin` header.\n\tfn header_value(&self, state: &State) -> Option {\n\t\tmatch self {\n\t\t\tSelf::None => None,\n\t\t\tSelf::Star => Some(\"*\".parse().unwrap()),\n\t\t\tSelf::Single(origin) => Some(origin.parse().unwrap()),\n\t\t\tSelf::Copy => {\n\t\t\t\tlet headers = HeaderMap::borrow_from(state);\n\t\t\t\theaders.get(ORIGIN).map(Clone::clone)\n\t\t\t}\n\t\t}\n\t}\n\n\t/// Returns true if the `Vary` header has to include `Origin`.\n\tfn varies(&self) -> bool {\n\t\tmatches!(self, Self::Copy)\n\t}\n}\n\n/// Specify the allowed headers of the request. It is up to the browser to check that only the allowed\n/// headers are sent with the request.\n#[derive(Clone, Debug)]\npub enum Headers {\n\t/// Do not send any `Access-Control-Allow-Headers` headers.\n\tNone,\n\t/// Set the `Access-Control-Allow-Headers` header to the following header list. If empty, this\n\t/// is treated as if it was [None].\n\tList(Vec),\n\t/// Copy the `Access-Control-Request-Headers` header into the `Access-Control-Allow-Header`\n\t/// header.\n\tCopy\n}\n\nimpl Default for Headers {\n\tfn default() -> Self {\n\t\tSelf::None\n\t}\n}\n\nimpl Headers {\n\t/// Get the header value for the `Access-Control-Allow-Headers` header.\n\tfn header_value(&self, state: &State) -> Option {\n\t\tmatch self {\n\t\t\tSelf::None => None,\n\t\t\tSelf::List(list) => Some(list.join(\",\").parse().unwrap()),\n\t\t\tSelf::Copy => {\n\t\t\t\tlet headers = HeaderMap::borrow_from(state);\n\t\t\t\theaders\n\t\t\t\t\t.get(ACCESS_CONTROL_REQUEST_HEADERS)\n\t\t\t\t\t.map(Clone::clone)\n\t\t\t}\n\t\t}\n\t}\n\n\t/// Returns true if the `Vary` header has to include `Origin`.\n\tfn varies(&self) -> bool {\n\t\tmatches!(self, Self::Copy)\n\t}\n}\n\n/// This is the configuration that the CORS handler will follow. Its default configuration is basically\n/// not to touch any responses, resulting in the browser's default behaviour.\n///\n/// To change settings, you need to put this type into gotham's [State]:\n///\n/// ```rust,no_run\n/// # use gotham::{router::builder::*, pipeline::*, state::State};\n/// # use gotham_restful::{*, cors::Origin};\n/// # #[cfg_attr(feature = \"cargo-clippy\", allow(clippy::needless_doctest_main))]\n/// fn main() {\n/// \tlet cors = CorsConfig {\n/// \t\torigin: Origin::Star,\n/// \t\t..Default::default()\n/// \t};\n/// \tlet (chain, pipelines) = single_pipeline(new_pipeline().add(cors).build());\n/// \tgotham::start(\n/// \t\t\"127.0.0.1:8080\",\n/// \t\tbuild_router(chain, pipelines, |route| {\n/// \t\t\t// your routing logic\n/// \t\t})\n/// \t);\n/// }\n/// ```\n///\n/// This easy approach allows you to have one global cors configuration. If you prefer to have separate\n/// configurations for different scopes, you need to register the middleware inside your routing logic:\n///\n/// ```rust,no_run\n/// # use gotham::{router::builder::*, pipeline::*, state::State};\n/// # use gotham_restful::{*, cors::Origin};\n/// let pipelines = new_pipeline_set();\n///\n/// // The first cors configuration\n/// let cors_a = CorsConfig {\n/// \torigin: Origin::Star,\n/// \t..Default::default()\n/// };\n/// let (pipelines, chain_a) = pipelines.add(new_pipeline().add(cors_a).build());\n///\n/// // The second cors configuration\n/// let cors_b = CorsConfig {\n/// \torigin: Origin::Copy,\n/// \t..Default::default()\n/// };\n/// let (pipelines, chain_b) = pipelines.add(new_pipeline().add(cors_b).build());\n///\n/// let pipeline_set = finalize_pipeline_set(pipelines);\n/// gotham::start(\n/// \t\"127.0.0.1:8080\",\n/// \tbuild_router((), pipeline_set, |route| {\n/// \t\t// routing without any cors config\n/// \t\troute.with_pipeline_chain((chain_a, ()), |route| {\n/// \t\t\t// routing with cors config a\n/// \t\t});\n/// \t\troute.with_pipeline_chain((chain_b, ()), |route| {\n/// \t\t\t// routing with cors config b\n/// \t\t});\n/// \t})\n/// );\n/// ```\n#[derive(Clone, Debug, Default, NewMiddleware, StateData)]\npub struct CorsConfig {\n\t/// The allowed origins.\n\tpub origin: Origin,\n\t/// The allowed headers.\n\tpub headers: Headers,\n\t/// The amount of seconds that the preflight request can be cached.\n\tpub max_age: u64,\n\t/// Whether or not the request may be made with supplying credentials.\n\tpub credentials: bool\n}\n\nimpl Middleware for CorsConfig {\n\tfn call(self, mut state: State, chain: Chain) -> Pin>\n\twhere\n\t\tChain: FnOnce(State) -> Pin>\n\t{\n\t\tstate.put(self);\n\t\tchain(state)\n\t}\n}\n\n/// Handle CORS for a non-preflight request. This means manipulating the `res` HTTP headers so that\n/// the response is aligned with the `state`'s [CorsConfig].\n///\n/// If you are using the [Resource](crate::Resource) type (which is the recommended way), you'll never\n/// have to call this method. However, if you are writing your own handler method, you might want to\n/// call this after your request to add the required CORS headers.\n///\n/// For further information on CORS, read .\npub fn handle_cors(state: &State, res: &mut Response) {\n\tlet config = CorsConfig::try_borrow_from(state);\n\tif let Some(cfg) = config {\n\t\tlet headers = res.headers_mut();\n\n\t\t// non-preflight requests require the Access-Control-Allow-Origin header\n\t\tif let Some(header) = cfg.origin.header_value(state) {\n\t\t\theaders.insert(ACCESS_CONTROL_ALLOW_ORIGIN, header);\n\t\t}\n\n\t\t// if the origin is copied over, we should tell the browser by specifying the Vary header\n\t\tif cfg.origin.varies() {\n\t\t\tlet vary = headers\n\t\t\t\t.get(VARY)\n\t\t\t\t.map(|vary| format!(\"{},origin\", vary.to_str().unwrap()));\n\t\t\theaders.insert(VARY, vary.as_deref().unwrap_or(\"origin\").parse().unwrap());\n\t\t}\n\n\t\t// if we allow credentials, tell the browser\n\t\tif cfg.credentials {\n\t\t\theaders.insert(\n\t\t\t\tACCESS_CONTROL_ALLOW_CREDENTIALS,\n\t\t\t\tHeaderValue::from_static(\"true\")\n\t\t\t);\n\t\t}\n\t}\n}\n\n/// Add CORS routing for your path. This is required for handling preflight requests.\n///\n/// Example:\n///\n/// ```rust,no_run\n/// # use gotham::{hyper::{Body, Method, Response}, router::builder::*};\n/// # use gotham_restful::*;\n/// build_simple_router(|router| {\n/// \t// The handler that needs preflight handling\n/// \trouter.post(\"/foo\").to(|state| {\n/// \t\tlet mut res: Response = unimplemented!();\n/// \t\thandle_cors(&state, &mut res);\n/// \t\t(state, res)\n/// \t});\n/// \t// Add preflight handling\n/// \trouter.cors(\"/foo\", Method::POST);\n/// });\n/// ```\npub trait CorsRoute\nwhere\n\tC: PipelineHandleChain

+ Copy + Send + Sync + 'static,\n\tP: RefUnwindSafe + Send + Sync + 'static\n{\n\t/// Handle a preflight request on `path` for `method`. To configure the behaviour, use\n\t/// [CorsConfig].\n\tfn cors(&mut self, path: &str, method: Method);\n}\n\npub(crate) fn cors_preflight_handler(state: State) -> (State, Response) {\n\tlet config = CorsConfig::try_borrow_from(&state);\n\n\t// prepare the response\n\tlet mut res = create_empty_response(&state, StatusCode::NO_CONTENT);\n\tlet headers = res.headers_mut();\n\tlet mut vary: Vec = Vec::new();\n\n\t// copy the request method over to the response\n\tlet method = HeaderMap::borrow_from(&state)\n\t\t.get(ACCESS_CONTROL_REQUEST_METHOD)\n\t\t.unwrap()\n\t\t.clone();\n\theaders.insert(ACCESS_CONTROL_ALLOW_METHODS, method);\n\tvary.push(ACCESS_CONTROL_REQUEST_METHOD);\n\n\tif let Some(cfg) = config {\n\t\t// if we allow any headers, copy them over\n\t\tif let Some(header) = cfg.headers.header_value(&state) {\n\t\t\theaders.insert(ACCESS_CONTROL_ALLOW_HEADERS, header);\n\t\t}\n\n\t\t// if the headers are copied over, we should tell the browser by specifying the Vary header\n\t\tif cfg.headers.varies() {\n\t\t\tvary.push(ACCESS_CONTROL_REQUEST_HEADERS);\n\t\t}\n\n\t\t// set the max age for the preflight cache\n\t\tif let Some(age) = config.map(|cfg| cfg.max_age) {\n\t\t\theaders.insert(ACCESS_CONTROL_MAX_AGE, age.into());\n\t\t}\n\t}\n\n\t// make sure the browser knows that this request was based on the method\n\theaders.insert(VARY, vary.join(\",\").parse().unwrap());\n\n\thandle_cors(&state, &mut res);\n\t(state, res)\n}\n\nimpl CorsRoute for D\nwhere\n\tD: DrawRoutes,\n\tC: PipelineHandleChain

+ Copy + Send + Sync + 'static,\n\tP: RefUnwindSafe + Send + Sync + 'static\n{\n\tfn cors(&mut self, path: &str, method: Method) {\n\t\tlet matcher = AccessControlRequestMethodMatcher::new(method);\n\t\tself.options(path)\n\t\t\t.extend_route_matcher(matcher)\n\t\t\t.to(cors_preflight_handler);\n\t}\n}\n","traces":[{"line":37,"address":[5946032],"length":1,"stats":{"Line":1},"fn_name":"default"},{"line":38,"address":[5946035],"length":1,"stats":{"Line":1},"fn_name":null},{"line":44,"address":[5946048],"length":1,"stats":{"Line":2},"fn_name":null},{"line":45,"address":[5946090],"length":1,"stats":{"Line":2},"fn_name":null},{"line":46,"address":[5946126],"length":1,"stats":{"Line":2},"fn_name":null},{"line":47,"address":[5946135],"length":1,"stats":{"Line":1},"fn_name":null},{"line":48,"address":[5946211],"length":1,"stats":{"Line":1},"fn_name":null},{"line":50,"address":[5946297],"length":1,"stats":{"Line":1},"fn_name":null},{"line":51,"address":[5946314],"length":1,"stats":{"Line":1},"fn_name":null},{"line":57,"address":[5946416],"length":1,"stats":{"Line":2},"fn_name":null},{"line":58,"address":[5946421],"length":1,"stats":{"Line":2},"fn_name":null},{"line":77,"address":[5946464],"length":1,"stats":{"Line":1},"fn_name":"default"},{"line":78,"address":[5946467],"length":1,"stats":{"Line":1},"fn_name":null},{"line":84,"address":[5946480,5946904],"length":1,"stats":{"Line":2},"fn_name":null},{"line":85,"address":[5946523],"length":1,"stats":{"Line":2},"fn_name":null},{"line":86,"address":[5946560],"length":1,"stats":{"Line":1},"fn_name":null},{"line":87,"address":[5946574,5946770],"length":1,"stats":{"Line":1},"fn_name":null},{"line":89,"address":[5946653],"length":1,"stats":{"Line":1},"fn_name":null},{"line":90,"address":[5946730],"length":1,"stats":{"Line":1},"fn_name":null},{"line":91,"address":[5946670],"length":1,"stats":{"Line":1},"fn_name":null},{"line":98,"address":[5946944],"length":1,"stats":{"Line":2},"fn_name":null},{"line":99,"address":[5946949],"length":1,"stats":{"Line":2},"fn_name":null},{"line":176,"address":[6311809,6311585,6311152,6311361,6311333,6311376,6311600,6311557,6311781],"length":1,"stats":{"Line":3},"fn_name":"call, gotham_restful::routing::MaybeMatchAcceptHeader>, (borrow_bag::handle::Handle, borrow_bag::handle::Take>, ()), (gotham::pipeline::Pipeline<(gotham_restful::cors::CorsConfig, ())>, ()), gotham_restful::endpoint::NoopExtractor, gotham_restful::endpoint::NoopExtractor, fn(&mut gotham::state::State) -> gotham_restful::routing::endpoint_handler::{async_fn_env#0}>, (borrow_bag::handle::Handle, borrow_bag::handle::Take>, ()), (gotham::pipeline::Pipeline<(gotham_restful::cors::CorsConfig, ())>, ())>>"},{"line":180,"address":[],"length":0,"stats":{"Line":3},"fn_name":null},{"line":181,"address":[],"length":0,"stats":{"Line":8},"fn_name":null},{"line":193,"address":[5947860,5946992,5947808],"length":1,"stats":{"Line":6},"fn_name":"handle_cors"},{"line":194,"address":[5947025],"length":1,"stats":{"Line":6},"fn_name":null},{"line":195,"address":[5947059],"length":1,"stats":{"Line":6},"fn_name":null},{"line":196,"address":[5947108],"length":1,"stats":{"Line":2},"fn_name":null},{"line":199,"address":[5947137,5947190],"length":1,"stats":{"Line":3},"fn_name":null},{"line":200,"address":[5947223],"length":1,"stats":{"Line":1},"fn_name":null},{"line":204,"address":[5947369],"length":1,"stats":{"Line":2},"fn_name":null},{"line":205,"address":[5947448],"length":1,"stats":{"Line":1},"fn_name":null},{"line":206,"address":[5947418],"length":1,"stats":{"Line":1},"fn_name":null},{"line":207,"address":[5948110,5948080],"length":1,"stats":{"Line":2},"fn_name":"{closure#0}"},{"line":208,"address":[5947491,5947789],"length":1,"stats":{"Line":1},"fn_name":null},{"line":212,"address":[5947398],"length":1,"stats":{"Line":2},"fn_name":null},{"line":213,"address":[5947979],"length":1,"stats":{"Line":1},"fn_name":null},{"line":214,"address":[5947875],"length":1,"stats":{"Line":1},"fn_name":null},{"line":215,"address":[5947913],"length":1,"stats":{"Line":1},"fn_name":null},{"line":249,"address":[5949620,5950219,5948240],"length":1,"stats":{"Line":1},"fn_name":"cors_preflight_handler"},{"line":250,"address":[5948276,5948393],"length":1,"stats":{"Line":3},"fn_name":null},{"line":253,"address":[5948401],"length":1,"stats":{"Line":2},"fn_name":null},{"line":254,"address":[5948503,5948433],"length":1,"stats":{"Line":3},"fn_name":null},{"line":255,"address":[5948519],"length":1,"stats":{"Line":1},"fn_name":null},{"line":258,"address":[5948619,5948531],"length":1,"stats":{"Line":4},"fn_name":null},{"line":259,"address":[5948589],"length":1,"stats":{"Line":2},"fn_name":null},{"line":262,"address":[5948692],"length":1,"stats":{"Line":2},"fn_name":null},{"line":263,"address":[5948824],"length":1,"stats":{"Line":2},"fn_name":null},{"line":265,"address":[5948877],"length":1,"stats":{"Line":2},"fn_name":null},{"line":267,"address":[5949017,5948932],"length":1,"stats":{"Line":3},"fn_name":null},{"line":268,"address":[5949111,5949203],"length":1,"stats":{"Line":2},"fn_name":null},{"line":272,"address":[5949245,5949283],"length":1,"stats":{"Line":3},"fn_name":null},{"line":273,"address":[5949314],"length":1,"stats":{"Line":1},"fn_name":null},{"line":277,"address":[5950256,5949379,5950261,5949289],"length":1,"stats":{"Line":7},"fn_name":"{closure#0}"},{"line":278,"address":[5949426],"length":1,"stats":{"Line":2},"fn_name":null},{"line":283,"address":[5948951,5949631],"length":1,"stats":{"Line":2},"fn_name":null},{"line":285,"address":[5950012],"length":1,"stats":{"Line":2},"fn_name":null},{"line":286,"address":[5950024],"length":1,"stats":{"Line":1},"fn_name":null},{"line":295,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":296,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":297,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":298,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":299,"address":[],"length":0,"stats":{"Line":0},"fn_name":null}],"covered":59,"coverable":64},{"path":["/","home","runner","work","gotham_restful","gotham_restful","src","endpoint.rs"],"content":"use crate::{IntoResponse, RequestBody};\nuse futures_util::future::BoxFuture;\nuse gotham::{\n\textractor::{PathExtractor, QueryStringExtractor},\n\thyper::{Body, Method, Response},\n\trouter::response::StaticResponseExtender,\n\tstate::{State, StateData}\n};\n#[cfg(feature = \"openapi\")]\nuse openapi_type::{OpenapiType, Visitor};\nuse serde::{Deserialize, Deserializer};\nuse std::borrow::Cow;\n\n/// A no-op extractor that can be used as a default type for [Endpoint::Placeholders] and\n/// [Endpoint::Params].\n#[derive(Debug, Clone, Copy)]\npub struct NoopExtractor;\n\nimpl<'de> Deserialize<'de> for NoopExtractor {\n\tfn deserialize>(_: D) -> Result {\n\t\tOk(Self)\n\t}\n}\n\n#[cfg(feature = \"openapi\")]\nimpl OpenapiType for NoopExtractor {\n\tfn visit_type(visitor: &mut V) {\n\t\twarn!(\n\t\t\t\"You're asking for the OpenAPI Schema for gotham_restful::NoopExtractor. This is probably not what you want.\"\n\t\t);\n\t\tvisitor.visit_unit();\n\t}\n}\n\nimpl StateData for NoopExtractor {}\n\nimpl StaticResponseExtender for NoopExtractor {\n\ttype ResBody = Body;\n\tfn extend(_: &mut State, _: &mut Response) {}\n}\n\n// TODO: Specify default types once https://github.com/rust-lang/rust/issues/29661 lands.\n#[_private_openapi_trait(EndpointWithSchema)]\npub trait Endpoint {\n\t/// The HTTP Verb of this endpoint.\n\tfn http_method() -> Method;\n\t/// The URI that this endpoint listens on in gotham's format.\n\tfn uri() -> Cow<'static, str>;\n\n\t/// The verb used for generating an operation id if [Self::operation_id] returns [None].\n\t/// For example `read`, `read_all`, `create`, `update` etc.\n\t#[openapi_only]\n\tfn operation_verb() -> Option<&'static str>;\n\n\t/// The output type that provides the response.\n\t#[openapi_bound(Output: crate::ResponseSchema)]\n\ttype Output: IntoResponse + Send;\n\n\t/// Returns `true` _iff_ the URI contains placeholders. `false` by default.\n\tfn has_placeholders() -> bool {\n\t\tfalse\n\t}\n\t/// The type that parses the URI placeholders. Use [NoopExtractor] if `has_placeholders()`\n\t/// returns `false`.\n\t#[openapi_bound(Placeholders: OpenapiType)]\n\ttype Placeholders: PathExtractor + Clone + Sync;\n\n\t/// Returns `true` _iff_ the request parameters should be parsed. `false` by default.\n\tfn needs_params() -> bool {\n\t\tfalse\n\t}\n\t/// The type that parses the request parameters. Use [NoopExtractor] if `needs_params()`\n\t/// returns `false`.\n\t#[openapi_bound(Params: OpenapiType)]\n\ttype Params: QueryStringExtractor + Clone + Sync;\n\n\t/// Returns `true` _iff_ the request body should be parsed. `false` by default.\n\tfn needs_body() -> bool {\n\t\tfalse\n\t}\n\t/// The type to parse the body into. Use `()` if `needs_body()` returns `false`.\n\ttype Body: RequestBody + Send;\n\n\t/// Returns `true` if the request wants to know the auth status of the client. `false` by default.\n\tfn wants_auth() -> bool {\n\t\tfalse\n\t}\n\n\t/// Replace the automatically generated operation id with a custom one. Only relevant for the\n\t/// OpenAPI Specification.\n\t#[openapi_only]\n\tfn operation_id() -> Option {\n\t\tNone\n\t}\n\n\t/// Add a description to the openapi specification. Usually taken from the rustdoc comment\n\t/// when using the proc macro.\n\t#[openapi_only]\n\tfn description() -> Option {\n\t\tNone\n\t}\n\n\t/// The handler for this endpoint.\n\tfn handle(\n\t\tstate: &mut State,\n\t\tplaceholders: Self::Placeholders,\n\t\tparams: Self::Params,\n\t\tbody: Option\n\t) -> BoxFuture<'_, Self::Output>;\n}\n\n#[cfg(feature = \"openapi\")]\nimpl Endpoint for E {\n\tfn http_method() -> Method {\n\t\tE::http_method()\n\t}\n\tfn uri() -> Cow<'static, str> {\n\t\tE::uri()\n\t}\n\n\ttype Output = E::Output;\n\n\tfn has_placeholders() -> bool {\n\t\tE::has_placeholders()\n\t}\n\ttype Placeholders = E::Placeholders;\n\n\tfn needs_params() -> bool {\n\t\tE::needs_params()\n\t}\n\ttype Params = E::Params;\n\n\tfn needs_body() -> bool {\n\t\tE::needs_body()\n\t}\n\ttype Body = E::Body;\n\n\tfn wants_auth() -> bool {\n\t\tE::wants_auth()\n\t}\n\n\tfn handle<'a>(\n\t\tstate: &'a mut State,\n\t\tplaceholders: Self::Placeholders,\n\t\tparams: Self::Params,\n\t\tbody: Option\n\t) -> BoxFuture<'a, Self::Output> {\n\t\tE::handle(state, placeholders, params, body)\n\t}\n}\n","traces":[{"line":20,"address":[],"length":0,"stats":{"Line":10},"fn_name":null},{"line":21,"address":[7035875,7035849],"length":1,"stats":{"Line":10},"fn_name":null},{"line":27,"address":[8193104],"length":1,"stats":{"Line":0},"fn_name":"visit_type"},{"line":28,"address":[8193178,8193118,8193228],"length":1,"stats":{"Line":0},"fn_name":null},{"line":31,"address":[8193217],"length":1,"stats":{"Line":0},"fn_name":null},{"line":39,"address":[8193306,8193296],"length":1,"stats":{"Line":0},"fn_name":"extend"},{"line":60,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":61,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":69,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":70,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":78,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":79,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":85,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":86,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":92,"address":[],"length":0,"stats":{"Line":6},"fn_name":null},{"line":93,"address":[],"length":0,"stats":{"Line":6},"fn_name":null},{"line":99,"address":[],"length":0,"stats":{"Line":7},"fn_name":null},{"line":100,"address":[],"length":0,"stats":{"Line":7},"fn_name":null},{"line":114,"address":[6653696,6653568,6653632,6653664,6653600,6653536,6653504],"length":1,"stats":{"Line":28},"fn_name":"http_method"},{"line":115,"address":[6653512,6653608,6653544,6653576,6653640,6653672,6653704],"length":1,"stats":{"Line":28},"fn_name":null},{"line":117,"address":[6653792,6653920,6653888,6653760,6653728,6653856,6653824],"length":1,"stats":{"Line":28},"fn_name":"uri"},{"line":118,"address":[],"length":0,"stats":{"Line":28},"fn_name":null},{"line":123,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":124,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":128,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":129,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":133,"address":[],"length":0,"stats":{"Line":21},"fn_name":null},{"line":134,"address":[],"length":0,"stats":{"Line":21},"fn_name":null},{"line":138,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":139,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":142,"address":[6654208,6654064,6654160,6654000,6654032,6654112,6653952],"length":1,"stats":{"Line":21},"fn_name":"handle"},{"line":148,"address":[],"length":0,"stats":{"Line":21},"fn_name":null}],"covered":14,"coverable":32},{"path":["/","home","runner","work","gotham_restful","gotham_restful","src","lib.rs"],"content":"#![warn(missing_debug_implementations, rust_2018_idioms, unreachable_pub)]\n#![forbid(unsafe_code)]\n// deny warnings in CI\n#![cfg_attr(gotham_restful_deny_warnings, deny(warnings))]\n// clippy doesn't like our code style\n#![cfg_attr(feature = \"cargo-clippy\", allow(clippy::tabs_in_doc_comments))]\n// intra-doc links only fully work when OpenAPI is enabled\n#![cfg_attr(feature = \"openapi\", deny(rustdoc::broken_intra_doc_links))]\n#![cfg_attr(not(feature = \"openapi\"), allow(rustdoc::broken_intra_doc_links))]\n\n//! This crate is an extension to the popular [gotham web framework][gotham] for Rust. It allows you to\n//! create resources with assigned endpoints that aim to be a more convenient way of creating handlers\n//! for requests.\n//!\n//! # Features\n//!\n//! - Automatically parse **JSON** request and produce response bodies\n//! - Allow using **raw** request and response bodies\n//! - Convenient **macros** to create responses that can be registered with gotham's router\n//! - Auto-Generate an **OpenAPI** specification for your API\n//! - Manage **CORS** headers so you don't have to\n//! - Manage **Authentication** with JWT\n//! - Integrate diesel connection pools for easy **database** integration\n//!\n//! # Safety\n//!\n//! This crate is just as safe as you'd expect from anything written in safe Rust - and\n//! `#![forbid(unsafe_code)]` ensures that no unsafe was used.\n//!\n//! # Endpoints\n//!\n//! There are a set of pre-defined endpoints that should cover the majority of REST APIs. However,\n//! it is also possible to define your own endpoints.\n//!\n//! ## Pre-defined Endpoints\n//!\n//! Assuming you assign `/foobar` to your resource, the following pre-defined endpoints exist:\n//!\n//! | Endpoint Name | Required Arguments | HTTP Verb | HTTP Path |\n//! | ------------- | ------------------ | --------- | -------------- |\n//! | read_all | | GET | /foobar |\n//! | read | id | GET | /foobar/:id |\n//! | search | query | GET | /foobar/search |\n//! | create | body | POST | /foobar |\n//! | update_all | body | PUT | /foobar |\n//! | update | id, body | PUT | /foobar/:id |\n//! | delete_all | | DELETE | /foobar |\n//! | delete | id | DELETE | /foobar/:id |\n//!\n//! Each of those endpoints has a macro that creates the neccessary boilerplate for the Resource. A\n//! simple example looks like this:\n//!\n//! ```rust,no_run\n//! # #[macro_use] extern crate gotham_restful_derive;\n//! # use gotham::router::builder::*;\n//! # use gotham_restful::*;\n//! # use serde::{Deserialize, Serialize};\n//! /// Our RESTful resource.\n//! #[derive(Resource)]\n//! #[resource(read)]\n//! struct FooResource;\n//!\n//! /// The return type of the foo read endpoint.\n//! #[derive(Serialize)]\n//! # #[cfg_attr(feature = \"openapi\", derive(openapi_type::OpenapiType))]\n//! struct Foo {\n//! \tid: u64\n//! }\n//!\n//! /// The foo read endpoint.\n//! #[read]\n//! fn read(id: u64) -> Success {\n//! \tFoo { id }.into()\n//! }\n//! # fn main() {\n//! # \tgotham::start(\"127.0.0.1:8080\", build_simple_router(|route| {\n//! # \t\troute.resource::(\"foo\");\n//! # \t})).expect(\"Failed to start gotham\");\n//! # }\n//! ```\n//!\n//! ## Custom Endpoints\n//!\n//! Defining custom endpoints is done with the `#[endpoint]` macro. The syntax is similar to that\n//! of the pre-defined endpoints, but you need to give it more context:\n//!\n//! ```rust,no_run\n//! # #[macro_use] extern crate gotham_restful_derive;\n//! # use gotham::{router::build_simple_router, prelude::*};\n//! # use gotham_restful::*;\n//! # use serde::{Deserialize, Serialize};\n//! use gotham_restful::gotham::hyper::Method;\n//!\n//! #[derive(Resource)]\n//! #[resource(custom_endpoint)]\n//! struct CustomResource;\n//!\n//! /// This type is used to parse path parameters.\n//! #[derive(Clone, Deserialize, StateData, StaticResponseExtender)]\n//! # #[cfg_attr(feature = \"openapi\", derive(openapi_type::OpenapiType))]\n//! struct CustomPath {\n//! \tname: String\n//! }\n//!\n//! #[endpoint(\n//! \turi = \"custom/:name/read\",\n//! \tmethod = \"Method::GET\",\n//! \tparams = false,\n//! \tbody = false\n//! )]\n//! fn custom_endpoint(path: CustomPath) -> Success {\n//! \tpath.name.into()\n//! }\n//! # fn main() {\n//! # \tgotham::start(\"127.0.0.1:8080\", build_simple_router(|route| {\n//! # \t\troute.resource::(\"custom\");\n//! # \t})).expect(\"Failed to start gotham\");\n//! # }\n//! ```\n//!\n//! # Arguments\n//!\n//! Some endpoints require arguments. Those should be\n//! * **id** Should be a deserializable json-primitive like [`i64`] or [`String`].\n//! * **body** Should be any deserializable object, or any type implementing [`RequestBody`].\n//! * **query** Should be any deserializable object whose variables are json-primitives. It will\n//! however not be parsed from json, but from HTTP GET parameters like in `search?id=1`. The\n//! type needs to implement [`QueryStringExtractor`](gotham::extractor::QueryStringExtractor).\n//!\n//! Additionally, all handlers may take a reference to gotham's [`State`]. Please note that for async\n//! handlers, it needs to be a mutable reference until rustc's lifetime checks across await bounds\n//! improve.\n//!\n//! # Uploads and Downloads\n//!\n//! By default, every request body is parsed from json, and every respone is converted to json using\n//! [serde_json]. However, you may also use raw bodies. This is an example where the request body\n//! is simply returned as the response again, no json parsing involved:\n//!\n//! ```rust,no_run\n//! # #[macro_use] extern crate gotham_restful_derive;\n//! # use gotham::{mime::{self, Mime}, router::builder::*};\n//! # use gotham_restful::*;\n//! # use serde::{Deserialize, Serialize};\n//! #[derive(Resource)]\n//! #[resource(create)]\n//! struct ImageResource;\n//!\n//! #[derive(FromBody, RequestBody)]\n//! #[supported_types(mime::IMAGE_GIF, mime::IMAGE_JPEG, mime::IMAGE_PNG)]\n//! struct RawImage {\n//! \tcontent: Vec,\n//! \tcontent_type: Mime\n//! }\n//!\n//! #[create]\n//! fn create(body: RawImage) -> Raw> {\n//! \tRaw::new(body.content, body.content_type)\n//! }\n//! # fn main() {\n//! # \tgotham::start(\"127.0.0.1:8080\", build_simple_router(|route| {\n//! # \t\troute.resource::(\"image\");\n//! # \t})).expect(\"Failed to start gotham\");\n//! # }\n//! ```\n//!\n//! # Custom HTTP Headers\n//!\n//! You can read request headers from the state as you would in any other gotham handler, and specify\n//! custom response headers using [Response::header].\n//!\n//! ```rust,no_run\n//! # #[macro_use] extern crate gotham_restful_derive;\n//! # use gotham::hyper::header::{ACCEPT, HeaderMap, VARY};\n//! # use gotham::{router::builder::*, state::State};\n//! # use gotham_restful::*;\n//! #[derive(Resource)]\n//! #[resource(read_all)]\n//! struct FooResource;\n//!\n//! #[read_all]\n//! async fn read_all(state: &mut State) -> NoContent {\n//! \tlet headers: &HeaderMap = state.borrow();\n//! \tlet accept = &headers[ACCEPT];\n//! # drop(accept);\n//!\n//! \tlet mut res = NoContent::default();\n//! \tres.header(VARY, \"accept\".parse().unwrap());\n//! \tres\n//! }\n//! # fn main() {\n//! # \tgotham::start(\"127.0.0.1:8080\", build_simple_router(|route| {\n//! # \t\troute.resource::(\"foo\");\n//! # \t})).expect(\"Failed to start gotham\");\n//! # }\n//! ```\n//!\n//! # Features\n//!\n//! To make life easier for common use-cases, this create offers a few features that might be helpful\n//! when you implement your web server. The complete feature list is\n//! - [`auth`](#authentication-feature) Advanced JWT middleware\n//! - [`cors`](#cors-feature) CORS handling for all endpoint handlers\n//! - [`database`](#database-feature) diesel middleware support\n//! - `errorlog` log errors returned from endpoint handlers\n//! - `full` enables all features except `without-openapi`\n//! - [`openapi`](#openapi-feature) router additions to generate an openapi spec\n//! - `without-openapi` (**default**) disables `openapi` support.\n//!\n//! ## Authentication Feature\n//!\n//! In order to enable authentication support, enable the `auth` feature gate. This allows you to\n//! register a middleware that can automatically check for the existence of an JWT authentication\n//! token. Besides being supported by the endpoint macros, it supports to lookup the required JWT secret\n//! with the JWT data, hence you can use several JWT secrets and decide on the fly which secret to use.\n//! None of this is currently supported by gotham's own JWT middleware.\n//!\n//! A simple example that uses only a single secret looks like this:\n//!\n//! ```rust,no_run\n//! # #[macro_use] extern crate gotham_restful_derive;\n//! # #[cfg(feature = \"auth\")]\n//! # mod auth_feature_enabled {\n//! # use gotham::{router::builder::*, pipeline::*, state::State};\n//! # use gotham_restful::*;\n//! # use serde::{Deserialize, Serialize};\n//! #[derive(Resource)]\n//! #[resource(read)]\n//! struct SecretResource;\n//!\n//! #[derive(Serialize)]\n//! # #[cfg_attr(feature = \"openapi\", derive(openapi_type::OpenapiType))]\n//! struct Secret {\n//! \tid: u64,\n//! \tintended_for: String\n//! }\n//!\n//! #[derive(Deserialize, Clone)]\n//! struct AuthData {\n//! \tsub: String,\n//! \texp: u64\n//! }\n//!\n//! #[read]\n//! fn read(auth: AuthStatus, id: u64) -> AuthSuccess {\n//! \tlet intended_for = auth.ok()?.sub;\n//! \tOk(Secret { id, intended_for })\n//! }\n//!\n//! fn main() {\n//! \tlet auth: AuthMiddleware = AuthMiddleware::new(\n//! \t\tAuthSource::AuthorizationHeader,\n//! \t\tAuthValidation::default(),\n//! \t\tStaticAuthHandler::from_array(b\"zlBsA2QXnkmpe0QTh8uCvtAEa4j33YAc\")\n//! \t);\n//! \tlet (chain, pipelines) = single_pipeline(new_pipeline().add(auth).build());\n//! \tgotham::start(\n//! \t\t\"127.0.0.1:8080\",\n//! \t\tbuild_router(chain, pipelines, |route| {\n//! \t\t\troute.resource::(\"secret\");\n//! \t\t})\n//! \t)\n//! \t.expect(\"Failed to start gotham\");\n//! }\n//! # }\n//! ```\n//!\n//! ## CORS Feature\n//!\n//! The cors feature allows an easy usage of this web server from other origins. By default, only\n//! the `Access-Control-Allow-Methods` header is touched. To change the behaviour, add your desired\n//! configuration as a middleware.\n//!\n//! A simple example that allows authentication from every origin (note that `*` always disallows\n//! authentication), and every content type, looks like this:\n//!\n//! ```rust,no_run\n//! # #[macro_use] extern crate gotham_restful_derive;\n//! # #[cfg(feature = \"cors\")]\n//! # mod cors_feature_enabled {\n//! # use gotham::{hyper::header::*, router::builder::*, pipeline::*, state::State};\n//! # use gotham_restful::{*, cors::*};\n//! # use serde::{Deserialize, Serialize};\n//! #[derive(Resource)]\n//! #[resource(read_all)]\n//! struct FooResource;\n//!\n//! #[read_all]\n//! fn read_all() {\n//! \t// your handler\n//! }\n//!\n//! fn main() {\n//! \tlet cors = CorsConfig {\n//! \t\torigin: Origin::Copy,\n//! \t\theaders: Headers::List(vec![CONTENT_TYPE]),\n//! \t\tmax_age: 0,\n//! \t\tcredentials: true\n//! \t};\n//! \tlet (chain, pipelines) = single_pipeline(new_pipeline().add(cors).build());\n//! \tgotham::start(\n//! \t\t\"127.0.0.1:8080\",\n//! \t\tbuild_router(chain, pipelines, |route| {\n//! \t\t\troute.resource::(\"foo\");\n//! \t\t})\n//! \t)\n//! \t.expect(\"Failed to start gotham\");\n//! }\n//! # }\n//! ```\n//!\n//! The cors feature can also be used for non-resource handlers. Take a look at [`CorsRoute`]\n//! for an example.\n//!\n//! ## Database Feature\n//!\n//! The database feature allows an easy integration of [diesel] into your handler functions. Please\n//! note however that due to the way gotham's diesel middleware implementation, it is not possible\n//! to run async code while holding a database connection. If you need to combine async and database,\n//! you'll need to borrow the connection from the [`State`] yourself and return a boxed future.\n//!\n//! A simple non-async example looks like this:\n//!\n//! ```rust,no_run\n//! # #[macro_use] extern crate diesel;\n//! # #[macro_use] extern crate gotham_restful_derive;\n//! # #[cfg(feature = \"database\")]\n//! # mod database_feature_enabled {\n//! # use diesel::{table, PgConnection, QueryResult, RunQueryDsl};\n//! # use gotham::{router::builder::*, pipeline::*, state::State};\n//! # use gotham_middleware_diesel::DieselMiddleware;\n//! # use gotham_restful::*;\n//! # use serde::{Deserialize, Serialize};\n//! # use std::env;\n//! # table! {\n//! # foo (id) {\n//! # id -> Int8,\n//! # value -> Text,\n//! # }\n//! # }\n//! #[derive(Resource)]\n//! #[resource(read_all)]\n//! struct FooResource;\n//!\n//! #[derive(Queryable, Serialize)]\n//! # #[cfg_attr(feature = \"openapi\", derive(openapi_type::OpenapiType))]\n//! struct Foo {\n//! \tid: i64,\n//! \tvalue: String\n//! }\n//!\n//! #[read_all]\n//! fn read_all(conn: &mut PgConnection) -> QueryResult> {\n//! \tfoo::table.load(conn)\n//! }\n//!\n//! type Repo = gotham_middleware_diesel::Repo;\n//!\n//! fn main() {\n//! \tlet repo = Repo::new(&env::var(\"DATABASE_URL\").unwrap());\n//! \tlet diesel = DieselMiddleware::new(repo);\n//!\n//! \tlet (chain, pipelines) = single_pipeline(new_pipeline().add(diesel).build());\n//! \tgotham::start(\n//! \t\t\"127.0.0.1:8080\",\n//! \t\tbuild_router(chain, pipelines, |route| {\n//! \t\t\troute.resource::(\"foo\");\n//! \t\t})\n//! \t)\n//! \t.expect(\"Failed to start gotham\");\n//! }\n//! # }\n//! ```\n//!\n//! ## OpenAPI Feature\n//!\n//! The OpenAPI feature is probably the most powerful one of this crate. Definitely read this section\n//! carefully both as a binary as well as a library author to avoid unwanted suprises.\n//!\n//! In order to automatically create an openapi specification, gotham-restful needs knowledge over\n//! all routes and the types returned. `serde` does a great job at serialization but doesn't give\n//! enough type information, so all types used in the router need to implement\n//! [`OpenapiType`](openapi_type::OpenapiType). This can be derived for almoust any type and there\n//! should be no need to implement it manually. A simple example looks like this:\n//!\n//! ```rust,no_run\n//! # #[macro_use] extern crate gotham_restful_derive;\n//! # #[cfg(feature = \"openapi\")]\n//! # mod openapi_feature_enabled {\n//! # use gotham::{router::builder::*, state::State};\n//! # use gotham_restful::*;\n//! # use openapi_type::OpenapiType;\n//! # use serde::{Deserialize, Serialize};\n//! #[derive(Resource)]\n//! #[resource(read_all)]\n//! struct FooResource;\n//!\n//! #[derive(OpenapiType, Serialize)]\n//! struct Foo {\n//! \tbar: String\n//! }\n//!\n//! #[read_all]\n//! fn read_all() -> Success {\n//! \tFoo {\n//! \t\tbar: \"Hello World\".to_owned()\n//! \t}\n//! \t.into()\n//! }\n//!\n//! fn main() {\n//! \tgotham::start(\n//! \t\t\"127.0.0.1:8080\",\n//! \t\tbuild_simple_router(|route| {\n//! \t\t\tlet info = OpenapiInfo {\n//! \t\t\t\ttitle: \"My Foo API\".to_owned(),\n//! \t\t\t\tversion: \"0.1.0\".to_owned(),\n//! \t\t\t\turls: vec![\"https://example.org/foo/api/v1\".to_owned()]\n//! \t\t\t};\n//! \t\t\troute.with_openapi(info, |mut route| {\n//! \t\t\t\troute.resource::(\"foo\");\n//! \t\t\t\troute.openapi_spec(\"openapi\");\n//! \t\t\t\troute.openapi_doc(\"/\");\n//! \t\t\t});\n//! \t\t})\n//! \t)\n//! \t.expect(\"Failed to start gotham\");\n//! }\n//! # }\n//! ```\n//!\n//! Above example adds the resource as before, but adds two other endpoints as well: `/openapi` and `/`.\n//! The first one will return the generated openapi specification in JSON format, allowing you to easily\n//! generate clients in different languages without worying to exactly replicate your api in each of those\n//! languages. The second one will return documentation in HTML format, so you can easily view your\n//! api and share it with other people.\n//!\n//! ### Gotchas\n//!\n//! The openapi feature has some gotchas you should be aware of.\n//!\n//! - The name of a struct is used as a \"link\" in the openapi specification. Therefore, if you have two\n//! structs with the same name in your project, the openapi specification will be invalid as only one\n//! of the two will make it into the spec.\n//! - By default, the `without-openapi` feature of this crate is enabled. Disabling it in favour of the\n//! `openapi` feature will add additional type bounds and method requirements to some of the traits and\n//! \ttypes in this crate, for example instead of [`Endpoint`] you now have to implement\n//! \t[`EndpointWithSchema`]. This means that some code might only compile on either feature, but not\n//! on both. If you are writing a library that uses gotham-restful, it is strongly recommended to pass\n//! \tboth features through and conditionally enable the openapi code, like this:\n//!\n//! ```rust\n//! # #[macro_use] extern crate gotham_restful;\n//! # use serde::{Deserialize, Serialize};\n//! #[derive(Deserialize, Serialize)]\n//! #[cfg_attr(feature = \"openapi\", derive(openapi_type::OpenapiType))]\n//! struct Foo;\n//! ```\n//!\n//! [diesel]: https://diesel.rs/\n//! [`State`]: gotham::state::State\n\n#[cfg(all(feature = \"openapi\", feature = \"without-openapi\"))]\ncompile_error!(\"The 'openapi' and 'without-openapi' features cannot be combined\");\n\n#[cfg(all(not(feature = \"openapi\"), not(feature = \"without-openapi\")))]\ncompile_error!(\"Either the 'openapi' or 'without-openapi' feature needs to be enabled\");\n\n// weird proc macro issue\nextern crate self as gotham_restful;\n\n#[macro_use]\nextern crate gotham_restful_derive;\n#[macro_use]\nextern crate log;\n#[macro_use]\nextern crate serde;\n\n#[cfg(test)]\n#[macro_use]\nextern crate pretty_assertions;\n\n#[doc(no_inline)]\npub use gotham;\n\npub use gotham_restful_derive::*;\n\n/// Not public API\n#[doc(hidden)]\npub mod private {\n\tpub use crate::routing::PathExtractor as IdPlaceholder;\n\tpub use futures_util::future::{BoxFuture, FutureExt};\n\t#[cfg(feature = \"database\")]\n\tpub use gotham_middleware_diesel::Repo;\n\t#[cfg(feature = \"openapi\")]\n\tpub use openapi_type::{OpenapiSchema, OpenapiType, Visitor};\n\tpub use serde_json;\n\n\t#[cfg(feature = \"openapi\")]\n\tuse gotham::hyper::StatusCode;\n\t#[cfg(feature = \"auth\")]\n\tuse gotham::state::{FromState, State};\n\n\t/// This method is used by the endpoint macro to generate a good error message\n\t/// when the used AuthData type does not implement Clone.\n\t#[cfg(feature = \"auth\")]\n\t#[inline]\n\tpub fn clone_from_state(state: &State) -> T\n\twhere\n\t\tT: FromState + Clone\n\t{\n\t\tT::borrow_from(state).clone()\n\t}\n\n\t/// This trait is used by the endpoint macro to generate a good error message\n\t/// when the schema function has the wrong signature.\n\t#[cfg(feature = \"openapi\")]\n\tpub trait CustomSchema {\n\t\tfn schema(self, code: StatusCode) -> OpenapiSchema;\n\t}\n\n\t#[cfg(feature = \"openapi\")]\n\timpl CustomSchema for F\n\twhere\n\t\tF: FnOnce(StatusCode) -> OpenapiSchema\n\t{\n\t\t#[inline]\n\t\tfn schema(self, code: StatusCode) -> OpenapiSchema {\n\t\t\tself(code)\n\t\t}\n\t}\n\n\t/// This trait is used by the endpoint macro to generate a good error message\n\t/// when the status_codes function has the wrong signature.\n\t#[cfg(feature = \"openapi\")]\n\tpub trait CustomStatusCodes {\n\t\tfn status_codes(self) -> Vec;\n\t}\n\n\t#[cfg(feature = \"openapi\")]\n\timpl CustomStatusCodes for F\n\twhere\n\t\tF: FnOnce() -> Vec\n\t{\n\t\t#[inline]\n\t\tfn status_codes(self) -> Vec {\n\t\t\tself()\n\t\t}\n\t}\n}\n\n#[cfg(feature = \"auth\")]\nmod auth;\n#[cfg(feature = \"auth\")]\npub use auth::{\n\tAuthHandler, AuthMiddleware, AuthSource, AuthStatus, AuthValidation, StaticAuthHandler\n};\n\n#[cfg(feature = \"cors\")]\npub mod cors;\n#[cfg(feature = \"cors\")]\npub use cors::{handle_cors, CorsConfig, CorsRoute};\n\n#[cfg(feature = \"openapi\")]\nmod openapi;\n#[cfg(feature = \"openapi\")]\npub use openapi::{builder::OpenapiInfo, router::GetOpenapi};\n\nmod endpoint;\n#[cfg(feature = \"openapi\")]\npub use endpoint::EndpointWithSchema;\npub use endpoint::{Endpoint, NoopExtractor};\n\nmod response;\npub use response::{\n\tAuthError, AuthErrorOrOther, AuthResult, AuthSuccess, IntoResponse, IntoResponseError,\n\tNoContent, Raw, Redirect, Response, Success\n};\n#[cfg(feature = \"openapi\")]\npub use response::{IntoResponseWithSchema, ResponseSchema};\n\nmod routing;\npub use routing::{DrawResourceRoutes, DrawResources};\n#[cfg(feature = \"openapi\")]\npub use routing::{DrawResourceRoutesWithSchema, DrawResourcesWithSchema, WithOpenapi};\n\nmod types;\npub use types::{FromBody, RequestBody, ResponseBody};\n\n/// This trait must be implemented for every resource. It allows you to register the different\n/// endpoints that can be handled by this resource to be registered with the underlying router.\n///\n/// It is not recommended to implement this yourself, just use `#[derive(Resource)]`.\n#[_private_openapi_trait(ResourceWithSchema)]\npub trait Resource {\n\t/// Register all methods handled by this resource with the underlying router.\n\t#[openapi_bound(D: crate::DrawResourceRoutesWithSchema)]\n\t#[non_openapi_bound(D: crate::DrawResourceRoutes)]\n\tfn setup(route: D);\n}\n","traces":[{"line":463,"address":[17694366],"length":1,"stats":{"Line":7},"fn_name":null},{"line":464,"address":[14690630],"length":1,"stats":{"Line":7},"fn_name":null},{"line":466,"address":[13961458,13961521],"length":1,"stats":{"Line":0},"fn_name":null},{"line":467,"address":[13211243],"length":1,"stats":{"Line":0},"fn_name":null},{"line":469,"address":[9937869],"length":1,"stats":{"Line":0},"fn_name":null},{"line":489,"address":[7836480],"length":1,"stats":{"Line":0},"fn_name":null},{"line":506,"address":[9938441],"length":1,"stats":{"Line":0},"fn_name":null},{"line":507,"address":[14072513],"length":1,"stats":{"Line":13},"fn_name":null},{"line":508,"address":[9938535],"length":1,"stats":{"Line":13},"fn_name":null},{"line":512,"address":[9938726,9938751],"length":1,"stats":{"Line":0},"fn_name":null},{"line":518,"address":[9938792],"length":1,"stats":{"Line":6},"fn_name":null},{"line":523,"address":[14693600],"length":1,"stats":{"Line":7},"fn_name":null},{"line":527,"address":[6666066],"length":1,"stats":{"Line":0},"fn_name":null},{"line":528,"address":[13211458],"length":1,"stats":{"Line":7},"fn_name":null},{"line":529,"address":[14693758],"length":1,"stats":{"Line":8},"fn_name":null},{"line":536,"address":[14693900],"length":1,"stats":{"Line":0},"fn_name":null},{"line":541,"address":[14072640],"length":1,"stats":{"Line":0},"fn_name":"next"},{"line":545,"address":[14072791],"length":1,"stats":{"Line":0},"fn_name":null},{"line":546,"address":[14072835],"length":1,"stats":{"Line":1},"fn_name":null},{"line":547,"address":[14072850],"length":1,"stats":{"Line":1},"fn_name":null},{"line":552,"address":[9938904],"length":1,"stats":{"Line":0},"fn_name":null},{"line":559,"address":[9938942],"length":1,"stats":{"Line":0},"fn_name":null},{"line":564,"address":[9234464,9234432],"length":1,"stats":{"Line":0},"fn_name":"read_i24"},{"line":595,"address":[17695608],"length":1,"stats":{"Line":0},"fn_name":null}],"covered":10,"coverable":24},{"path":["/","home","runner","work","gotham_restful","gotham_restful","src","openapi","builder.rs"],"content":"use openapi_type::{\n\tindexmap::IndexMap,\n\topenapiv3::{\n\t\tself, Components, OpenAPI, PathItem, ReferenceOr,\n\t\tReferenceOr::{Item, Reference},\n\t\tSchema, Server\n\t},\n\tOpenapiSchema\n};\nuse parking_lot::RwLock;\nuse std::sync::Arc;\n\n#[derive(Clone, Debug)]\npub struct OpenapiInfo {\n\tpub title: String,\n\tpub version: String,\n\tpub urls: Vec\n}\n\n#[derive(Clone, Debug)]\npub(crate) struct OpenapiBuilder {\n\tpub(crate) openapi: Arc>\n}\n\nimpl OpenapiBuilder {\n\tpub(crate) fn new(info: OpenapiInfo) -> Self {\n\t\tSelf {\n\t\t\topenapi: Arc::new(RwLock::new(OpenAPI {\n\t\t\t\topenapi: \"3.0.2\".to_string(),\n\t\t\t\tinfo: openapiv3::Info {\n\t\t\t\t\ttitle: info.title,\n\t\t\t\t\tversion: info.version,\n\t\t\t\t\t..Default::default()\n\t\t\t\t},\n\t\t\t\tservers: info\n\t\t\t\t\t.urls\n\t\t\t\t\t.into_iter()\n\t\t\t\t\t.map(|url| Server {\n\t\t\t\t\t\turl,\n\t\t\t\t\t\t..Default::default()\n\t\t\t\t\t})\n\t\t\t\t\t.collect(),\n\t\t\t\t..Default::default()\n\t\t\t}))\n\t\t}\n\t}\n\n\t/// Remove path from the OpenAPI spec, or return an empty one if not included. This is handy if you need to\n\t/// modify the path and add it back after the modification\n\tpub(crate) fn remove_path(&mut self, path: &str) -> PathItem {\n\t\tlet mut openapi = self.openapi.write();\n\t\tmatch openapi.paths.paths.swap_remove(path) {\n\t\t\tSome(Item(item)) => item,\n\t\t\t_ => PathItem::default()\n\t\t}\n\t}\n\n\tpub(crate) fn add_path(&mut self, path: Path, item: PathItem) {\n\t\tlet mut openapi = self.openapi.write();\n\t\topenapi.paths.paths.insert(path.to_string(), Item(item));\n\t}\n\n\tfn add_schema_impl(&mut self, name: String, mut schema: OpenapiSchema) {\n\t\tself.add_schema_dependencies(&mut schema.dependencies);\n\n\t\tlet mut openapi = self.openapi.write();\n\t\tmatch &mut openapi.components {\n\t\t\tSome(comp) => {\n\t\t\t\tcomp.schemas.insert(name, Item(schema.schema));\n\t\t\t},\n\t\t\tNone => {\n\t\t\t\tlet mut comp = Components::default();\n\t\t\t\tcomp.schemas.insert(name, Item(schema.schema));\n\t\t\t\topenapi.components = Some(comp);\n\t\t\t}\n\t\t};\n\t}\n\n\tfn add_schema_dependencies(&mut self, dependencies: &mut IndexMap) {\n\t\tlet keys: Vec = dependencies.keys().map(|k| k.to_string()).collect();\n\t\tfor dep in keys {\n\t\t\tlet dep_schema = dependencies.swap_remove(&dep);\n\t\t\tif let Some(dep_schema) = dep_schema {\n\t\t\t\tself.add_schema_impl(dep, dep_schema);\n\t\t\t}\n\t\t}\n\t}\n\n\tpub(crate) fn add_schema(&mut self, mut schema: OpenapiSchema) -> ReferenceOr {\n\t\tmatch schema.schema.schema_data.title.clone() {\n\t\t\tSome(name) => {\n\t\t\t\tlet reference = Reference {\n\t\t\t\t\treference: format!(\"#/components/schemas/{name}\")\n\t\t\t\t};\n\t\t\t\tself.add_schema_impl(name, schema);\n\t\t\t\treference\n\t\t\t},\n\t\t\tNone => {\n\t\t\t\tself.add_schema_dependencies(&mut schema.dependencies);\n\t\t\t\tItem(schema.schema)\n\t\t\t}\n\t\t}\n\t}\n}\n\n#[cfg(test)]\n#[allow(dead_code)]\nmod test {\n\tuse super::*;\n\tuse openapi_type::OpenapiType;\n\n\t#[derive(OpenapiType)]\n\tstruct Message {\n\t\tmsg: String\n\t}\n\n\t#[derive(OpenapiType)]\n\tstruct Messages {\n\t\tmsgs: Vec\n\t}\n\n\tfn info() -> OpenapiInfo {\n\t\tOpenapiInfo {\n\t\t\ttitle: \"TEST CASE\".to_owned(),\n\t\t\tversion: \"1.2.3\".to_owned(),\n\t\t\turls: vec![\n\t\t\t\t\"http://localhost:1234\".to_owned(),\n\t\t\t\t\"https://example.org\".to_owned(),\n\t\t\t]\n\t\t}\n\t}\n\n\tfn openapi(builder: OpenapiBuilder) -> OpenAPI {\n\t\tArc::try_unwrap(builder.openapi).unwrap().into_inner()\n\t}\n\n\t#[test]\n\tfn new_builder() {\n\t\tlet info = info();\n\t\tlet builder = OpenapiBuilder::new(info.clone());\n\t\tlet openapi = openapi(builder);\n\n\t\tassert_eq!(info.title, openapi.info.title);\n\t\tassert_eq!(info.version, openapi.info.version);\n\t\tassert_eq!(info.urls.len(), openapi.servers.len());\n\t}\n\n\t#[test]\n\tfn add_schema() {\n\t\tlet mut builder = OpenapiBuilder::new(info());\n\t\tbuilder.add_schema(>::schema());\n\t\tlet openapi = openapi(builder);\n\n\t\tassert_eq!(\n\t\t\topenapi.components.clone().unwrap_or_default().schemas[\"Message\"],\n\t\t\tReferenceOr::Item(Message::schema().schema)\n\t\t);\n\t\tassert_eq!(\n\t\t\topenapi.components.clone().unwrap_or_default().schemas[\"Messages\"],\n\t\t\tReferenceOr::Item(Messages::schema().schema)\n\t\t);\n\t}\n}\n","traces":[{"line":26,"address":[6087864,6089005,6087168],"length":1,"stats":{"Line":3},"fn_name":null},{"line":28,"address":[8266699,8267581,8268116],"length":1,"stats":{"Line":9},"fn_name":null},{"line":50,"address":[8269233,8268944],"length":1,"stats":{"Line":2},"fn_name":null},{"line":51,"address":[8269067],"length":1,"stats":{"Line":2},"fn_name":null},{"line":52,"address":[8269174,8269101,8269259],"length":1,"stats":{"Line":5},"fn_name":null},{"line":53,"address":[8269297],"length":1,"stats":{"Line":1},"fn_name":null},{"line":54,"address":[6089734,6089831],"length":1,"stats":{"Line":4},"fn_name":null},{"line":58,"address":[],"length":0,"stats":{"Line":2},"fn_name":null},{"line":59,"address":[],"length":0,"stats":{"Line":4},"fn_name":null},{"line":60,"address":[],"length":0,"stats":{"Line":4},"fn_name":null},{"line":63,"address":[6090096,6091188,6091324],"length":1,"stats":{"Line":2},"fn_name":null},{"line":64,"address":[6090169],"length":1,"stats":{"Line":2},"fn_name":null},{"line":66,"address":[8269841],"length":1,"stats":{"Line":2},"fn_name":null},{"line":67,"address":[8269976,8269903],"length":1,"stats":{"Line":4},"fn_name":null},{"line":68,"address":[8270040],"length":1,"stats":{"Line":2},"fn_name":null},{"line":69,"address":[8270048],"length":1,"stats":{"Line":2},"fn_name":null},{"line":72,"address":[6090425],"length":1,"stats":{"Line":2},"fn_name":null},{"line":73,"address":[6090877,6090672],"length":1,"stats":{"Line":4},"fn_name":null},{"line":74,"address":[6090896,6091166],"length":1,"stats":{"Line":2},"fn_name":null},{"line":79,"address":[6092044,6092001,6091360],"length":1,"stats":{"Line":3},"fn_name":null},{"line":80,"address":[6091406,6092099,6092064],"length":1,"stats":{"Line":7},"fn_name":"{closure#0}"},{"line":81,"address":[6091654,6092020,6091451],"length":1,"stats":{"Line":7},"fn_name":null},{"line":82,"address":[6091710,6091758],"length":1,"stats":{"Line":4},"fn_name":null},{"line":83,"address":[6091766],"length":1,"stats":{"Line":2},"fn_name":null},{"line":84,"address":[6091928,6091845],"length":1,"stats":{"Line":4},"fn_name":null},{"line":89,"address":[6092753,6092128,6092891],"length":1,"stats":{"Line":3},"fn_name":null},{"line":90,"address":[6092171,6092275],"length":1,"stats":{"Line":6},"fn_name":null},{"line":91,"address":[6092321],"length":1,"stats":{"Line":1},"fn_name":null},{"line":93,"address":[6092349,6092426],"length":1,"stats":{"Line":2},"fn_name":null},{"line":95,"address":[6092582],"length":1,"stats":{"Line":1},"fn_name":null},{"line":96,"address":[6092728],"length":1,"stats":{"Line":1},"fn_name":null},{"line":99,"address":[6092311],"length":1,"stats":{"Line":3},"fn_name":null},{"line":100,"address":[6092804],"length":1,"stats":{"Line":3},"fn_name":null}],"covered":33,"coverable":33},{"path":["/","home","runner","work","gotham_restful","gotham_restful","src","openapi","handler","mod.rs"],"content":"#![cfg_attr(not(feature = \"auth\"), allow(unused_imports))]\nuse super::SECURITY_NAME;\nuse base64::prelude::*;\nuse futures_util::{future, future::FutureExt};\nuse gotham::{\n\tanyhow,\n\thandler::{Handler, HandlerError, HandlerFuture, NewHandler},\n\thelpers::http::response::{create_empty_response, create_response},\n\thyper::{\n\t\theader::{\n\t\t\tHeaderMap, HeaderValue, CACHE_CONTROL, CONTENT_SECURITY_POLICY, ETAG, IF_NONE_MATCH,\n\t\t\tREFERRER_POLICY, X_CONTENT_TYPE_OPTIONS\n\t\t},\n\t\tBody, Response, StatusCode\n\t},\n\tmime::{APPLICATION_JSON, TEXT_HTML_UTF_8, TEXT_PLAIN_UTF_8},\n\tstate::State\n};\nuse gotham_restful_redoc::Redoc;\nuse openapi_type::{\n\tindexmap::IndexMap,\n\topenapiv3::{APIKeyLocation, OpenAPI, ReferenceOr, SecurityScheme}\n};\nuse parking_lot::RwLock;\nuse sha2::{Digest, Sha256};\nuse std::{panic::RefUnwindSafe, pin::Pin, sync::Arc};\n\n#[cfg(feature = \"auth\")]\nfn get_security(state: &State) -> IndexMap> {\n\tuse crate::AuthSource;\n\tuse gotham::state::FromState;\n\n\tlet source = match AuthSource::try_borrow_from(state) {\n\t\tSome(source) => source,\n\t\tNone => return Default::default()\n\t};\n\n\tlet security_scheme = match source {\n\t\tAuthSource::Cookie(name) => SecurityScheme::APIKey {\n\t\t\tlocation: APIKeyLocation::Cookie,\n\t\t\tname: name.to_string(),\n\t\t\tdescription: None\n\t\t},\n\t\tAuthSource::Header(name) => SecurityScheme::APIKey {\n\t\t\tlocation: APIKeyLocation::Header,\n\t\t\tname: name.to_string(),\n\t\t\tdescription: None\n\t\t},\n\t\tAuthSource::AuthorizationHeader => SecurityScheme::HTTP {\n\t\t\tscheme: \"bearer\".to_owned(),\n\t\t\tbearer_format: Some(\"JWT\".to_owned()),\n\t\t\tdescription: None\n\t\t}\n\t};\n\n\tlet mut security_schemes: IndexMap> = Default::default();\n\tsecurity_schemes.insert(SECURITY_NAME.to_owned(), ReferenceOr::Item(security_scheme));\n\n\tsecurity_schemes\n}\n\n#[cfg(not(feature = \"auth\"))]\nfn get_security(_state: &State) -> IndexMap> {\n\tDefault::default()\n}\n\nfn openapi_string(\n\tstate: &State,\n\topenapi: &Arc>\n) -> Result {\n\tlet openapi = openapi.read();\n\n\tlet mut openapi = openapi.clone();\n\tlet security_schemes = get_security(state);\n\tlet mut components = openapi.components.unwrap_or_default();\n\tcomponents.security_schemes = security_schemes;\n\topenapi.components = Some(components);\n\n\tserde_json::to_string(&openapi)\n}\n\nfn create_openapi_response(state: &State, openapi: &Arc>) -> Response {\n\tmatch openapi_string(state, openapi) {\n\t\tOk(body) => {\n\t\t\tlet mut res = create_response(state, StatusCode::OK, APPLICATION_JSON, body);\n\t\t\tlet headers = res.headers_mut();\n\t\t\theaders.insert(X_CONTENT_TYPE_OPTIONS, HeaderValue::from_static(\"nosniff\"));\n\t\t\tres\n\t\t},\n\t\tErr(e) => {\n\t\t\terror!(\"Unable to handle OpenAPI request due to error: {e}\");\n\t\t\tcreate_response(\n\t\t\t\tstate,\n\t\t\t\tStatusCode::INTERNAL_SERVER_ERROR,\n\t\t\t\tTEXT_PLAIN_UTF_8,\n\t\t\t\t\"\"\n\t\t\t)\n\t\t}\n\t}\n}\n\n#[derive(Clone)]\npub(crate) struct OpenapiSpecHandler {\n\topenapi: Arc>\n}\n\n// safety: the handler only ever aquires a read lock, so this usage of\n// RwLock is, in fact, unwind safe\nimpl RefUnwindSafe for OpenapiSpecHandler {}\n\nimpl OpenapiSpecHandler {\n\tpub(crate) fn new(openapi: Arc>) -> Self {\n\t\tSelf { openapi }\n\t}\n}\n\nimpl NewHandler for OpenapiSpecHandler {\n\ttype Instance = Self;\n\n\tfn new_handler(&self) -> anyhow::Result {\n\t\tOk(self.clone())\n\t}\n}\n\nimpl Handler for OpenapiSpecHandler {\n\tfn handle(self, mut state: State) -> Pin> {\n\t\tlet res = create_openapi_response(&mut state, &self.openapi);\n\t\tfuture::ok((state, res)).boxed()\n\t}\n}\n\n#[derive(Clone)]\npub(crate) struct OpenapiDocHandler {\n\topenapi: Arc>\n}\n\n// safety: the handler only ever aquires a read lock, so this usage of\n// RwLock is, in fact, unwind safe\nimpl RefUnwindSafe for OpenapiDocHandler {}\n\nimpl OpenapiDocHandler {\n\tpub(crate) fn new(openapi: Arc>) -> Self {\n\t\tSelf { openapi }\n\t}\n}\n\nimpl NewHandler for OpenapiDocHandler {\n\ttype Instance = Self;\n\n\tfn new_handler(&self) -> anyhow::Result {\n\t\tOk(self.clone())\n\t}\n}\n\nfn redoc_handler(\n\tstate: &State,\n\topenapi: &Arc>\n) -> Result, HandlerError> {\n\tlet spec = openapi_string(state, openapi)?;\n\tlet Redoc { html, script_hash } = gotham_restful_redoc::html(spec);\n\n\tlet mut etag = Sha256::new();\n\tetag.update(&html);\n\tlet etag = format!(\"\\\"{}\\\"\", BASE64_STANDARD.encode(etag.finalize()));\n\n\tif state\n\t\t.borrow::()\n\t\t.get(IF_NONE_MATCH)\n\t\t.map_or(false, |header| header.as_bytes() == etag.as_bytes())\n\t{\n\t\tlet res = create_empty_response(state, StatusCode::NOT_MODIFIED);\n\t\treturn Ok(res);\n\t}\n\n\tlet mut res = create_response(state, StatusCode::OK, TEXT_HTML_UTF_8, html);\n\tlet headers = res.headers_mut();\n\theaders.insert(\n\t\tCACHE_CONTROL,\n\t\tHeaderValue::from_static(\"public,max-age=2592000\")\n\t);\n\theaders.insert(\n\t\tCONTENT_SECURITY_POLICY,\n\t\tformat!(\n\t\t\t\"default-src 'none';base-uri 'none';script-src 'unsafe-inline' https://cdn.jsdelivr.net 'sha256-{script_hash}' 'strict-dynamic';style-src 'unsafe-inline' https://fonts.googleapis.com;font-src https://fonts.gstatic.com;connect-src 'self';img-src blob: data:\",\n\t\t).parse().unwrap()\n\t);\n\theaders.insert(ETAG, etag.parse().unwrap());\n\theaders.insert(REFERRER_POLICY, HeaderValue::from_static(\"no-referrer\"));\n\theaders.insert(X_CONTENT_TYPE_OPTIONS, HeaderValue::from_static(\"nosniff\"));\n\tOk(res)\n}\n\nimpl Handler for OpenapiDocHandler {\n\tfn handle(self, state: State) -> Pin> {\n\t\tmatch redoc_handler(&state, &self.openapi) {\n\t\t\tOk(res) => future::ok((state, res)).boxed(),\n\t\t\tErr(err) => future::err((state, err)).boxed()\n\t\t}\n\t}\n}\n","traces":[{"line":29,"address":[6362800,6363593],"length":1,"stats":{"Line":2},"fn_name":"get_security"},{"line":33,"address":[6362838,6362953],"length":1,"stats":{"Line":2},"fn_name":null},{"line":34,"address":[6362898],"length":1,"stats":{"Line":1},"fn_name":null},{"line":35,"address":[6362887],"length":1,"stats":{"Line":1},"fn_name":null},{"line":38,"address":[6362916],"length":1,"stats":{"Line":1},"fn_name":null},{"line":41,"address":[6362980],"length":1,"stats":{"Line":0},"fn_name":null},{"line":46,"address":[6363147],"length":1,"stats":{"Line":0},"fn_name":null},{"line":50,"address":[6363289],"length":1,"stats":{"Line":1},"fn_name":null},{"line":51,"address":[6363385,6363314],"length":1,"stats":{"Line":2},"fn_name":null},{"line":56,"address":[6363619],"length":1,"stats":{"Line":1},"fn_name":null},{"line":57,"address":[6363676,6363744],"length":1,"stats":{"Line":2},"fn_name":null},{"line":59,"address":[6363878],"length":1,"stats":{"Line":1},"fn_name":null},{"line":67,"address":[6363952,6365339,6364840],"length":1,"stats":{"Line":2},"fn_name":"openapi_string"},{"line":71,"address":[6364018],"length":1,"stats":{"Line":2},"fn_name":null},{"line":73,"address":[6364073,6364132],"length":1,"stats":{"Line":4},"fn_name":null},{"line":74,"address":[6364160,6364211],"length":1,"stats":{"Line":4},"fn_name":null},{"line":75,"address":[6364317,6364219],"length":1,"stats":{"Line":4},"fn_name":null},{"line":76,"address":[6364333],"length":1,"stats":{"Line":2},"fn_name":null},{"line":77,"address":[6364589],"length":1,"stats":{"Line":2},"fn_name":null},{"line":79,"address":[6364725],"length":1,"stats":{"Line":2},"fn_name":null},{"line":82,"address":[6365360,6366167],"length":1,"stats":{"Line":2},"fn_name":"create_openapi_response"},{"line":83,"address":[6365398],"length":1,"stats":{"Line":2},"fn_name":null},{"line":84,"address":[6365451],"length":1,"stats":{"Line":2},"fn_name":null},{"line":85,"address":[6365474],"length":1,"stats":{"Line":2},"fn_name":null},{"line":86,"address":[6365609,6366252],"length":1,"stats":{"Line":4},"fn_name":null},{"line":87,"address":[6366260],"length":1,"stats":{"Line":2},"fn_name":null},{"line":88,"address":[6366464],"length":1,"stats":{"Line":2},"fn_name":null},{"line":90,"address":[6365628],"length":1,"stats":{"Line":0},"fn_name":null},{"line":91,"address":[6365731,6366002,6365789,6365641],"length":1,"stats":{"Line":0},"fn_name":null},{"line":95,"address":[6365865],"length":1,"stats":{"Line":0},"fn_name":null},{"line":112,"address":[6366496],"length":1,"stats":{"Line":2},"fn_name":null},{"line":120,"address":[6366512],"length":1,"stats":{"Line":2},"fn_name":"new_handler"},{"line":121,"address":[6366521],"length":1,"stats":{"Line":2},"fn_name":null},{"line":126,"address":[6366560,6366898],"length":1,"stats":{"Line":2},"fn_name":"handle"},{"line":127,"address":[6366603],"length":1,"stats":{"Line":2},"fn_name":null},{"line":128,"address":[6366656,6366577],"length":1,"stats":{"Line":4},"fn_name":null},{"line":142,"address":[6366928],"length":1,"stats":{"Line":0},"fn_name":null},{"line":150,"address":[6366944],"length":1,"stats":{"Line":0},"fn_name":"new_handler"},{"line":151,"address":[6366953],"length":1,"stats":{"Line":0},"fn_name":null},{"line":155,"address":[6370214,6367916,6366992],"length":1,"stats":{"Line":0},"fn_name":"redoc_handler"},{"line":159,"address":[6367039,6367309],"length":1,"stats":{"Line":0},"fn_name":null},{"line":160,"address":[6367234,6367391],"length":1,"stats":{"Line":0},"fn_name":null},{"line":162,"address":[6367463],"length":1,"stats":{"Line":0},"fn_name":null},{"line":163,"address":[6367542],"length":1,"stats":{"Line":0},"fn_name":null},{"line":164,"address":[6367927,6367549],"length":1,"stats":{"Line":0},"fn_name":null},{"line":166,"address":[6368011,6368157,6368112],"length":1,"stats":{"Line":0},"fn_name":null},{"line":168,"address":[6368082],"length":1,"stats":{"Line":0},"fn_name":null},{"line":169,"address":[6370281,6370256,6368149],"length":1,"stats":{"Line":0},"fn_name":"{closure#0}"},{"line":171,"address":[6368381],"length":1,"stats":{"Line":0},"fn_name":null},{"line":172,"address":[6368448],"length":1,"stats":{"Line":0},"fn_name":null},{"line":175,"address":[6368200],"length":1,"stats":{"Line":0},"fn_name":null},{"line":176,"address":[6368602,6368675],"length":1,"stats":{"Line":0},"fn_name":null},{"line":177,"address":[6368790],"length":1,"stats":{"Line":0},"fn_name":null},{"line":178,"address":[6368683],"length":1,"stats":{"Line":0},"fn_name":null},{"line":179,"address":[6368721],"length":1,"stats":{"Line":0},"fn_name":null},{"line":181,"address":[6369249],"length":1,"stats":{"Line":0},"fn_name":null},{"line":182,"address":[6368882],"length":1,"stats":{"Line":0},"fn_name":null},{"line":183,"address":[6368920,6369003,6369191],"length":1,"stats":{"Line":0},"fn_name":null},{"line":187,"address":[6369401],"length":1,"stats":{"Line":0},"fn_name":null},{"line":188,"address":[6369665],"length":1,"stats":{"Line":0},"fn_name":null},{"line":189,"address":[6369864],"length":1,"stats":{"Line":0},"fn_name":null},{"line":190,"address":[6370106],"length":1,"stats":{"Line":0},"fn_name":null},{"line":194,"address":[6370947,6370352],"length":1,"stats":{"Line":0},"fn_name":"handle"},{"line":195,"address":[6370820,6370369,6370443],"length":1,"stats":{"Line":0},"fn_name":null},{"line":196,"address":[6370513,6370868],"length":1,"stats":{"Line":0},"fn_name":null},{"line":197,"address":[6370643],"length":1,"stats":{"Line":0},"fn_name":null}],"covered":31,"coverable":66},{"path":["/","home","runner","work","gotham_restful","gotham_restful","src","openapi","mod.rs"],"content":"const SECURITY_NAME: &str = \"authToken\";\n\npub(crate) mod builder;\npub(crate) mod handler;\npub(crate) mod operation;\npub(crate) mod router;\n","traces":[],"covered":0,"coverable":0},{"path":["/","home","runner","work","gotham_restful","gotham_restful","src","openapi","operation.rs"],"content":"use super::SECURITY_NAME;\nuse crate::{response::OrAllTypes, EndpointWithSchema, IntoResponse, RequestBody};\nuse gotham::{hyper::StatusCode, mime::Mime};\nuse openapi_type::{\n\tindexmap::IndexMap,\n\topenapiv3::{\n\t\tMediaType, Operation, Parameter, ParameterData, ParameterSchemaOrContent, ReferenceOr,\n\t\tReferenceOr::Item, RequestBody as OARequestBody, Response, Responses, Schema, SchemaKind,\n\t\tStatusCode as OAStatusCode, Type\n\t},\n\tOpenapiSchema\n};\nuse std::collections::HashMap;\n\nfn new_parameter_data(\n\tname: String,\n\trequired: bool,\n\tschema: ReferenceOr>\n) -> ParameterData {\n\tParameterData {\n\t\tname,\n\t\tdescription: None,\n\t\trequired,\n\t\tdeprecated: None,\n\t\tformat: ParameterSchemaOrContent::Schema(schema.unbox()),\n\t\texample: None,\n\t\texamples: Default::default(),\n\t\texplode: None,\n\t\textensions: Default::default()\n\t}\n}\n\n#[derive(Default)]\nstruct OperationParams {\n\tpath_params: Option,\n\tquery_params: Option\n}\n\nimpl OperationParams {\n\t// TODO shouldn't this be a custom openapi_type::Visitor\n\t// rather than this hacky code?\n\tfn add_path_params(\n\t\tpath_params: Option,\n\t\tparams: &mut Vec>\n\t) {\n\t\tlet path_params = match path_params {\n\t\t\tSome(pp) => pp.schema,\n\t\t\tNone => return\n\t\t};\n\t\tlet path_params = match path_params.schema_kind {\n\t\t\tSchemaKind::Type(Type::Object(ty)) => ty,\n\t\t\t_ => panic!(\"Path Parameters needs to be a plain struct\")\n\t\t};\n\t\tfor (name, schema) in path_params.properties {\n\t\t\tlet required = path_params.required.contains(&name);\n\t\t\tparams.push(Item(Parameter::Path {\n\t\t\t\tparameter_data: new_parameter_data(name, required, schema),\n\t\t\t\tstyle: Default::default()\n\t\t\t}))\n\t\t}\n\t}\n\n\t// TODO shouldn't this be a custom openapi_type::Visitor\n\t// rather than this hacky code?\n\tfn add_query_params(\n\t\tquery_params: Option,\n\t\tparams: &mut Vec>\n\t) {\n\t\tlet query_params = match query_params {\n\t\t\tSome(qp) => qp.schema,\n\t\t\tNone => return\n\t\t};\n\t\tlet query_params = match query_params.schema_kind {\n\t\t\tSchemaKind::Type(Type::Object(ty)) => ty,\n\t\t\t_ => panic!(\"Query Parameters needs to be a plain struct\")\n\t\t};\n\t\tfor (name, schema) in query_params.properties {\n\t\t\tlet required = query_params.required.contains(&name);\n\t\t\tparams.push(Item(Parameter::Query {\n\t\t\t\tparameter_data: new_parameter_data(name, required, schema),\n\t\t\t\tallow_reserved: false,\n\t\t\t\tstyle: Default::default(),\n\t\t\t\tallow_empty_value: None\n\t\t\t}))\n\t\t}\n\t}\n\n\tfn into_params(self) -> Vec> {\n\t\tlet mut params: Vec> = Vec::new();\n\t\tSelf::add_path_params(self.path_params, &mut params);\n\t\tSelf::add_query_params(self.query_params, &mut params);\n\t\tparams\n\t}\n}\n\npub(crate) struct OperationDescription {\n\toperation_id: Option,\n\tdescription: Option,\n\n\taccepted_types: Option>,\n\tresponses: HashMap>,\n\tparams: OperationParams,\n\tbody_schema: Option>,\n\tsupported_types: Option>,\n\trequires_auth: bool\n}\n\nimpl OperationDescription {\n\t/// Create a new operation description for the given endpoint type and schema. If the endpoint\n\t/// does not specify an operation id, the path is used to generate one.\n\tpub(crate) fn new(\n\t\tresponses: HashMap>,\n\t\tpath: &str\n\t) -> Self {\n\t\tlet operation_id = E::operation_id().or_else(|| {\n\t\t\tE::operation_verb()\n\t\t\t\t.map(|verb| format!(\"{verb}_{}\", path.replace(\"/\", \"_\").trim_start_matches('_')))\n\t\t});\n\t\tSelf {\n\t\t\toperation_id,\n\t\t\tdescription: E::description(),\n\n\t\t\taccepted_types: E::Output::accepted_types(),\n\t\t\tresponses,\n\t\t\tparams: Default::default(),\n\t\t\tbody_schema: None,\n\t\t\tsupported_types: None,\n\t\t\trequires_auth: E::wants_auth()\n\t\t}\n\t}\n\n\tpub(crate) fn set_path_params(&mut self, params: OpenapiSchema) {\n\t\tself.params.path_params = Some(params);\n\t}\n\n\tpub(crate) fn set_query_params(&mut self, params: OpenapiSchema) {\n\t\tself.params.query_params = Some(params);\n\t}\n\n\tpub(crate) fn set_body(&mut self, schema: ReferenceOr) {\n\t\tself.body_schema = Some(schema);\n\t\tself.supported_types = Body::supported_types();\n\t}\n\n\tfn schema_to_content(\n\t\ttypes: Vec,\n\t\tschema: ReferenceOr\n\t) -> IndexMap {\n\t\tlet mut content: IndexMap = IndexMap::new();\n\t\tfor ty in types {\n\t\t\tcontent.insert(ty.to_string(), MediaType {\n\t\t\t\tschema: Some(schema.clone()),\n\t\t\t\t..Default::default()\n\t\t\t});\n\t\t}\n\t\tcontent\n\t}\n\n\tpub(crate) fn into_operation(self) -> Operation {\n\t\t// this is unfortunately neccessary to prevent rust from complaining about partially moving self\n\t\tlet (\n\t\t\toperation_id,\n\t\t\tdescription,\n\t\t\taccepted_types,\n\t\t\tresponses,\n\t\t\tparams,\n\t\t\tbody_schema,\n\t\t\tsupported_types,\n\t\t\trequires_auth\n\t\t) = (\n\t\t\tself.operation_id,\n\t\t\tself.description,\n\t\t\tself.accepted_types,\n\t\t\tself.responses,\n\t\t\tself.params,\n\t\t\tself.body_schema,\n\t\t\tself.supported_types,\n\t\t\tself.requires_auth\n\t\t);\n\n\t\tlet responses: IndexMap> = responses\n\t\t\t.into_iter()\n\t\t\t.map(|(code, schema)| {\n\t\t\t\tlet content =\n\t\t\t\t\tSelf::schema_to_content(accepted_types.clone().or_all_types(), schema);\n\t\t\t\t(\n\t\t\t\t\tOAStatusCode::Code(code.as_u16()),\n\t\t\t\t\tItem(Response {\n\t\t\t\t\t\tdescription: code\n\t\t\t\t\t\t\t.canonical_reason()\n\t\t\t\t\t\t\t.map(|d| d.to_string())\n\t\t\t\t\t\t\t.unwrap_or_default(),\n\t\t\t\t\t\tcontent,\n\t\t\t\t\t\t..Default::default()\n\t\t\t\t\t})\n\t\t\t\t)\n\t\t\t})\n\t\t\t.collect();\n\n\t\tlet request_body = body_schema.map(|schema| {\n\t\t\tItem(OARequestBody {\n\t\t\t\tcontent: Self::schema_to_content(supported_types.or_all_types(), schema),\n\t\t\t\trequired: true,\n\t\t\t\t..Default::default()\n\t\t\t})\n\t\t});\n\n\t\tlet mut security = None;\n\t\tif requires_auth {\n\t\t\tlet mut sec = IndexMap::new();\n\t\t\tsec.insert(SECURITY_NAME.to_owned(), Vec::new());\n\t\t\tsecurity = Some(vec![sec]);\n\t\t}\n\n\t\tOperation {\n\t\t\ttags: Vec::new(),\n\t\t\toperation_id,\n\t\t\tdescription,\n\t\t\tparameters: params.into_params(),\n\t\t\trequest_body,\n\t\t\tresponses: Responses {\n\t\t\t\tresponses,\n\t\t\t\t..Default::default()\n\t\t\t},\n\t\t\tdeprecated: false,\n\t\t\tsecurity,\n\t\t\t..Default::default()\n\t\t}\n\t}\n}\n\n#[cfg(test)]\nmod test {\n\tuse super::*;\n\tuse crate::{NoContent, Raw, ResponseSchema};\n\n\t#[test]\n\tfn no_content_schema_to_content() {\n\t\tlet types = NoContent::accepted_types();\n\t\tlet schema = ::schema(StatusCode::NO_CONTENT);\n\t\tlet content =\n\t\t\tOperationDescription::schema_to_content(types.or_all_types(), Item(schema.schema));\n\t\tassert!(content.is_empty());\n\t}\n\n\t#[test]\n\tfn raw_schema_to_content() {\n\t\tlet types = Raw::<&str>::accepted_types();\n\t\tlet schema = as ResponseSchema>::schema(StatusCode::OK);\n\t\tlet content =\n\t\t\tOperationDescription::schema_to_content(types.or_all_types(), Item(schema.schema));\n\t\tassert_eq!(content.len(), 1);\n\t\tlet json = serde_json::to_string(&content.values().nth(0).unwrap()).unwrap();\n\t\tassert_eq!(json, r#\"{\"schema\":{\"type\":\"string\",\"format\":\"binary\"}}\"#);\n\t}\n}\n","traces":[{"line":15,"address":[6228832,6229362,6229408],"length":1,"stats":{"Line":1},"fn_name":"new_parameter_data"},{"line":25,"address":[6228988,6228915],"length":1,"stats":{"Line":2},"fn_name":null},{"line":27,"address":[6228998],"length":1,"stats":{"Line":1},"fn_name":null},{"line":29,"address":[6229069],"length":1,"stats":{"Line":1},"fn_name":null},{"line":42,"address":[6229424,6230633,6230927],"length":1,"stats":{"Line":2},"fn_name":null},{"line":46,"address":[6229464],"length":1,"stats":{"Line":2},"fn_name":null},{"line":47,"address":[6229531],"length":1,"stats":{"Line":1},"fn_name":null},{"line":50,"address":[6229598],"length":1,"stats":{"Line":1},"fn_name":null},{"line":51,"address":[6229690],"length":1,"stats":{"Line":1},"fn_name":null},{"line":54,"address":[6229768,6229984,6230660],"length":1,"stats":{"Line":3},"fn_name":null},{"line":55,"address":[6230326,6230238],"length":1,"stats":{"Line":2},"fn_name":null},{"line":56,"address":[6230529],"length":1,"stats":{"Line":1},"fn_name":null},{"line":57,"address":[6230353],"length":1,"stats":{"Line":1},"fn_name":null},{"line":58,"address":[6230470],"length":1,"stats":{"Line":1},"fn_name":null},{"line":65,"address":[6232797,6231264,6232503],"length":1,"stats":{"Line":2},"fn_name":null},{"line":69,"address":[6231304],"length":1,"stats":{"Line":2},"fn_name":null},{"line":70,"address":[6231371],"length":1,"stats":{"Line":1},"fn_name":null},{"line":73,"address":[6231438],"length":1,"stats":{"Line":1},"fn_name":null},{"line":74,"address":[6231530],"length":1,"stats":{"Line":1},"fn_name":null},{"line":77,"address":[6231608,6232530,6231824],"length":1,"stats":{"Line":3},"fn_name":null},{"line":78,"address":[6232166,6232078],"length":1,"stats":{"Line":2},"fn_name":null},{"line":79,"address":[6232377],"length":1,"stats":{"Line":1},"fn_name":null},{"line":80,"address":[6232193],"length":1,"stats":{"Line":1},"fn_name":null},{"line":82,"address":[6232310],"length":1,"stats":{"Line":1},"fn_name":null},{"line":83,"address":[6232369],"length":1,"stats":{"Line":1},"fn_name":null},{"line":88,"address":[6233410,6233136,6233449],"length":1,"stats":{"Line":2},"fn_name":null},{"line":89,"address":[6233161],"length":1,"stats":{"Line":2},"fn_name":null},{"line":90,"address":[6233246],"length":1,"stats":{"Line":2},"fn_name":null},{"line":91,"address":[6233338],"length":1,"stats":{"Line":2},"fn_name":null},{"line":111,"address":[6467151,6464499,6467077,6461749,6462633,6460976,6462752,6465391,6466271,6466304,6461823,6464425,6462707,6461856,6464544,6463603,6465317,6463648,6466197,6463529,6465424],"length":1,"stats":{"Line":8},"fn_name":null},{"line":115,"address":[],"length":0,"stats":{"Line":22},"fn_name":null},{"line":116,"address":[],"length":0,"stats":{"Line":12},"fn_name":null},{"line":117,"address":[],"length":0,"stats":{"Line":14},"fn_name":null},{"line":121,"address":[],"length":0,"stats":{"Line":8},"fn_name":null},{"line":123,"address":[],"length":0,"stats":{"Line":8},"fn_name":null},{"line":125,"address":[],"length":0,"stats":{"Line":8},"fn_name":null},{"line":128,"address":[],"length":0,"stats":{"Line":8},"fn_name":null},{"line":132,"address":[6233567,6233488],"length":1,"stats":{"Line":1},"fn_name":null},{"line":133,"address":[6233609,6233525],"length":1,"stats":{"Line":2},"fn_name":null},{"line":136,"address":[6233632,6233725],"length":1,"stats":{"Line":1},"fn_name":null},{"line":137,"address":[6233767,6233669],"length":1,"stats":{"Line":2},"fn_name":null},{"line":140,"address":[],"length":0,"stats":{"Line":2},"fn_name":null},{"line":141,"address":[],"length":0,"stats":{"Line":2},"fn_name":null},{"line":142,"address":[],"length":0,"stats":{"Line":2},"fn_name":null},{"line":145,"address":[6233808,6234786,6234959],"length":1,"stats":{"Line":3},"fn_name":null},{"line":149,"address":[6233852],"length":1,"stats":{"Line":3},"fn_name":null},{"line":150,"address":[6233920,6234000],"length":1,"stats":{"Line":6},"fn_name":null},{"line":151,"address":[6234448,6234247],"length":1,"stats":{"Line":6},"fn_name":null},{"line":152,"address":[6234302,6234390],"length":1,"stats":{"Line":6},"fn_name":null},{"line":153,"address":[6234400],"length":1,"stats":{"Line":3},"fn_name":null},{"line":159,"address":[6236626,6234992,6237946],"length":1,"stats":{"Line":2},"fn_name":null},{"line":161,"address":[6235413,6235059],"length":1,"stats":{"Line":4},"fn_name":null},{"line":162,"address":[6235660],"length":1,"stats":{"Line":2},"fn_name":null},{"line":163,"address":[6235700],"length":1,"stats":{"Line":2},"fn_name":null},{"line":164,"address":[6235740],"length":1,"stats":{"Line":2},"fn_name":null},{"line":165,"address":[6235772],"length":1,"stats":{"Line":2},"fn_name":null},{"line":166,"address":[6235828],"length":1,"stats":{"Line":2},"fn_name":null},{"line":167,"address":[6235861],"length":1,"stats":{"Line":2},"fn_name":null},{"line":168,"address":[6235879],"length":1,"stats":{"Line":2},"fn_name":null},{"line":169,"address":[6235919],"length":1,"stats":{"Line":2},"fn_name":null},{"line":171,"address":[6235139],"length":1,"stats":{"Line":2},"fn_name":null},{"line":172,"address":[6235169],"length":1,"stats":{"Line":2},"fn_name":null},{"line":173,"address":[6235199],"length":1,"stats":{"Line":2},"fn_name":null},{"line":174,"address":[6235229],"length":1,"stats":{"Line":2},"fn_name":null},{"line":175,"address":[6235309],"length":1,"stats":{"Line":2},"fn_name":null},{"line":176,"address":[6235321],"length":1,"stats":{"Line":2},"fn_name":null},{"line":177,"address":[6235373],"length":1,"stats":{"Line":2},"fn_name":null},{"line":178,"address":[6235403],"length":1,"stats":{"Line":2},"fn_name":null},{"line":181,"address":[6235937,6236073],"length":1,"stats":{"Line":4},"fn_name":null},{"line":183,"address":[6236065,6240382,6239387,6240521,6239344],"length":1,"stats":{"Line":6},"fn_name":"{closure#0}"},{"line":185,"address":[6239522,6239447],"length":1,"stats":{"Line":4},"fn_name":null},{"line":187,"address":[6239668,6239610],"length":1,"stats":{"Line":4},"fn_name":null},{"line":188,"address":[6239907],"length":1,"stats":{"Line":2},"fn_name":null},{"line":189,"address":[6239686],"length":1,"stats":{"Line":2},"fn_name":null},{"line":191,"address":[6240560,6240582],"length":1,"stats":{"Line":4},"fn_name":"{closure#0}"},{"line":193,"address":[6239760],"length":1,"stats":{"Line":2},"fn_name":null},{"line":194,"address":[6239856],"length":1,"stats":{"Line":2},"fn_name":null},{"line":200,"address":[6240608,6241080,6241104,6236135],"length":1,"stats":{"Line":3},"fn_name":"{closure#1}"},{"line":201,"address":[6240630,6240863],"length":1,"stats":{"Line":2},"fn_name":null},{"line":202,"address":[6240646,6240738],"length":1,"stats":{"Line":2},"fn_name":null},{"line":204,"address":[6240807],"length":1,"stats":{"Line":1},"fn_name":null},{"line":208,"address":[6236299],"length":1,"stats":{"Line":2},"fn_name":null},{"line":209,"address":[6237011,6236311],"length":1,"stats":{"Line":3},"fn_name":null},{"line":210,"address":[6236345],"length":1,"stats":{"Line":1},"fn_name":null},{"line":211,"address":[6236469,6236396],"length":1,"stats":{"Line":2},"fn_name":null},{"line":212,"address":[6236647],"length":1,"stats":{"Line":1},"fn_name":null},{"line":216,"address":[6236315],"length":1,"stats":{"Line":2},"fn_name":null},{"line":219,"address":[6237118],"length":1,"stats":{"Line":2},"fn_name":null},{"line":221,"address":[6237438],"length":1,"stats":{"Line":2},"fn_name":null}],"covered":89,"coverable":89},{"path":["/","home","runner","work","gotham_restful","gotham_restful","src","openapi","router.rs"],"content":"use super::{\n\tbuilder::OpenapiBuilder,\n\thandler::{OpenapiDocHandler, OpenapiSpecHandler},\n\toperation::OperationDescription\n};\nuse crate::{routing::*, EndpointWithSchema, ResourceWithSchema, ResponseSchema};\nuse gotham::{\n\thyper::{Method, StatusCode},\n\tpipeline::PipelineHandleChain,\n\tprelude::*,\n\trouter::builder::{RouterBuilder, ScopeBuilder}\n};\nuse lazy_regex::regex_replace_all;\nuse openapi_type::OpenapiType;\nuse std::{collections::HashMap, panic::RefUnwindSafe};\n\n/// This trait adds the `openapi_spec` and `openapi_doc` method to an OpenAPI-aware router.\npub trait GetOpenapi {\n\t/// Register a GET route to `path` that returns the OpenAPI specification in JSON format.\n\tfn openapi_spec(&mut self, path: &str);\n\n\t/// Register a GET route to `path` that returns the OpenAPI documentation in HTML format.\n\tfn openapi_doc(&mut self, path: &str);\n}\n\n#[derive(Debug)]\npub struct OpenapiRouter<'a, D> {\n\tpub(crate) router: &'a mut D,\n\tpub(crate) scope: Option<&'a str>,\n\tpub(crate) openapi_builder: &'a mut OpenapiBuilder\n}\n\nmacro_rules! implOpenapiRouter {\n\t($implType:ident) => {\n\t\timpl<'a, 'b, C, P> OpenapiRouter<'a, $implType<'b, C, P>>\n\t\twhere\n\t\t\tC: PipelineHandleChain

+ Copy + Send + Sync + 'static,\n\t\t\tP: RefUnwindSafe + Send + Sync + 'static\n\t\t{\n\t\t\tpub fn scope(&mut self, path: &str, callback: F)\n\t\t\twhere\n\t\t\t\tF: FnOnce(&mut OpenapiRouter<'_, ScopeBuilder<'_, C, P>>)\n\t\t\t{\n\t\t\t\tlet mut openapi_builder = self.openapi_builder.clone();\n\t\t\t\tlet new_scope = self\n\t\t\t\t\t.scope\n\t\t\t\t\t.map(|scope| format!(\"{scope}/{path}\").replace(\"//\", \"/\"));\n\t\t\t\tself.router.scope(path, |router| {\n\t\t\t\t\tlet mut router = OpenapiRouter {\n\t\t\t\t\t\trouter,\n\t\t\t\t\t\tscope: Some(new_scope.as_ref().map(String::as_ref).unwrap_or(path)),\n\t\t\t\t\t\topenapi_builder: &mut openapi_builder\n\t\t\t\t\t};\n\t\t\t\t\tcallback(&mut router);\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\timpl<'a, 'b, C, P> GetOpenapi for OpenapiRouter<'a, $implType<'b, C, P>>\n\t\twhere\n\t\t\tC: PipelineHandleChain

+ Copy + Send + Sync + 'static,\n\t\t\tP: RefUnwindSafe + Send + Sync + 'static\n\t\t{\n\t\t\tfn openapi_spec(&mut self, path: &str) {\n\t\t\t\tself.router\n\t\t\t\t\t.get(path)\n\t\t\t\t\t.to_new_handler(OpenapiSpecHandler::new(\n\t\t\t\t\t\tself.openapi_builder.openapi.clone()\n\t\t\t\t\t));\n\t\t\t}\n\n\t\t\tfn openapi_doc(&mut self, path: &str) {\n\t\t\t\tself.router\n\t\t\t\t\t.get(path)\n\t\t\t\t\t.to_new_handler(OpenapiDocHandler::new(self.openapi_builder.openapi.clone()));\n\t\t\t}\n\t\t}\n\n\t\timpl<'a, 'b, C, P> DrawResourcesWithSchema for OpenapiRouter<'a, $implType<'b, C, P>>\n\t\twhere\n\t\t\tC: PipelineHandleChain

+ Copy + Send + Sync + 'static,\n\t\t\tP: RefUnwindSafe + Send + Sync + 'static\n\t\t{\n\t\t\tfn resource(&mut self, mut path: &str) {\n\t\t\t\tif path.starts_with('/') {\n\t\t\t\t\tpath = &path[1..];\n\t\t\t\t}\n\t\t\t\tR::setup((self, path));\n\t\t\t}\n\t\t}\n\n\t\timpl<'a, 'b, C, P> DrawResourceRoutesWithSchema\n\t\t\tfor (&mut OpenapiRouter<'a, $implType<'b, C, P>>, &str)\n\t\twhere\n\t\t\tC: PipelineHandleChain

+ Copy + Send + Sync + 'static,\n\t\t\tP: RefUnwindSafe + Send + Sync + 'static\n\t\t{\n\t\t\tfn endpoint(&mut self) {\n\t\t\t\tlet mut responses: HashMap = HashMap::new();\n\t\t\t\tfor code in E::Output::status_codes() {\n\t\t\t\t\tresponses.insert(\n\t\t\t\t\t\tcode,\n\t\t\t\t\t\t(self.0).openapi_builder.add_schema(E::Output::schema(code))\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tlet mut path = format!(\"{}/{}\", self.0.scope.unwrap_or_default(), self.1);\n\t\t\t\tlet mut descr = OperationDescription::new::(responses, &path);\n\t\t\t\tif E::has_placeholders() {\n\t\t\t\t\tdescr.set_path_params(E::Placeholders::schema());\n\t\t\t\t}\n\t\t\t\tif E::needs_params() {\n\t\t\t\t\tdescr.set_query_params(E::Params::schema());\n\t\t\t\t}\n\t\t\t\tif E::needs_body() {\n\t\t\t\t\tlet body_schema = (self.0).openapi_builder.add_schema(E::Body::schema());\n\t\t\t\t\tdescr.set_body::(body_schema);\n\t\t\t\t}\n\n\t\t\t\tlet uri: &str = &E::uri();\n\t\t\t\tlet uri =\n\t\t\t\t\tregex_replace_all!(r#\"(^|/):([^/]+)(/|$)\"#, uri, |_, prefix, name, suffix| {\n\t\t\t\t\t\tformat!(\"{prefix}{{{name}}}{suffix}\")\n\t\t\t\t\t});\n\t\t\t\tif !uri.is_empty() {\n\t\t\t\t\tpath = format!(\"{path}/{uri}\");\n\t\t\t\t}\n\n\t\t\t\tlet op = descr.into_operation();\n\t\t\t\tlet mut item = (self.0).openapi_builder.remove_path(&path);\n\t\t\t\tmatch E::http_method() {\n\t\t\t\t\tMethod::GET => item.get = Some(op),\n\t\t\t\t\tMethod::PUT => item.put = Some(op),\n\t\t\t\t\tMethod::POST => item.post = Some(op),\n\t\t\t\t\tMethod::DELETE => item.delete = Some(op),\n\t\t\t\t\tMethod::OPTIONS => item.options = Some(op),\n\t\t\t\t\tMethod::HEAD => item.head = Some(op),\n\t\t\t\t\tMethod::PATCH => item.patch = Some(op),\n\t\t\t\t\tMethod::TRACE => item.trace = Some(op),\n\t\t\t\t\tmethod => {\n\t\t\t\t\t\twarn!(\"Ignoring unsupported method '{method}' in OpenAPI Specification\")\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t\t(self.0).openapi_builder.add_path(path, item);\n\n\t\t\t\t(&mut *(self.0).router, self.1).endpoint::()\n\t\t\t}\n\t\t}\n\t};\n}\n\nimplOpenapiRouter!(RouterBuilder);\nimplOpenapiRouter!(ScopeBuilder);\n","traces":[{"line":40,"address":[6718938,6717898,6717863,6717552,6718903,6718592],"length":1,"stats":{"Line":2},"fn_name":null},{"line":44,"address":[6717653,6717579,6718619,6718693],"length":1,"stats":{"Line":4},"fn_name":null},{"line":45,"address":[6718698,6718715,6717658,6717675],"length":1,"stats":{"Line":4},"fn_name":null},{"line":47,"address":[6718240,6719248,6719280,6718208,6717670,6718710],"length":1,"stats":{"Line":4},"fn_name":"{closure#0}<(), (), openapi_supports_scope::openapi_supports_scope::{closure#0}::{closure#0}::{closure#0}::{closure_env#0}>"},{"line":48,"address":[6717735,6718177,6719217,6718960,6717920,6718775],"length":1,"stats":{"Line":4},"fn_name":"{closure#1}<(), (), openapi_supports_scope::openapi_supports_scope::{closure#0}::{closure#0}::{closure#0}::{closure_env#0}>"},{"line":49,"address":[6718112,6719152,6718985,6717945],"length":1,"stats":{"Line":4},"fn_name":null},{"line":51,"address":[6718995,6719058,6717955,6718018],"length":1,"stats":{"Line":4},"fn_name":null},{"line":52,"address":[6719148,6718108],"length":1,"stats":{"Line":2},"fn_name":null},{"line":54,"address":[6718142,6719182],"length":1,"stats":{"Line":2},"fn_name":null},{"line":64,"address":[6263941,6263760,6263917],"length":1,"stats":{"Line":2},"fn_name":"openapi_spec<(borrow_bag::handle::Handle, ())>, borrow_bag::handle::Take>, ()), (gotham::pipeline::Pipeline<(gotham_restful::auth::AuthMiddleware, ())>, ())>"},{"line":65,"address":[6263790,6263890],"length":1,"stats":{"Line":4},"fn_name":null},{"line":67,"address":[6263869],"length":1,"stats":{"Line":2},"fn_name":null},{"line":68,"address":[6263819],"length":1,"stats":{"Line":2},"fn_name":null},{"line":84,"address":[6264240,6264384,6263952,6264096],"length":1,"stats":{"Line":6},"fn_name":"resource<(borrow_bag::handle::Handle, ())>, borrow_bag::handle::Take>, ()), (gotham::pipeline::Pipeline<(gotham_restful::auth::AuthMiddleware, ())>, ()), openapi_specification::CustomResource>"},{"line":85,"address":[6263976,6264264,6264120,6264237,6264381,6264408,6264093,6264525],"length":1,"stats":{"Line":7},"fn_name":null},{"line":86,"address":[6264478,6264046,6264190,6264334],"length":1,"stats":{"Line":1},"fn_name":null},{"line":88,"address":[6264294,6264150,6264438,6264006],"length":1,"stats":{"Line":6},"fn_name":null},{"line":98,"address":[6270640,6288610,6295293,6270598,6271261,6289285,6294672,6300672,6277261,6282640,6265253,6283261,6300638,6276640,6288656,6264624,6301301,6306650,6294626,6276606,6282606],"length":1,"stats":{"Line":9},"fn_name":"endpoint<(borrow_bag::handle::Handle, ())>, borrow_bag::handle::Take>, ()), (gotham::pipeline::Pipeline<(gotham_restful::auth::AuthMiddleware, ())>, ()), openapi_specification::custom_read_with___gotham_restful_endpoint>"},{"line":99,"address":[6270690,6288706,6294722,6300722,6282690,6276690,6264674],"length":1,"stats":{"Line":9},"fn_name":null},{"line":100,"address":[6294871,6288847,6288923,6294935,6264891,6270839,6264815,6282839,6276839,6276903,6300939,6282903,6270903,6300863],"length":1,"stats":{"Line":18},"fn_name":null},{"line":101,"address":[6283205,6265197,6289229,6295237,6271205,6301245,6277205],"length":1,"stats":{"Line":9},"fn_name":null},{"line":103,"address":[6295161,6301165,6271129,6283129,6289149,6277129,6265117],"length":1,"stats":{"Line":9},"fn_name":null},{"line":106,"address":[6289304,6277280,6301320,6271280,6283280,6265272,6295312],"length":1,"stats":{"Line":9},"fn_name":null},{"line":107,"address":[6295874,6301657,6271617,6265609,6283617,6277842,6289641,6289866,6295649,6301882,6277617,6271842,6283842,6265834],"length":1,"stats":{"Line":9},"fn_name":null},{"line":108,"address":[6271906,6283906,6289930,6283809,6277906,6295841,6295938,6301849,6265801,6265898,6289833,6277809,6271809,6301946],"length":1,"stats":{"Line":18},"fn_name":null},{"line":109,"address":[6277934,6289958,6295958,6283926,6301966,6265926,6271934],"length":1,"stats":{"Line":4},"fn_name":null},{"line":111,"address":[6277977,6283981,6283912,6302021,6289936,6271977,6295944,6301952,6265904,6277912,6290001,6265969,6271912,6296013],"length":1,"stats":{"Line":18},"fn_name":null},{"line":112,"address":[6290021,6271997,6296041,6302041,6277997,6284001,6265989],"length":1,"stats":{"Line":1},"fn_name":null},{"line":114,"address":[6272052,6265975,6277983,6284056,6290007,6283987,6290076,6296084,6278052,6302027,6302096,6296019,6271983,6266044],"length":1,"stats":{"Line":18},"fn_name":null},{"line":115,"address":[6284088,6296116,6278084,6266076,6302128,6272084,6290108],"length":1,"stats":{"Line":2},"fn_name":null},{"line":116,"address":[6302233,6290209,6296221,6266181,6272189,6278189,6284193],"length":1,"stats":{"Line":2},"fn_name":null},{"line":119,"address":[6284318,6278066,6272066,6290090,6290334,6296251,6272314,6284070,6302358,6278314,6266306,6284223,6302110,6290239,6278219,6296098,6302263,6296346,6266058,6266211,6272219],"length":1,"stats":{"Line":27},"fn_name":null},{"line":121,"address":[6186304,6186912,6186419,6186739,6186624,6186639,6186319,6186592],"length":1,"stats":{"Line":62},"fn_name":"{closure#0}"},{"line":122,"address":[6312029,6310941,6311277,6311597,6312413,6310157,6310493],"length":1,"stats":{"Line":4},"fn_name":null},{"line":124,"address":[6284517,6266505,6296450,6278418,6279034,6297066,6284422,6302557,6266410,6290438,6302462,6267026,6296545,6285038,6290533,6272513,6291054,6278513,6303078,6272418,6273034],"length":1,"stats":{"Line":23},"fn_name":null},{"line":125,"address":[6290636,6278616,6284620,6302660,6296648,6266608,6272616],"length":1,"stats":{"Line":5},"fn_name":null},{"line":128,"address":[6297079,6279047,6291067,6296572,6272540,6273047,6278540,6266532,6290560,6302584,6284544,6267039,6285051,6303091],"length":1,"stats":{"Line":18},"fn_name":null},{"line":129,"address":[6267047,6291075,6291186,6303099,6285170,6297087,6279166,6285059,6279055,6297198,6267158,6303210,6273055,6273166],"length":1,"stats":{"Line":18},"fn_name":null},{"line":130,"address":[6267257,6267305,6291285,6279265,6273265,6291333,6285317,6303309,6279313,6297345,6285269,6297297,6273313,6303357],"length":1,"stats":{"Line":18},"fn_name":null},{"line":131,"address":[6275435,6297605,6305479,6273573,6267565,6287439,6269427,6293455,6299467,6303617,6281435,6279573,6291593,6285577],"length":1,"stats":{"Line":7},"fn_name":null},{"line":132,"address":[6297841,6269199,6281207,6303853,6299239,6305251,6279809,6273809,6275207,6267801,6285813,6287211,6291829,6293227],"length":1,"stats":{"Line":1},"fn_name":null},{"line":133,"address":[6267683,6273691,6287325,6275321,6291711,6303735,6297723,6299353,6269313,6285695,6293341,6305365,6281321,6279691],"length":1,"stats":{"Line":0},"fn_name":null},{"line":134,"address":[6273927,6279927,6267919,6291947,6305137,6297959,6299125,6285931,6303971,6269085,6287097,6281093,6293113,6275093],"length":1,"stats":{"Line":0},"fn_name":null},{"line":135,"address":[6291475,6305579,6297487,6273455,6275535,6267447,6299567,6303499,6269527,6285459,6293555,6279455,6281535,6287539],"length":1,"stats":{"Line":0},"fn_name":null},{"line":136,"address":[6286049,6280045,6286983,6298077,6268971,6304089,6292065,6268037,6274979,6280979,6299011,6305023,6274045,6292999],"length":1,"stats":{"Line":0},"fn_name":null},{"line":137,"address":[6280245,6292265,6268749,6286761,6274245,6298277,6298789,6274757,6292777,6304289,6286249,6268237,6280757,6304801],"length":1,"stats":{"Line":1},"fn_name":null},{"line":138,"address":[6292165,6292885,6298177,6304189,6268137,6286149,6274145,6268857,6286869,6280145,6304909,6280865,6298897,6274865],"length":1,"stats":{"Line":0},"fn_name":null},{"line":139,"address":[6285371,6267359,6279367,6273367,6291387,6297399,6303411],"length":1,"stats":{"Line":0},"fn_name":null},{"line":140,"address":[6285411,6286458,6274546,6268388,6268446,6280396,6280546,6274454,6286400,6298486,6303451,6274396,6291427,6304440,6304498,6267399,6304590,6268538,6279407,6292474,6292566,6273407,6297439,6298578,6298428,6286550,6292416,6280454],"length":1,"stats":{"Line":0},"fn_name":null},{"line":143,"address":[6299719,6281687,6305731,6287691,6269679,6275687,6293707],"length":1,"stats":{"Line":9},"fn_name":null},{"line":145,"address":[6287905,6281901,6293921,6305945,6299933,6275901,6269893],"length":1,"stats":{"Line":9},"fn_name":null}],"covered":44,"coverable":51},{"path":["/","home","runner","work","gotham_restful","gotham_restful","src","response","auth_result.rs"],"content":"use crate::{IntoResponseError, Response};\nuse gotham::{hyper::StatusCode, mime::TEXT_PLAIN_UTF_8};\nuse gotham_restful_derive::ResourceError;\n#[cfg(feature = \"openapi\")]\nuse openapi_type::{OpenapiSchema, OpenapiType};\n\n/// This is an error type that always yields a _403 Forbidden_ response. This type\n/// is best used in combination with [`AuthSuccess`] or [`AuthResult`].\n#[derive(Clone, Debug)]\npub struct AuthError(String);\n\nimpl AuthError {\n\tpub fn new>(msg: T) -> Self {\n\t\tSelf(msg.into())\n\t}\n}\n\nimpl IntoResponseError for AuthError {\n\t// TODO why does this need to be serde_json::Error ?!?\n\ttype Err = serde_json::Error;\n\n\tfn into_response_error(self) -> Result {\n\t\tOk(Response::new(\n\t\t\tStatusCode::FORBIDDEN,\n\t\t\tself.0,\n\t\t\tSome(TEXT_PLAIN_UTF_8)\n\t\t))\n\t}\n\n\t#[cfg(feature = \"openapi\")]\n\tfn status_codes() -> Vec {\n\t\tvec![StatusCode::FORBIDDEN]\n\t}\n\n\t#[cfg(feature = \"openapi\")]\n\tfn schema(code: StatusCode) -> OpenapiSchema {\n\t\tassert_eq!(code, StatusCode::FORBIDDEN);\n\t\t as OpenapiType>::schema()\n\t}\n}\n\n/// This return type can be used to wrap any type implementing [IntoResponse](crate::IntoResponse)\n/// that can only be returned if the client is authenticated. Otherwise, an empty _403 Forbidden_\n/// response will be issued.\n///\n/// Use can look something like this (assuming the `auth` feature is enabled):\n///\n/// ```rust\n/// # #[macro_use] extern crate gotham_restful_derive;\n/// # #[cfg(feature = \"auth\")]\n/// # mod auth_feature_enabled {\n/// # use gotham::state::State;\n/// # use gotham_restful::*;\n/// # use serde::Deserialize;\n/// #\n/// # #[derive(Resource)]\n/// # #[resource(read_all)]\n/// # struct MyResource;\n/// #\n/// # #[derive(Clone, Deserialize)]\n/// # struct MyAuthData { exp : u64 }\n/// #\n/// #[read_all]\n/// fn read_all(auth: AuthStatus) -> AuthSuccess {\n/// \tlet auth_data = auth.ok()?;\n/// \t// do something\n/// \tOk(NoContent::default())\n/// }\n/// # }\n/// ```\npub type AuthSuccess = Result;\n\n/// This is an error type that either yields a _403 Forbidden_ response if produced\n/// from an authentication error, or delegates to another error type. This type is\n/// best used with [`AuthResult`].\n#[derive(Debug, Clone, ResourceError)]\npub enum AuthErrorOrOther {\n\tForbidden(#[from] AuthError),\n\n\t#[status(INTERNAL_SERVER_ERROR)]\n\t#[display(\"{0}\")]\n\tOther(E)\n}\n\nmod private {\n\tuse gotham::handler::HandlerError;\n\tpub trait Sealed {}\n\timpl> Sealed for E {}\n}\n\nimpl From for AuthErrorOrOther\nwhere\n\t// TODO https://github.com/msrd0/gotham_restful/issues/20\n\tF: private::Sealed + Into\n{\n\tfn from(err: F) -> Self {\n\t\tSelf::Other(err.into())\n\t}\n}\n\n/// This return type can be used to wrap any type implementing [IntoResponse](crate::IntoResponse)\n/// that can only be returned if the client is authenticated. Otherwise, an empty _403 Forbidden_\n/// response will be issued.\n///\n/// Use can look something like this (assuming the `auth` feature is enabled):\n///\n/// ```\n/// # #[macro_use] extern crate gotham_restful_derive;\n/// # #[cfg(feature = \"auth\")]\n/// # mod auth_feature_enabled {\n/// # use gotham::state::State;\n/// # use gotham_restful::*;\n/// # use serde::Deserialize;\n/// # use std::io;\n/// #\n/// # #[derive(Resource)]\n/// # #[resource(read_all)]\n/// # struct MyResource;\n/// #\n/// # #[derive(Clone, Deserialize)]\n/// # struct MyAuthData { exp : u64 }\n/// #\n/// #[read_all]\n/// fn read_all(auth: AuthStatus) -> AuthResult {\n/// \tlet auth_data = auth.ok()?;\n/// \t// do something\n/// \tOk(NoContent::default().into())\n/// }\n/// # }\n/// ```\npub type AuthResult = Result>;\n","traces":[{"line":13,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":14,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":22,"address":[7718704],"length":1,"stats":{"Line":0},"fn_name":"into_response_error"},{"line":23,"address":[6163719],"length":1,"stats":{"Line":0},"fn_name":null},{"line":25,"address":[7718721],"length":1,"stats":{"Line":0},"fn_name":null},{"line":26,"address":[8958340],"length":1,"stats":{"Line":0},"fn_name":null},{"line":31,"address":[6163792,6163902],"length":1,"stats":{"Line":1},"fn_name":"status_codes"},{"line":32,"address":[8958477,8958552],"length":1,"stats":{"Line":1},"fn_name":null},{"line":36,"address":[6163920],"length":1,"stats":{"Line":1},"fn_name":"schema"},{"line":38,"address":[6164019],"length":1,"stats":{"Line":1},"fn_name":null},{"line":96,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":97,"address":[],"length":0,"stats":{"Line":0},"fn_name":null}],"covered":4,"coverable":12},{"path":["/","home","runner","work","gotham_restful","gotham_restful","src","response","mod.rs"],"content":"use futures_util::future::{self, BoxFuture, FutureExt};\nuse gotham::{\n\thandler::HandlerError,\n\thyper::{\n\t\theader::{HeaderMap, HeaderName, HeaderValue},\n\t\tBody, StatusCode\n\t},\n\tmime::{Mime, APPLICATION_JSON, STAR_STAR}\n};\n#[cfg(feature = \"openapi\")]\nuse openapi_type::{OpenapiSchema, OpenapiType};\nuse serde::Serialize;\n#[cfg(feature = \"errorlog\")]\nuse std::fmt::Display;\nuse std::{convert::Infallible, fmt::Debug, future::Future, pin::Pin};\n\nmod auth_result;\n#[allow(unreachable_pub)]\npub use auth_result::{AuthError, AuthErrorOrOther, AuthResult, AuthSuccess};\n\nmod no_content;\n#[allow(unreachable_pub)]\npub use no_content::NoContent;\n\nmod raw;\n#[allow(unreachable_pub)]\npub use raw::Raw;\n\nmod redirect;\n#[allow(unreachable_pub)]\npub use redirect::Redirect;\n\nmod result;\n#[allow(unreachable_pub)]\npub use result::IntoResponseError;\n\nmod success;\n#[allow(unreachable_pub)]\npub use success::Success;\n\npub(crate) trait OrAllTypes {\n\tfn or_all_types(self) -> Vec;\n}\n\nimpl OrAllTypes for Option> {\n\tfn or_all_types(self) -> Vec {\n\t\tself.unwrap_or_else(|| vec![STAR_STAR])\n\t}\n}\n\n/// A response, used to create the final gotham response from.\n///\n/// This type is not meant to be used as the return type of endpoint handlers. While it can be\n/// freely used without the `openapi` feature, it is more complicated to use when you enable it,\n/// since this type does not store any schema information. You can attach schema information\n/// like so:\n///\n/// ```rust\n/// # #[cfg(feature = \"openapi\")] mod example {\n/// # use gotham::hyper::StatusCode;\n/// # use gotham_restful::*;\n/// # use openapi_type::*;\n/// fn schema(code: StatusCode) -> OpenapiSchema {\n/// \tassert_eq!(code, StatusCode::ACCEPTED);\n/// \t<()>::schema()\n/// }\n///\n/// fn status_codes() -> Vec {\n/// \tvec![StatusCode::ACCEPTED]\n/// }\n///\n/// #[create(schema = \"schema\", status_codes = \"status_codes\")]\n/// fn create(body: Raw>) {}\n/// # }\n/// ```\n#[derive(Debug)]\npub struct Response {\n\tpub(crate) status: StatusCode,\n\tpub(crate) body: Body,\n\tpub(crate) mime: Option,\n\tpub(crate) headers: HeaderMap\n}\n\nimpl Response {\n\t/// Create a new [Response] from raw data.\n\t#[must_use = \"Creating a response is pointless if you don't use it\"]\n\tpub fn new>(status: StatusCode, body: B, mime: Option) -> Self {\n\t\tSelf {\n\t\t\tstatus,\n\t\t\tbody: body.into(),\n\t\t\tmime,\n\t\t\theaders: Default::default()\n\t\t}\n\t}\n\n\t/// Create a [Response] with mime type json from already serialized data.\n\t#[must_use = \"Creating a response is pointless if you don't use it\"]\n\tpub fn json>(status: StatusCode, body: B) -> Self {\n\t\tSelf {\n\t\t\tstatus,\n\t\t\tbody: body.into(),\n\t\t\tmime: Some(APPLICATION_JSON),\n\t\t\theaders: Default::default()\n\t\t}\n\t}\n\n\t/// Create a _204 No Content_ [Response].\n\t#[must_use = \"Creating a response is pointless if you don't use it\"]\n\tpub fn no_content() -> Self {\n\t\tSelf {\n\t\t\tstatus: StatusCode::NO_CONTENT,\n\t\t\tbody: Body::empty(),\n\t\t\tmime: None,\n\t\t\theaders: Default::default()\n\t\t}\n\t}\n\n\t/// Create an empty _403 Forbidden_ [Response].\n\t#[must_use = \"Creating a response is pointless if you don't use it\"]\n\tpub fn forbidden() -> Self {\n\t\tSelf {\n\t\t\tstatus: StatusCode::FORBIDDEN,\n\t\t\tbody: Body::empty(),\n\t\t\tmime: None,\n\t\t\theaders: Default::default()\n\t\t}\n\t}\n\n\t/// Return the status code of this [Response].\n\tpub fn status(&self) -> StatusCode {\n\t\tself.status\n\t}\n\n\t/// Return the mime type of this [Response].\n\tpub fn mime(&self) -> Option<&Mime> {\n\t\tself.mime.as_ref()\n\t}\n\n\t/// Add an HTTP header to the [Response].\n\tpub fn header(&mut self, name: HeaderName, value: HeaderValue) {\n\t\tself.headers.insert(name, value);\n\t}\n\n\tpub(crate) fn with_headers(mut self, headers: HeaderMap) -> Self {\n\t\tself.headers = headers;\n\t\tself\n\t}\n\n\t#[cfg(test)]\n\tpub(crate) fn full_body(\n\t\tmut self\n\t) -> Result, ::Error> {\n\t\tuse futures_executor::block_on;\n\t\tuse gotham::hyper::body::to_bytes;\n\n\t\tlet bytes: &[u8] = &block_on(to_bytes(&mut self.body))?;\n\t\tOk(bytes.to_vec())\n\t}\n}\n\nimpl IntoResponse for Response {\n\ttype Err = Infallible;\n\n\tfn into_response(self) -> BoxFuture<'static, Result> {\n\t\tfuture::ok(self).boxed()\n\t}\n}\n\n/// This trait needs to be implemented by every type returned from an endpoint to\n/// to provide the response.\npub trait IntoResponse {\n\ttype Err: Into + Send + Sync + 'static;\n\n\t/// Turn this into a response that can be returned to the browser. This api will likely\n\t/// change in the future.\n\tfn into_response(self) -> BoxFuture<'static, Result>;\n\n\t/// Return a list of supported mime types.\n\tfn accepted_types() -> Option> {\n\t\tNone\n\t}\n}\n\n/// Additional details for [IntoResponse] to be used with an OpenAPI-aware router.\n#[cfg(feature = \"openapi\")]\npub trait ResponseSchema {\n\t/// All status codes returned by this response. Returns `[StatusCode::OK]` by default.\n\tfn status_codes() -> Vec {\n\t\tvec![StatusCode::OK]\n\t}\n\n\t/// Return the schema of the response for the given status code. The code may\n\t/// only be one that was previously returned by [Self::status_codes]. The\n\t/// implementation should panic if that is not the case.\n\tfn schema(code: StatusCode) -> OpenapiSchema;\n}\n\n#[cfg(feature = \"openapi\")]\nmod private {\n\tpub trait Sealed {}\n}\n\n/// A trait provided to convert a resource's result to json, and provide an OpenAPI schema to the\n/// router. This trait is implemented for all types that implement [IntoResponse] and\n/// [ResponseSchema].\n#[cfg(feature = \"openapi\")]\npub trait IntoResponseWithSchema: IntoResponse + ResponseSchema + private::Sealed {}\n\n#[cfg(feature = \"openapi\")]\nimpl private::Sealed for R {}\n\n#[cfg(feature = \"openapi\")]\nimpl IntoResponseWithSchema for R {}\n\n/// The default json returned on an 500 Internal Server Error.\n#[derive(Debug, Serialize)]\n#[cfg_attr(feature = \"openapi\", derive(OpenapiType))]\npub(crate) struct ResourceError {\n\t/// This is always `true` and can be used to detect an error response without looking at the\n\t/// HTTP status code.\n\terror: bool,\n\t/// The error message.\n\tmessage: String\n}\n\nimpl From for ResourceError {\n\tfn from(message: T) -> Self {\n\t\tSelf {\n\t\t\terror: true,\n\t\t\tmessage: message.to_string()\n\t\t}\n\t}\n}\n\n#[cfg(feature = \"errorlog\")]\nfn errorlog(e: E) {\n\terror!(\"The handler encountered an error: {e}\");\n}\n\n#[cfg(not(feature = \"errorlog\"))]\nfn errorlog(_e: E) {}\n\nfn handle_error(e: E) -> Pin> + Send>>\nwhere\n\tE: Debug + IntoResponseError\n{\n\tlet msg = format!(\"{e:?}\");\n\tlet res = e.into_response_error();\n\tmatch &res {\n\t\tOk(res) if res.status.is_server_error() => errorlog(msg),\n\t\tErr(err) => {\n\t\t\terrorlog(msg);\n\t\t\terrorlog(format!(\"{err:?}\"));\n\t\t},\n\t\t_ => {}\n\t};\n\tfuture::ready(res).boxed()\n}\n\nimpl IntoResponse for Pin + Send>>\nwhere\n\tRes: IntoResponse + 'static\n{\n\ttype Err = Res::Err;\n\n\tfn into_response(self) -> Pin> + Send>> {\n\t\tself.then(IntoResponse::into_response).boxed()\n\t}\n\n\tfn accepted_types() -> Option> {\n\t\tRes::accepted_types()\n\t}\n}\n\n#[cfg(feature = \"openapi\")]\nimpl ResponseSchema for Pin + Send>>\nwhere\n\tRes: ResponseSchema\n{\n\tfn status_codes() -> Vec {\n\t\tRes::status_codes()\n\t}\n\n\tfn schema(code: StatusCode) -> OpenapiSchema {\n\t\tRes::schema(code)\n\t}\n}\n\n#[cfg(test)]\nmod test {\n\tuse super::*;\n\tuse futures_executor::block_on;\n\tuse thiserror::Error;\n\n\t#[derive(Debug, Default, Deserialize, Serialize)]\n\t#[cfg_attr(feature = \"openapi\", derive(openapi_type::OpenapiType))]\n\tstruct Msg {\n\t\tmsg: String\n\t}\n\n\t#[derive(Debug, Default, Error)]\n\t#[error(\"An Error\")]\n\tstruct MsgError;\n\n\t#[test]\n\tfn result_from_future() {\n\t\tlet nc = NoContent::default();\n\t\tlet res = block_on(nc.into_response()).unwrap();\n\n\t\tlet fut_nc = async move { NoContent::default() }.boxed();\n\t\tlet fut_res = block_on(fut_nc.into_response()).unwrap();\n\n\t\tassert_eq!(res.status, fut_res.status);\n\t\tassert_eq!(res.mime, fut_res.mime);\n\t\tassert_eq!(res.full_body().unwrap(), fut_res.full_body().unwrap());\n\t}\n}\n","traces":[{"line":46,"address":[6193552],"length":1,"stats":{"Line":3},"fn_name":"or_all_types"},{"line":47,"address":[5908945,5908928],"length":1,"stats":{"Line":9},"fn_name":"{closure#0}"},{"line":87,"address":[5909904,5909968,5909487,5909934,5909457,5910355,5909104,5909520,5910325],"length":1,"stats":{"Line":8},"fn_name":null},{"line":90,"address":[5909611,5909172,5910031],"length":1,"stats":{"Line":9},"fn_name":null},{"line":92,"address":[5910166,5909298,5909745],"length":1,"stats":{"Line":9},"fn_name":null},{"line":98,"address":[5910790,5910400,5910817],"length":1,"stats":{"Line":2},"fn_name":null},{"line":101,"address":[5910440],"length":1,"stats":{"Line":2},"fn_name":null},{"line":102,"address":[5910454],"length":1,"stats":{"Line":2},"fn_name":null},{"line":103,"address":[5910631],"length":1,"stats":{"Line":2},"fn_name":null},{"line":109,"address":[5911024,5911051,5910832],"length":1,"stats":{"Line":2},"fn_name":null},{"line":112,"address":[5910854],"length":1,"stats":{"Line":2},"fn_name":null},{"line":114,"address":[5910868],"length":1,"stats":{"Line":2},"fn_name":null},{"line":120,"address":[5911264,5911291,5911072],"length":1,"stats":{"Line":0},"fn_name":null},{"line":123,"address":[5911094],"length":1,"stats":{"Line":0},"fn_name":null},{"line":125,"address":[5911108],"length":1,"stats":{"Line":0},"fn_name":null},{"line":130,"address":[5911312],"length":1,"stats":{"Line":1},"fn_name":null},{"line":131,"address":[5911317],"length":1,"stats":{"Line":1},"fn_name":null},{"line":135,"address":[5911328],"length":1,"stats":{"Line":1},"fn_name":null},{"line":136,"address":[5911333],"length":1,"stats":{"Line":1},"fn_name":null},{"line":140,"address":[5911344],"length":1,"stats":{"Line":2},"fn_name":null},{"line":141,"address":[5911362],"length":1,"stats":{"Line":2},"fn_name":null},{"line":144,"address":[5911408,5911601],"length":1,"stats":{"Line":2},"fn_name":null},{"line":145,"address":[5911440,5911557],"length":1,"stats":{"Line":4},"fn_name":null},{"line":146,"address":[5911581],"length":1,"stats":{"Line":2},"fn_name":null},{"line":150,"address":[5912035,5912061,5911632],"length":1,"stats":{"Line":1},"fn_name":null},{"line":156,"address":[5911726,5911654,5911956],"length":1,"stats":{"Line":3},"fn_name":null},{"line":157,"address":[5911972],"length":1,"stats":{"Line":2},"fn_name":null},{"line":164,"address":[5912080],"length":1,"stats":{"Line":0},"fn_name":"into_response"},{"line":165,"address":[5912100],"length":1,"stats":{"Line":0},"fn_name":null},{"line":179,"address":[6012560],"length":1,"stats":{"Line":7},"fn_name":"accepted_types>"},{"line":180,"address":[6012563],"length":1,"stats":{"Line":7},"fn_name":null},{"line":188,"address":[6012576,6012686],"length":1,"stats":{"Line":4},"fn_name":"status_codes>"},{"line":189,"address":[6012663,6012589],"length":1,"stats":{"Line":4},"fn_name":null},{"line":227,"address":[5912160,5912284],"length":1,"stats":{"Line":2},"fn_name":"from"},{"line":230,"address":[5912189],"length":1,"stats":{"Line":2},"fn_name":null},{"line":236,"address":[5912683,5912320],"length":1,"stats":{"Line":1},"fn_name":"errorlog"},{"line":237,"address":[5912413,5912332,5912468,5912539],"length":1,"stats":{"Line":3},"fn_name":null},{"line":243,"address":[5915569,5915600,5914609,5916458,5912720,5915498,5916529,5914640,5913578,5913680,5913649,5914538],"length":1,"stats":{"Line":1},"fn_name":"handle_error"},{"line":247,"address":[5915644,5912764,5913792,5914684,5913724,5912832,5914752,5915712],"length":1,"stats":{"Line":2},"fn_name":null},{"line":248,"address":[5913959,5915879,5915815,5912935,5914919,5914855,5913895,5912999],"length":1,"stats":{"Line":2},"fn_name":null},{"line":249,"address":[5914927,5913007,5913967,5915887],"length":1,"stats":{"Line":1},"fn_name":null},{"line":250,"address":[5915373,5915045,5916005,5916333,5913125,5913453,5914413,5914085],"length":1,"stats":{"Line":2},"fn_name":null},{"line":251,"address":[5914146,5913186,5915106,5916066],"length":1,"stats":{"Line":0},"fn_name":null},{"line":252,"address":[5913194,5914154,5915114,5916074],"length":1,"stats":{"Line":0},"fn_name":null},{"line":253,"address":[5914252,5913292,5915212,5916172],"length":1,"stats":{"Line":0},"fn_name":null},{"line":255,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":257,"address":[5914011,5916404,5914484,5915931,5915444,5912727,5913051,5914971,5914647,5915607,5913687,5913524],"length":1,"stats":{"Line":3},"fn_name":null},{"line":266,"address":[6336304],"length":1,"stats":{"Line":1},"fn_name":"into_response"},{"line":267,"address":[6336334],"length":1,"stats":{"Line":1},"fn_name":null},{"line":270,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":271,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":280,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":281,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":284,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":285,"address":[],"length":0,"stats":{"Line":0},"fn_name":null}],"covered":40,"coverable":55},{"path":["/","home","runner","work","gotham_restful","gotham_restful","src","response","no_content.rs"],"content":"use super::{handle_error, IntoResponse};\n#[cfg(feature = \"openapi\")]\nuse crate::ResponseSchema;\nuse crate::{IntoResponseError, Response};\nuse futures_util::{future, future::FutureExt};\n#[cfg(feature = \"openapi\")]\nuse gotham::hyper::StatusCode;\nuse gotham::{\n\thyper::header::{HeaderMap, HeaderValue, IntoHeaderName},\n\tmime::Mime\n};\n#[cfg(feature = \"openapi\")]\nuse openapi_type::{OpenapiSchema, OpenapiType};\nuse std::{fmt::Debug, future::Future, pin::Pin};\n\n/// This is the return type of a resource that doesn't actually return something. It will result\n/// in a _204 No Content_ answer by default. You don't need to use this type directly if using\n/// the function attributes:\n///\n/// ```\n/// # #[macro_use] extern crate gotham_restful_derive;\n/// # mod doc_tests_are_broken {\n/// # use gotham::state::State;\n/// # use gotham_restful::*;\n/// #\n/// # #[derive(Resource)]\n/// # #[resource(read_all)]\n/// # struct MyResource;\n/// #\n/// #[read_all]\n/// fn read_all() {\n/// \t// do something\n/// }\n/// # }\n/// ```\n#[derive(Clone, Debug, Default)]\npub struct NoContent {\n\theaders: HeaderMap\n}\n\nimpl From<()> for NoContent {\n\tfn from(_: ()) -> Self {\n\t\tSelf::default()\n\t}\n}\n\nimpl NoContent {\n\t/// Set a custom HTTP header. If a header with this name was set before, its value is being updated.\n\tpub fn header(&mut self, name: K, value: HeaderValue) {\n\t\tself.headers.insert(name, value);\n\t}\n\n\t/// Allow manipulating HTTP headers.\n\tpub fn headers_mut(&mut self) -> &mut HeaderMap {\n\t\t&mut self.headers\n\t}\n}\n\nimpl IntoResponse for NoContent {\n\t// TODO this shouldn't be a serde_json::Error\n\ttype Err = serde_json::Error; // just for easier handling of `Result`\n\n\t/// This will always be a _204 No Content_ together with an empty string.\n\tfn into_response(self) -> Pin> + Send>> {\n\t\tfuture::ok(Response::no_content().with_headers(self.headers)).boxed()\n\t}\n\n\tfn accepted_types() -> Option> {\n\t\tSome(Vec::new())\n\t}\n}\n\n#[cfg(feature = \"openapi\")]\nimpl ResponseSchema for NoContent {\n\tfn status_codes() -> Vec {\n\t\tvec![StatusCode::NO_CONTENT]\n\t}\n\n\t/// Returns the schema of the `()` type.\n\tfn schema(code: StatusCode) -> OpenapiSchema {\n\t\tassert_eq!(code, StatusCode::NO_CONTENT);\n\t\t<()>::schema()\n\t}\n}\n\nimpl IntoResponse for Result\nwhere\n\tE: Debug + IntoResponseError\n{\n\ttype Err = serde_json::Error;\n\n\tfn into_response(\n\t\tself\n\t) -> Pin> + Send>> {\n\t\tmatch self {\n\t\t\tOk(nc) => nc.into_response(),\n\t\t\tErr(e) => handle_error(e)\n\t\t}\n\t}\n\n\tfn accepted_types() -> Option> {\n\t\tNoContent::accepted_types()\n\t}\n}\n\n#[cfg(feature = \"openapi\")]\nimpl ResponseSchema for Result\nwhere\n\tE: Debug + IntoResponseError\n{\n\tfn status_codes() -> Vec {\n\t\tlet mut status_codes = E::status_codes();\n\t\tstatus_codes.push(StatusCode::NO_CONTENT);\n\t\tstatus_codes\n\t}\n\n\tfn schema(code: StatusCode) -> OpenapiSchema {\n\t\tmatch code {\n\t\t\tStatusCode::NO_CONTENT => ::schema(StatusCode::NO_CONTENT),\n\t\t\tcode => E::schema(code)\n\t\t}\n\t}\n}\n\n#[cfg(test)]\nmod test {\n\tuse super::*;\n\tuse futures_executor::block_on;\n\tuse gotham::hyper::{header::ACCESS_CONTROL_ALLOW_ORIGIN, StatusCode};\n\tuse thiserror::Error;\n\n\t#[derive(Debug, Default, Error)]\n\t#[error(\"An Error\")]\n\tstruct MsgError;\n\n\t#[test]\n\tfn no_content_has_empty_response() {\n\t\tlet no_content = NoContent::default();\n\t\tlet res = block_on(no_content.into_response()).expect(\"didn't expect error response\");\n\t\tassert_eq!(res.status, StatusCode::NO_CONTENT);\n\t\tassert_eq!(res.mime, None);\n\t\tassert_eq!(res.full_body().unwrap(), &[] as &[u8]);\n\n\t\t#[cfg(feature = \"openapi\")]\n\t\tassert_eq!(NoContent::status_codes(), vec![StatusCode::NO_CONTENT]);\n\t}\n\n\t#[test]\n\tfn no_content_result() {\n\t\tlet no_content: Result = Ok(NoContent::default());\n\t\tlet res = block_on(no_content.into_response()).expect(\"didn't expect error response\");\n\t\tassert_eq!(res.status, StatusCode::NO_CONTENT);\n\t\tassert_eq!(res.mime, None);\n\t\tassert_eq!(res.full_body().unwrap(), &[] as &[u8]);\n\n\t\t#[cfg(feature = \"openapi\")]\n\t\tassert_eq!(>::status_codes(), vec![\n\t\t\tStatusCode::INTERNAL_SERVER_ERROR,\n\t\t\tStatusCode::NO_CONTENT\n\t\t]);\n\t}\n\n\t#[test]\n\tfn no_content_custom_headers() {\n\t\tlet mut no_content = NoContent::default();\n\t\tno_content.header(ACCESS_CONTROL_ALLOW_ORIGIN, HeaderValue::from_static(\"*\"));\n\t\tlet res = block_on(no_content.into_response()).expect(\"didn't expect error response\");\n\t\tlet cors = res.headers.get(ACCESS_CONTROL_ALLOW_ORIGIN);\n\t\tassert_eq!(cors.map(|value| value.to_str().unwrap()), Some(\"*\"));\n\t}\n}\n","traces":[{"line":42,"address":[8315760],"length":1,"stats":{"Line":0},"fn_name":"from"},{"line":43,"address":[8315772],"length":1,"stats":{"Line":0},"fn_name":null},{"line":49,"address":[],"length":0,"stats":{"Line":1},"fn_name":null},{"line":50,"address":[],"length":0,"stats":{"Line":1},"fn_name":null},{"line":54,"address":[8315792],"length":1,"stats":{"Line":0},"fn_name":null},{"line":64,"address":[6010416,6010673,6010704],"length":1,"stats":{"Line":2},"fn_name":"into_response"},{"line":65,"address":[8315820,8315901],"length":1,"stats":{"Line":4},"fn_name":null},{"line":68,"address":[8316128],"length":1,"stats":{"Line":3},"fn_name":"accepted_types"},{"line":69,"address":[8316141],"length":1,"stats":{"Line":3},"fn_name":null},{"line":75,"address":[6010894,6010784],"length":1,"stats":{"Line":2},"fn_name":"status_codes"},{"line":76,"address":[6010797,6010871],"length":1,"stats":{"Line":2},"fn_name":null},{"line":80,"address":[8316320],"length":1,"stats":{"Line":2},"fn_name":"schema"},{"line":82,"address":[8316416],"length":1,"stats":{"Line":2},"fn_name":null},{"line":92,"address":[6296656],"length":1,"stats":{"Line":1},"fn_name":"into_response"},{"line":95,"address":[6296747,6296668],"length":1,"stats":{"Line":2},"fn_name":null},{"line":96,"address":[],"length":0,"stats":{"Line":1},"fn_name":null},{"line":97,"address":[6296732],"length":1,"stats":{"Line":0},"fn_name":null},{"line":101,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":102,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":111,"address":[],"length":0,"stats":{"Line":1},"fn_name":null},{"line":112,"address":[6296785],"length":1,"stats":{"Line":1},"fn_name":null},{"line":113,"address":[6296800],"length":1,"stats":{"Line":1},"fn_name":null},{"line":114,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":117,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":118,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":119,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":120,"address":[],"length":0,"stats":{"Line":0},"fn_name":null}],"covered":16,"coverable":27},{"path":["/","home","runner","work","gotham_restful","gotham_restful","src","response","raw.rs"],"content":"use super::{handle_error, IntoResponse, IntoResponseError};\nuse crate::{types::ResourceType, FromBody, RequestBody, Response};\n#[cfg(feature = \"openapi\")]\nuse crate::{IntoResponseWithSchema, ResponseSchema};\nuse futures_core::future::Future;\nuse futures_util::{future, future::FutureExt};\nuse gotham::{\n\thyper::{\n\t\tbody::{Body, Bytes},\n\t\tStatusCode\n\t},\n\tmime::Mime\n};\n#[cfg(feature = \"openapi\")]\nuse openapi_type::{OpenapiSchema, OpenapiType, Visitor};\nuse serde_json::error::Error as SerdeJsonError;\nuse std::{convert::Infallible, fmt::Debug, pin::Pin};\n\n/// This type can be used both as a raw request body, as well as as a raw response. However, all types\n/// of request bodies are accepted by this type. It is therefore recommended to derive your own type\n/// from [RequestBody] and only use this when you need to return a raw response. This is a usage\n/// example that simply returns its body:\n///\n/// ```rust,no_run\n/// # #[macro_use] extern crate gotham_restful_derive;\n/// # use gotham::router::builder::*;\n/// # use gotham_restful::*;\n/// #[derive(Resource)]\n/// #[resource(create)]\n/// struct ImageResource;\n///\n/// #[create]\n/// fn create(body: Raw>) -> Raw> {\n/// \tbody\n/// }\n/// # fn main() {\n/// # \tgotham::start(\"127.0.0.1:8080\", build_simple_router(|route| {\n/// # \t\troute.resource::(\"img\");\n/// # \t}));\n/// # }\n/// ```\n#[derive(Debug)]\npub struct Raw {\n\tpub raw: T,\n\tpub mime: Mime\n}\n\nimpl Raw {\n\tpub fn new(raw: T, mime: Mime) -> Self {\n\t\tSelf { raw, mime }\n\t}\n}\n\nimpl AsMut for Raw\nwhere\n\tT: AsMut\n{\n\tfn as_mut(&mut self) -> &mut U {\n\t\tself.raw.as_mut()\n\t}\n}\n\nimpl AsRef for Raw\nwhere\n\tT: AsRef\n{\n\tfn as_ref(&self) -> &U {\n\t\tself.raw.as_ref()\n\t}\n}\n\nimpl Clone for Raw {\n\tfn clone(&self) -> Self {\n\t\tSelf {\n\t\t\traw: self.raw.clone(),\n\t\t\tmime: self.mime.clone()\n\t\t}\n\t}\n}\n\nimpl From<&'a [u8]>> FromBody for Raw {\n\ttype Err = Infallible;\n\n\tfn from_body(body: Bytes, mime: Mime) -> Result {\n\t\tOk(Self::new(body.as_ref().into(), mime))\n\t}\n}\n\nimpl RequestBody for Raw where Raw: FromBody + ResourceType {}\n\n#[cfg(feature = \"openapi\")]\nimpl OpenapiType for Raw {\n\tfn visit_type(visitor: &mut V) {\n\t\tvisitor.visit_binary()\n\t}\n}\n\nimpl> IntoResponse for Raw\nwhere\n\tSelf: Send\n{\n\ttype Err = SerdeJsonError; // just for easier handling of `Result, E>`\n\n\tfn into_response(\n\t\tself\n\t) -> Pin> + Send>> {\n\t\tfuture::ok(Response::new(StatusCode::OK, self.raw, Some(self.mime))).boxed()\n\t}\n}\n\n#[cfg(feature = \"openapi\")]\nimpl> ResponseSchema for Raw\nwhere\n\tSelf: Send\n{\n\tfn schema(code: StatusCode) -> OpenapiSchema {\n\t\tassert_eq!(code, StatusCode::OK);\n\t\t::schema()\n\t}\n}\n\nimpl IntoResponse for Result, E>\nwhere\n\tRaw: IntoResponse,\n\tE: Debug + IntoResponseError as IntoResponse>::Err>\n{\n\ttype Err = E::Err;\n\n\tfn into_response(self) -> Pin> + Send>> {\n\t\tmatch self {\n\t\t\tOk(raw) => raw.into_response(),\n\t\t\tErr(e) => handle_error(e)\n\t\t}\n\t}\n}\n\n#[cfg(feature = \"openapi\")]\nimpl ResponseSchema for Result, E>\nwhere\n\tRaw: IntoResponseWithSchema,\n\tE: Debug + IntoResponseError as IntoResponse>::Err>\n{\n\tfn status_codes() -> Vec {\n\t\tlet mut status_codes = E::status_codes();\n\t\tstatus_codes.push(StatusCode::OK);\n\t\tstatus_codes\n\t}\n\n\tfn schema(code: StatusCode) -> OpenapiSchema {\n\t\tmatch code {\n\t\t\tStatusCode::OK => as ResponseSchema>::schema(StatusCode::OK),\n\t\t\tcode => E::schema(code)\n\t\t}\n\t}\n}\n\n#[cfg(test)]\nmod test {\n\tuse super::*;\n\tuse futures_executor::block_on;\n\tuse gotham::mime::TEXT_PLAIN;\n\tuse thiserror::Error;\n\n\t#[derive(Debug, Default, Error)]\n\t#[error(\"An Error\")]\n\tstruct MsgError;\n\n\t#[test]\n\tfn raw_response() {\n\t\tlet msg = \"Test\";\n\t\tlet raw = Raw::new(msg, TEXT_PLAIN);\n\t\tlet res = block_on(raw.into_response()).expect(\"didn't expect error response\");\n\t\tassert_eq!(res.status, StatusCode::OK);\n\t\tassert_eq!(res.mime, Some(TEXT_PLAIN));\n\t\tassert_eq!(res.full_body().unwrap(), msg.as_bytes());\n\n\t\t#[cfg(feature = \"openapi\")]\n\t\tassert_eq!(>::status_codes(), vec![StatusCode::OK]);\n\t}\n\n\t#[test]\n\tfn raw_result() {\n\t\tlet msg = \"Test\";\n\t\tlet raw: Result, MsgError> = Ok(Raw::new(msg, TEXT_PLAIN));\n\t\tlet res = block_on(raw.into_response()).expect(\"didn't expect error response\");\n\t\tassert_eq!(res.status, StatusCode::OK);\n\t\tassert_eq!(res.mime, Some(TEXT_PLAIN));\n\t\tassert_eq!(res.full_body().unwrap(), msg.as_bytes());\n\n\t\t#[cfg(feature = \"openapi\")]\n\t\tassert_eq!(, MsgError>>::status_codes(), vec![\n\t\t\tStatusCode::INTERNAL_SERVER_ERROR,\n\t\t\tStatusCode::OK\n\t\t]);\n\t}\n}\n","traces":[{"line":49,"address":[6917104],"length":1,"stats":{"Line":7},"fn_name":null},{"line":58,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":59,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":67,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":68,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":73,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":75,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":76,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":84,"address":[],"length":0,"stats":{"Line":1},"fn_name":null},{"line":85,"address":[],"length":0,"stats":{"Line":2},"fn_name":null},{"line":93,"address":[6457952],"length":1,"stats":{"Line":4},"fn_name":"visit_type<&[u8], openapi_type::visitor::openapi::OpenapiVisitor>"},{"line":94,"address":[6457957],"length":1,"stats":{"Line":4},"fn_name":null},{"line":104,"address":[6011408],"length":1,"stats":{"Line":5},"fn_name":"into_response<&str>"},{"line":107,"address":[6011415],"length":1,"stats":{"Line":5},"fn_name":null},{"line":116,"address":[6409760],"length":1,"stats":{"Line":3},"fn_name":"schema<&[u8]>"},{"line":118,"address":[6409856],"length":1,"stats":{"Line":3},"fn_name":null},{"line":129,"address":[6296880],"length":1,"stats":{"Line":1},"fn_name":"into_response<&str, gotham_restful::response::raw::test::MsgError>"},{"line":130,"address":[],"length":0,"stats":{"Line":2},"fn_name":null},{"line":131,"address":[],"length":0,"stats":{"Line":1},"fn_name":null},{"line":132,"address":[6296956],"length":1,"stats":{"Line":0},"fn_name":null},{"line":143,"address":[6297069,6296992],"length":1,"stats":{"Line":1},"fn_name":"status_codes"},{"line":144,"address":[6297009],"length":1,"stats":{"Line":1},"fn_name":null},{"line":145,"address":[6297024],"length":1,"stats":{"Line":1},"fn_name":null},{"line":146,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":149,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":150,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":151,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":152,"address":[],"length":0,"stats":{"Line":0},"fn_name":null}],"covered":15,"coverable":28},{"path":["/","home","runner","work","gotham_restful","gotham_restful","src","response","redirect.rs"],"content":"use super::{handle_error, IntoResponse};\nuse crate::{IntoResponseError, Response};\n#[cfg(feature = \"openapi\")]\nuse crate::{NoContent, ResponseSchema};\nuse futures_util::future::{BoxFuture, FutureExt, TryFutureExt};\nuse gotham::hyper::{\n\theader::{InvalidHeaderValue, LOCATION},\n\tBody, StatusCode\n};\n#[cfg(feature = \"openapi\")]\nuse openapi_type::OpenapiSchema;\nuse std::{error::Error as StdError, fmt::Debug};\nuse thiserror::Error;\n\n/// This is the return type of a resource that only returns a redirect. It will result\n/// in a _303 See Other_ answer, meaning the redirect will always result in a GET request\n/// on the target.\n///\n/// ```\n/// # #[macro_use] extern crate gotham_restful_derive;\n/// # mod doc_tests_are_broken {\n/// # use gotham::state::State;\n/// # use gotham_restful::*;\n/// #\n/// # #[derive(Resource)]\n/// # #[resource(read_all)]\n/// # struct MyResource;\n/// #\n/// #[read_all]\n/// fn read_all() -> Redirect {\n/// \tRedirect {\n/// \t\tto: \"http://localhost:8080/cool/new/location\".to_owned()\n/// \t}\n/// }\n/// # }\n/// ```\n#[derive(Clone, Debug, Default)]\npub struct Redirect {\n\tpub to: String\n}\n\nimpl IntoResponse for Redirect {\n\ttype Err = InvalidHeaderValue;\n\n\tfn into_response(self) -> BoxFuture<'static, Result> {\n\t\tasync move {\n\t\t\tlet mut res = Response::new(StatusCode::SEE_OTHER, Body::empty(), None);\n\t\t\tres.header(LOCATION, self.to.parse()?);\n\t\t\tOk(res)\n\t\t}\n\t\t.boxed()\n\t}\n}\n\n#[cfg(feature = \"openapi\")]\nimpl ResponseSchema for Redirect {\n\tfn status_codes() -> Vec {\n\t\tvec![StatusCode::SEE_OTHER]\n\t}\n\n\tfn schema(code: StatusCode) -> OpenapiSchema {\n\t\tassert_eq!(code, StatusCode::SEE_OTHER);\n\t\t::schema(StatusCode::NO_CONTENT)\n\t}\n}\n\n// private type due to parent mod\n#[derive(Debug, Error)]\npub enum RedirectError {\n\t#[error(\"{0}\")]\n\tInvalidLocation(#[from] InvalidHeaderValue),\n\t#[error(\"{0}\")]\n\tOther(#[source] E)\n}\n\n#[allow(ambiguous_associated_items)] // an enum variant is not a type. never.\nimpl IntoResponse for Result\nwhere\n\tE: Debug + IntoResponseError,\n\t::Err: StdError + Sync\n{\n\ttype Err = RedirectError<::Err>;\n\n\tfn into_response(self) -> BoxFuture<'static, Result> {\n\t\tmatch self {\n\t\t\tOk(nc) => nc.into_response().map_err(Into::into).boxed(),\n\t\t\tErr(e) => handle_error(e).map_err(RedirectError::Other).boxed()\n\t\t}\n\t}\n}\n\n#[cfg(feature = \"openapi\")]\nimpl ResponseSchema for Result\nwhere\n\tE: Debug + IntoResponseError,\n\t::Err: StdError + Sync\n{\n\tfn status_codes() -> Vec {\n\t\tlet mut status_codes = E::status_codes();\n\t\tstatus_codes.push(StatusCode::SEE_OTHER);\n\t\tstatus_codes\n\t}\n\n\tfn schema(code: StatusCode) -> OpenapiSchema {\n\t\tmatch code {\n\t\t\tStatusCode::SEE_OTHER => ::schema(StatusCode::SEE_OTHER),\n\t\t\tcode => E::schema(code)\n\t\t}\n\t}\n}\n\n#[cfg(test)]\nmod test {\n\tuse super::*;\n\tuse futures_executor::block_on;\n\tuse gotham::hyper::StatusCode;\n\tuse thiserror::Error;\n\n\t#[derive(Debug, Default, Error)]\n\t#[error(\"An Error\")]\n\tstruct MsgError;\n\n\t#[test]\n\tfn redirect_response() {\n\t\tlet redir = Redirect {\n\t\t\tto: \"http://localhost/foo\".to_owned()\n\t\t};\n\t\tlet res = block_on(redir.into_response()).expect(\"didn't expect error response\");\n\t\tassert_eq!(res.status, StatusCode::SEE_OTHER);\n\t\tassert_eq!(res.mime, None);\n\t\tassert_eq!(\n\t\t\tres.headers.get(LOCATION).map(|hdr| hdr.to_str().unwrap()),\n\t\t\tSome(\"http://localhost/foo\")\n\t\t);\n\t\tassert_eq!(res.full_body().unwrap(), &[] as &[u8]);\n\n\t\t#[cfg(feature = \"openapi\")]\n\t\tassert_eq!(Redirect::status_codes(), vec![StatusCode::SEE_OTHER]);\n\t}\n\n\t#[test]\n\tfn redirect_result() {\n\t\tlet redir: Result = Ok(Redirect {\n\t\t\tto: \"http://localhost/foo\".to_owned()\n\t\t});\n\t\tlet res = block_on(redir.into_response()).expect(\"didn't expect error response\");\n\t\tassert_eq!(res.status, StatusCode::SEE_OTHER);\n\t\tassert_eq!(res.mime, None);\n\t\tassert_eq!(\n\t\t\tres.headers.get(LOCATION).map(|hdr| hdr.to_str().unwrap()),\n\t\t\tSome(\"http://localhost/foo\")\n\t\t);\n\t\tassert_eq!(res.full_body().unwrap(), &[] as &[u8]);\n\n\t\t#[cfg(feature = \"openapi\")]\n\t\tassert_eq!(>::status_codes(), vec![\n\t\t\tStatusCode::INTERNAL_SERVER_ERROR,\n\t\t\tStatusCode::SEE_OTHER\n\t\t]);\n\t}\n}\n","traces":[{"line":45,"address":[5907424],"length":1,"stats":{"Line":1},"fn_name":"into_response"},{"line":46,"address":[7806484,7806528,7806558,7806966,7807253,7806615],"length":1,"stats":{"Line":3},"fn_name":"{async_block#0}"},{"line":47,"address":[8432032,8432170],"length":1,"stats":{"Line":4},"fn_name":null},{"line":48,"address":[7719483,7720140,7719681,7719294,7719708,7720048],"length":1,"stats":{"Line":6},"fn_name":null},{"line":49,"address":[7720095],"length":1,"stats":{"Line":2},"fn_name":null},{"line":57,"address":[8433023,8432912],"length":1,"stats":{"Line":1},"fn_name":"status_codes"},{"line":58,"address":[7720189,7720264],"length":1,"stats":{"Line":1},"fn_name":null},{"line":61,"address":[7720304],"length":1,"stats":{"Line":0},"fn_name":"schema"},{"line":63,"address":[7720400],"length":1,"stats":{"Line":0},"fn_name":null},{"line":84,"address":[6297104],"length":1,"stats":{"Line":1},"fn_name":"into_response"},{"line":85,"address":[6297112,6297248],"length":1,"stats":{"Line":2},"fn_name":null},{"line":86,"address":[6297141],"length":1,"stats":{"Line":1},"fn_name":null},{"line":87,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":98,"address":[6297341,6297264],"length":1,"stats":{"Line":1},"fn_name":"status_codes"},{"line":99,"address":[6297281],"length":1,"stats":{"Line":1},"fn_name":null},{"line":100,"address":[6297296],"length":1,"stats":{"Line":1},"fn_name":null},{"line":101,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":104,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":105,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":106,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":107,"address":[],"length":0,"stats":{"Line":0},"fn_name":null}],"covered":13,"coverable":21},{"path":["/","home","runner","work","gotham_restful","gotham_restful","src","response","result.rs"],"content":"use super::{handle_error, IntoResponse, ResourceError};\n#[cfg(feature = \"openapi\")]\nuse crate::ResponseSchema;\nuse crate::{Response, ResponseBody, Success};\nuse futures_core::future::Future;\nuse gotham::{\n\tanyhow::Error,\n\thyper::StatusCode,\n\tmime::{Mime, APPLICATION_JSON}\n};\n#[cfg(feature = \"openapi\")]\nuse openapi_type::{OpenapiSchema, OpenapiType};\nuse std::{fmt::Debug, pin::Pin};\n\npub trait IntoResponseError {\n\ttype Err: Debug + Send + 'static;\n\n\tfn into_response_error(self) -> Result;\n\n\t#[cfg(feature = \"openapi\")]\n\tfn status_codes() -> Vec;\n\n\t#[cfg(feature = \"openapi\")]\n\tfn schema(code: StatusCode) -> OpenapiSchema;\n}\n\nimpl IntoResponseError for E\nwhere\n\tE: Into\n{\n\ttype Err = serde_json::Error;\n\n\tfn into_response_error(self) -> Result {\n\t\tlet err: Error = self.into();\n\t\tlet err: ResourceError = err.into();\n\t\tOk(Response::json(\n\t\t\tStatusCode::INTERNAL_SERVER_ERROR,\n\t\t\tserde_json::to_string(&err)?\n\t\t))\n\t}\n\n\t#[cfg(feature = \"openapi\")]\n\tfn status_codes() -> Vec {\n\t\tvec![StatusCode::INTERNAL_SERVER_ERROR]\n\t}\n\n\t#[cfg(feature = \"openapi\")]\n\tfn schema(code: StatusCode) -> OpenapiSchema {\n\t\tassert_eq!(code, StatusCode::INTERNAL_SERVER_ERROR);\n\t\tResourceError::schema()\n\t}\n}\n\nimpl IntoResponse for Result\nwhere\n\tR: ResponseBody,\n\tE: Debug + IntoResponseError\n{\n\ttype Err = E::Err;\n\n\tfn into_response(self) -> Pin> + Send>> {\n\t\tmatch self {\n\t\t\tOk(r) => Success::from(r).into_response(),\n\t\t\tErr(e) => handle_error(e)\n\t\t}\n\t}\n\n\tfn accepted_types() -> Option> {\n\t\tSome(vec![APPLICATION_JSON])\n\t}\n}\n\n#[cfg(feature = \"openapi\")]\nimpl ResponseSchema for Result\nwhere\n\tR: ResponseBody,\n\tE: Debug + IntoResponseError\n{\n\tfn status_codes() -> Vec {\n\t\tlet mut status_codes = E::status_codes();\n\t\tstatus_codes.push(StatusCode::OK);\n\t\tstatus_codes\n\t}\n\n\tfn schema(code: StatusCode) -> OpenapiSchema {\n\t\tmatch code {\n\t\t\tStatusCode::OK => R::schema(),\n\t\t\tcode => E::schema(code)\n\t\t}\n\t}\n}\n\n#[cfg(test)]\nmod test {\n\tuse super::*;\n\tuse crate::response::OrAllTypes;\n\tuse futures_executor::block_on;\n\tuse thiserror::Error;\n\n\t#[derive(Debug, Default, Deserialize, Serialize)]\n\t#[cfg_attr(feature = \"openapi\", derive(openapi_type::OpenapiType))]\n\tstruct Msg {\n\t\tmsg: String\n\t}\n\n\t#[derive(Debug, Default, Error)]\n\t#[error(\"An Error\")]\n\tstruct MsgError;\n\n\t#[test]\n\tfn result_ok() {\n\t\tlet ok: Result = Ok(Msg::default());\n\t\tlet res = block_on(ok.into_response()).expect(\"didn't expect error response\");\n\t\tassert_eq!(res.status, StatusCode::OK);\n\t\tassert_eq!(res.mime, Some(APPLICATION_JSON));\n\t\tassert_eq!(res.full_body().unwrap(), br#\"{\"msg\":\"\"}\"#);\n\t}\n\n\t#[test]\n\tfn result_err() {\n\t\tlet err: Result = Err(MsgError::default());\n\t\tlet res = block_on(err.into_response()).expect(\"didn't expect error response\");\n\t\tassert_eq!(res.status, StatusCode::INTERNAL_SERVER_ERROR);\n\t\tassert_eq!(res.mime, Some(APPLICATION_JSON));\n\t\tassert_eq!(\n\t\t\tres.full_body().unwrap(),\n\t\t\tformat!(r#\"{{\"error\":true,\"message\":\"{}\"}}\"#, MsgError::default()).as_bytes()\n\t\t);\n\t}\n\n\t#[test]\n\tfn success_accepts_json() {\n\t\tassert!(\n\t\t\t>::accepted_types()\n\t\t\t\t.or_all_types()\n\t\t\t\t.contains(&APPLICATION_JSON)\n\t\t)\n\t}\n}\n","traces":[{"line":33,"address":[5950635,5950480],"length":1,"stats":{"Line":2},"fn_name":"into_response_error"},{"line":34,"address":[5950496],"length":1,"stats":{"Line":2},"fn_name":null},{"line":35,"address":[5950522],"length":1,"stats":{"Line":2},"fn_name":null},{"line":36,"address":[5950813,5950711],"length":1,"stats":{"Line":4},"fn_name":null},{"line":37,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":38,"address":[6371036,6371093,6371525,6371218,6371157,6371404,6371461,6371586],"length":1,"stats":{"Line":6},"fn_name":null},{"line":43,"address":[6012542,6012432],"length":1,"stats":{"Line":3},"fn_name":"status_codes"},{"line":44,"address":[],"length":0,"stats":{"Line":3},"fn_name":null},{"line":48,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":50,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":61,"address":[7093872,7094032],"length":1,"stats":{"Line":2},"fn_name":"into_response"},{"line":62,"address":[7094044,7094007,7093883,7094171],"length":1,"stats":{"Line":3},"fn_name":null},{"line":63,"address":[6297418],"length":1,"stats":{"Line":1},"fn_name":null},{"line":64,"address":[6297481],"length":1,"stats":{"Line":1},"fn_name":null},{"line":68,"address":[6297520,6297713],"length":1,"stats":{"Line":3},"fn_name":"accepted_types"},{"line":69,"address":[6297690,6297537],"length":1,"stats":{"Line":3},"fn_name":null},{"line":79,"address":[],"length":0,"stats":{"Line":2},"fn_name":null},{"line":80,"address":[],"length":0,"stats":{"Line":2},"fn_name":null},{"line":81,"address":[],"length":0,"stats":{"Line":2},"fn_name":null},{"line":82,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":85,"address":[],"length":0,"stats":{"Line":2},"fn_name":null},{"line":86,"address":[],"length":0,"stats":{"Line":2},"fn_name":null},{"line":87,"address":[],"length":0,"stats":{"Line":2},"fn_name":null},{"line":88,"address":[],"length":0,"stats":{"Line":2},"fn_name":null}],"covered":20,"coverable":24},{"path":["/","home","runner","work","gotham_restful","gotham_restful","src","response","success.rs"],"content":"use super::IntoResponse;\n#[cfg(feature = \"openapi\")]\nuse crate::ResponseSchema;\nuse crate::{Response, ResponseBody};\nuse futures_util::future::{self, FutureExt};\nuse gotham::{\n\thyper::{\n\t\theader::{HeaderMap, HeaderValue, IntoHeaderName},\n\t\tStatusCode\n\t},\n\tmime::{Mime, APPLICATION_JSON}\n};\n#[cfg(feature = \"openapi\")]\nuse openapi_type::OpenapiSchema;\nuse std::{fmt::Debug, future::Future, pin::Pin};\n\n/// This can be returned from a resource when there is no cause of an error.\n///\n/// Usage example:\n///\n/// ```\n/// # #[macro_use] extern crate gotham_restful_derive;\n/// # mod doc_tests_are_broken {\n/// # use gotham::state::State;\n/// # use gotham_restful::*;\n/// # use serde::{Deserialize, Serialize};\n/// #\n/// # #[derive(Resource)]\n/// # #[resource(read_all)]\n/// # struct MyResource;\n/// #\n/// #[derive(Deserialize, Serialize)]\n/// # #[cfg_attr(feature = \"openapi\", derive(openapi_type::OpenapiType))]\n/// struct MyResponse {\n/// \tmessage: &'static str\n/// }\n///\n/// #[read_all]\n/// fn read_all() -> Success {\n/// \tlet res = MyResponse {\n/// \t\tmessage: \"I'm always happy\"\n/// \t};\n/// \tres.into()\n/// }\n/// # }\n/// ```\n#[derive(Clone, Debug, Default)]\npub struct Success {\n\tvalue: T,\n\theaders: HeaderMap\n}\n\nimpl From for Success {\n\tfn from(t: T) -> Self {\n\t\tSelf {\n\t\t\tvalue: t,\n\t\t\theaders: HeaderMap::new()\n\t\t}\n\t}\n}\n\nimpl Success {\n\t/// Set a custom HTTP header. If a header with this name was set before, its value is being updated.\n\tpub fn header(&mut self, name: K, value: HeaderValue) {\n\t\tself.headers.insert(name, value);\n\t}\n\n\t/// Allow manipulating HTTP headers.\n\tpub fn headers_mut(&mut self) -> &mut HeaderMap {\n\t\t&mut self.headers\n\t}\n}\n\nimpl IntoResponse for Success {\n\ttype Err = serde_json::Error;\n\n\tfn into_response(self) -> Pin> + Send>> {\n\t\tlet res = serde_json::to_string(&self.value)\n\t\t\t.map(|body| Response::json(StatusCode::OK, body).with_headers(self.headers));\n\t\tfuture::ready(res).boxed()\n\t}\n\n\tfn accepted_types() -> Option> {\n\t\tSome(vec![APPLICATION_JSON])\n\t}\n}\n\n#[cfg(feature = \"openapi\")]\nimpl ResponseSchema for Success {\n\tfn schema(code: StatusCode) -> OpenapiSchema {\n\t\tassert_eq!(code, StatusCode::OK);\n\t\tT::schema()\n\t}\n}\n\n#[cfg(test)]\nmod test {\n\tuse super::*;\n\tuse crate::response::OrAllTypes;\n\tuse futures_executor::block_on;\n\tuse gotham::hyper::header::ACCESS_CONTROL_ALLOW_ORIGIN;\n\n\t#[derive(Debug, Default, Serialize)]\n\t#[cfg_attr(feature = \"openapi\", derive(openapi_type::OpenapiType))]\n\tstruct Msg {\n\t\tmsg: String\n\t}\n\n\t#[test]\n\tfn success_always_successfull() {\n\t\tlet success: Success = Msg::default().into();\n\t\tlet res = block_on(success.into_response()).expect(\"didn't expect error response\");\n\t\tassert_eq!(res.status, StatusCode::OK);\n\t\tassert_eq!(res.mime, Some(APPLICATION_JSON));\n\t\tassert_eq!(res.full_body().unwrap(), br#\"{\"msg\":\"\"}\"#);\n\t\t#[cfg(feature = \"openapi\")]\n\t\tassert_eq!(>::status_codes(), vec![StatusCode::OK]);\n\t}\n\n\t#[test]\n\tfn success_custom_headers() {\n\t\tlet mut success: Success = Msg::default().into();\n\t\tsuccess.header(ACCESS_CONTROL_ALLOW_ORIGIN, HeaderValue::from_static(\"*\"));\n\t\tlet res = block_on(success.into_response()).expect(\"didn't expect error response\");\n\t\tlet cors = res.headers.get(ACCESS_CONTROL_ALLOW_ORIGIN);\n\t\tassert_eq!(cors.map(|value| value.to_str().unwrap()), Some(\"*\"));\n\t}\n\n\t#[test]\n\tfn success_accepts_json() {\n\t\tassert!(\n\t\t\t>::accepted_types()\n\t\t\t\t.or_all_types()\n\t\t\t\t.contains(&APPLICATION_JSON)\n\t\t)\n\t}\n}\n","traces":[{"line":54,"address":[],"length":0,"stats":{"Line":3},"fn_name":null},{"line":57,"address":[6410305,6410481],"length":1,"stats":{"Line":3},"fn_name":null},{"line":64,"address":[6410624],"length":1,"stats":{"Line":1},"fn_name":null},{"line":65,"address":[6410642],"length":1,"stats":{"Line":1},"fn_name":null},{"line":69,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":70,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":77,"address":[],"length":0,"stats":{"Line":2},"fn_name":null},{"line":78,"address":[6410703,6411071,6410868,6411236],"length":1,"stats":{"Line":6},"fn_name":null},{"line":79,"address":[6411408,6411136,6411680,6411429,6410768,6411701],"length":1,"stats":{"Line":9},"fn_name":"{closure#0}"},{"line":80,"address":[6411273,6410905,6411055,6410687],"length":1,"stats":{"Line":5},"fn_name":null},{"line":83,"address":[6412145,6411952],"length":1,"stats":{"Line":1},"fn_name":"accepted_types"},{"line":84,"address":[6411969,6412122],"length":1,"stats":{"Line":1},"fn_name":null},{"line":90,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":92,"address":[],"length":0,"stats":{"Line":0},"fn_name":null}],"covered":10,"coverable":14},{"path":["/","home","runner","work","gotham_restful","gotham_restful","src","routing.rs"],"content":"#[cfg(feature = \"openapi\")]\nuse crate::openapi::{\n\tbuilder::{OpenapiBuilder, OpenapiInfo},\n\trouter::OpenapiRouter\n};\nuse crate::{response::ResourceError, Endpoint, FromBody, IntoResponse, Resource, Response};\n#[cfg(feature = \"cors\")]\nuse gotham::router::route::matcher::AccessControlRequestMethodMatcher;\nuse gotham::{\n\thandler::HandlerError,\n\thelpers::http::response::{create_empty_response, create_response},\n\thyper::{body::to_bytes, header::CONTENT_TYPE, Body, HeaderMap, Method, StatusCode},\n\tmime::{Mime, APPLICATION_JSON},\n\tpipeline::PipelineHandleChain,\n\tprelude::*,\n\trouter::{\n\t\tbuilder::{RouterBuilder, ScopeBuilder},\n\t\troute::matcher::{AcceptHeaderRouteMatcher, ContentTypeHeaderRouteMatcher, RouteMatcher},\n\t\tRouteNonMatch\n\t},\n\tstate::{FromState, State}\n};\n#[cfg(feature = \"openapi\")]\nuse openapi_type::OpenapiType;\nuse std::{any::TypeId, panic::RefUnwindSafe};\n\n/// Allow us to extract an id from a path.\n#[derive(Clone, Copy, Debug, Deserialize, StateData, StaticResponseExtender)]\n#[cfg_attr(feature = \"openapi\", derive(OpenapiType))]\npub struct PathExtractor {\n\tpub id: ID\n}\n\n/// This trait adds the `with_openapi` method to gotham's routing. It turns the default\n/// router into one that will only allow RESTful resources, but record them and generate\n/// an OpenAPI specification on request.\n#[cfg(feature = \"openapi\")]\npub trait WithOpenapi {\n\tfn with_openapi(&mut self, info: OpenapiInfo, block: F)\n\twhere\n\t\tF: FnOnce(OpenapiRouter<'_, D>);\n}\n\n/// This trait adds the `resource` method to gotham's routing. It allows you to register\n/// any RESTful [Resource] with a path.\n#[_private_openapi_trait(DrawResourcesWithSchema)]\npub trait DrawResources {\n\t#[openapi_bound(R: crate::ResourceWithSchema)]\n\t#[non_openapi_bound(R: crate::Resource)]\n\tfn resource(&mut self, path: &str);\n}\n\n/// This trait allows to draw routes within an resource. Use this only inside the\n/// [Resource::setup] method.\n#[_private_openapi_trait(DrawResourceRoutesWithSchema)]\npub trait DrawResourceRoutes {\n\t#[openapi_bound(E: crate::EndpointWithSchema)]\n\t#[non_openapi_bound(E: crate::Endpoint)]\n\tfn endpoint(&mut self);\n}\n\nfn response_from(res: Response, state: &State) -> gotham::hyper::Response {\n\tlet mut r = create_empty_response(state, res.status);\n\tlet headers = r.headers_mut();\n\tif let Some(mime) = res.mime {\n\t\theaders.insert(CONTENT_TYPE, mime.as_ref().parse().unwrap());\n\t}\n\tlet mut last_name = None;\n\tfor (name, value) in res.headers {\n\t\tif name.is_some() {\n\t\t\tlast_name = name;\n\t\t}\n\t\t// this unwrap is safe: the first item will always be Some\n\t\tlet name = last_name.clone().unwrap();\n\t\theaders.insert(name, value);\n\t}\n\n\tlet method = Method::borrow_from(state);\n\tif method != Method::HEAD {\n\t\t*r.body_mut() = res.body;\n\t}\n\n\t#[cfg(feature = \"cors\")]\n\tcrate::cors::handle_cors(state, &mut r);\n\n\tr\n}\n\nasync fn endpoint_handler(\n\tstate: &mut State\n) -> Result, HandlerError>\nwhere\n\tE: Endpoint,\n\t::Err: Into\n{\n\ttrace!(\"entering endpoint_handler\");\n\tlet placeholders = E::Placeholders::take_from(state);\n\t// workaround for E::Placeholders and E::Param being the same type\n\t// when fixed remove `Clone` requirement on endpoint\n\tif TypeId::of::() == TypeId::of::() {\n\t\tstate.put(placeholders.clone());\n\t}\n\tlet params = E::Params::take_from(state);\n\n\tlet body = match E::needs_body() {\n\t\ttrue => {\n\t\t\tlet body = to_bytes(Body::take_from(state)).await?;\n\n\t\t\tlet content_type: Mime = match HeaderMap::borrow_from(state).get(CONTENT_TYPE) {\n\t\t\t\tSome(content_type) => content_type.to_str().unwrap().parse().unwrap(),\n\t\t\t\tNone => {\n\t\t\t\t\tdebug!(\"Missing Content-Type: Returning 415 Response\");\n\t\t\t\t\tlet res = create_empty_response(state, StatusCode::UNSUPPORTED_MEDIA_TYPE);\n\t\t\t\t\treturn Ok(res);\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tmatch E::Body::from_body(body, content_type) {\n\t\t\t\tOk(body) => Some(body),\n\t\t\t\tErr(e) => {\n\t\t\t\t\tdebug!(\"Invalid Body: Returning 400 Response\");\n\t\t\t\t\tlet error: ResourceError = e.into();\n\t\t\t\t\tlet json = serde_json::to_string(&error)?;\n\t\t\t\t\tlet res =\n\t\t\t\t\t\tcreate_response(state, StatusCode::BAD_REQUEST, APPLICATION_JSON, json);\n\t\t\t\t\treturn Ok(res);\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\tfalse => None\n\t};\n\n\tlet out = E::handle(state, placeholders, params, body).await;\n\tlet res = out.into_response().await.map_err(Into::into)?;\n\tdebug!(\"Returning response {res:?}\");\n\tOk(response_from(res, state))\n}\n\n#[derive(Clone)]\nstruct MaybeMatchAcceptHeader {\n\tmatcher: Option\n}\n\nimpl RouteMatcher for MaybeMatchAcceptHeader {\n\tfn is_match(&self, state: &State) -> Result<(), RouteNonMatch> {\n\t\tmatch &self.matcher {\n\t\t\tSome(matcher) => matcher.is_match(state),\n\t\t\tNone => Ok(())\n\t\t}\n\t}\n}\n\nimpl MaybeMatchAcceptHeader {\n\tfn new(types: Option>) -> Self {\n\t\tlet types = match types {\n\t\t\tSome(types) if types.is_empty() => None,\n\t\t\ttypes => types\n\t\t};\n\t\tSelf {\n\t\t\tmatcher: types.map(AcceptHeaderRouteMatcher::new)\n\t\t}\n\t}\n}\n\nimpl From>> for MaybeMatchAcceptHeader {\n\tfn from(types: Option>) -> Self {\n\t\tSelf::new(types)\n\t}\n}\n\n#[derive(Clone)]\nstruct MaybeMatchContentTypeHeader {\n\tmatcher: Option\n}\n\nimpl RouteMatcher for MaybeMatchContentTypeHeader {\n\tfn is_match(&self, state: &State) -> Result<(), RouteNonMatch> {\n\t\tmatch &self.matcher {\n\t\t\tSome(matcher) => matcher.is_match(state),\n\t\t\tNone => Ok(())\n\t\t}\n\t}\n}\n\nimpl MaybeMatchContentTypeHeader {\n\tfn new(types: Option>) -> Self {\n\t\tSelf {\n\t\t\tmatcher: types.map(|types| ContentTypeHeaderRouteMatcher::new(types).allow_no_type())\n\t\t}\n\t}\n}\n\nimpl From>> for MaybeMatchContentTypeHeader {\n\tfn from(types: Option>) -> Self {\n\t\tSelf::new(types)\n\t}\n}\n\nmacro_rules! implDrawResourceRoutes {\n\t($implType:ident) => {\n\t\t#[cfg(feature = \"openapi\")]\n\t\timpl<'a, C, P> WithOpenapi for $implType<'a, C, P>\n\t\twhere\n\t\t\tC: PipelineHandleChain

+ Copy + Send + Sync + 'static,\n\t\t\tP: RefUnwindSafe + Send + Sync + 'static\n\t\t{\n\t\t\tfn with_openapi(&mut self, info: OpenapiInfo, block: F)\n\t\t\twhere\n\t\t\t\tF: FnOnce(OpenapiRouter<'_, $implType<'a, C, P>>)\n\t\t\t{\n\t\t\t\tlet router = OpenapiRouter {\n\t\t\t\t\trouter: self,\n\t\t\t\t\tscope: None,\n\t\t\t\t\topenapi_builder: &mut OpenapiBuilder::new(info)\n\t\t\t\t};\n\t\t\t\tblock(router);\n\t\t\t}\n\t\t}\n\n\t\timpl<'a, C, P> DrawResources for $implType<'a, C, P>\n\t\twhere\n\t\t\tC: PipelineHandleChain

+ Copy + Send + Sync + 'static,\n\t\t\tP: RefUnwindSafe + Send + Sync + 'static\n\t\t{\n\t\t\tfn resource(&mut self, mut path: &str) {\n\t\t\t\tif path.starts_with('/') {\n\t\t\t\t\tpath = &path[1..];\n\t\t\t\t}\n\t\t\t\tR::setup((self, path));\n\t\t\t}\n\t\t}\n\n\t\timpl<'a, C, P> DrawResourceRoutes for (&mut $implType<'a, C, P>, &str)\n\t\twhere\n\t\t\tC: PipelineHandleChain

+ Copy + Send + Sync + 'static,\n\t\t\tP: RefUnwindSafe + Send + Sync + 'static\n\t\t{\n\t\t\tfn endpoint(&mut self) {\n\t\t\t\tlet uri = format!(\"{}/{}\", self.1, E::uri());\n\t\t\t\tdebug!(\"Registering endpoint for {uri}\");\n\t\t\t\tself.0.associate(&uri, |assoc| {\n\t\t\t\t\tassoc\n\t\t\t\t\t\t.request(vec![E::http_method()])\n\t\t\t\t\t\t.add_route_matcher(MaybeMatchAcceptHeader::new(E::Output::accepted_types()))\n\t\t\t\t\t\t.with_path_extractor::()\n\t\t\t\t\t\t.with_query_string_extractor::()\n\t\t\t\t\t\t.to_async_borrowing(endpoint_handler::);\n\n\t\t\t\t\t#[cfg(feature = \"cors\")]\n\t\t\t\t\tif E::http_method() != Method::GET {\n\t\t\t\t\t\tassoc\n\t\t\t\t\t\t\t.options()\n\t\t\t\t\t\t\t.add_route_matcher(AccessControlRequestMethodMatcher::new(\n\t\t\t\t\t\t\t\tE::http_method()\n\t\t\t\t\t\t\t))\n\t\t\t\t\t\t\t.to(crate::cors::cors_preflight_handler);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t};\n}\n\nimplDrawResourceRoutes!(RouterBuilder);\nimplDrawResourceRoutes!(ScopeBuilder);\n","traces":[{"line":62,"address":[6371968,6372778,6374205],"length":1,"stats":{"Line":5},"fn_name":"response_from"},{"line":63,"address":[6372011,6372162],"length":1,"stats":{"Line":10},"fn_name":null},{"line":64,"address":[6372170,6372239],"length":1,"stats":{"Line":10},"fn_name":null},{"line":65,"address":[6372247],"length":1,"stats":{"Line":5},"fn_name":null},{"line":66,"address":[6372357,6372558,6372759],"length":1,"stats":{"Line":4},"fn_name":null},{"line":68,"address":[6372428],"length":1,"stats":{"Line":5},"fn_name":null},{"line":69,"address":[6372440,6373635,6372877],"length":1,"stats":{"Line":10},"fn_name":null},{"line":70,"address":[6373127,6373369,6373183],"length":1,"stats":{"Line":0},"fn_name":null},{"line":71,"address":[6373215],"length":1,"stats":{"Line":0},"fn_name":null},{"line":74,"address":[6373374,6373205],"length":1,"stats":{"Line":0},"fn_name":null},{"line":75,"address":[6373409],"length":1,"stats":{"Line":0},"fn_name":null},{"line":78,"address":[6373664],"length":1,"stats":{"Line":5},"fn_name":null},{"line":79,"address":[6373991,6373693],"length":1,"stats":{"Line":10},"fn_name":null},{"line":80,"address":[6373758,6373996],"length":1,"stats":{"Line":5},"fn_name":null},{"line":84,"address":[6373743],"length":1,"stats":{"Line":5},"fn_name":null},{"line":86,"address":[6374023],"length":1,"stats":{"Line":5},"fn_name":null},{"line":89,"address":[6746080,6746176,6746208,6746240,6746272,6746112,6746144],"length":1,"stats":{"Line":21},"fn_name":"endpoint_handler"},{"line":96,"address":[],"length":0,"stats":{"Line":63},"fn_name":null},{"line":97,"address":[],"length":0,"stats":{"Line":42},"fn_name":null},{"line":100,"address":[],"length":0,"stats":{"Line":42},"fn_name":null},{"line":101,"address":[],"length":0,"stats":{"Line":13},"fn_name":null},{"line":103,"address":[],"length":0,"stats":{"Line":42},"fn_name":null},{"line":105,"address":[],"length":0,"stats":{"Line":42},"fn_name":null},{"line":106,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":107,"address":[],"length":0,"stats":{"Line":24},"fn_name":null},{"line":109,"address":[],"length":0,"stats":{"Line":16},"fn_name":null},{"line":110,"address":[],"length":0,"stats":{"Line":8},"fn_name":null},{"line":111,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":112,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":113,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":114,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":118,"address":[],"length":0,"stats":{"Line":8},"fn_name":null},{"line":119,"address":[],"length":0,"stats":{"Line":8},"fn_name":null},{"line":120,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":121,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":122,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":123,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":124,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":125,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":126,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":130,"address":[],"length":0,"stats":{"Line":13},"fn_name":null},{"line":133,"address":[],"length":0,"stats":{"Line":64},"fn_name":null},{"line":134,"address":[],"length":0,"stats":{"Line":42},"fn_name":null},{"line":135,"address":[],"length":0,"stats":{"Line":63},"fn_name":null},{"line":136,"address":[],"length":0,"stats":{"Line":42},"fn_name":null},{"line":145,"address":[6374416],"length":1,"stats":{"Line":6},"fn_name":"is_match"},{"line":146,"address":[6374449],"length":1,"stats":{"Line":5},"fn_name":null},{"line":147,"address":[6374499],"length":1,"stats":{"Line":0},"fn_name":null},{"line":148,"address":[6374479],"length":1,"stats":{"Line":6},"fn_name":null},{"line":154,"address":[6374977,6374528,6374906],"length":1,"stats":{"Line":6},"fn_name":null},{"line":155,"address":[6374550],"length":1,"stats":{"Line":6},"fn_name":null},{"line":156,"address":[6374755,6374612],"length":1,"stats":{"Line":4},"fn_name":null},{"line":157,"address":[6374636],"length":1,"stats":{"Line":5},"fn_name":null},{"line":160,"address":[6374819],"length":1,"stats":{"Line":6},"fn_name":null},{"line":166,"address":[6374992],"length":1,"stats":{"Line":0},"fn_name":"from"},{"line":167,"address":[6375000],"length":1,"stats":{"Line":0},"fn_name":null},{"line":177,"address":[6375024],"length":1,"stats":{"Line":0},"fn_name":"is_match"},{"line":178,"address":[6375057],"length":1,"stats":{"Line":0},"fn_name":null},{"line":179,"address":[6375103],"length":1,"stats":{"Line":0},"fn_name":null},{"line":180,"address":[6375083],"length":1,"stats":{"Line":0},"fn_name":null},{"line":186,"address":[6375136],"length":1,"stats":{"Line":0},"fn_name":null},{"line":188,"address":[6375200,6375213,6375150],"length":1,"stats":{"Line":0},"fn_name":"{closure#0}"},{"line":194,"address":[6375264],"length":1,"stats":{"Line":0},"fn_name":"from"},{"line":195,"address":[6375272],"length":1,"stats":{"Line":0},"fn_name":null},{"line":207,"address":[7356373,7356392,7356128],"length":1,"stats":{"Line":2},"fn_name":"with_openapi<(borrow_bag::handle::Handle, ())>, borrow_bag::handle::Take>, ()), (gotham::pipeline::Pipeline<(gotham_restful::auth::AuthMiddleware, ())>, ()), openapi_specification::openapi_specification::{closure#0}::{closure_env#0}>"},{"line":211,"address":[7356156,7356244],"length":1,"stats":{"Line":4},"fn_name":null},{"line":213,"address":[7356166],"length":1,"stats":{"Line":2},"fn_name":null},{"line":214,"address":[7356175,7356239],"length":1,"stats":{"Line":4},"fn_name":null},{"line":216,"address":[7356279],"length":1,"stats":{"Line":2},"fn_name":null},{"line":225,"address":[6221520],"length":1,"stats":{"Line":4},"fn_name":"resource<(), (), custom_request_body::FooResource>"},{"line":226,"address":[6221544,6221661],"length":1,"stats":{"Line":5},"fn_name":null},{"line":227,"address":[6221614],"length":1,"stats":{"Line":1},"fn_name":null},{"line":229,"address":[6221574],"length":1,"stats":{"Line":4},"fn_name":null},{"line":238,"address":[7352160,7349712,7351344,7348896,7351608,7350528,7352976,7353792,7350792,7349160,7353240,7352424,7349976,7354056],"length":1,"stats":{"Line":29},"fn_name":"endpoint<(borrow_bag::handle::Handle, ())>, borrow_bag::handle::Take>, ()), (gotham::pipeline::Pipeline<(gotham_restful::auth::AuthMiddleware, ())>, ()), openapi_specification::custom_read_with___gotham_restful_endpoint>"},{"line":239,"address":[7352180,7348916,7349732,7350548,7351364,7352996,7350002,7351634,7350818,7353266,7353812,7352450,7349186,7354082],"length":1,"stats":{"Line":29},"fn_name":null},{"line":240,"address":[7352665,7349401,7349256,7350888,7351704,7352520,7350217,7349501,7353581,7349343,7354152,7353481,7354397,7351133,7350159,7350072,7351033,7351949,7353423,7353336,7351791,7354239,7354297,7351849,7352765,7350317,7350975,7352607],"length":1,"stats":{"Line":87},"fn_name":null},{"line":241,"address":[6745436,6740719,6742160,6743084,6743855,6745423,6740592,6744512,6741519,6742290,6745296,6742944,6741506,6744642,6740732,6743071,6742303,6741376,6743728,6744655,6743868],"length":1,"stats":{"Line":87},"fn_name":"{closure#0}<(borrow_bag::handle::Handle, ())>, borrow_bag::handle::Take>, ()), (gotham::pipeline::Pipeline<(gotham_restful::auth::AuthMiddleware, ())>, ()), openapi_specification::get_image___gotham_restful_endpoint>"},{"line":242,"address":[6741009,6743361,6745646,6743294,6742964,6740816,6743168,6740612,6742584,6741396,6740942,6741733,6744532,6744869,6744936,6744739,6744078,6741603,6744145,6745316,6743952,6745520,6741800,6742180,6742517,6743748,6745713,6742387],"length":1,"stats":{"Line":116},"fn_name":null},{"line":243,"address":[6743957,6744675,6743888,6745342,6743104,6745456,6743082,6743866,6744558,6743774,6745525,6740752,6744744,6743985,6741608,6741539,6745434,6742424,6744653,6743201,6742990,6741640,6740730,6740849,6743173,6742392,6742323,6745553,6740638,6744776,6741517,6742206,6740821,6742301,6741422],"length":1,"stats":{"Line":87},"fn_name":null},{"line":244,"address":[6745685,6745578,6744232,6740981,6745800,6743226,6740837,6741096,6743973,6744752,6741772,6743189,6742449,6741887,6744117,6744908,6741616,6742556,6743333,6740874,6742671,6742400,6741665,6743448,6744010,6745023,6744801,6745541],"length":1,"stats":{"Line":58},"fn_name":null},{"line":250,"address":[6743458,6741897,6744242,6744983,6741056,6741106,6742681,6741847,6745760,6745810,6743408,6742631,6744192,6745033],"length":1,"stats":{"Line":29},"fn_name":null},{"line":251,"address":[6743684,6741976,6744468,6745889,6744421,6745989,6742860,6741185,6743637,6745112,6742123,6742760,6745212,6742907,6741285,6746036,6742076,6745259,6744321,6743537,6741332],"length":1,"stats":{"Line":42},"fn_name":null},{"line":253,"address":[6744394,6745185,6745962,6742049,6741258,6743610,6742833],"length":1,"stats":{"Line":14},"fn_name":null},{"line":254,"address":[6741214,6742789,6743566,6744350,6742005,6745141,6745918],"length":1,"stats":{"Line":14},"fn_name":null}],"covered":57,"coverable":84},{"path":["/","home","runner","work","gotham_restful","gotham_restful","src","types.rs"],"content":"use gotham::{\n\thyper::body::Bytes,\n\tmime::{Mime, APPLICATION_JSON}\n};\n#[cfg(feature = \"openapi\")]\nuse openapi_type::OpenapiType;\nuse serde::{de::DeserializeOwned, Serialize};\nuse std::error::Error;\n\n#[cfg(not(feature = \"openapi\"))]\npub trait ResourceType {}\n\n#[cfg(not(feature = \"openapi\"))]\nimpl ResourceType for T {}\n\n#[cfg(feature = \"openapi\")]\npub trait ResourceType: OpenapiType {}\n\n#[cfg(feature = \"openapi\")]\nimpl ResourceType for T {}\n\n/// A type that can be used inside a response body. Implemented for every type that is\n/// serializable with serde. If the `openapi` feature is used, it must also be of type\n/// [OpenapiType].\npub trait ResponseBody: ResourceType + Serialize {}\n\nimpl ResponseBody for T {}\n\n/// This trait should be implemented for every type that can be built from an HTTP request body\n/// plus its media type.\n///\n/// For most use cases it is sufficient to derive this trait, you usually don't need to manually\n/// implement this. Therefore, make sure that the first variable of your struct can be built from\n/// [Bytes], and the second one can be build from [Mime]. If you have any additional variables, they\n/// need to be [Default]. This is an example of such a struct:\n///\n/// ```rust\n/// # use gotham::mime::{self, Mime};\n/// # use gotham_restful::{FromBody, RequestBody};\n/// #[derive(FromBody, RequestBody)]\n/// #[supported_types(mime::IMAGE_GIF, mime::IMAGE_JPEG, mime::IMAGE_PNG)]\n/// struct RawImage {\n/// \tcontent: Vec,\n/// \tcontent_type: Mime\n/// }\n/// ```\npub trait FromBody: Sized {\n\t/// The error type returned by the conversion if it was unsuccessfull. When using the derive\n\t/// macro, there is no way to trigger an error, so [std::convert::Infallible] is used here.\n\t/// However, this might change in the future.\n\ttype Err: Error;\n\n\t/// Perform the conversion.\n\tfn from_body(body: Bytes, content_type: Mime) -> Result;\n}\n\nimpl FromBody for T {\n\ttype Err = serde_json::Error;\n\n\tfn from_body(body: Bytes, _content_type: Mime) -> Result {\n\t\tserde_json::from_slice(&body)\n\t}\n}\n\n/// A type that can be used inside a request body. Implemented for every type that is deserializable\n/// with serde. If the `openapi` feature is used, it must also be of type [OpenapiType].\n///\n/// If you want a non-deserializable type to be used as a request body, e.g. because you'd like to\n/// get the raw data, you can derive it for your own type. All you need is to have a type implementing\n/// [FromBody] and optionally a list of supported media types:\n///\n/// ```rust\n/// # use gotham::mime::{self, Mime};\n/// # use gotham_restful::{FromBody, RequestBody};\n/// #[derive(FromBody, RequestBody)]\n/// #[supported_types(mime::IMAGE_GIF, mime::IMAGE_JPEG, mime::IMAGE_PNG)]\n/// struct RawImage {\n/// \tcontent: Vec,\n/// \tcontent_type: Mime\n/// }\n/// ```\npub trait RequestBody: ResourceType + FromBody {\n\t/// Return all types that are supported as content types. Use `None` if all types are supported.\n\tfn supported_types() -> Option> {\n\t\tNone\n\t}\n}\n\nimpl RequestBody for T {\n\tfn supported_types() -> Option> {\n\t\tSome(vec![APPLICATION_JSON])\n\t}\n}\n","traces":[{"line":60,"address":[],"length":0,"stats":{"Line":2},"fn_name":null},{"line":61,"address":[6678464,6678528],"length":1,"stats":{"Line":4},"fn_name":null},{"line":84,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":85,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":90,"address":[],"length":0,"stats":{"Line":1},"fn_name":null},{"line":91,"address":[],"length":0,"stats":{"Line":1},"fn_name":null}],"covered":4,"coverable":6},{"path":["/","home","runner","work","gotham_restful","gotham_restful","tests","async_methods.rs"],"content":"use gotham::{\n\thyper::{HeaderMap, Method},\n\tmime::{APPLICATION_JSON, TEXT_PLAIN},\n\tprelude::*,\n\trouter::build_simple_router,\n\tstate::State,\n\ttest::TestServer\n};\nuse gotham_restful::*;\n#[cfg(feature = \"openapi\")]\nuse openapi_type::OpenapiType;\nuse serde::Deserialize;\nuse tokio::time::{sleep, Duration};\n\nmod util {\n\tinclude!(\"util/mod.rs\");\n}\nuse util::{test_delete_response, test_get_response, test_post_response, test_put_response};\n\n#[derive(Resource)]\n#[resource(\n\tread_all, read, search, create, update_all, update, delete_all, delete, state_test\n)]\nstruct FooResource;\n\n#[derive(Deserialize)]\n#[cfg_attr(feature = \"openapi\", derive(OpenapiType))]\n#[allow(dead_code)]\nstruct FooBody {\n\tdata: String\n}\n\n#[derive(Clone, Deserialize, StateData, StaticResponseExtender)]\n#[cfg_attr(feature = \"openapi\", derive(OpenapiType))]\n#[allow(dead_code)]\nstruct FooSearch {\n\tquery: String\n}\n\nconst READ_ALL_RESPONSE: &[u8] = b\"1ARwwSPVyOKpJKrYwqGgECPVWDl1BqajAAj7g7WJ3e\";\n#[read_all]\nasync fn read_all() -> Raw<&'static [u8]> {\n\tRaw::new(READ_ALL_RESPONSE, TEXT_PLAIN)\n}\n\nconst READ_RESPONSE: &[u8] = b\"FEReHoeBKU17X2bBpVAd1iUvktFL43CDu0cFYHdaP9\";\n#[read]\nasync fn read(_id: u64) -> Raw<&'static [u8]> {\n\tRaw::new(READ_RESPONSE, TEXT_PLAIN)\n}\n\nconst SEARCH_RESPONSE: &[u8] = b\"AWqcQUdBRHXKh3at4u79mdupOAfEbnTcx71ogCVF0E\";\n#[search]\nasync fn search(_body: FooSearch) -> Raw<&'static [u8]> {\n\tRaw::new(SEARCH_RESPONSE, TEXT_PLAIN)\n}\n\nconst CREATE_RESPONSE: &[u8] = b\"y6POY7wOMAB0jBRBw0FJT7DOpUNbhmT8KdpQPLkI83\";\n#[create]\nasync fn create(_body: FooBody) -> Raw<&'static [u8]> {\n\tRaw::new(CREATE_RESPONSE, TEXT_PLAIN)\n}\n\nconst UPDATE_ALL_RESPONSE: &[u8] = b\"QlbYg8gHE9OQvvk3yKjXJLTSXlIrg9mcqhfMXJmQkv\";\n#[update_all]\nasync fn update_all(_body: FooBody) -> Raw<&'static [u8]> {\n\tRaw::new(UPDATE_ALL_RESPONSE, TEXT_PLAIN)\n}\n\nconst UPDATE_RESPONSE: &[u8] = b\"qGod55RUXkT1lgPO8h0uVM6l368O2S0GrwENZFFuRu\";\n#[update]\nasync fn update(_id: u64, _body: FooBody) -> Raw<&'static [u8]> {\n\tRaw::new(UPDATE_RESPONSE, TEXT_PLAIN)\n}\n\nconst DELETE_ALL_RESPONSE: &[u8] = b\"Y36kZ749MRk2Nem4BedJABOZiZWPLOtiwLfJlGTwm5\";\n#[delete_all]\nasync fn delete_all() -> Raw<&'static [u8]> {\n\tRaw::new(DELETE_ALL_RESPONSE, TEXT_PLAIN)\n}\n\nconst DELETE_RESPONSE: &[u8] = b\"CwRzBrKErsVZ1N7yeNfjZuUn1MacvgBqk4uPOFfDDq\";\n#[delete]\nasync fn delete(_id: u64) -> Raw<&'static [u8]> {\n\tRaw::new(DELETE_RESPONSE, TEXT_PLAIN)\n}\n\nconst STATE_TEST_RESPONSE: &[u8] = b\"xxJbxOuwioqR5DfzPuVqvaqRSfpdNQGluIvHU4n1LM\";\n#[endpoint(method = \"Method::GET\", uri = \"state_test\")]\nasync fn state_test(state: &mut State) -> Raw<&'static [u8]> {\n\tsleep(Duration::from_nanos(1)).await;\n\tstate.borrow::();\n\tsleep(Duration::from_nanos(1)).await;\n\tRaw::new(STATE_TEST_RESPONSE, TEXT_PLAIN)\n}\n\n#[test]\nfn async_methods() {\n\tlet _ = pretty_env_logger::try_init_timed();\n\n\tlet server = TestServer::new(build_simple_router(|router| {\n\t\trouter.resource::(\"foo\");\n\t}))\n\t.unwrap();\n\n\ttest_get_response(&server, \"http://localhost/foo\", READ_ALL_RESPONSE);\n\ttest_get_response(&server, \"http://localhost/foo/1\", READ_RESPONSE);\n\ttest_get_response(\n\t\t&server,\n\t\t\"http://localhost/foo/search?query=hello+world\",\n\t\tSEARCH_RESPONSE\n\t);\n\ttest_post_response(\n\t\t&server,\n\t\t\"http://localhost/foo\",\n\t\tr#\"{\"data\":\"hello world\"}\"#,\n\t\tAPPLICATION_JSON,\n\t\tCREATE_RESPONSE\n\t);\n\ttest_put_response(\n\t\t&server,\n\t\t\"http://localhost/foo\",\n\t\tr#\"{\"data\":\"hello world\"}\"#,\n\t\tAPPLICATION_JSON,\n\t\tUPDATE_ALL_RESPONSE\n\t);\n\ttest_put_response(\n\t\t&server,\n\t\t\"http://localhost/foo/1\",\n\t\tr#\"{\"data\":\"hello world\"}\"#,\n\t\tAPPLICATION_JSON,\n\t\tUPDATE_RESPONSE\n\t);\n\ttest_delete_response(&server, \"http://localhost/foo\", DELETE_ALL_RESPONSE);\n\ttest_delete_response(&server, \"http://localhost/foo/1\", DELETE_RESPONSE);\n\ttest_get_response(\n\t\t&server,\n\t\t\"http://localhost/foo/state_test\",\n\t\tSTATE_TEST_RESPONSE\n\t);\n}\n","traces":[],"covered":0,"coverable":0},{"path":["/","home","runner","work","gotham_restful","gotham_restful","tests","cors_handling.rs"],"content":"#![cfg(feature = \"cors\")]\nuse gotham::{\n\thyper::{body::Body, client::connect::Connect, header::*, StatusCode},\n\tmime::TEXT_PLAIN,\n\tpipeline::{new_pipeline, single_pipeline},\n\trouter::build_router,\n\ttest::{Server, TestRequest, TestServer}\n};\nuse gotham_restful::{\n\tcors::{Headers, Origin},\n\tread_all, update_all, CorsConfig, DrawResources, Raw, Resource\n};\n\n#[derive(Resource)]\n#[resource(read_all, update_all)]\nstruct FooResource;\n\n#[read_all]\nfn read_all() {}\n\n#[update_all]\nfn update_all(_body: Raw>) {}\n\nfn test_server(cfg: CorsConfig) -> TestServer {\n\tlet (chain, pipeline) = single_pipeline(new_pipeline().add(cfg).build());\n\tTestServer::new(build_router(chain, pipeline, |router| {\n\t\trouter.resource::(\"/foo\")\n\t}))\n\t.unwrap()\n}\n\nfn test_response(\n\treq: TestRequest,\n\torigin: Option<&str>,\n\tvary: Option<&str>,\n\tcredentials: bool\n) where\n\tTS: Server + 'static,\n\tC: Connect + Clone + Send + Sync + 'static\n{\n\tlet res = req\n\t\t.with_header(ORIGIN, \"http://example.org\".parse().unwrap())\n\t\t.perform()\n\t\t.unwrap();\n\tassert_eq!(res.status(), StatusCode::NO_CONTENT);\n\tlet headers = res.headers();\n\tprintln!(\n\t\t\"{}\",\n\t\theaders\n\t\t\t.keys()\n\t\t\t.map(|name| name.as_str())\n\t\t\t.collect::>()\n\t\t\t.join(\",\")\n\t);\n\tassert_eq!(\n\t\theaders\n\t\t\t.get(ACCESS_CONTROL_ALLOW_ORIGIN)\n\t\t\t.and_then(|value| value.to_str().ok())\n\t\t\t.as_deref(),\n\t\torigin\n\t);\n\tassert_eq!(\n\t\theaders\n\t\t\t.get(VARY)\n\t\t\t.and_then(|value| value.to_str().ok())\n\t\t\t.as_deref(),\n\t\tvary\n\t);\n\tassert_eq!(\n\t\theaders\n\t\t\t.get(ACCESS_CONTROL_ALLOW_CREDENTIALS)\n\t\t\t.and_then(|value| value.to_str().ok())\n\t\t\t.map(|value| value == \"true\")\n\t\t\t.unwrap_or(false),\n\t\tcredentials\n\t);\n\tassert!(headers.get(ACCESS_CONTROL_MAX_AGE).is_none());\n}\n\nfn test_preflight(\n\tserver: &TestServer,\n\tmethod: &str,\n\torigin: Option<&str>,\n\tvary: &str,\n\tcredentials: bool,\n\tmax_age: u64\n) {\n\tlet res = server\n\t\t.client()\n\t\t.options(\"http://example.org/foo\")\n\t\t.with_header(ACCESS_CONTROL_REQUEST_METHOD, method.parse().unwrap())\n\t\t.with_header(ORIGIN, \"http://example.org\".parse().unwrap())\n\t\t.perform()\n\t\t.unwrap();\n\tassert_eq!(res.status(), StatusCode::NO_CONTENT);\n\tlet headers = res.headers();\n\tprintln!(\n\t\t\"{}\",\n\t\theaders\n\t\t\t.keys()\n\t\t\t.map(|name| name.as_str())\n\t\t\t.collect::>()\n\t\t\t.join(\",\")\n\t);\n\tassert_eq!(\n\t\theaders\n\t\t\t.get(ACCESS_CONTROL_ALLOW_METHODS)\n\t\t\t.and_then(|value| value.to_str().ok())\n\t\t\t.as_deref(),\n\t\tSome(method)\n\t);\n\tassert_eq!(\n\t\theaders\n\t\t\t.get(ACCESS_CONTROL_ALLOW_ORIGIN)\n\t\t\t.and_then(|value| value.to_str().ok())\n\t\t\t.as_deref(),\n\t\torigin\n\t);\n\tassert_eq!(\n\t\theaders\n\t\t\t.get(VARY)\n\t\t\t.and_then(|value| value.to_str().ok())\n\t\t\t.as_deref(),\n\t\tSome(vary)\n\t);\n\tassert_eq!(\n\t\theaders\n\t\t\t.get(ACCESS_CONTROL_ALLOW_CREDENTIALS)\n\t\t\t.and_then(|value| value.to_str().ok())\n\t\t\t.map(|value| value == \"true\")\n\t\t\t.unwrap_or(false),\n\t\tcredentials\n\t);\n\tassert_eq!(\n\t\theaders\n\t\t\t.get(ACCESS_CONTROL_MAX_AGE)\n\t\t\t.and_then(|value| value.to_str().ok())\n\t\t\t.and_then(|value| value.parse().ok()),\n\t\tSome(max_age)\n\t);\n}\n\nfn test_preflight_headers(\n\tserver: &TestServer,\n\tmethod: &str,\n\trequest_headers: Option<&str>,\n\tallowed_headers: Option<&str>,\n\tvary: &str\n) {\n\tlet client = server.client();\n\tlet mut res = client\n\t\t.options(\"http://example.org/foo\")\n\t\t.with_header(ACCESS_CONTROL_REQUEST_METHOD, method.parse().unwrap())\n\t\t.with_header(ORIGIN, \"http://example.org\".parse().unwrap());\n\tif let Some(hdr) = request_headers {\n\t\tres = res.with_header(ACCESS_CONTROL_REQUEST_HEADERS, hdr.parse().unwrap());\n\t}\n\tlet res = res.perform().unwrap();\n\tassert_eq!(res.status(), StatusCode::NO_CONTENT);\n\tlet headers = res.headers();\n\tprintln!(\n\t\t\"{}\",\n\t\theaders\n\t\t\t.keys()\n\t\t\t.map(|name| name.as_str())\n\t\t\t.collect::>()\n\t\t\t.join(\",\")\n\t);\n\tif let Some(hdr) = allowed_headers {\n\t\tassert_eq!(\n\t\t\theaders\n\t\t\t\t.get(ACCESS_CONTROL_ALLOW_HEADERS)\n\t\t\t\t.and_then(|value| value.to_str().ok())\n\t\t\t\t.as_deref(),\n\t\t\tSome(hdr)\n\t\t)\n\t} else {\n\t\tassert!(!headers.contains_key(ACCESS_CONTROL_ALLOW_HEADERS));\n\t}\n\tassert_eq!(\n\t\theaders\n\t\t\t.get(VARY)\n\t\t\t.and_then(|value| value.to_str().ok())\n\t\t\t.as_deref(),\n\t\tSome(vary)\n\t);\n}\n\n#[test]\nfn cors_origin_none() {\n\tlet cfg = Default::default();\n\tlet server = test_server(cfg);\n\n\ttest_preflight(\n\t\t&server,\n\t\t\"PUT\",\n\t\tNone,\n\t\t\"access-control-request-method\",\n\t\tfalse,\n\t\t0\n\t);\n\n\ttest_response(\n\t\tserver.client().get(\"http://example.org/foo\"),\n\t\tNone,\n\t\tNone,\n\t\tfalse\n\t);\n\ttest_response(\n\t\tserver\n\t\t\t.client()\n\t\t\t.put(\"http://example.org/foo\", Body::empty(), TEXT_PLAIN),\n\t\tNone,\n\t\tNone,\n\t\tfalse\n\t);\n}\n\n#[test]\nfn cors_origin_star() {\n\tlet cfg = CorsConfig {\n\t\torigin: Origin::Star,\n\t\t..Default::default()\n\t};\n\tlet server = test_server(cfg);\n\n\ttest_preflight(\n\t\t&server,\n\t\t\"PUT\",\n\t\tSome(\"*\"),\n\t\t\"access-control-request-method\",\n\t\tfalse,\n\t\t0\n\t);\n\n\ttest_response(\n\t\tserver.client().get(\"http://example.org/foo\"),\n\t\tSome(\"*\"),\n\t\tNone,\n\t\tfalse\n\t);\n\ttest_response(\n\t\tserver\n\t\t\t.client()\n\t\t\t.put(\"http://example.org/foo\", Body::empty(), TEXT_PLAIN),\n\t\tSome(\"*\"),\n\t\tNone,\n\t\tfalse\n\t);\n}\n\n#[test]\nfn cors_origin_single() {\n\tlet cfg = CorsConfig {\n\t\torigin: Origin::Single(\"https://foo.com\".to_owned()),\n\t\t..Default::default()\n\t};\n\tlet server = test_server(cfg);\n\n\ttest_preflight(\n\t\t&server,\n\t\t\"PUT\",\n\t\tSome(\"https://foo.com\"),\n\t\t\"access-control-request-method\",\n\t\tfalse,\n\t\t0\n\t);\n\n\ttest_response(\n\t\tserver.client().get(\"http://example.org/foo\"),\n\t\tSome(\"https://foo.com\"),\n\t\tNone,\n\t\tfalse\n\t);\n\ttest_response(\n\t\tserver\n\t\t\t.client()\n\t\t\t.put(\"http://example.org/foo\", Body::empty(), TEXT_PLAIN),\n\t\tSome(\"https://foo.com\"),\n\t\tNone,\n\t\tfalse\n\t);\n}\n\n#[test]\nfn cors_origin_copy() {\n\tlet cfg = CorsConfig {\n\t\torigin: Origin::Copy,\n\t\t..Default::default()\n\t};\n\tlet server = test_server(cfg);\n\n\ttest_preflight(\n\t\t&server,\n\t\t\"PUT\",\n\t\tSome(\"http://example.org\"),\n\t\t\"access-control-request-method,origin\",\n\t\tfalse,\n\t\t0\n\t);\n\n\ttest_response(\n\t\tserver.client().get(\"http://example.org/foo\"),\n\t\tSome(\"http://example.org\"),\n\t\tSome(\"origin\"),\n\t\tfalse\n\t);\n\ttest_response(\n\t\tserver\n\t\t\t.client()\n\t\t\t.put(\"http://example.org/foo\", Body::empty(), TEXT_PLAIN),\n\t\tSome(\"http://example.org\"),\n\t\tSome(\"origin\"),\n\t\tfalse\n\t);\n}\n\n#[test]\nfn cors_headers_none() {\n\tlet cfg = Default::default();\n\tlet server = test_server(cfg);\n\n\ttest_preflight_headers(&server, \"PUT\", None, None, \"access-control-request-method\");\n\ttest_preflight_headers(\n\t\t&server,\n\t\t\"PUT\",\n\t\tSome(\"Content-Type\"),\n\t\tNone,\n\t\t\"access-control-request-method\"\n\t);\n}\n\n#[test]\nfn cors_headers_list() {\n\tlet cfg = CorsConfig {\n\t\theaders: Headers::List(vec![CONTENT_TYPE]),\n\t\t..Default::default()\n\t};\n\tlet server = test_server(cfg);\n\n\ttest_preflight_headers(\n\t\t&server,\n\t\t\"PUT\",\n\t\tNone,\n\t\tSome(\"content-type\"),\n\t\t\"access-control-request-method\"\n\t);\n\ttest_preflight_headers(\n\t\t&server,\n\t\t\"PUT\",\n\t\tSome(\"content-type\"),\n\t\tSome(\"content-type\"),\n\t\t\"access-control-request-method\"\n\t);\n}\n\n#[test]\nfn cors_headers_copy() {\n\tlet cfg = CorsConfig {\n\t\theaders: Headers::Copy,\n\t\t..Default::default()\n\t};\n\tlet server = test_server(cfg);\n\n\ttest_preflight_headers(\n\t\t&server,\n\t\t\"PUT\",\n\t\tNone,\n\t\tNone,\n\t\t\"access-control-request-method,access-control-request-headers\"\n\t);\n\ttest_preflight_headers(\n\t\t&server,\n\t\t\"PUT\",\n\t\tSome(\"content-type\"),\n\t\tSome(\"content-type\"),\n\t\t\"access-control-request-method,access-control-request-headers\"\n\t);\n}\n\n#[test]\nfn cors_credentials() {\n\tlet cfg = CorsConfig {\n\t\torigin: Origin::None,\n\t\tcredentials: true,\n\t\t..Default::default()\n\t};\n\tlet server = test_server(cfg);\n\n\ttest_preflight(\n\t\t&server,\n\t\t\"PUT\",\n\t\tNone,\n\t\t\"access-control-request-method\",\n\t\ttrue,\n\t\t0\n\t);\n\n\ttest_response(\n\t\tserver.client().get(\"http://example.org/foo\"),\n\t\tNone,\n\t\tNone,\n\t\ttrue\n\t);\n\ttest_response(\n\t\tserver\n\t\t\t.client()\n\t\t\t.put(\"http://example.org/foo\", Body::empty(), TEXT_PLAIN),\n\t\tNone,\n\t\tNone,\n\t\ttrue\n\t);\n}\n\n#[test]\nfn cors_max_age() {\n\tlet cfg = CorsConfig {\n\t\torigin: Origin::None,\n\t\tmax_age: 31536000,\n\t\t..Default::default()\n\t};\n\tlet server = test_server(cfg);\n\n\ttest_preflight(\n\t\t&server,\n\t\t\"PUT\",\n\t\tNone,\n\t\t\"access-control-request-method\",\n\t\tfalse,\n\t\t31536000\n\t);\n\n\ttest_response(\n\t\tserver.client().get(\"http://example.org/foo\"),\n\t\tNone,\n\t\tNone,\n\t\tfalse\n\t);\n\ttest_response(\n\t\tserver\n\t\t\t.client()\n\t\t\t.put(\"http://example.org/foo\", Body::empty(), TEXT_PLAIN),\n\t\tNone,\n\t\tNone,\n\t\tfalse\n\t);\n}\n","traces":[],"covered":0,"coverable":0},{"path":["/","home","runner","work","gotham_restful","gotham_restful","tests","custom_request_body.rs"],"content":"use gotham::{\n\thyper::header::CONTENT_TYPE,\n\tmime::{Mime, TEXT_PLAIN},\n\trouter::builder::*,\n\ttest::TestServer\n};\nuse gotham_restful::{create, DrawResources, FromBody, Raw, RequestBody, Resource};\n\nconst RESPONSE: &[u8] = b\"This is the only valid response.\";\n\n#[derive(Resource)]\n#[resource(create)]\nstruct FooResource;\n\n#[derive(FromBody, RequestBody)]\n#[supported_types(TEXT_PLAIN)]\nstruct Foo {\n\tcontent: Vec,\n\tcontent_type: Mime\n}\n\n#[create]\nfn create(body: Foo) -> Raw> {\n\tRaw::new(body.content, body.content_type)\n}\n\n#[test]\nfn custom_request_body() {\n\tlet server = TestServer::new(build_simple_router(|router| {\n\t\trouter.resource::(\"foo\");\n\t}))\n\t.unwrap();\n\n\tlet res = server\n\t\t.client()\n\t\t.post(\"http://localhost/foo\", RESPONSE, TEXT_PLAIN)\n\t\t.perform()\n\t\t.unwrap();\n\tassert_eq!(\n\t\tres.headers().get(CONTENT_TYPE).unwrap().to_str().unwrap(),\n\t\t\"text/plain\"\n\t);\n\tlet res = res.read_body().unwrap();\n\tlet body: &[u8] = res.as_ref();\n\tassert_eq!(body, RESPONSE);\n}\n","traces":[],"covered":0,"coverable":0},{"path":["/","home","runner","work","gotham_restful","gotham_restful","tests","openapi_specification.rs"],"content":"#![cfg(all(feature = \"auth\", feature = \"openapi\"))]\n#![allow(clippy::approx_constant)]\n\n#[macro_use]\nextern crate pretty_assertions;\n\nuse gotham::{\n\thyper::{Method, StatusCode},\n\tmime::{IMAGE_PNG, TEXT_PLAIN_UTF_8},\n\tpipeline::{new_pipeline, single_pipeline},\n\tprelude::*,\n\trouter::build_router,\n\ttest::TestServer\n};\nuse gotham_restful::*;\nuse openapi_type::{OpenapiSchema, OpenapiType, Visitor};\nuse serde::{Deserialize, Serialize};\n\n#[allow(dead_code)]\nmod util {\n\tinclude!(\"util/mod.rs\");\n}\nuse util::test_openapi_response;\n\nconst IMAGE_RESPONSE : &[u8] = b\"iVBORw0KGgoAAAANSUhEUgAAAAEAAAABAQMAAAAl21bKAAAAA1BMVEUA/wA0XsCoAAAAAXRSTlN/gFy0ywAAAApJREFUeJxjYgAAAAYAAzY3fKgAAAAASUVORK5CYII=\";\n\n#[derive(Resource)]\n#[resource(get_image, set_image)]\nstruct ImageResource;\n\n#[derive(FromBody, RequestBody)]\n#[supported_types(IMAGE_PNG)]\nstruct Image(Vec);\n\n#[read(operation_id = \"getImage\")]\nfn get_image(_id: u64) -> Raw<&'static [u8]> {\n\tRaw::new(IMAGE_RESPONSE, \"image/png;base64\".parse().unwrap())\n}\n\n#[update(operation_id = \"setImage\")]\nfn set_image(_id: u64, _image: Image) {}\n\n#[derive(Resource)]\n#[resource(read_secret, search_secret)]\nstruct SecretResource;\n\n#[derive(Deserialize, Clone)]\nstruct AuthData {\n\tsub: String,\n\tiat: u64,\n\texp: u64\n}\n\ntype AuthStatus = gotham_restful::AuthStatus;\n\n#[derive(OpenapiType, Serialize)]\nstruct Secret {\n\tcode: f32\n}\n\n#[derive(OpenapiType, Serialize)]\nstruct Secrets {\n\tsecrets: Vec\n}\n\n#[derive(Clone, Deserialize, OpenapiType, StateData, StaticResponseExtender)]\nstruct SecretQuery {\n\tdate: String,\n\thour: Option,\n\tminute: Option\n}\n\n/// This endpoint gives access to the secret.\n///\n/// You need to be authenticated to call this endpoint.\n#[read]\nfn read_secret(auth: AuthStatus, _id: String) -> AuthSuccess {\n\tauth.ok()?;\n\tOk(Secret { code: 4.2 })\n}\n\n#[search]\nfn search_secret(auth: AuthStatus, _query: SecretQuery) -> AuthSuccess {\n\tauth.ok()?;\n\tOk(Secrets {\n\t\tsecrets: vec![Secret { code: 4.2 }, Secret { code: 3.14 }]\n\t})\n}\n\n#[derive(Resource)]\n#[resource(coffee_read_all)]\nstruct CoffeeResource;\n\nfn teapot_status_codes() -> Vec {\n\tvec![StatusCode::IM_A_TEAPOT]\n}\n\nfn teapot_schema(code: StatusCode) -> OpenapiSchema {\n\tassert_eq!(code, StatusCode::IM_A_TEAPOT);\n\n\tstruct Binary;\n\n\timpl OpenapiType for Binary {\n\t\tfn visit_type(visitor: &mut V) {\n\t\t\tvisitor.visit_binary();\n\t\t}\n\t}\n\n\tBinary::schema()\n}\n\n#[read_all(status_codes = \"teapot_status_codes\", schema = \"teapot_schema\")]\nfn coffee_read_all() -> Response {\n\tResponse::new(\n\t\tStatusCode::IM_A_TEAPOT,\n\t\t\"Sorry, this is just your fancy grandma's teapot. Can't make coffee.\",\n\t\tSome(TEXT_PLAIN_UTF_8)\n\t)\n}\n\n#[derive(Resource)]\n#[resource(custom_read_with, custom_patch)]\nstruct CustomResource;\n\n#[derive(Clone, Deserialize, OpenapiType, StateData, StaticResponseExtender)]\nstruct ReadWithPath {\n\tfrom: String,\n\tid: u64\n}\n\n#[endpoint(method = \"Method::GET\", uri = \"read/:from/with/:id\")]\nfn custom_read_with(_path: ReadWithPath) {}\n\n#[endpoint(method = \"Method::PATCH\", uri = \"\", body = true)]\nfn custom_patch(_body: String) {}\n\n#[test]\nfn openapi_specification() {\n\tlet info = OpenapiInfo {\n\t\ttitle: \"This is just a test\".to_owned(),\n\t\tversion: \"1.2.3\".to_owned(),\n\t\turls: vec![\"http://localhost:12345/api/v1\".to_owned()]\n\t};\n\tlet auth: AuthMiddleware = AuthMiddleware::new(\n\t\tAuthSource::AuthorizationHeader,\n\t\tAuthValidation::default(),\n\t\tStaticAuthHandler::from_array(b\"zlBsA2QXnkmpe0QTh8uCvtAEa4j33YAc\")\n\t);\n\tlet (chain, pipelines) = single_pipeline(new_pipeline().add(auth).build());\n\tlet server = TestServer::new(build_router(chain, pipelines, |router| {\n\t\trouter.with_openapi(info, |mut router| {\n\t\t\t// the leading slash tests that the spec doesn't contain '//img' nonsense\n\t\t\trouter.resource::(\"/img\");\n\t\t\trouter.resource::(\"secret\");\n\t\t\trouter.resource::(\"coffee\");\n\t\t\trouter.resource::(\"custom\");\n\t\t\trouter.openapi_spec(\"openapi\");\n\t\t});\n\t}))\n\t.unwrap();\n\n\ttest_openapi_response(\n\t\t&server,\n\t\t\"http://localhost/openapi\",\n\t\t\"tests/openapi_specification.json\"\n\t);\n}\n","traces":[],"covered":0,"coverable":0},{"path":["/","home","runner","work","gotham_restful","gotham_restful","tests","openapi_supports_scope.rs"],"content":"#![cfg(feature = \"openapi\")]\n\n#[macro_use]\nextern crate pretty_assertions;\n\nuse gotham::{mime::TEXT_PLAIN, router::builder::*, test::TestServer};\nuse gotham_restful::*;\n\n#[allow(dead_code)]\nmod util {\n\tinclude!(\"util/mod.rs\");\n}\nuse util::{test_get_response, test_openapi_response};\n\nconst RESPONSE: &[u8] = b\"This is the only valid response.\";\n\n#[derive(Resource)]\n#[resource(read_all)]\nstruct FooResource;\n\n#[read_all]\nfn read_all() -> Raw<&'static [u8]> {\n\tRaw::new(RESPONSE, TEXT_PLAIN)\n}\n\n#[test]\nfn openapi_supports_scope() {\n\tlet info = OpenapiInfo {\n\t\ttitle: \"Test\".to_owned(),\n\t\tversion: \"1.2.3\".to_owned(),\n\t\turls: Vec::new()\n\t};\n\tlet server = TestServer::new(build_simple_router(|router| {\n\t\trouter.with_openapi(info, |mut router| {\n\t\t\trouter.openapi_spec(\"openapi\");\n\t\t\trouter.resource::(\"foo1\");\n\t\t\trouter.scope(\"/bar\", |router| {\n\t\t\t\trouter.resource::(\"foo2\");\n\t\t\t\trouter.scope(\"/baz\", |router| {\n\t\t\t\t\trouter.resource::(\"foo3\");\n\t\t\t\t})\n\t\t\t});\n\t\t\trouter.resource::(\"foo4\");\n\t\t});\n\t}))\n\t.unwrap();\n\n\ttest_get_response(&server, \"http://localhost/foo1\", RESPONSE);\n\ttest_get_response(&server, \"http://localhost/bar/foo2\", RESPONSE);\n\ttest_get_response(&server, \"http://localhost/bar/baz/foo3\", RESPONSE);\n\ttest_get_response(&server, \"http://localhost/foo4\", RESPONSE);\n\ttest_openapi_response(\n\t\t&server,\n\t\t\"http://localhost/openapi\",\n\t\t\"tests/openapi_supports_scope.json\"\n\t);\n}\n","traces":[],"covered":0,"coverable":0},{"path":["/","home","runner","work","gotham_restful","gotham_restful","tests","resource_error.rs"],"content":"use gotham_restful::ResourceError;\n\n#[derive(ResourceError)]\nenum Error {\n\t#[display(\"I/O Error: {0}\")]\n\tIoError(#[from] std::io::Error),\n\n\t#[status(INTERNAL_SERVER_ERROR)]\n\t#[display(\"Internal Server Error: {0}\")]\n\tInternalServerError(String)\n}\n\n#[allow(deprecated)]\nmod resource_error {\n\tuse super::Error;\n\tuse gotham::{hyper::StatusCode, mime::APPLICATION_JSON};\n\tuse gotham_restful::IntoResponseError;\n\n\t#[test]\n\tfn io_error() {\n\t\tlet err = Error::IoError(std::io::Error::last_os_error());\n\t\tlet res = err.into_response_error().unwrap();\n\t\tassert_eq!(res.status(), StatusCode::INTERNAL_SERVER_ERROR);\n\t\tassert_eq!(res.mime(), Some(&APPLICATION_JSON));\n\t}\n\n\t#[test]\n\tfn internal_server_error() {\n\t\tlet err = Error::InternalServerError(\"Brocken\".to_owned());\n\t\tassert_eq!(&format!(\"{err}\"), \"Internal Server Error: Brocken\");\n\n\t\tlet res = err.into_response_error().unwrap();\n\t\tassert_eq!(res.status(), StatusCode::INTERNAL_SERVER_ERROR);\n\t\tassert_eq!(res.mime(), None); // TODO shouldn't this be a json error message?\n\t}\n}\n","traces":[],"covered":0,"coverable":0},{"path":["/","home","runner","work","gotham_restful","gotham_restful","tests","sync_methods.rs"],"content":"use gotham::{\n\tmime::{APPLICATION_JSON, TEXT_PLAIN},\n\tprelude::*,\n\trouter::build_simple_router,\n\ttest::TestServer\n};\nuse gotham_restful::*;\n#[cfg(feature = \"openapi\")]\nuse openapi_type::OpenapiType;\nuse serde::Deserialize;\n\nmod util {\n\tinclude!(\"util/mod.rs\");\n}\nuse util::{test_delete_response, test_get_response, test_post_response, test_put_response};\n\n#[derive(Resource)]\n#[resource(read_all, read, search, create, update_all, update, delete_all, delete)]\nstruct FooResource;\n\n#[derive(Deserialize)]\n#[cfg_attr(feature = \"openapi\", derive(OpenapiType))]\n#[allow(dead_code)]\nstruct FooBody {\n\tdata: String\n}\n\n#[derive(Clone, Deserialize, StateData, StaticResponseExtender)]\n#[cfg_attr(feature = \"openapi\", derive(OpenapiType))]\n#[allow(dead_code)]\nstruct FooSearch {\n\tquery: String\n}\n\nconst READ_ALL_RESPONSE: &[u8] = b\"1ARwwSPVyOKpJKrYwqGgECPVWDl1BqajAAj7g7WJ3e\";\n#[read_all]\nfn read_all() -> Raw<&'static [u8]> {\n\tRaw::new(READ_ALL_RESPONSE, TEXT_PLAIN)\n}\n\nconst READ_RESPONSE: &[u8] = b\"FEReHoeBKU17X2bBpVAd1iUvktFL43CDu0cFYHdaP9\";\n#[read]\nfn read(_id: u64) -> Raw<&'static [u8]> {\n\tRaw::new(READ_RESPONSE, TEXT_PLAIN)\n}\n\nconst SEARCH_RESPONSE: &[u8] = b\"AWqcQUdBRHXKh3at4u79mdupOAfEbnTcx71ogCVF0E\";\n#[search]\nfn search(_body: FooSearch) -> Raw<&'static [u8]> {\n\tRaw::new(SEARCH_RESPONSE, TEXT_PLAIN)\n}\n\nconst CREATE_RESPONSE: &[u8] = b\"y6POY7wOMAB0jBRBw0FJT7DOpUNbhmT8KdpQPLkI83\";\n#[create]\nfn create(_body: FooBody) -> Raw<&'static [u8]> {\n\tRaw::new(CREATE_RESPONSE, TEXT_PLAIN)\n}\n\nconst UPDATE_ALL_RESPONSE: &[u8] = b\"QlbYg8gHE9OQvvk3yKjXJLTSXlIrg9mcqhfMXJmQkv\";\n#[update_all]\nfn update_all(_body: FooBody) -> Raw<&'static [u8]> {\n\tRaw::new(UPDATE_ALL_RESPONSE, TEXT_PLAIN)\n}\n\nconst UPDATE_RESPONSE: &[u8] = b\"qGod55RUXkT1lgPO8h0uVM6l368O2S0GrwENZFFuRu\";\n#[update]\nfn update(_id: u64, _body: FooBody) -> Raw<&'static [u8]> {\n\tRaw::new(UPDATE_RESPONSE, TEXT_PLAIN)\n}\n\nconst DELETE_ALL_RESPONSE: &[u8] = b\"Y36kZ749MRk2Nem4BedJABOZiZWPLOtiwLfJlGTwm5\";\n#[delete_all]\nfn delete_all() -> Raw<&'static [u8]> {\n\tRaw::new(DELETE_ALL_RESPONSE, TEXT_PLAIN)\n}\n\nconst DELETE_RESPONSE: &[u8] = b\"CwRzBrKErsVZ1N7yeNfjZuUn1MacvgBqk4uPOFfDDq\";\n#[delete]\nfn delete(_id: u64) -> Raw<&'static [u8]> {\n\tRaw::new(DELETE_RESPONSE, TEXT_PLAIN)\n}\n\n#[test]\nfn sync_methods() {\n\tlet _ = pretty_env_logger::try_init_timed();\n\n\tlet server = TestServer::new(build_simple_router(|router| {\n\t\trouter.resource::(\"foo\");\n\t}))\n\t.unwrap();\n\n\ttest_get_response(&server, \"http://localhost/foo\", READ_ALL_RESPONSE);\n\ttest_get_response(&server, \"http://localhost/foo/1\", READ_RESPONSE);\n\ttest_get_response(\n\t\t&server,\n\t\t\"http://localhost/foo/search?query=hello+world\",\n\t\tSEARCH_RESPONSE\n\t);\n\ttest_post_response(\n\t\t&server,\n\t\t\"http://localhost/foo\",\n\t\tr#\"{\"data\":\"hello world\"}\"#,\n\t\tAPPLICATION_JSON,\n\t\tCREATE_RESPONSE\n\t);\n\ttest_put_response(\n\t\t&server,\n\t\t\"http://localhost/foo\",\n\t\tr#\"{\"data\":\"hello world\"}\"#,\n\t\tAPPLICATION_JSON,\n\t\tUPDATE_ALL_RESPONSE\n\t);\n\ttest_put_response(\n\t\t&server,\n\t\t\"http://localhost/foo/1\",\n\t\tr#\"{\"data\":\"hello world\"}\"#,\n\t\tAPPLICATION_JSON,\n\t\tUPDATE_RESPONSE\n\t);\n\ttest_delete_response(&server, \"http://localhost/foo\", DELETE_ALL_RESPONSE);\n\ttest_delete_response(&server, \"http://localhost/foo/1\", DELETE_RESPONSE);\n}\n","traces":[],"covered":0,"coverable":0},{"path":["/","home","runner","work","gotham_restful","gotham_restful","tests","trybuild_ui.rs"],"content":"use trybuild::TestCases;\n\n#[test]\n#[ignore]\nfn trybuild_ui() {\n\tlet t = TestCases::new();\n\tt.compile_fail(\"tests/ui/endpoint/*.rs\");\n\tt.compile_fail(\"tests/ui/from_body/*.rs\");\n\tt.compile_fail(\"tests/ui/resource/*.rs\");\n}\n","traces":[],"covered":0,"coverable":0},{"path":["/","home","runner","work","gotham_restful","gotham_restful","tests","ui","endpoint","async_state.rs"],"content":"#[macro_use]\nextern crate gotham_restful;\nuse gotham::state::State;\n\n#[derive(Resource)]\n#[resource(read_all)]\nstruct FooResource;\n\n#[read_all]\nasync fn read_all(state: &State) {}\n\nfn main() {}\n","traces":[],"covered":0,"coverable":0},{"path":["/","home","runner","work","gotham_restful","gotham_restful","tests","ui","endpoint","auth_data_non_clone.rs"],"content":"use gotham_restful::*;\nuse serde::Deserialize;\n\n#[derive(Resource)]\n#[resource(read_all)]\nstruct FooResource;\n\n#[derive(Deserialize)]\nstruct AuthData {\n\tiat: u64,\n\texp: u64\n}\n\n#[read_all]\nasync fn read_all(auth: AuthStatus) -> Result {\n\tauth.ok()?;\n\tOk(NoContent::default())\n}\n\nfn main() {}\n","traces":[],"covered":0,"coverable":0},{"path":["/","home","runner","work","gotham_restful","gotham_restful","tests","ui","endpoint","custom_method_invalid_expr.rs"],"content":"#[macro_use]\nextern crate gotham_restful;\n\n#[derive(Resource)]\n#[resource(read_all)]\nstruct FooResource;\n\n#[endpoint(method = \"I like pizza\", uri = \"custom_read\")]\nasync fn read_all() {}\n\nfn main() {}\n","traces":[],"covered":0,"coverable":0},{"path":["/","home","runner","work","gotham_restful","gotham_restful","tests","ui","endpoint","custom_method_invalid_type.rs"],"content":"#[macro_use]\nextern crate gotham_restful;\n\n#[derive(Resource)]\n#[resource(read_all)]\nstruct FooResource;\n\n#[endpoint(method = \"String::new()\", uri = \"custom_read\")]\nasync fn read_all() {}\n\nfn main() {}\n","traces":[],"covered":0,"coverable":0},{"path":["/","home","runner","work","gotham_restful","gotham_restful","tests","ui","endpoint","custom_method_missing.rs"],"content":"#[macro_use]\nextern crate gotham_restful;\n\n#[derive(Resource)]\n#[resource(read_all)]\nstruct FooResource;\n\n#[endpoint(uri = \"custom_read\")]\nasync fn read_all() {}\n\nfn main() {}\n","traces":[],"covered":0,"coverable":0},{"path":["/","home","runner","work","gotham_restful","gotham_restful","tests","ui","endpoint","custom_uri_missing.rs"],"content":"#[macro_use]\nextern crate gotham_restful;\n\n#[derive(Resource)]\n#[resource(read_all)]\nstruct FooResource;\n\n#[endpoint(method = \"gotham_restful::gotham::hyper::Method::GET\")]\nasync fn read_all() {}\n\nfn main() {}\n","traces":[],"covered":0,"coverable":0},{"path":["/","home","runner","work","gotham_restful","gotham_restful","tests","ui","endpoint","dynamic_schema_missing_schema.rs"],"content":"#[macro_use]\nextern crate gotham_restful;\n\nuse gotham::hyper::StatusCode;\n\n#[derive(Resource)]\n#[resource(read_all)]\nstruct FooResource;\n\nfn status_codes() -> Vec {\n\tunimplemented!()\n}\n\n#[read_all(status_codes = \"status_codes\")]\nasync fn read_all() {}\n\nfn main() {}\n","traces":[],"covered":0,"coverable":0},{"path":["/","home","runner","work","gotham_restful","gotham_restful","tests","ui","endpoint","dynamic_schema_missing_status_codes.rs"],"content":"#[macro_use]\nextern crate gotham_restful;\n\nuse gotham::hyper::StatusCode;\nuse gotham_restful::private::OpenapiSchema;\n\n#[derive(Resource)]\n#[resource(read_all)]\nstruct FooResource;\n\nfn schema(_: StatusCode) -> OpenapiSchema {\n\tunimplemented!()\n}\n\n#[read_all(schema = \"schema\")]\nasync fn read_all() {}\n\nfn main() {}\n","traces":[],"covered":0,"coverable":0},{"path":["/","home","runner","work","gotham_restful","gotham_restful","tests","ui","endpoint","dynamic_schema_wrong_type.rs"],"content":"#[macro_use]\nextern crate gotham_restful;\n\n#[derive(Resource)]\n#[resource(read_all)]\nstruct FooResource;\n\nfn schema(_: u16) -> String {\n\tunimplemented!()\n}\n\nfn status_codes() -> Vec {\n\tunimplemented!()\n}\n\n#[read_all(schema = \"schema\", status_codes = \"status_codes\")]\nasync fn read_all() {}\n\nfn main() {}\n","traces":[],"covered":0,"coverable":0},{"path":["/","home","runner","work","gotham_restful","gotham_restful","tests","ui","endpoint","invalid_attribute.rs"],"content":"#[macro_use]\nextern crate gotham_restful;\n\n#[derive(Resource)]\n#[resource(read_all)]\nstruct FooResource;\n\n#[read_all(FooResource)]\nfn read_all() {}\n\nfn main() {}\n","traces":[],"covered":0,"coverable":0},{"path":["/","home","runner","work","gotham_restful","gotham_restful","tests","ui","endpoint","invalid_body_ty.rs"],"content":"#[macro_use]\nextern crate gotham_restful;\nuse gotham_restful::gotham::hyper::Method;\n\n#[derive(Resource)]\n#[resource(endpoint)]\nstruct FooResource;\n\n#[derive(Debug)]\nstruct FooBody {\n\tfoo: String\n}\n\n#[endpoint(method = \"Method::GET\", uri = \"\", body = true)]\nfn endpoint(_: FooBody) {\n\tunimplemented!()\n}\n\nfn main() {}\n","traces":[],"covered":0,"coverable":0},{"path":["/","home","runner","work","gotham_restful","gotham_restful","tests","ui","endpoint","invalid_params_ty.rs"],"content":"#[macro_use]\nextern crate gotham_restful;\nuse gotham_restful::gotham::hyper::Method;\n\n#[derive(Resource)]\n#[resource(endpoint)]\nstruct FooResource;\n\n#[derive(Debug)]\nstruct FooParams {\n\tfoo: String\n}\n\n#[endpoint(method = \"Method::GET\", uri = \"\", params = true)]\nfn endpoint(_: FooParams) {\n\tunimplemented!()\n}\n\nfn main() {}\n","traces":[],"covered":0,"coverable":0},{"path":["/","home","runner","work","gotham_restful","gotham_restful","tests","ui","endpoint","invalid_placeholders_ty.rs"],"content":"#[macro_use]\nextern crate gotham_restful;\nuse gotham_restful::gotham::hyper::Method;\n\n#[derive(Resource)]\n#[resource(endpoint)]\nstruct FooResource;\n\n#[derive(Debug)]\nstruct FooPlaceholders {\n\tfoo: String\n}\n\n#[endpoint(method = \"Method::GET\", uri = \":foo\")]\nfn endpoint(_: FooPlaceholders) {\n\tunimplemented!()\n}\n\nfn main() {}\n","traces":[],"covered":0,"coverable":0},{"path":["/","home","runner","work","gotham_restful","gotham_restful","tests","ui","endpoint","invalid_return_type.rs"],"content":"#[macro_use]\nextern crate gotham_restful;\nuse gotham_restful::gotham::hyper::Method;\n\n#[derive(Resource)]\n#[resource(endpoint)]\nstruct FooResource;\n\nstruct FooResponse;\n\n#[endpoint(method = \"Method::GET\", uri = \"\")]\nfn endpoint() -> FooResponse {\n\tunimplemented!()\n}\n\nfn main() {}\n","traces":[],"covered":0,"coverable":0},{"path":["/","home","runner","work","gotham_restful","gotham_restful","tests","ui","endpoint","non_custom_body_attribute.rs"],"content":"#[macro_use]\nextern crate gotham_restful;\n\n#[derive(Resource)]\n#[resource(read_all)]\nstruct FooResource;\n\n#[read_all(body = false)]\nasync fn read_all() {}\n\nfn main() {}\n","traces":[],"covered":0,"coverable":0},{"path":["/","home","runner","work","gotham_restful","gotham_restful","tests","ui","endpoint","non_custom_method_attribute.rs"],"content":"#[macro_use]\nextern crate gotham_restful;\n\n#[derive(Resource)]\n#[resource(read_all)]\nstruct FooResource;\n\n#[read_all(method = \"gotham_restful::gotham::hyper::Method::GET\")]\nasync fn read_all() {}\n\nfn main() {}\n","traces":[],"covered":0,"coverable":0},{"path":["/","home","runner","work","gotham_restful","gotham_restful","tests","ui","endpoint","non_custom_params_attribute.rs"],"content":"#[macro_use]\nextern crate gotham_restful;\n\n#[derive(Resource)]\n#[resource(read_all)]\nstruct FooResource;\n\n#[read_all(params = true)]\nasync fn read_all() {}\n\nfn main() {}\n","traces":[],"covered":0,"coverable":0},{"path":["/","home","runner","work","gotham_restful","gotham_restful","tests","ui","endpoint","non_custom_uri_attribute.rs"],"content":"#[macro_use]\nextern crate gotham_restful;\n\n#[derive(Resource)]\n#[resource(read_all)]\nstruct FooResource;\n\n#[read_all(uri = \"custom_read\")]\nasync fn read_all() {}\n\nfn main() {}\n","traces":[],"covered":0,"coverable":0},{"path":["/","home","runner","work","gotham_restful","gotham_restful","tests","ui","endpoint","self.rs"],"content":"#[macro_use]\nextern crate gotham_restful;\n\n#[derive(Resource)]\n#[resource(read_all)]\nstruct FooResource;\n\n#[read_all]\nfn read_all(self) {}\n\nfn main() {}\n","traces":[],"covered":0,"coverable":0},{"path":["/","home","runner","work","gotham_restful","gotham_restful","tests","ui","endpoint","too_few_args.rs"],"content":"#[macro_use]\nextern crate gotham_restful;\n\n#[derive(Resource)]\n#[resource(read)]\nstruct FooResource;\n\n#[read]\nfn read() {}\n\nfn main() {}\n","traces":[],"covered":0,"coverable":0},{"path":["/","home","runner","work","gotham_restful","gotham_restful","tests","ui","endpoint","too_many_args.rs"],"content":"#[macro_use]\nextern crate gotham_restful;\n\n#[derive(Resource)]\n#[resource(read_all)]\nstruct FooResource;\n\n#[read_all]\nfn read_all(_id: u64) {}\n\nfn main() {}\n","traces":[],"covered":0,"coverable":0},{"path":["/","home","runner","work","gotham_restful","gotham_restful","tests","ui","endpoint","unknown_attribute.rs"],"content":"#[macro_use]\nextern crate gotham_restful;\n\n#[derive(Resource)]\n#[resource(read_all)]\nstruct FooResource;\n\n#[read_all(pineapple = \"on pizza\")]\nfn read_all() {}\n\nfn main() {}\n","traces":[],"covered":0,"coverable":0},{"path":["/","home","runner","work","gotham_restful","gotham_restful","tests","ui","endpoint","unsafe.rs"],"content":"#[macro_use]\nextern crate gotham_restful;\n\n#[derive(Resource)]\n#[resource(read_all)]\nstruct FooResource;\n\n#[read_all]\nunsafe fn read_all() {}\n\nfn main() {}\n","traces":[],"covered":0,"coverable":0},{"path":["/","home","runner","work","gotham_restful","gotham_restful","tests","ui","endpoint","wants_auth_non_bool.rs"],"content":"#[macro_use]\nextern crate gotham_restful;\n\n#[derive(Resource)]\n#[resource(read_all)]\nstruct FooResource;\n\n#[read_all(wants_auth = \"yes, please\")]\nasync fn read_all() {}\n\nfn main() {}\n","traces":[],"covered":0,"coverable":0},{"path":["/","home","runner","work","gotham_restful","gotham_restful","tests","ui","from_body","enum.rs"],"content":"#[macro_use]\nextern crate gotham_restful;\n\n#[derive(FromBody)]\nenum FromBodyEnum {\n\tSomeVariant(Vec),\n\tOtherVariant(String)\n}\n\nfn main() {}\n","traces":[],"covered":0,"coverable":0},{"path":["/","home","runner","work","gotham_restful","gotham_restful","tests","ui","resource","unknown_method.rs"],"content":"#[macro_use]\nextern crate gotham_restful;\n\n#[derive(Resource)]\n#[resource(read_any)]\nstruct FooResource;\n\n#[read_all]\nfn read_all() {}\n\nfn main() {}\n","traces":[],"covered":0,"coverable":0},{"path":["/","home","runner","work","gotham_restful","gotham_restful","tests","util","mod.rs"],"content":"use gotham::{\n\thyper::Body,\n\ttest::TestServer\n};\nuse log::info;\nuse gotham::mime::Mime;\n#[allow(unused_imports)]\nuse std::{fs::File, io::{Read, Write}, str};\n\npub fn test_get_response(server : &TestServer, path : &str, expected : &[u8])\n{\n\tinfo!(\"GET {path}\");\n\tlet res = server.client().get(path).perform().unwrap().read_body().unwrap();\n\tlet body : &[u8] = res.as_ref();\n\tassert_eq!(body, expected);\n}\n\npub fn test_post_response(server : &TestServer, path : &str, body : B, mime : Mime, expected : &[u8])\nwhere\n\tB : Into\n{\n\tinfo!(\"POST {path}\");\n\tlet res = server.client().post(path, body, mime).perform().unwrap().read_body().unwrap();\n\tlet body : &[u8] = res.as_ref();\n\tassert_eq!(body, expected);\n}\n\npub fn test_put_response(server : &TestServer, path : &str, body : B, mime : Mime, expected : &[u8])\nwhere\n\tB : Into\n{\n\tinfo!(\"PUT {path}\");\n\tlet res = server.client().put(path, body, mime).perform().unwrap().read_body().unwrap();\n\tlet body : &[u8] = res.as_ref();\n\tassert_eq!(body, expected);\n}\n\npub fn test_delete_response(server : &TestServer, path : &str, expected : &[u8])\n{\n\tinfo!(\"DELETE {path}\");\n\tlet res = server.client().delete(path).perform().unwrap().read_body().unwrap();\n\tlet body : &[u8] = res.as_ref();\n\tassert_eq!(body, expected);\n}\n\n#[cfg(feature = \"openapi\")]\npub fn test_openapi_response(server : &TestServer, path : &str, output_file : &str)\n{\n\tinfo!(\"GET {path}\");\n\tlet res = server.client().get(path).perform().unwrap().read_body().unwrap();\n\tlet body: serde_json::Value = serde_json::from_slice(&res).unwrap();\n\n\tlet mut file = File::open(output_file).unwrap();\n\tlet expected: serde_json::Value = serde_json::from_reader(&mut file).unwrap();\n\n\t//eprintln!(\"{body}\");\n\tassert_eq!(body, expected);\n}\n","traces":[],"covered":0,"coverable":0}]} \ No newline at end of file +{"files":[{"path":["/","home","runner","work","gotham_restful","gotham_restful","redoc","src","lib.rs"],"content":"#![forbid(elided_lifetimes_in_paths, unsafe_code)]\n\n//! Private implementation detail of the `gotham_restful` crate.\n\nuse base64::prelude::*;\nuse either::Either;\nuse sha2::{Digest, Sha256};\nuse std::{io::Write, iter};\n\n#[doc(hidden)]\npub struct Redoc {\n\t/// HTML code.\n\tpub html: Vec,\n\n\t/// JS hash base64 encoded.\n\tpub script_hash: String\n}\n\n#[doc(hidden)]\npub fn html(spec: String) -> Redoc {\n\tlet encoded_spec = spec\n\t\t.chars()\n\t\t.flat_map(|c| match c {\n\t\t\t'&' => Either::Left(\"&\".chars()),\n\t\t\t'<' => Either::Left(\"<\".chars()),\n\t\t\t'>' => Either::Left(\">\".chars()),\n\t\t\tc => Either::Right(iter::once(c))\n\t\t})\n\t\t.collect::();\n\n\tlet script = include_str!(\"script.min.js\");\n\tlet mut script_hash = Sha256::new();\n\tscript_hash.update(script);\n\tlet script_hash = BASE64_STANDARD.encode(script_hash.finalize());\n\n\tlet mut html = Vec::::new();\n\twrite!(\n\t\thtml,\n\t\tconcat!(\n\t\t\t\"\",\n\t\t\t\"\",\n\t\t\t\"\",\n\t\t\tr#\"\"#,\n\t\t\tr#\"\"#,\n\t\t\t\"\",\n\t\t\tr#\"\"#,\n\t\t\tr#\"

{}
\"#,\n\t\t\tr#\"
\"#,\n\t\t\tr#\"\"#,\n\t\t\t\"\",\n\t\t\t\"\"\n\t\t),\n\t\tencoded_spec, script\n\t)\n\t.unwrap();\n\n\tRedoc { html, script_hash }\n}\n","traces":[{"line":20,"address":[7851961,7850880,7851926],"length":1,"stats":{"Line":0},"fn_name":"html"},{"line":21,"address":[7850931,7850999],"length":1,"stats":{"Line":0},"fn_name":null},{"line":23,"address":[8899339,8899312],"length":1,"stats":{"Line":0},"fn_name":"{closure#0}"},{"line":24,"address":[7852069],"length":1,"stats":{"Line":0},"fn_name":null},{"line":25,"address":[8899431],"length":1,"stats":{"Line":0},"fn_name":null},{"line":26,"address":[8899465],"length":1,"stats":{"Line":0},"fn_name":null},{"line":27,"address":[8899372],"length":1,"stats":{"Line":0},"fn_name":null},{"line":31,"address":[7850910,7851072],"length":1,"stats":{"Line":0},"fn_name":null},{"line":32,"address":[8898427],"length":1,"stats":{"Line":0},"fn_name":null},{"line":33,"address":[8576762],"length":1,"stats":{"Line":0},"fn_name":null},{"line":34,"address":[7851197],"length":1,"stats":{"Line":0},"fn_name":null},{"line":36,"address":[7851370],"length":1,"stats":{"Line":0},"fn_name":null},{"line":37,"address":[7851665],"length":1,"stats":{"Line":0},"fn_name":null}],"covered":0,"coverable":13},{"path":["/","home","runner","work","gotham_restful","gotham_restful","src","auth.rs"],"content":"use crate::AuthError;\n\nuse base64::prelude::*;\nuse cookie::CookieJar;\nuse futures_util::{\n\tfuture,\n\tfuture::{FutureExt, TryFutureExt}\n};\nuse gotham::{\n\tanyhow,\n\thandler::HandlerFuture,\n\thyper::header::{HeaderMap, HeaderName, AUTHORIZATION},\n\tmiddleware::{cookie::CookieParser, Middleware, NewMiddleware},\n\tprelude::*,\n\tstate::State\n};\nuse jsonwebtoken::DecodingKey;\nuse serde::de::DeserializeOwned;\nuse std::{marker::PhantomData, panic::RefUnwindSafe, pin::Pin};\n\npub type AuthValidation = jsonwebtoken::Validation;\n\n/// The authentication status returned by the auth middleware for each request.\n#[derive(Debug, StateData)]\npub enum AuthStatus {\n\t/// The auth status is unknown. This is likely because no secret was provided\n\t/// that could be used to verify the token of the client.\n\tUnknown,\n\n\t/// The request has been performed without any kind of authentication.\n\tUnauthenticated,\n\n\t/// The request has been performed with an invalid authentication. This\n\t/// includes expired tokens. Further details can be obtained from the\n\t/// included error.\n\tInvalid(jsonwebtoken::errors::Error),\n\n\t/// The request has been performed with a valid authentication. The claims\n\t/// that were decoded from the token are attached.\n\tAuthenticated(T)\n}\n\nimpl Clone for AuthStatus\nwhere\n\tT: Clone + Send + 'static\n{\n\tfn clone(&self) -> Self {\n\t\t// TODO why is this manually implemented?\n\t\tmatch self {\n\t\t\tSelf::Unknown => Self::Unknown,\n\t\t\tSelf::Unauthenticated => Self::Unauthenticated,\n\t\t\tSelf::Invalid(err) => Self::Invalid(err.clone()),\n\t\t\tSelf::Authenticated(data) => Self::Authenticated(data.clone())\n\t\t}\n\t}\n}\n\nimpl AuthStatus {\n\tpub fn ok(self) -> Result {\n\t\tmatch self {\n\t\t\tSelf::Unknown => Err(AuthError::new(\"The authentication could not be determined\")),\n\t\t\tSelf::Unauthenticated => Err(AuthError::new(\"Missing token\")),\n\t\t\tSelf::Invalid(err) => Err(AuthError::new(format!(\"Invalid token: {err}\"))),\n\t\t\tSelf::Authenticated(data) => Ok(data)\n\t\t}\n\t}\n}\n\n/// The source of the authentication token in the request.\n#[derive(Clone, Debug, StateData)]\npub enum AuthSource {\n\t/// Take the token from a cookie with the given name.\n\tCookie(String),\n\t/// Take the token from a header with the given name.\n\tHeader(HeaderName),\n\t/// Take the token from the HTTP Authorization header. This is different from `Header(\"Authorization\")`\n\t/// as it will follow the `scheme param` format from the HTTP specification. The `scheme` will\n\t/// be discarded, so its value doesn't matter.\n\tAuthorizationHeader\n}\n\n/// This trait will help the auth middleware to determine the validity of an authentication token.\n///\n/// A very basic implementation could look like this:\n///\n/// ```\n/// # use gotham_restful::{AuthHandler, gotham::state::State};\n/// #\n/// const SECRET: &'static [u8; 32] = b\"zlBsA2QXnkmpe0QTh8uCvtAEa4j33YAc\";\n///\n/// struct CustomAuthHandler;\n/// impl AuthHandler for CustomAuthHandler {\n/// \tfn jwt_secret Option>(\n/// \t\t&self,\n/// \t\t_state: &mut State,\n/// \t\t_decode_data: F\n/// \t) -> Option> {\n/// \t\tSome(SECRET.to_vec())\n/// \t}\n/// }\n/// ```\npub trait AuthHandler {\n\t/// Return the SHA256-HMAC secret used to verify the JWT token.\n\tfn jwt_secret Option>(\n\t\t&self,\n\t\tstate: &mut State,\n\t\tdecode_data: F\n\t) -> Option>;\n}\n\n/// An [AuthHandler] returning always the same secret. See [AuthMiddleware] for a usage example.\n#[derive(Clone, Debug)]\npub struct StaticAuthHandler {\n\tsecret: Vec\n}\n\nimpl StaticAuthHandler {\n\tpub fn from_vec(secret: Vec) -> Self {\n\t\tSelf { secret }\n\t}\n\n\tpub fn from_array(secret: &[u8]) -> Self {\n\t\tSelf::from_vec(secret.to_vec())\n\t}\n}\n\nimpl AuthHandler for StaticAuthHandler {\n\tfn jwt_secret Option>(\n\t\t&self,\n\t\t_state: &mut State,\n\t\t_decode_data: F\n\t) -> Option> {\n\t\tSome(self.secret.clone())\n\t}\n}\n\n/// This is the auth middleware. To use it, first make sure you have the `auth` feature enabled. Then\n/// simply add it to your pipeline and request it inside your handler:\n///\n/// ```rust,no_run\n/// # #[macro_use] extern crate gotham_restful_derive;\n/// # use gotham::{router::builder::*, pipeline::*, state::State};\n/// # use gotham_restful::*;\n/// # use serde::{Deserialize, Serialize};\n/// #\n/// #[derive(Resource)]\n/// #[resource(read_all)]\n/// struct AuthResource;\n///\n/// #[derive(Debug, Deserialize, Clone)]\n/// struct AuthData {\n/// \tsub: String,\n/// \texp: u64\n/// }\n///\n/// #[read_all]\n/// fn read_all(auth: &AuthStatus) -> Success {\n/// \tformat!(\"{auth:?}\").into()\n/// }\n///\n/// fn main() {\n/// \tlet auth: AuthMiddleware = AuthMiddleware::new(\n/// \t\tAuthSource::AuthorizationHeader,\n/// \t\tAuthValidation::default(),\n/// \t\tStaticAuthHandler::from_array(b\"zlBsA2QXnkmpe0QTh8uCvtAEa4j33YAc\")\n/// \t);\n/// \tlet (chain, pipelines) = single_pipeline(new_pipeline().add(auth).build());\n/// \tgotham::start(\n/// \t\t\"127.0.0.1:8080\",\n/// \t\tbuild_router(chain, pipelines, |route| {\n/// \t\t\troute.resource::(\"auth\");\n/// \t\t})\n/// \t);\n/// }\n/// ```\n#[derive(Debug)]\npub struct AuthMiddleware {\n\tsource: AuthSource,\n\tvalidation: AuthValidation,\n\thandler: Handler,\n\t_data: PhantomData\n}\n\nimpl Clone for AuthMiddleware\nwhere\n\tHandler: Clone\n{\n\tfn clone(&self) -> Self {\n\t\tSelf {\n\t\t\tsource: self.source.clone(),\n\t\t\tvalidation: self.validation.clone(),\n\t\t\thandler: self.handler.clone(),\n\t\t\t_data: self._data\n\t\t}\n\t}\n}\n\nimpl AuthMiddleware\nwhere\n\tData: DeserializeOwned + Send,\n\tHandler: AuthHandler + Default\n{\n\tpub fn from_source(source: AuthSource) -> Self {\n\t\tSelf {\n\t\t\tsource,\n\t\t\tvalidation: Default::default(),\n\t\t\thandler: Default::default(),\n\t\t\t_data: Default::default()\n\t\t}\n\t}\n}\n\nimpl AuthMiddleware\nwhere\n\tData: DeserializeOwned + Send,\n\tHandler: AuthHandler\n{\n\tpub fn new(source: AuthSource, validation: AuthValidation, handler: Handler) -> Self {\n\t\tSelf {\n\t\t\tsource,\n\t\t\tvalidation,\n\t\t\thandler,\n\t\t\t_data: Default::default()\n\t\t}\n\t}\n\n\tfn auth_status(&self, state: &mut State) -> AuthStatus {\n\t\t// extract the provided token, if any\n\t\tlet token = match &self.source {\n\t\t\tAuthSource::Cookie(name) => CookieJar::try_borrow_from(&state)\n\t\t\t\t.map(|jar| jar.get(&name).map(|cookie| cookie.value().to_owned()))\n\t\t\t\t.unwrap_or_else(|| {\n\t\t\t\t\tCookieParser::from_state(&state)\n\t\t\t\t\t\t.get(&name)\n\t\t\t\t\t\t.map(|cookie| cookie.value().to_owned())\n\t\t\t\t}),\n\t\t\tAuthSource::Header(name) => HeaderMap::try_borrow_from(&state)\n\t\t\t\t.and_then(|map| map.get(name))\n\t\t\t\t.and_then(|header| header.to_str().ok())\n\t\t\t\t.map(|value| value.to_owned()),\n\t\t\tAuthSource::AuthorizationHeader => HeaderMap::try_borrow_from(&state)\n\t\t\t\t.and_then(|map| map.get(AUTHORIZATION))\n\t\t\t\t.and_then(|header| header.to_str().ok())\n\t\t\t\t.and_then(|value| value.split_whitespace().nth(1))\n\t\t\t\t.map(|value| value.to_owned())\n\t\t};\n\n\t\t// unauthed if no token\n\t\tlet token = match token {\n\t\t\tSome(token) => token,\n\t\t\tNone => return AuthStatus::Unauthenticated\n\t\t};\n\n\t\t// get the secret from the handler, possibly decoding claims ourselves\n\t\tlet secret = self.handler.jwt_secret(state, || {\n\t\t\tlet b64 = token.split('.').nth(1)?;\n\t\t\tlet raw = BASE64_URL_SAFE_NO_PAD.decode(b64).ok()?;\n\t\t\tserde_json::from_slice(&raw).ok()?\n\t\t});\n\n\t\t// unknown if no secret\n\t\tlet secret = match secret {\n\t\t\tSome(secret) => secret,\n\t\t\tNone => return AuthStatus::Unknown\n\t\t};\n\n\t\t// validate the token\n\t\tlet data: Data = match jsonwebtoken::decode(\n\t\t\t&token,\n\t\t\t&DecodingKey::from_secret(&secret),\n\t\t\t&self.validation\n\t\t) {\n\t\t\tOk(data) => data.claims,\n\t\t\tErr(e) => return AuthStatus::Invalid(e)\n\t\t};\n\n\t\t// we found a valid token\n\t\tAuthStatus::Authenticated(data)\n\t}\n}\n\nimpl Middleware for AuthMiddleware\nwhere\n\tData: DeserializeOwned + Send + 'static,\n\tHandler: AuthHandler\n{\n\tfn call(self, mut state: State, chain: Chain) -> Pin>\n\twhere\n\t\tChain: FnOnce(State) -> Pin>\n\t{\n\t\t// put the source in our state, required for e.g. openapi\n\t\tstate.put(self.source.clone());\n\n\t\t// put the status in our state\n\t\tlet status = self.auth_status(&mut state);\n\t\tstate.put(status);\n\n\t\t// call the rest of the chain\n\t\tchain(state)\n\t\t\t.and_then(|(state, res)| future::ok((state, res)))\n\t\t\t.boxed()\n\t}\n}\n\nimpl NewMiddleware for AuthMiddleware\nwhere\n\tSelf: Clone + Middleware + Sync + RefUnwindSafe\n{\n\ttype Instance = Self;\n\n\tfn new_middleware(&self) -> anyhow::Result {\n\t\tlet c: Self = self.clone();\n\t\tOk(c)\n\t}\n}\n\n#[cfg(test)]\nmod test {\n\tuse super::*;\n\tuse cookie::Cookie;\n\tuse gotham::hyper::header::COOKIE;\n\tuse jsonwebtoken::errors::ErrorKind;\n\tuse std::fmt::Debug;\n\n\t// 256-bit random string\n\tconst JWT_SECRET: &'static [u8; 32] = b\"Lyzsfnta0cdxyF0T9y6VGxp3jpgoMUuW\";\n\n\t// some known tokens\n\tconst VALID_TOKEN: &'static str = \"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJtc3JkMCIsInN1YiI6ImdvdGhhbS1yZXN0ZnVsIiwiaWF0IjoxNTc3ODM2ODAwLCJleHAiOjQxMDI0NDQ4MDB9.8h8Ax-nnykqEQ62t7CxmM3ja6NzUQ4L0MLOOzddjLKk\";\n\tconst EXPIRED_TOKEN: &'static str = \"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJtc3JkMCIsInN1YiI6ImdvdGhhbS1yZXN0ZnVsIiwiaWF0IjoxNTc3ODM2ODAwLCJleHAiOjE1Nzc4MzcxMDB9.eV1snaGLYrJ7qUoMk74OvBY3WUU9M0Je5HTU2xtX1v0\";\n\tconst INVALID_TOKEN: &'static str = \"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJtc3JkMCIsInN1YiI6ImdvdGhhbS1yZXN0ZnVsIiwiaWF0IjoxNTc3ODM2ODAwLCJleHAiOjQxMDI0NDQ4MDB9\";\n\n\t#[derive(Debug, Deserialize, PartialEq)]\n\tstruct TestData {\n\t\tiss: String,\n\t\tsub: String,\n\t\tiat: u64,\n\t\texp: u64\n\t}\n\n\timpl Default for TestData {\n\t\tfn default() -> Self {\n\t\t\tSelf {\n\t\t\t\tiss: \"msrd0\".to_owned(),\n\t\t\t\tsub: \"gotham-restful\".to_owned(),\n\t\t\t\tiat: 1577836800,\n\t\t\t\texp: 4102444800\n\t\t\t}\n\t\t}\n\t}\n\n\t#[derive(Default)]\n\tstruct NoneAuthHandler;\n\timpl AuthHandler for NoneAuthHandler {\n\t\tfn jwt_secret Option>(\n\t\t\t&self,\n\t\t\t_state: &mut State,\n\t\t\t_decode_data: F\n\t\t) -> Option> {\n\t\t\tNone\n\t\t}\n\t}\n\n\t#[test]\n\tfn test_auth_middleware_none_secret() {\n\t\tlet middleware = >::from_source(\n\t\t\tAuthSource::AuthorizationHeader\n\t\t);\n\t\tState::with_new(|mut state| {\n\t\t\tlet mut headers = HeaderMap::new();\n\t\t\theaders.insert(\n\t\t\t\tAUTHORIZATION,\n\t\t\t\tformat!(\"Bearer {VALID_TOKEN}\").parse().unwrap()\n\t\t\t);\n\t\t\tstate.put(headers);\n\t\t\tmiddleware.auth_status(&mut state);\n\t\t});\n\t}\n\n\t#[derive(Default)]\n\tstruct TestAssertingHandler;\n\timpl AuthHandler for TestAssertingHandler\n\twhere\n\t\tT: Debug + Default + PartialEq\n\t{\n\t\tfn jwt_secret Option>(\n\t\t\t&self,\n\t\t\t_state: &mut State,\n\t\t\tdecode_data: F\n\t\t) -> Option> {\n\t\t\tassert_eq!(decode_data(), Some(T::default()));\n\t\t\tSome(JWT_SECRET.to_vec())\n\t\t}\n\t}\n\n\t#[test]\n\tfn test_auth_middleware_decode_data() {\n\t\tlet middleware = >::from_source(\n\t\t\tAuthSource::AuthorizationHeader\n\t\t);\n\t\tState::with_new(|mut state| {\n\t\t\tlet mut headers = HeaderMap::new();\n\t\t\theaders.insert(\n\t\t\t\tAUTHORIZATION,\n\t\t\t\tformat!(\"Bearer {VALID_TOKEN}\").parse().unwrap()\n\t\t\t);\n\t\t\tstate.put(headers);\n\t\t\tmiddleware.auth_status(&mut state);\n\t\t});\n\t}\n\n\tfn new_middleware(source: AuthSource) -> AuthMiddleware\n\twhere\n\t\tT: DeserializeOwned + Send\n\t{\n\t\tAuthMiddleware::new(\n\t\t\tsource,\n\t\t\tDefault::default(),\n\t\t\tStaticAuthHandler::from_array(JWT_SECRET)\n\t\t)\n\t}\n\n\t#[test]\n\tfn test_auth_middleware_no_token() {\n\t\tlet middleware = new_middleware::(AuthSource::AuthorizationHeader);\n\t\tState::with_new(|mut state| {\n\t\t\tlet status = middleware.auth_status(&mut state);\n\t\t\tmatch status {\n\t\t\t\tAuthStatus::Unauthenticated => {},\n\t\t\t\t_ => panic!(\"Expected AuthStatus::Unauthenticated, got {status:?}\")\n\t\t\t};\n\t\t});\n\t}\n\n\t#[test]\n\tfn test_auth_middleware_expired_token() {\n\t\tlet middleware = new_middleware::(AuthSource::AuthorizationHeader);\n\t\tState::with_new(|mut state| {\n\t\t\tlet mut headers = HeaderMap::new();\n\t\t\theaders.insert(\n\t\t\t\tAUTHORIZATION,\n\t\t\t\tformat!(\"Bearer {EXPIRED_TOKEN}\").parse().unwrap()\n\t\t\t);\n\t\t\tstate.put(headers);\n\t\t\tlet status = middleware.auth_status(&mut state);\n\t\t\tmatch status {\n\t\t\t\tAuthStatus::Invalid(err) if *err.kind() == ErrorKind::ExpiredSignature => {},\n\t\t\t\t_ => panic!(\n\t\t\t\t\t\"Expected AuthStatus::Invalid(..) with ErrorKind::ExpiredSignature, got {status:?}\"\n\t\t\t\t)\n\t\t\t};\n\t\t});\n\t}\n\n\t#[test]\n\tfn test_auth_middleware_invalid_token() {\n\t\tlet middleware = new_middleware::(AuthSource::AuthorizationHeader);\n\t\tState::with_new(|mut state| {\n\t\t\tlet mut headers = HeaderMap::new();\n\t\t\theaders.insert(\n\t\t\t\tAUTHORIZATION,\n\t\t\t\tformat!(\"Bearer {INVALID_TOKEN}\").parse().unwrap()\n\t\t\t);\n\t\t\tstate.put(headers);\n\t\t\tlet status = middleware.auth_status(&mut state);\n\t\t\tmatch status {\n\t\t\t\tAuthStatus::Invalid(err) if *err.kind() == ErrorKind::InvalidToken => {},\n\t\t\t\t_ => panic!(\n\t\t\t\t\t\"Expected AuthStatus::Invalid(..) with ErrorKind::InvalidToken, got {status:?}\"\n\t\t\t\t)\n\t\t\t};\n\t\t});\n\t}\n\n\t#[test]\n\tfn test_auth_middleware_auth_header_token() {\n\t\tlet middleware = new_middleware::(AuthSource::AuthorizationHeader);\n\t\tState::with_new(|mut state| {\n\t\t\tlet mut headers = HeaderMap::new();\n\t\t\theaders.insert(\n\t\t\t\tAUTHORIZATION,\n\t\t\t\tformat!(\"Bearer {VALID_TOKEN}\").parse().unwrap()\n\t\t\t);\n\t\t\tstate.put(headers);\n\t\t\tlet status = middleware.auth_status(&mut state);\n\t\t\tmatch status {\n\t\t\t\tAuthStatus::Authenticated(data) => assert_eq!(data, TestData::default()),\n\t\t\t\t_ => panic!(\"Expected AuthStatus::Authenticated, got {status:?}\")\n\t\t\t};\n\t\t})\n\t}\n\n\t#[test]\n\tfn test_auth_middleware_header_token() {\n\t\tlet header_name = \"x-znoiprwmvfexju\";\n\t\tlet middleware =\n\t\t\tnew_middleware::(AuthSource::Header(HeaderName::from_static(header_name)));\n\t\tState::with_new(|mut state| {\n\t\t\tlet mut headers = HeaderMap::new();\n\t\t\theaders.insert(header_name, VALID_TOKEN.parse().unwrap());\n\t\t\tstate.put(headers);\n\t\t\tlet status = middleware.auth_status(&mut state);\n\t\t\tmatch status {\n\t\t\t\tAuthStatus::Authenticated(data) => assert_eq!(data, TestData::default()),\n\t\t\t\t_ => panic!(\"Expected AuthStatus::Authenticated, got {status:?}\")\n\t\t\t};\n\t\t})\n\t}\n\n\t#[test]\n\tfn test_auth_middleware_cookie_token() {\n\t\tlet cookie_name = \"znoiprwmvfexju\";\n\t\tlet middleware = new_middleware::(AuthSource::Cookie(cookie_name.to_owned()));\n\t\tState::with_new(|mut state| {\n\t\t\tlet mut jar = CookieJar::new();\n\t\t\tjar.add_original(Cookie::new(cookie_name, VALID_TOKEN));\n\t\t\tstate.put(jar);\n\t\t\tlet status = middleware.auth_status(&mut state);\n\t\t\tmatch status {\n\t\t\t\tAuthStatus::Authenticated(data) => assert_eq!(data, TestData::default()),\n\t\t\t\t_ => panic!(\"Expected AuthStatus::Authenticated, got {status:?}\")\n\t\t\t};\n\t\t})\n\t}\n\n\t#[test]\n\tfn test_auth_middleware_cookie_no_jar() {\n\t\tlet cookie_name = \"znoiprwmvfexju\";\n\t\tlet middleware = new_middleware::(AuthSource::Cookie(cookie_name.to_owned()));\n\t\tState::with_new(|mut state| {\n\t\t\tlet mut headers = HeaderMap::new();\n\t\t\theaders.insert(\n\t\t\t\tCOOKIE,\n\t\t\t\tformat!(\"{cookie_name}={VALID_TOKEN}\").parse().unwrap()\n\t\t\t);\n\t\t\tstate.put(headers);\n\t\t\tlet status = middleware.auth_status(&mut state);\n\t\t\tmatch status {\n\t\t\t\tAuthStatus::Authenticated(data) => assert_eq!(data, TestData::default()),\n\t\t\t\t_ => panic!(\"Expected AuthStatus::Authenticated, got {status:?}\")\n\t\t\t};\n\t\t})\n\t}\n}\n","traces":[{"line":47,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":49,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":50,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":51,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":52,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":53,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":59,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":60,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":61,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":62,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":63,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":64,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":118,"address":[7757968],"length":1,"stats":{"Line":3},"fn_name":null},{"line":122,"address":[7758000],"length":1,"stats":{"Line":3},"fn_name":null},{"line":123,"address":[7758023],"length":1,"stats":{"Line":3},"fn_name":null},{"line":128,"address":[7241520,7241565],"length":1,"stats":{"Line":2},"fn_name":"jwt_secret>"},{"line":133,"address":[],"length":0,"stats":{"Line":4},"fn_name":null},{"line":188,"address":[],"length":0,"stats":{"Line":1},"fn_name":null},{"line":190,"address":[],"length":0,"stats":{"Line":1},"fn_name":null},{"line":191,"address":[],"length":0,"stats":{"Line":1},"fn_name":null},{"line":192,"address":[],"length":0,"stats":{"Line":1},"fn_name":null},{"line":193,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":203,"address":[],"length":0,"stats":{"Line":2},"fn_name":null},{"line":206,"address":[],"length":0,"stats":{"Line":2},"fn_name":null},{"line":207,"address":[],"length":0,"stats":{"Line":2},"fn_name":null},{"line":208,"address":[],"length":0,"stats":{"Line":2},"fn_name":null},{"line":218,"address":[],"length":0,"stats":{"Line":3},"fn_name":null},{"line":223,"address":[],"length":0,"stats":{"Line":3},"fn_name":null},{"line":227,"address":[],"length":0,"stats":{"Line":5},"fn_name":null},{"line":229,"address":[],"length":0,"stats":{"Line":5},"fn_name":null},{"line":230,"address":[],"length":0,"stats":{"Line":3},"fn_name":null},{"line":231,"address":[],"length":0,"stats":{"Line":5},"fn_name":null},{"line":232,"address":[],"length":0,"stats":{"Line":2},"fn_name":null},{"line":233,"address":[],"length":0,"stats":{"Line":2},"fn_name":null},{"line":234,"address":[],"length":0,"stats":{"Line":1},"fn_name":null},{"line":235,"address":[],"length":0,"stats":{"Line":2},"fn_name":null},{"line":237,"address":[],"length":0,"stats":{"Line":2},"fn_name":null},{"line":238,"address":[],"length":0,"stats":{"Line":3},"fn_name":null},{"line":239,"address":[],"length":0,"stats":{"Line":2},"fn_name":null},{"line":240,"address":[],"length":0,"stats":{"Line":2},"fn_name":null},{"line":241,"address":[],"length":0,"stats":{"Line":4},"fn_name":null},{"line":242,"address":[],"length":0,"stats":{"Line":8},"fn_name":null},{"line":243,"address":[],"length":0,"stats":{"Line":6},"fn_name":null},{"line":244,"address":[],"length":0,"stats":{"Line":6},"fn_name":null},{"line":245,"address":[],"length":0,"stats":{"Line":6},"fn_name":null},{"line":249,"address":[],"length":0,"stats":{"Line":4},"fn_name":null},{"line":250,"address":[],"length":0,"stats":{"Line":3},"fn_name":null},{"line":251,"address":[],"length":0,"stats":{"Line":2},"fn_name":null},{"line":255,"address":[],"length":0,"stats":{"Line":5},"fn_name":null},{"line":256,"address":[],"length":0,"stats":{"Line":1},"fn_name":null},{"line":257,"address":[],"length":0,"stats":{"Line":2},"fn_name":null},{"line":258,"address":[],"length":0,"stats":{"Line":4},"fn_name":null},{"line":262,"address":[],"length":0,"stats":{"Line":4},"fn_name":null},{"line":263,"address":[],"length":0,"stats":{"Line":3},"fn_name":null},{"line":264,"address":[],"length":0,"stats":{"Line":1},"fn_name":null},{"line":268,"address":[],"length":0,"stats":{"Line":6},"fn_name":null},{"line":269,"address":[],"length":0,"stats":{"Line":3},"fn_name":null},{"line":270,"address":[],"length":0,"stats":{"Line":3},"fn_name":null},{"line":271,"address":[],"length":0,"stats":{"Line":3},"fn_name":null},{"line":273,"address":[],"length":0,"stats":{"Line":3},"fn_name":null},{"line":274,"address":[],"length":0,"stats":{"Line":1},"fn_name":null},{"line":278,"address":[],"length":0,"stats":{"Line":3},"fn_name":null},{"line":287,"address":[7245376,7243006,7241648,7244414,7244448,7244878,7245342,7243504,7243924,7243040,7243470,7242112,7242078,7242576,7243963,7243984,7244912,7242542,7245806],"length":1,"stats":{"Line":1},"fn_name":"call, gotham_restful::routing::MaybeMatchAcceptHeader>, (borrow_bag::handle::Handle, ())>, borrow_bag::handle::Take>, ()), (gotham::pipeline::Pipeline<(gotham_restful::auth::AuthMiddleware, ())>, ()), gotham_restful::endpoint::NoopExtractor, openapi_specification::SecretQuery, fn(&mut gotham::state::State) -> gotham_restful::routing::endpoint_handler::{async_fn_env#0}>, (borrow_bag::handle::Handle, ())>, borrow_bag::handle::Take>, ()), (gotham::pipeline::Pipeline<(gotham_restful::auth::AuthMiddleware, ())>, ())>>"},{"line":292,"address":[],"length":0,"stats":{"Line":2},"fn_name":null},{"line":295,"address":[],"length":0,"stats":{"Line":1},"fn_name":null},{"line":296,"address":[],"length":0,"stats":{"Line":1},"fn_name":null},{"line":299,"address":[],"length":0,"stats":{"Line":2},"fn_name":null},{"line":300,"address":[],"length":0,"stats":{"Line":2},"fn_name":null},{"line":311,"address":[],"length":0,"stats":{"Line":1},"fn_name":null},{"line":312,"address":[],"length":0,"stats":{"Line":1},"fn_name":null},{"line":313,"address":[],"length":0,"stats":{"Line":1},"fn_name":null}],"covered":58,"coverable":71},{"path":["/","home","runner","work","gotham_restful","gotham_restful","src","cors.rs"],"content":"use gotham::{\n\thandler::HandlerFuture,\n\thelpers::http::response::create_empty_response,\n\thyper::{\n\t\theader::{\n\t\t\tHeaderMap, HeaderName, HeaderValue, ACCESS_CONTROL_ALLOW_CREDENTIALS,\n\t\t\tACCESS_CONTROL_ALLOW_HEADERS, ACCESS_CONTROL_ALLOW_METHODS,\n\t\t\tACCESS_CONTROL_ALLOW_ORIGIN, ACCESS_CONTROL_MAX_AGE, ACCESS_CONTROL_REQUEST_HEADERS,\n\t\t\tACCESS_CONTROL_REQUEST_METHOD, ORIGIN, VARY\n\t\t},\n\t\tBody, Method, Response, StatusCode\n\t},\n\tmiddleware::Middleware,\n\tpipeline::PipelineHandleChain,\n\tprelude::*,\n\trouter::{builder::ExtendRouteMatcher, route::matcher::AccessControlRequestMethodMatcher},\n\tstate::State\n};\nuse std::{panic::RefUnwindSafe, pin::Pin};\n\n/// Specify the allowed origins of the request. It is up to the browser to check the validity of the\n/// origin. This, when sent to the browser, will indicate whether or not the request's origin was\n/// allowed to make the request.\n#[derive(Clone, Debug)]\npub enum Origin {\n\t/// Do not send any `Access-Control-Allow-Origin` headers.\n\tNone,\n\t/// Send `Access-Control-Allow-Origin: *`. Note that browser will not send credentials.\n\tStar,\n\t/// Set the `Access-Control-Allow-Origin` header to a single origin.\n\tSingle(String),\n\t/// Copy the `Origin` header into the `Access-Control-Allow-Origin` header.\n\tCopy\n}\n\nimpl Default for Origin {\n\tfn default() -> Self {\n\t\tSelf::None\n\t}\n}\n\nimpl Origin {\n\t/// Get the header value for the `Access-Control-Allow-Origin` header.\n\tfn header_value(&self, state: &State) -> Option {\n\t\tmatch self {\n\t\t\tSelf::None => None,\n\t\t\tSelf::Star => Some(\"*\".parse().unwrap()),\n\t\t\tSelf::Single(origin) => Some(origin.parse().unwrap()),\n\t\t\tSelf::Copy => {\n\t\t\t\tlet headers = HeaderMap::borrow_from(state);\n\t\t\t\theaders.get(ORIGIN).map(Clone::clone)\n\t\t\t}\n\t\t}\n\t}\n\n\t/// Returns true if the `Vary` header has to include `Origin`.\n\tfn varies(&self) -> bool {\n\t\tmatches!(self, Self::Copy)\n\t}\n}\n\n/// Specify the allowed headers of the request. It is up to the browser to check that only the allowed\n/// headers are sent with the request.\n#[derive(Clone, Debug)]\npub enum Headers {\n\t/// Do not send any `Access-Control-Allow-Headers` headers.\n\tNone,\n\t/// Set the `Access-Control-Allow-Headers` header to the following header list. If empty, this\n\t/// is treated as if it was [None].\n\tList(Vec),\n\t/// Copy the `Access-Control-Request-Headers` header into the `Access-Control-Allow-Header`\n\t/// header.\n\tCopy\n}\n\nimpl Default for Headers {\n\tfn default() -> Self {\n\t\tSelf::None\n\t}\n}\n\nimpl Headers {\n\t/// Get the header value for the `Access-Control-Allow-Headers` header.\n\tfn header_value(&self, state: &State) -> Option {\n\t\tmatch self {\n\t\t\tSelf::None => None,\n\t\t\tSelf::List(list) => Some(list.join(\",\").parse().unwrap()),\n\t\t\tSelf::Copy => {\n\t\t\t\tlet headers = HeaderMap::borrow_from(state);\n\t\t\t\theaders\n\t\t\t\t\t.get(ACCESS_CONTROL_REQUEST_HEADERS)\n\t\t\t\t\t.map(Clone::clone)\n\t\t\t}\n\t\t}\n\t}\n\n\t/// Returns true if the `Vary` header has to include `Origin`.\n\tfn varies(&self) -> bool {\n\t\tmatches!(self, Self::Copy)\n\t}\n}\n\n/// This is the configuration that the CORS handler will follow. Its default configuration is basically\n/// not to touch any responses, resulting in the browser's default behaviour.\n///\n/// To change settings, you need to put this type into gotham's [State]:\n///\n/// ```rust,no_run\n/// # use gotham::{router::builder::*, pipeline::*, state::State};\n/// # use gotham_restful::{*, cors::Origin};\n/// # #[cfg_attr(feature = \"cargo-clippy\", allow(clippy::needless_doctest_main))]\n/// fn main() {\n/// \tlet cors = CorsConfig {\n/// \t\torigin: Origin::Star,\n/// \t\t..Default::default()\n/// \t};\n/// \tlet (chain, pipelines) = single_pipeline(new_pipeline().add(cors).build());\n/// \tgotham::start(\n/// \t\t\"127.0.0.1:8080\",\n/// \t\tbuild_router(chain, pipelines, |route| {\n/// \t\t\t// your routing logic\n/// \t\t})\n/// \t);\n/// }\n/// ```\n///\n/// This easy approach allows you to have one global cors configuration. If you prefer to have separate\n/// configurations for different scopes, you need to register the middleware inside your routing logic:\n///\n/// ```rust,no_run\n/// # use gotham::{router::builder::*, pipeline::*, state::State};\n/// # use gotham_restful::{*, cors::Origin};\n/// let pipelines = new_pipeline_set();\n///\n/// // The first cors configuration\n/// let cors_a = CorsConfig {\n/// \torigin: Origin::Star,\n/// \t..Default::default()\n/// };\n/// let (pipelines, chain_a) = pipelines.add(new_pipeline().add(cors_a).build());\n///\n/// // The second cors configuration\n/// let cors_b = CorsConfig {\n/// \torigin: Origin::Copy,\n/// \t..Default::default()\n/// };\n/// let (pipelines, chain_b) = pipelines.add(new_pipeline().add(cors_b).build());\n///\n/// let pipeline_set = finalize_pipeline_set(pipelines);\n/// gotham::start(\n/// \t\"127.0.0.1:8080\",\n/// \tbuild_router((), pipeline_set, |route| {\n/// \t\t// routing without any cors config\n/// \t\troute.with_pipeline_chain((chain_a, ()), |route| {\n/// \t\t\t// routing with cors config a\n/// \t\t});\n/// \t\troute.with_pipeline_chain((chain_b, ()), |route| {\n/// \t\t\t// routing with cors config b\n/// \t\t});\n/// \t})\n/// );\n/// ```\n#[derive(Clone, Debug, Default, NewMiddleware, StateData)]\npub struct CorsConfig {\n\t/// The allowed origins.\n\tpub origin: Origin,\n\t/// The allowed headers.\n\tpub headers: Headers,\n\t/// The amount of seconds that the preflight request can be cached.\n\tpub max_age: u64,\n\t/// Whether or not the request may be made with supplying credentials.\n\tpub credentials: bool\n}\n\nimpl Middleware for CorsConfig {\n\tfn call(self, mut state: State, chain: Chain) -> Pin>\n\twhere\n\t\tChain: FnOnce(State) -> Pin>\n\t{\n\t\tstate.put(self);\n\t\tchain(state)\n\t}\n}\n\n/// Handle CORS for a non-preflight request. This means manipulating the `res` HTTP headers so that\n/// the response is aligned with the `state`'s [CorsConfig].\n///\n/// If you are using the [Resource](crate::Resource) type (which is the recommended way), you'll never\n/// have to call this method. However, if you are writing your own handler method, you might want to\n/// call this after your request to add the required CORS headers.\n///\n/// For further information on CORS, read .\npub fn handle_cors(state: &State, res: &mut Response) {\n\tlet config = CorsConfig::try_borrow_from(state);\n\tif let Some(cfg) = config {\n\t\tlet headers = res.headers_mut();\n\n\t\t// non-preflight requests require the Access-Control-Allow-Origin header\n\t\tif let Some(header) = cfg.origin.header_value(state) {\n\t\t\theaders.insert(ACCESS_CONTROL_ALLOW_ORIGIN, header);\n\t\t}\n\n\t\t// if the origin is copied over, we should tell the browser by specifying the Vary header\n\t\tif cfg.origin.varies() {\n\t\t\tlet vary = headers\n\t\t\t\t.get(VARY)\n\t\t\t\t.map(|vary| format!(\"{},origin\", vary.to_str().unwrap()));\n\t\t\theaders.insert(VARY, vary.as_deref().unwrap_or(\"origin\").parse().unwrap());\n\t\t}\n\n\t\t// if we allow credentials, tell the browser\n\t\tif cfg.credentials {\n\t\t\theaders.insert(\n\t\t\t\tACCESS_CONTROL_ALLOW_CREDENTIALS,\n\t\t\t\tHeaderValue::from_static(\"true\")\n\t\t\t);\n\t\t}\n\t}\n}\n\n/// Add CORS routing for your path. This is required for handling preflight requests.\n///\n/// Example:\n///\n/// ```rust,no_run\n/// # use gotham::{hyper::{Body, Method, Response}, router::builder::*};\n/// # use gotham_restful::*;\n/// build_simple_router(|router| {\n/// \t// The handler that needs preflight handling\n/// \trouter.post(\"/foo\").to(|state| {\n/// \t\tlet mut res: Response = unimplemented!();\n/// \t\thandle_cors(&state, &mut res);\n/// \t\t(state, res)\n/// \t});\n/// \t// Add preflight handling\n/// \trouter.cors(\"/foo\", Method::POST);\n/// });\n/// ```\npub trait CorsRoute\nwhere\n\tC: PipelineHandleChain

+ Copy + Send + Sync + 'static,\n\tP: RefUnwindSafe + Send + Sync + 'static\n{\n\t/// Handle a preflight request on `path` for `method`. To configure the behaviour, use\n\t/// [CorsConfig].\n\tfn cors(&mut self, path: &str, method: Method);\n}\n\npub(crate) fn cors_preflight_handler(state: State) -> (State, Response) {\n\tlet config = CorsConfig::try_borrow_from(&state);\n\n\t// prepare the response\n\tlet mut res = create_empty_response(&state, StatusCode::NO_CONTENT);\n\tlet headers = res.headers_mut();\n\tlet mut vary: Vec = Vec::new();\n\n\t// copy the request method over to the response\n\tlet method = HeaderMap::borrow_from(&state)\n\t\t.get(ACCESS_CONTROL_REQUEST_METHOD)\n\t\t.unwrap()\n\t\t.clone();\n\theaders.insert(ACCESS_CONTROL_ALLOW_METHODS, method);\n\tvary.push(ACCESS_CONTROL_REQUEST_METHOD);\n\n\tif let Some(cfg) = config {\n\t\t// if we allow any headers, copy them over\n\t\tif let Some(header) = cfg.headers.header_value(&state) {\n\t\t\theaders.insert(ACCESS_CONTROL_ALLOW_HEADERS, header);\n\t\t}\n\n\t\t// if the headers are copied over, we should tell the browser by specifying the Vary header\n\t\tif cfg.headers.varies() {\n\t\t\tvary.push(ACCESS_CONTROL_REQUEST_HEADERS);\n\t\t}\n\n\t\t// set the max age for the preflight cache\n\t\tif let Some(age) = config.map(|cfg| cfg.max_age) {\n\t\t\theaders.insert(ACCESS_CONTROL_MAX_AGE, age.into());\n\t\t}\n\t}\n\n\t// make sure the browser knows that this request was based on the method\n\theaders.insert(VARY, vary.join(\",\").parse().unwrap());\n\n\thandle_cors(&state, &mut res);\n\t(state, res)\n}\n\nimpl CorsRoute for D\nwhere\n\tD: DrawRoutes,\n\tC: PipelineHandleChain

+ Copy + Send + Sync + 'static,\n\tP: RefUnwindSafe + Send + Sync + 'static\n{\n\tfn cors(&mut self, path: &str, method: Method) {\n\t\tlet matcher = AccessControlRequestMethodMatcher::new(method);\n\t\tself.options(path)\n\t\t\t.extend_route_matcher(matcher)\n\t\t\t.to(cors_preflight_handler);\n\t}\n}\n","traces":[{"line":37,"address":[7566816],"length":1,"stats":{"Line":2},"fn_name":"default"},{"line":38,"address":[7566819],"length":1,"stats":{"Line":2},"fn_name":null},{"line":44,"address":[7566832],"length":1,"stats":{"Line":2},"fn_name":null},{"line":45,"address":[7566874],"length":1,"stats":{"Line":2},"fn_name":null},{"line":46,"address":[7566910],"length":1,"stats":{"Line":2},"fn_name":null},{"line":47,"address":[7566919],"length":1,"stats":{"Line":1},"fn_name":null},{"line":48,"address":[7566995],"length":1,"stats":{"Line":1},"fn_name":null},{"line":50,"address":[7567081],"length":1,"stats":{"Line":1},"fn_name":null},{"line":51,"address":[7567098],"length":1,"stats":{"Line":1},"fn_name":null},{"line":57,"address":[7567200],"length":1,"stats":{"Line":2},"fn_name":null},{"line":58,"address":[7567205],"length":1,"stats":{"Line":2},"fn_name":null},{"line":77,"address":[7567248],"length":1,"stats":{"Line":2},"fn_name":"default"},{"line":78,"address":[7567251],"length":1,"stats":{"Line":2},"fn_name":null},{"line":84,"address":[7567264,7567697],"length":1,"stats":{"Line":2},"fn_name":null},{"line":85,"address":[7567307],"length":1,"stats":{"Line":2},"fn_name":null},{"line":86,"address":[7567344],"length":1,"stats":{"Line":1},"fn_name":null},{"line":87,"address":[7567358,7567563],"length":1,"stats":{"Line":1},"fn_name":null},{"line":89,"address":[7567445],"length":1,"stats":{"Line":1},"fn_name":null},{"line":90,"address":[7567522],"length":1,"stats":{"Line":1},"fn_name":null},{"line":91,"address":[7567462],"length":1,"stats":{"Line":1},"fn_name":null},{"line":98,"address":[7567728],"length":1,"stats":{"Line":2},"fn_name":null},{"line":99,"address":[7567733],"length":1,"stats":{"Line":2},"fn_name":null},{"line":176,"address":[6413280,6413461,6413489,6413056,6413013,6413041,6413237,6413265,6412832],"length":1,"stats":{"Line":4},"fn_name":"call, gotham_restful::routing::MaybeMatchAcceptHeader>, (borrow_bag::handle::Handle, borrow_bag::handle::Take>, ()), (gotham::pipeline::Pipeline<(gotham_restful::cors::CorsConfig, ())>, ()), gotham_restful::endpoint::NoopExtractor, gotham_restful::endpoint::NoopExtractor, fn(&mut gotham::state::State) -> gotham_restful::routing::endpoint_handler::{async_fn_env#0}>, (borrow_bag::handle::Handle, borrow_bag::handle::Take>, ()), (gotham::pipeline::Pipeline<(gotham_restful::cors::CorsConfig, ())>, ())>>"},{"line":180,"address":[],"length":0,"stats":{"Line":4},"fn_name":null},{"line":181,"address":[],"length":0,"stats":{"Line":8},"fn_name":null},{"line":193,"address":[7568657,7568605,7567776],"length":1,"stats":{"Line":6},"fn_name":"handle_cors"},{"line":194,"address":[7567809],"length":1,"stats":{"Line":6},"fn_name":null},{"line":195,"address":[7567844],"length":1,"stats":{"Line":6},"fn_name":null},{"line":196,"address":[7567893],"length":1,"stats":{"Line":2},"fn_name":null},{"line":199,"address":[7567922,7567979],"length":1,"stats":{"Line":3},"fn_name":null},{"line":200,"address":[7568012],"length":1,"stats":{"Line":1},"fn_name":null},{"line":204,"address":[7568158],"length":1,"stats":{"Line":2},"fn_name":null},{"line":205,"address":[7568241],"length":1,"stats":{"Line":1},"fn_name":null},{"line":206,"address":[7568211],"length":1,"stats":{"Line":1},"fn_name":null},{"line":207,"address":[7569022,7568880,7568918],"length":1,"stats":{"Line":3},"fn_name":"{closure#0}"},{"line":208,"address":[7568586,7568288],"length":1,"stats":{"Line":1},"fn_name":null},{"line":212,"address":[7568191],"length":1,"stats":{"Line":2},"fn_name":null},{"line":213,"address":[7568776],"length":1,"stats":{"Line":1},"fn_name":null},{"line":214,"address":[7568672],"length":1,"stats":{"Line":1},"fn_name":null},{"line":215,"address":[7568710],"length":1,"stats":{"Line":1},"fn_name":null},{"line":249,"address":[7570540,7569136,7571151],"length":1,"stats":{"Line":2},"fn_name":"cors_preflight_handler"},{"line":250,"address":[7569293,7569172],"length":1,"stats":{"Line":4},"fn_name":null},{"line":253,"address":[7569301],"length":1,"stats":{"Line":2},"fn_name":null},{"line":254,"address":[7569333,7569403],"length":1,"stats":{"Line":4},"fn_name":null},{"line":255,"address":[7569411],"length":1,"stats":{"Line":2},"fn_name":null},{"line":258,"address":[7569527,7569435],"length":1,"stats":{"Line":4},"fn_name":null},{"line":259,"address":[7569497],"length":1,"stats":{"Line":2},"fn_name":null},{"line":262,"address":[7569604],"length":1,"stats":{"Line":2},"fn_name":null},{"line":263,"address":[7569736],"length":1,"stats":{"Line":2},"fn_name":null},{"line":265,"address":[7569793],"length":1,"stats":{"Line":2},"fn_name":null},{"line":267,"address":[7569856,7569933],"length":1,"stats":{"Line":3},"fn_name":null},{"line":268,"address":[7570119,7570027],"length":1,"stats":{"Line":2},"fn_name":null},{"line":272,"address":[7570161,7570195],"length":1,"stats":{"Line":3},"fn_name":null},{"line":273,"address":[7570230],"length":1,"stats":{"Line":1},"fn_name":null},{"line":277,"address":[7570299,7571189,7570201,7571184],"length":1,"stats":{"Line":7},"fn_name":"{closure#0}"},{"line":278,"address":[7570346],"length":1,"stats":{"Line":2},"fn_name":null},{"line":283,"address":[7569863,7570551],"length":1,"stats":{"Line":2},"fn_name":null},{"line":285,"address":[7570928],"length":1,"stats":{"Line":2},"fn_name":null},{"line":286,"address":[7570952],"length":1,"stats":{"Line":1},"fn_name":null},{"line":295,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":296,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":297,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":298,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":299,"address":[],"length":0,"stats":{"Line":0},"fn_name":null}],"covered":59,"coverable":64},{"path":["/","home","runner","work","gotham_restful","gotham_restful","src","endpoint.rs"],"content":"use crate::{IntoResponse, RequestBody};\nuse futures_util::future::BoxFuture;\nuse gotham::{\n\textractor::{PathExtractor, QueryStringExtractor},\n\thyper::{Body, Method, Response},\n\trouter::response::StaticResponseExtender,\n\tstate::{State, StateData}\n};\n#[cfg(feature = \"openapi\")]\nuse openapi_type::{OpenapiType, Visitor};\nuse serde::{Deserialize, Deserializer};\nuse std::borrow::Cow;\n\n/// A no-op extractor that can be used as a default type for [Endpoint::Placeholders] and\n/// [Endpoint::Params].\n#[derive(Debug, Clone, Copy)]\npub struct NoopExtractor;\n\nimpl<'de> Deserialize<'de> for NoopExtractor {\n\tfn deserialize>(_: D) -> Result {\n\t\tOk(Self)\n\t}\n}\n\n#[cfg(feature = \"openapi\")]\nimpl OpenapiType for NoopExtractor {\n\tfn visit_type(visitor: &mut V) {\n\t\twarn!(\n\t\t\t\"You're asking for the OpenAPI Schema for gotham_restful::NoopExtractor. This is probably not what you want.\"\n\t\t);\n\t\tvisitor.visit_unit();\n\t}\n}\n\nimpl StateData for NoopExtractor {}\n\nimpl StaticResponseExtender for NoopExtractor {\n\ttype ResBody = Body;\n\tfn extend(_: &mut State, _: &mut Response) {}\n}\n\n// TODO: Specify default types once https://github.com/rust-lang/rust/issues/29661 lands.\n#[_private_openapi_trait(EndpointWithSchema)]\npub trait Endpoint {\n\t/// The HTTP Verb of this endpoint.\n\tfn http_method() -> Method;\n\t/// The URI that this endpoint listens on in gotham's format.\n\tfn uri() -> Cow<'static, str>;\n\n\t/// The verb used for generating an operation id if [Self::operation_id] returns [None].\n\t/// For example `read`, `read_all`, `create`, `update` etc.\n\t#[openapi_only]\n\tfn operation_verb() -> Option<&'static str>;\n\n\t/// The output type that provides the response.\n\t#[openapi_bound(Output: crate::ResponseSchema)]\n\ttype Output: IntoResponse + Send;\n\n\t/// Returns `true` _iff_ the URI contains placeholders. `false` by default.\n\tfn has_placeholders() -> bool {\n\t\tfalse\n\t}\n\t/// The type that parses the URI placeholders. Use [NoopExtractor] if `has_placeholders()`\n\t/// returns `false`.\n\t#[openapi_bound(Placeholders: OpenapiType)]\n\ttype Placeholders: PathExtractor + Clone + Sync;\n\n\t/// Returns `true` _iff_ the request parameters should be parsed. `false` by default.\n\tfn needs_params() -> bool {\n\t\tfalse\n\t}\n\t/// The type that parses the request parameters. Use [NoopExtractor] if `needs_params()`\n\t/// returns `false`.\n\t#[openapi_bound(Params: OpenapiType)]\n\ttype Params: QueryStringExtractor + Clone + Sync;\n\n\t/// Returns `true` _iff_ the request body should be parsed. `false` by default.\n\tfn needs_body() -> bool {\n\t\tfalse\n\t}\n\t/// The type to parse the body into. Use `()` if `needs_body()` returns `false`.\n\ttype Body: RequestBody + Send;\n\n\t/// Returns `true` if the request wants to know the auth status of the client. `false` by default.\n\tfn wants_auth() -> bool {\n\t\tfalse\n\t}\n\n\t/// Replace the automatically generated operation id with a custom one. Only relevant for the\n\t/// OpenAPI Specification.\n\t#[openapi_only]\n\tfn operation_id() -> Option {\n\t\tNone\n\t}\n\n\t/// Add a description to the openapi specification. Usually taken from the rustdoc comment\n\t/// when using the proc macro.\n\t#[openapi_only]\n\tfn description() -> Option {\n\t\tNone\n\t}\n\n\t/// The handler for this endpoint.\n\tfn handle(\n\t\tstate: &mut State,\n\t\tplaceholders: Self::Placeholders,\n\t\tparams: Self::Params,\n\t\tbody: Option\n\t) -> BoxFuture<'_, Self::Output>;\n}\n\n#[cfg(feature = \"openapi\")]\nimpl Endpoint for E {\n\tfn http_method() -> Method {\n\t\tE::http_method()\n\t}\n\tfn uri() -> Cow<'static, str> {\n\t\tE::uri()\n\t}\n\n\ttype Output = E::Output;\n\n\tfn has_placeholders() -> bool {\n\t\tE::has_placeholders()\n\t}\n\ttype Placeholders = E::Placeholders;\n\n\tfn needs_params() -> bool {\n\t\tE::needs_params()\n\t}\n\ttype Params = E::Params;\n\n\tfn needs_body() -> bool {\n\t\tE::needs_body()\n\t}\n\ttype Body = E::Body;\n\n\tfn wants_auth() -> bool {\n\t\tE::wants_auth()\n\t}\n\n\tfn handle<'a>(\n\t\tstate: &'a mut State,\n\t\tplaceholders: Self::Placeholders,\n\t\tparams: Self::Params,\n\t\tbody: Option\n\t) -> BoxFuture<'a, Self::Output> {\n\t\tE::handle(state, placeholders, params, body)\n\t}\n}\n","traces":[{"line":20,"address":[6896016,6895968],"length":1,"stats":{"Line":10},"fn_name":"deserialize>, alloc::vec::Vec<&gotham::helpers::http::PercentDecoded, alloc::alloc::Global>, gotham::helpers::http::PercentDecoded>>>"},{"line":21,"address":[6912483,6912521],"length":1,"stats":{"Line":10},"fn_name":null},{"line":27,"address":[8270800],"length":1,"stats":{"Line":0},"fn_name":"visit_type"},{"line":28,"address":[8270924,8270814,8270874],"length":1,"stats":{"Line":0},"fn_name":null},{"line":31,"address":[8270913],"length":1,"stats":{"Line":0},"fn_name":null},{"line":39,"address":[8270992,8271002],"length":1,"stats":{"Line":0},"fn_name":"extend"},{"line":60,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":61,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":69,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":70,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":78,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":79,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":85,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":86,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":92,"address":[6827280],"length":1,"stats":{"Line":6},"fn_name":"operation_id"},{"line":93,"address":[6827283],"length":1,"stats":{"Line":6},"fn_name":null},{"line":99,"address":[6827264],"length":1,"stats":{"Line":7},"fn_name":"description"},{"line":100,"address":[6644531,6644499,6644515,6644467,6644547,6644483],"length":1,"stats":{"Line":7},"fn_name":null},{"line":114,"address":[6650752,6650592,6650624,6650560,6650688,6650656,6650720],"length":1,"stats":{"Line":30},"fn_name":"http_method"},{"line":115,"address":[6650600,6650728,6650664,6650696,6650632,6650568,6650760],"length":1,"stats":{"Line":30},"fn_name":null},{"line":117,"address":[6836208],"length":1,"stats":{"Line":30},"fn_name":"uri"},{"line":118,"address":[6836216],"length":1,"stats":{"Line":30},"fn_name":null},{"line":123,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":124,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":128,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":129,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":133,"address":[6836160],"length":1,"stats":{"Line":21},"fn_name":"needs_body"},{"line":134,"address":[6836161],"length":1,"stats":{"Line":21},"fn_name":null},{"line":138,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":139,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":142,"address":[6836240],"length":1,"stats":{"Line":21},"fn_name":"handle"},{"line":148,"address":[6836248],"length":1,"stats":{"Line":21},"fn_name":null}],"covered":14,"coverable":32},{"path":["/","home","runner","work","gotham_restful","gotham_restful","src","lib.rs"],"content":"#![warn(missing_debug_implementations, rust_2018_idioms, unreachable_pub)]\n#![forbid(unsafe_code)]\n// deny warnings in CI\n#![cfg_attr(gotham_restful_deny_warnings, deny(warnings))]\n// clippy doesn't like our code style\n#![cfg_attr(feature = \"cargo-clippy\", allow(clippy::tabs_in_doc_comments))]\n// intra-doc links only fully work when OpenAPI is enabled\n#![cfg_attr(feature = \"openapi\", deny(rustdoc::broken_intra_doc_links))]\n#![cfg_attr(not(feature = \"openapi\"), allow(rustdoc::broken_intra_doc_links))]\n\n//! This crate is an extension to the popular [gotham web framework][gotham] for Rust. It allows you to\n//! create resources with assigned endpoints that aim to be a more convenient way of creating handlers\n//! for requests.\n//!\n//! # Features\n//!\n//! - Automatically parse **JSON** request and produce response bodies\n//! - Allow using **raw** request and response bodies\n//! - Convenient **macros** to create responses that can be registered with gotham's router\n//! - Auto-Generate an **OpenAPI** specification for your API\n//! - Manage **CORS** headers so you don't have to\n//! - Manage **Authentication** with JWT\n//! - Integrate diesel connection pools for easy **database** integration\n//!\n//! # Safety\n//!\n//! This crate is just as safe as you'd expect from anything written in safe Rust - and\n//! `#![forbid(unsafe_code)]` ensures that no unsafe was used.\n//!\n//! # Endpoints\n//!\n//! There are a set of pre-defined endpoints that should cover the majority of REST APIs. However,\n//! it is also possible to define your own endpoints.\n//!\n//! ## Pre-defined Endpoints\n//!\n//! Assuming you assign `/foobar` to your resource, the following pre-defined endpoints exist:\n//!\n//! | Endpoint Name | Required Arguments | HTTP Verb | HTTP Path |\n//! | ------------- | ------------------ | --------- | -------------- |\n//! | read_all | | GET | /foobar |\n//! | read | id | GET | /foobar/:id |\n//! | search | query | GET | /foobar/search |\n//! | create | body | POST | /foobar |\n//! | update_all | body | PUT | /foobar |\n//! | update | id, body | PUT | /foobar/:id |\n//! | delete_all | | DELETE | /foobar |\n//! | delete | id | DELETE | /foobar/:id |\n//!\n//! Each of those endpoints has a macro that creates the neccessary boilerplate for the Resource. A\n//! simple example looks like this:\n//!\n//! ```rust,no_run\n//! # #[macro_use] extern crate gotham_restful_derive;\n//! # use gotham::router::builder::*;\n//! # use gotham_restful::*;\n//! # use serde::{Deserialize, Serialize};\n//! /// Our RESTful resource.\n//! #[derive(Resource)]\n//! #[resource(read)]\n//! struct FooResource;\n//!\n//! /// The return type of the foo read endpoint.\n//! #[derive(Serialize)]\n//! # #[cfg_attr(feature = \"openapi\", derive(openapi_type::OpenapiType))]\n//! struct Foo {\n//! \tid: u64\n//! }\n//!\n//! /// The foo read endpoint.\n//! #[read]\n//! fn read(id: u64) -> Success {\n//! \tFoo { id }.into()\n//! }\n//! # fn main() {\n//! # \tgotham::start(\"127.0.0.1:8080\", build_simple_router(|route| {\n//! # \t\troute.resource::(\"foo\");\n//! # \t})).expect(\"Failed to start gotham\");\n//! # }\n//! ```\n//!\n//! ## Custom Endpoints\n//!\n//! Defining custom endpoints is done with the `#[endpoint]` macro. The syntax is similar to that\n//! of the pre-defined endpoints, but you need to give it more context:\n//!\n//! ```rust,no_run\n//! # #[macro_use] extern crate gotham_restful_derive;\n//! # use gotham::{router::build_simple_router, prelude::*};\n//! # use gotham_restful::*;\n//! # use serde::{Deserialize, Serialize};\n//! use gotham_restful::gotham::hyper::Method;\n//!\n//! #[derive(Resource)]\n//! #[resource(custom_endpoint)]\n//! struct CustomResource;\n//!\n//! /// This type is used to parse path parameters.\n//! #[derive(Clone, Deserialize, StateData, StaticResponseExtender)]\n//! # #[cfg_attr(feature = \"openapi\", derive(openapi_type::OpenapiType))]\n//! struct CustomPath {\n//! \tname: String\n//! }\n//!\n//! #[endpoint(\n//! \turi = \"custom/:name/read\",\n//! \tmethod = \"Method::GET\",\n//! \tparams = false,\n//! \tbody = false\n//! )]\n//! fn custom_endpoint(path: CustomPath) -> Success {\n//! \tpath.name.into()\n//! }\n//! # fn main() {\n//! # \tgotham::start(\"127.0.0.1:8080\", build_simple_router(|route| {\n//! # \t\troute.resource::(\"custom\");\n//! # \t})).expect(\"Failed to start gotham\");\n//! # }\n//! ```\n//!\n//! # Arguments\n//!\n//! Some endpoints require arguments. Those should be\n//! * **id** Should be a deserializable json-primitive like [`i64`] or [`String`].\n//! * **body** Should be any deserializable object, or any type implementing [`RequestBody`].\n//! * **query** Should be any deserializable object whose variables are json-primitives. It will\n//! however not be parsed from json, but from HTTP GET parameters like in `search?id=1`. The\n//! type needs to implement [`QueryStringExtractor`](gotham::extractor::QueryStringExtractor).\n//!\n//! Additionally, all handlers may take a reference to gotham's [`State`]. Please note that for async\n//! handlers, it needs to be a mutable reference until rustc's lifetime checks across await bounds\n//! improve.\n//!\n//! # Uploads and Downloads\n//!\n//! By default, every request body is parsed from json, and every respone is converted to json using\n//! [serde_json]. However, you may also use raw bodies. This is an example where the request body\n//! is simply returned as the response again, no json parsing involved:\n//!\n//! ```rust,no_run\n//! # #[macro_use] extern crate gotham_restful_derive;\n//! # use gotham::{mime::{self, Mime}, router::builder::*};\n//! # use gotham_restful::*;\n//! # use serde::{Deserialize, Serialize};\n//! #[derive(Resource)]\n//! #[resource(create)]\n//! struct ImageResource;\n//!\n//! #[derive(FromBody, RequestBody)]\n//! #[supported_types(mime::IMAGE_GIF, mime::IMAGE_JPEG, mime::IMAGE_PNG)]\n//! struct RawImage {\n//! \tcontent: Vec,\n//! \tcontent_type: Mime\n//! }\n//!\n//! #[create]\n//! fn create(body: RawImage) -> Raw> {\n//! \tRaw::new(body.content, body.content_type)\n//! }\n//! # fn main() {\n//! # \tgotham::start(\"127.0.0.1:8080\", build_simple_router(|route| {\n//! # \t\troute.resource::(\"image\");\n//! # \t})).expect(\"Failed to start gotham\");\n//! # }\n//! ```\n//!\n//! # Custom HTTP Headers\n//!\n//! You can read request headers from the state as you would in any other gotham handler, and specify\n//! custom response headers using [Response::header].\n//!\n//! ```rust,no_run\n//! # #[macro_use] extern crate gotham_restful_derive;\n//! # use gotham::hyper::header::{ACCEPT, HeaderMap, VARY};\n//! # use gotham::{router::builder::*, state::State};\n//! # use gotham_restful::*;\n//! #[derive(Resource)]\n//! #[resource(read_all)]\n//! struct FooResource;\n//!\n//! #[read_all]\n//! async fn read_all(state: &mut State) -> NoContent {\n//! \tlet headers: &HeaderMap = state.borrow();\n//! \tlet accept = &headers[ACCEPT];\n//! # drop(accept);\n//!\n//! \tlet mut res = NoContent::default();\n//! \tres.header(VARY, \"accept\".parse().unwrap());\n//! \tres\n//! }\n//! # fn main() {\n//! # \tgotham::start(\"127.0.0.1:8080\", build_simple_router(|route| {\n//! # \t\troute.resource::(\"foo\");\n//! # \t})).expect(\"Failed to start gotham\");\n//! # }\n//! ```\n//!\n//! # Features\n//!\n//! To make life easier for common use-cases, this create offers a few features that might be helpful\n//! when you implement your web server. The complete feature list is\n//! - [`auth`](#authentication-feature) Advanced JWT middleware\n//! - [`cors`](#cors-feature) CORS handling for all endpoint handlers\n//! - [`database`](#database-feature) diesel middleware support\n//! - `errorlog` log errors returned from endpoint handlers\n//! - `full` enables all features except `without-openapi`\n//! - [`openapi`](#openapi-feature) router additions to generate an openapi spec\n//! - `without-openapi` (**default**) disables `openapi` support.\n//!\n//! ## Authentication Feature\n//!\n//! In order to enable authentication support, enable the `auth` feature gate. This allows you to\n//! register a middleware that can automatically check for the existence of an JWT authentication\n//! token. Besides being supported by the endpoint macros, it supports to lookup the required JWT secret\n//! with the JWT data, hence you can use several JWT secrets and decide on the fly which secret to use.\n//! None of this is currently supported by gotham's own JWT middleware.\n//!\n//! A simple example that uses only a single secret looks like this:\n//!\n//! ```rust,no_run\n//! # #[macro_use] extern crate gotham_restful_derive;\n//! # #[cfg(feature = \"auth\")]\n//! # mod auth_feature_enabled {\n//! # use gotham::{router::builder::*, pipeline::*, state::State};\n//! # use gotham_restful::*;\n//! # use serde::{Deserialize, Serialize};\n//! #[derive(Resource)]\n//! #[resource(read)]\n//! struct SecretResource;\n//!\n//! #[derive(Serialize)]\n//! # #[cfg_attr(feature = \"openapi\", derive(openapi_type::OpenapiType))]\n//! struct Secret {\n//! \tid: u64,\n//! \tintended_for: String\n//! }\n//!\n//! #[derive(Deserialize, Clone)]\n//! struct AuthData {\n//! \tsub: String,\n//! \texp: u64\n//! }\n//!\n//! #[read]\n//! fn read(auth: AuthStatus, id: u64) -> AuthSuccess {\n//! \tlet intended_for = auth.ok()?.sub;\n//! \tOk(Secret { id, intended_for })\n//! }\n//!\n//! fn main() {\n//! \tlet auth: AuthMiddleware = AuthMiddleware::new(\n//! \t\tAuthSource::AuthorizationHeader,\n//! \t\tAuthValidation::default(),\n//! \t\tStaticAuthHandler::from_array(b\"zlBsA2QXnkmpe0QTh8uCvtAEa4j33YAc\")\n//! \t);\n//! \tlet (chain, pipelines) = single_pipeline(new_pipeline().add(auth).build());\n//! \tgotham::start(\n//! \t\t\"127.0.0.1:8080\",\n//! \t\tbuild_router(chain, pipelines, |route| {\n//! \t\t\troute.resource::(\"secret\");\n//! \t\t})\n//! \t)\n//! \t.expect(\"Failed to start gotham\");\n//! }\n//! # }\n//! ```\n//!\n//! ## CORS Feature\n//!\n//! The cors feature allows an easy usage of this web server from other origins. By default, only\n//! the `Access-Control-Allow-Methods` header is touched. To change the behaviour, add your desired\n//! configuration as a middleware.\n//!\n//! A simple example that allows authentication from every origin (note that `*` always disallows\n//! authentication), and every content type, looks like this:\n//!\n//! ```rust,no_run\n//! # #[macro_use] extern crate gotham_restful_derive;\n//! # #[cfg(feature = \"cors\")]\n//! # mod cors_feature_enabled {\n//! # use gotham::{hyper::header::*, router::builder::*, pipeline::*, state::State};\n//! # use gotham_restful::{*, cors::*};\n//! # use serde::{Deserialize, Serialize};\n//! #[derive(Resource)]\n//! #[resource(read_all)]\n//! struct FooResource;\n//!\n//! #[read_all]\n//! fn read_all() {\n//! \t// your handler\n//! }\n//!\n//! fn main() {\n//! \tlet cors = CorsConfig {\n//! \t\torigin: Origin::Copy,\n//! \t\theaders: Headers::List(vec![CONTENT_TYPE]),\n//! \t\tmax_age: 0,\n//! \t\tcredentials: true\n//! \t};\n//! \tlet (chain, pipelines) = single_pipeline(new_pipeline().add(cors).build());\n//! \tgotham::start(\n//! \t\t\"127.0.0.1:8080\",\n//! \t\tbuild_router(chain, pipelines, |route| {\n//! \t\t\troute.resource::(\"foo\");\n//! \t\t})\n//! \t)\n//! \t.expect(\"Failed to start gotham\");\n//! }\n//! # }\n//! ```\n//!\n//! The cors feature can also be used for non-resource handlers. Take a look at [`CorsRoute`]\n//! for an example.\n//!\n//! ## Database Feature\n//!\n//! The database feature allows an easy integration of [diesel] into your handler functions. Please\n//! note however that due to the way gotham's diesel middleware implementation, it is not possible\n//! to run async code while holding a database connection. If you need to combine async and database,\n//! you'll need to borrow the connection from the [`State`] yourself and return a boxed future.\n//!\n//! A simple non-async example looks like this:\n//!\n//! ```rust,no_run\n//! # #[macro_use] extern crate diesel;\n//! # #[macro_use] extern crate gotham_restful_derive;\n//! # #[cfg(feature = \"database\")]\n//! # mod database_feature_enabled {\n//! # use diesel::{table, PgConnection, QueryResult, RunQueryDsl};\n//! # use gotham::{router::builder::*, pipeline::*, state::State};\n//! # use gotham_middleware_diesel::DieselMiddleware;\n//! # use gotham_restful::*;\n//! # use serde::{Deserialize, Serialize};\n//! # use std::env;\n//! # table! {\n//! # foo (id) {\n//! # id -> Int8,\n//! # value -> Text,\n//! # }\n//! # }\n//! #[derive(Resource)]\n//! #[resource(read_all)]\n//! struct FooResource;\n//!\n//! #[derive(Queryable, Serialize)]\n//! # #[cfg_attr(feature = \"openapi\", derive(openapi_type::OpenapiType))]\n//! struct Foo {\n//! \tid: i64,\n//! \tvalue: String\n//! }\n//!\n//! #[read_all]\n//! fn read_all(conn: &mut PgConnection) -> QueryResult> {\n//! \tfoo::table.load(conn)\n//! }\n//!\n//! type Repo = gotham_middleware_diesel::Repo;\n//!\n//! fn main() {\n//! \tlet repo = Repo::new(&env::var(\"DATABASE_URL\").unwrap());\n//! \tlet diesel = DieselMiddleware::new(repo);\n//!\n//! \tlet (chain, pipelines) = single_pipeline(new_pipeline().add(diesel).build());\n//! \tgotham::start(\n//! \t\t\"127.0.0.1:8080\",\n//! \t\tbuild_router(chain, pipelines, |route| {\n//! \t\t\troute.resource::(\"foo\");\n//! \t\t})\n//! \t)\n//! \t.expect(\"Failed to start gotham\");\n//! }\n//! # }\n//! ```\n//!\n//! ## OpenAPI Feature\n//!\n//! The OpenAPI feature is probably the most powerful one of this crate. Definitely read this section\n//! carefully both as a binary as well as a library author to avoid unwanted suprises.\n//!\n//! In order to automatically create an openapi specification, gotham-restful needs knowledge over\n//! all routes and the types returned. `serde` does a great job at serialization but doesn't give\n//! enough type information, so all types used in the router need to implement\n//! [`OpenapiType`](openapi_type::OpenapiType). This can be derived for almoust any type and there\n//! should be no need to implement it manually. A simple example looks like this:\n//!\n//! ```rust,no_run\n//! # #[macro_use] extern crate gotham_restful_derive;\n//! # #[cfg(feature = \"openapi\")]\n//! # mod openapi_feature_enabled {\n//! # use gotham::{router::builder::*, state::State};\n//! # use gotham_restful::*;\n//! # use openapi_type::OpenapiType;\n//! # use serde::{Deserialize, Serialize};\n//! #[derive(Resource)]\n//! #[resource(read_all)]\n//! struct FooResource;\n//!\n//! #[derive(OpenapiType, Serialize)]\n//! struct Foo {\n//! \tbar: String\n//! }\n//!\n//! #[read_all]\n//! fn read_all() -> Success {\n//! \tFoo {\n//! \t\tbar: \"Hello World\".to_owned()\n//! \t}\n//! \t.into()\n//! }\n//!\n//! fn main() {\n//! \tgotham::start(\n//! \t\t\"127.0.0.1:8080\",\n//! \t\tbuild_simple_router(|route| {\n//! \t\t\tlet info = OpenapiInfo {\n//! \t\t\t\ttitle: \"My Foo API\".to_owned(),\n//! \t\t\t\tversion: \"0.1.0\".to_owned(),\n//! \t\t\t\turls: vec![\"https://example.org/foo/api/v1\".to_owned()]\n//! \t\t\t};\n//! \t\t\troute.with_openapi(info, |mut route| {\n//! \t\t\t\troute.resource::(\"foo\");\n//! \t\t\t\troute.openapi_spec(\"openapi\");\n//! \t\t\t\troute.openapi_doc(\"/\");\n//! \t\t\t});\n//! \t\t})\n//! \t)\n//! \t.expect(\"Failed to start gotham\");\n//! }\n//! # }\n//! ```\n//!\n//! Above example adds the resource as before, but adds two other endpoints as well: `/openapi` and `/`.\n//! The first one will return the generated openapi specification in JSON format, allowing you to easily\n//! generate clients in different languages without worying to exactly replicate your api in each of those\n//! languages. The second one will return documentation in HTML format, so you can easily view your\n//! api and share it with other people.\n//!\n//! ### Gotchas\n//!\n//! The openapi feature has some gotchas you should be aware of.\n//!\n//! - The name of a struct is used as a \"link\" in the openapi specification. Therefore, if you have two\n//! structs with the same name in your project, the openapi specification will be invalid as only one\n//! of the two will make it into the spec.\n//! - By default, the `without-openapi` feature of this crate is enabled. Disabling it in favour of the\n//! `openapi` feature will add additional type bounds and method requirements to some of the traits and\n//! \ttypes in this crate, for example instead of [`Endpoint`] you now have to implement\n//! \t[`EndpointWithSchema`]. This means that some code might only compile on either feature, but not\n//! on both. If you are writing a library that uses gotham-restful, it is strongly recommended to pass\n//! \tboth features through and conditionally enable the openapi code, like this:\n//!\n//! ```rust\n//! # #[macro_use] extern crate gotham_restful;\n//! # use serde::{Deserialize, Serialize};\n//! #[derive(Deserialize, Serialize)]\n//! #[cfg_attr(feature = \"openapi\", derive(openapi_type::OpenapiType))]\n//! struct Foo;\n//! ```\n//!\n//! [diesel]: https://diesel.rs/\n//! [`State`]: gotham::state::State\n\n#[cfg(all(feature = \"openapi\", feature = \"without-openapi\"))]\ncompile_error!(\"The 'openapi' and 'without-openapi' features cannot be combined\");\n\n#[cfg(all(not(feature = \"openapi\"), not(feature = \"without-openapi\")))]\ncompile_error!(\"Either the 'openapi' or 'without-openapi' feature needs to be enabled\");\n\n// weird proc macro issue\nextern crate self as gotham_restful;\n\n#[macro_use]\nextern crate gotham_restful_derive;\n#[macro_use]\nextern crate log;\n#[macro_use]\nextern crate serde;\n\n#[cfg(test)]\n#[macro_use]\nextern crate pretty_assertions;\n\n#[doc(no_inline)]\npub use gotham;\n\npub use gotham_restful_derive::*;\n\n/// Not public API\n#[doc(hidden)]\npub mod private {\n\tpub use crate::routing::PathExtractor as IdPlaceholder;\n\tpub use futures_util::future::{BoxFuture, FutureExt};\n\t#[cfg(feature = \"database\")]\n\tpub use gotham_middleware_diesel::Repo;\n\t#[cfg(feature = \"openapi\")]\n\tpub use openapi_type::{OpenapiSchema, OpenapiType, Visitor};\n\tpub use serde_json;\n\n\t#[cfg(feature = \"openapi\")]\n\tuse gotham::hyper::StatusCode;\n\t#[cfg(feature = \"auth\")]\n\tuse gotham::state::{FromState, State};\n\n\t/// This method is used by the endpoint macro to generate a good error message\n\t/// when the used AuthData type does not implement Clone.\n\t#[cfg(feature = \"auth\")]\n\t#[inline]\n\tpub fn clone_from_state(state: &State) -> T\n\twhere\n\t\tT: FromState + Clone\n\t{\n\t\tT::borrow_from(state).clone()\n\t}\n\n\t/// This trait is used by the endpoint macro to generate a good error message\n\t/// when the schema function has the wrong signature.\n\t#[cfg(feature = \"openapi\")]\n\tpub trait CustomSchema {\n\t\tfn schema(self, code: StatusCode) -> OpenapiSchema;\n\t}\n\n\t#[cfg(feature = \"openapi\")]\n\timpl CustomSchema for F\n\twhere\n\t\tF: FnOnce(StatusCode) -> OpenapiSchema\n\t{\n\t\t#[inline]\n\t\tfn schema(self, code: StatusCode) -> OpenapiSchema {\n\t\t\tself(code)\n\t\t}\n\t}\n\n\t/// This trait is used by the endpoint macro to generate a good error message\n\t/// when the status_codes function has the wrong signature.\n\t#[cfg(feature = \"openapi\")]\n\tpub trait CustomStatusCodes {\n\t\tfn status_codes(self) -> Vec;\n\t}\n\n\t#[cfg(feature = \"openapi\")]\n\timpl CustomStatusCodes for F\n\twhere\n\t\tF: FnOnce() -> Vec\n\t{\n\t\t#[inline]\n\t\tfn status_codes(self) -> Vec {\n\t\t\tself()\n\t\t}\n\t}\n}\n\n#[cfg(feature = \"auth\")]\nmod auth;\n#[cfg(feature = \"auth\")]\npub use auth::{\n\tAuthHandler, AuthMiddleware, AuthSource, AuthStatus, AuthValidation, StaticAuthHandler\n};\n\n#[cfg(feature = \"cors\")]\npub mod cors;\n#[cfg(feature = \"cors\")]\npub use cors::{handle_cors, CorsConfig, CorsRoute};\n\n#[cfg(feature = \"openapi\")]\nmod openapi;\n#[cfg(feature = \"openapi\")]\npub use openapi::{builder::OpenapiInfo, router::GetOpenapi};\n\nmod endpoint;\n#[cfg(feature = \"openapi\")]\npub use endpoint::EndpointWithSchema;\npub use endpoint::{Endpoint, NoopExtractor};\n\nmod response;\npub use response::{\n\tAuthError, AuthErrorOrOther, AuthResult, AuthSuccess, IntoResponse, IntoResponseError,\n\tNoContent, Raw, Redirect, Response, Success\n};\n#[cfg(feature = \"openapi\")]\npub use response::{IntoResponseWithSchema, ResponseSchema};\n\nmod routing;\npub use routing::{DrawResourceRoutes, DrawResources};\n#[cfg(feature = \"openapi\")]\npub use routing::{DrawResourceRoutesWithSchema, DrawResourcesWithSchema, WithOpenapi};\n\nmod types;\npub use types::{FromBody, RequestBody, ResponseBody};\n\n/// This trait must be implemented for every resource. It allows you to register the different\n/// endpoints that can be handled by this resource to be registered with the underlying router.\n///\n/// It is not recommended to implement this yourself, just use `#[derive(Resource)]`.\n#[_private_openapi_trait(ResourceWithSchema)]\npub trait Resource {\n\t/// Register all methods handled by this resource with the underlying router.\n\t#[openapi_bound(D: crate::DrawResourceRoutesWithSchema)]\n\t#[non_openapi_bound(D: crate::DrawResourceRoutes)]\n\tfn setup(route: D);\n}\n","traces":[{"line":463,"address":[15569646],"length":1,"stats":{"Line":9},"fn_name":null},{"line":464,"address":[16240502],"length":1,"stats":{"Line":9},"fn_name":null},{"line":466,"address":[11060432],"length":1,"stats":{"Line":0},"fn_name":null},{"line":467,"address":[15569712,15569808],"length":1,"stats":{"Line":0},"fn_name":"ok_or"},{"line":489,"address":[4033744],"length":1,"stats":{"Line":0},"fn_name":null},{"line":506,"address":[15618436],"length":1,"stats":{"Line":0},"fn_name":null},{"line":507,"address":[14689591],"length":1,"stats":{"Line":14},"fn_name":null},{"line":508,"address":[11061239],"length":1,"stats":{"Line":14},"fn_name":null},{"line":512,"address":[15570457],"length":1,"stats":{"Line":0},"fn_name":null},{"line":518,"address":[7415995,7415970,7415740,7415658,7415750,7415766],"length":1,"stats":{"Line":7},"fn_name":null},{"line":523,"address":[11061557],"length":1,"stats":{"Line":7},"fn_name":null},{"line":527,"address":[14689732],"length":1,"stats":{"Line":0},"fn_name":null},{"line":528,"address":[7396110],"length":1,"stats":{"Line":8},"fn_name":null},{"line":529,"address":[16243630],"length":1,"stats":{"Line":8},"fn_name":null},{"line":536,"address":[16243768],"length":1,"stats":{"Line":0},"fn_name":null},{"line":541,"address":[15570624],"length":1,"stats":{"Line":0},"fn_name":null},{"line":545,"address":[15618727],"length":1,"stats":{"Line":0},"fn_name":null},{"line":546,"address":[15618771],"length":1,"stats":{"Line":1},"fn_name":null},{"line":547,"address":[15618786],"length":1,"stats":{"Line":1},"fn_name":null},{"line":552,"address":[11061608],"length":1,"stats":{"Line":0},"fn_name":null},{"line":559,"address":[11061646],"length":1,"stats":{"Line":0},"fn_name":null},{"line":564,"address":[10347552,10347520],"length":1,"stats":{"Line":0},"fn_name":"read_i24"},{"line":595,"address":[15570888],"length":1,"stats":{"Line":0},"fn_name":null}],"covered":10,"coverable":23},{"path":["/","home","runner","work","gotham_restful","gotham_restful","src","openapi","builder.rs"],"content":"use openapi_type::{\n\tindexmap::IndexMap,\n\topenapiv3::{\n\t\tself, Components, OpenAPI, PathItem, ReferenceOr,\n\t\tReferenceOr::{Item, Reference},\n\t\tSchema, Server\n\t},\n\tOpenapiSchema\n};\nuse parking_lot::RwLock;\nuse std::sync::Arc;\n\n#[derive(Clone, Debug)]\npub struct OpenapiInfo {\n\tpub title: String,\n\tpub version: String,\n\tpub urls: Vec\n}\n\n#[derive(Clone, Debug)]\npub(crate) struct OpenapiBuilder {\n\tpub(crate) openapi: Arc>\n}\n\nimpl OpenapiBuilder {\n\tpub(crate) fn new(info: OpenapiInfo) -> Self {\n\t\tSelf {\n\t\t\topenapi: Arc::new(RwLock::new(OpenAPI {\n\t\t\t\topenapi: \"3.0.2\".to_string(),\n\t\t\t\tinfo: openapiv3::Info {\n\t\t\t\t\ttitle: info.title,\n\t\t\t\t\tversion: info.version,\n\t\t\t\t\t..Default::default()\n\t\t\t\t},\n\t\t\t\tservers: info\n\t\t\t\t\t.urls\n\t\t\t\t\t.into_iter()\n\t\t\t\t\t.map(|url| Server {\n\t\t\t\t\t\turl,\n\t\t\t\t\t\t..Default::default()\n\t\t\t\t\t})\n\t\t\t\t\t.collect(),\n\t\t\t\t..Default::default()\n\t\t\t}))\n\t\t}\n\t}\n\n\t/// Remove path from the OpenAPI spec, or return an empty one if not included. This is handy if you need to\n\t/// modify the path and add it back after the modification\n\tpub(crate) fn remove_path(&mut self, path: &str) -> PathItem {\n\t\tlet mut openapi = self.openapi.write();\n\t\tmatch openapi.paths.paths.swap_remove(path) {\n\t\t\tSome(Item(item)) => item,\n\t\t\t_ => PathItem::default()\n\t\t}\n\t}\n\n\tpub(crate) fn add_path(&mut self, path: Path, item: PathItem) {\n\t\tlet mut openapi = self.openapi.write();\n\t\topenapi.paths.paths.insert(path.to_string(), Item(item));\n\t}\n\n\tfn add_schema_impl(&mut self, name: String, mut schema: OpenapiSchema) {\n\t\tself.add_schema_dependencies(&mut schema.dependencies);\n\n\t\tlet mut openapi = self.openapi.write();\n\t\tmatch &mut openapi.components {\n\t\t\tSome(comp) => {\n\t\t\t\tcomp.schemas.insert(name, Item(schema.schema));\n\t\t\t},\n\t\t\tNone => {\n\t\t\t\tlet mut comp = Components::default();\n\t\t\t\tcomp.schemas.insert(name, Item(schema.schema));\n\t\t\t\topenapi.components = Some(comp);\n\t\t\t}\n\t\t};\n\t}\n\n\tfn add_schema_dependencies(&mut self, dependencies: &mut IndexMap) {\n\t\tlet keys: Vec = dependencies.keys().map(|k| k.to_string()).collect();\n\t\tfor dep in keys {\n\t\t\tlet dep_schema = dependencies.swap_remove(&dep);\n\t\t\tif let Some(dep_schema) = dep_schema {\n\t\t\t\tself.add_schema_impl(dep, dep_schema);\n\t\t\t}\n\t\t}\n\t}\n\n\tpub(crate) fn add_schema(&mut self, mut schema: OpenapiSchema) -> ReferenceOr {\n\t\tmatch schema.schema.schema_data.title.clone() {\n\t\t\tSome(name) => {\n\t\t\t\tlet reference = Reference {\n\t\t\t\t\treference: format!(\"#/components/schemas/{name}\")\n\t\t\t\t};\n\t\t\t\tself.add_schema_impl(name, schema);\n\t\t\t\treference\n\t\t\t},\n\t\t\tNone => {\n\t\t\t\tself.add_schema_dependencies(&mut schema.dependencies);\n\t\t\t\tItem(schema.schema)\n\t\t\t}\n\t\t}\n\t}\n}\n\n#[cfg(test)]\n#[allow(dead_code)]\nmod test {\n\tuse super::*;\n\tuse openapi_type::OpenapiType;\n\n\t#[derive(OpenapiType)]\n\tstruct Message {\n\t\tmsg: String\n\t}\n\n\t#[derive(OpenapiType)]\n\tstruct Messages {\n\t\tmsgs: Vec\n\t}\n\n\tfn info() -> OpenapiInfo {\n\t\tOpenapiInfo {\n\t\t\ttitle: \"TEST CASE\".to_owned(),\n\t\t\tversion: \"1.2.3\".to_owned(),\n\t\t\turls: vec![\n\t\t\t\t\"http://localhost:1234\".to_owned(),\n\t\t\t\t\"https://example.org\".to_owned(),\n\t\t\t]\n\t\t}\n\t}\n\n\tfn openapi(builder: OpenapiBuilder) -> OpenAPI {\n\t\tArc::try_unwrap(builder.openapi).unwrap().into_inner()\n\t}\n\n\t#[test]\n\tfn new_builder() {\n\t\tlet info = info();\n\t\tlet builder = OpenapiBuilder::new(info.clone());\n\t\tlet openapi = openapi(builder);\n\n\t\tassert_eq!(info.title, openapi.info.title);\n\t\tassert_eq!(info.version, openapi.info.version);\n\t\tassert_eq!(info.urls.len(), openapi.servers.len());\n\t}\n\n\t#[test]\n\tfn add_schema() {\n\t\tlet mut builder = OpenapiBuilder::new(info());\n\t\tbuilder.add_schema(>::schema());\n\t\tlet openapi = openapi(builder);\n\n\t\tassert_eq!(\n\t\t\topenapi.components.clone().unwrap_or_default().schemas[\"Message\"],\n\t\t\tReferenceOr::Item(Message::schema().schema)\n\t\t);\n\t\tassert_eq!(\n\t\t\topenapi.components.clone().unwrap_or_default().schemas[\"Messages\"],\n\t\t\tReferenceOr::Item(Messages::schema().schema)\n\t\t);\n\t}\n}\n","traces":[{"line":26,"address":[7639362,7638204,7637504],"length":1,"stats":{"Line":3},"fn_name":null},{"line":28,"address":[8363131,8364013,8364546],"length":1,"stats":{"Line":9},"fn_name":null},{"line":50,"address":[8365376,8365662],"length":1,"stats":{"Line":2},"fn_name":null},{"line":51,"address":[8365499],"length":1,"stats":{"Line":2},"fn_name":null},{"line":52,"address":[8365533,8365688,8365606],"length":1,"stats":{"Line":5},"fn_name":null},{"line":53,"address":[8365723],"length":1,"stats":{"Line":1},"fn_name":null},{"line":54,"address":[7640217,7640116],"length":1,"stats":{"Line":4},"fn_name":null},{"line":58,"address":[],"length":0,"stats":{"Line":2},"fn_name":null},{"line":59,"address":[],"length":0,"stats":{"Line":4},"fn_name":null},{"line":60,"address":[],"length":0,"stats":{"Line":4},"fn_name":null},{"line":63,"address":[7641786,7641640,7640480],"length":1,"stats":{"Line":2},"fn_name":null},{"line":64,"address":[7640553],"length":1,"stats":{"Line":2},"fn_name":null},{"line":66,"address":[8366264],"length":1,"stats":{"Line":2},"fn_name":null},{"line":67,"address":[8366399,8366326],"length":1,"stats":{"Line":4},"fn_name":null},{"line":68,"address":[8366481],"length":1,"stats":{"Line":2},"fn_name":null},{"line":69,"address":[8366489],"length":1,"stats":{"Line":2},"fn_name":null},{"line":72,"address":[7640850],"length":1,"stats":{"Line":2},"fn_name":null},{"line":73,"address":[7641101,7641306],"length":1,"stats":{"Line":4},"fn_name":null},{"line":74,"address":[7641325,7641618],"length":1,"stats":{"Line":2},"fn_name":null},{"line":79,"address":[7642525,7642482,7641824],"length":1,"stats":{"Line":3},"fn_name":null},{"line":80,"address":[7642579,7641870,7642544],"length":1,"stats":{"Line":7},"fn_name":"{closure#0}"},{"line":81,"address":[7641918,7642131,7642501],"length":1,"stats":{"Line":7},"fn_name":null},{"line":82,"address":[7642239,7642171],"length":1,"stats":{"Line":4},"fn_name":null},{"line":83,"address":[7642247],"length":1,"stats":{"Line":2},"fn_name":null},{"line":84,"address":[7642409,7642326],"length":1,"stats":{"Line":4},"fn_name":null},{"line":89,"address":[7643413,7642608,7643283],"length":1,"stats":{"Line":3},"fn_name":null},{"line":90,"address":[7642651,7642755],"length":1,"stats":{"Line":6},"fn_name":null},{"line":91,"address":[7642808],"length":1,"stats":{"Line":1},"fn_name":null},{"line":93,"address":[7642959],"length":1,"stats":{"Line":1},"fn_name":null},{"line":95,"address":[7643112],"length":1,"stats":{"Line":1},"fn_name":null},{"line":96,"address":[7643258],"length":1,"stats":{"Line":1},"fn_name":null},{"line":99,"address":[7642791],"length":1,"stats":{"Line":3},"fn_name":null},{"line":100,"address":[7643334],"length":1,"stats":{"Line":3},"fn_name":null}],"covered":33,"coverable":33},{"path":["/","home","runner","work","gotham_restful","gotham_restful","src","openapi","handler","mod.rs"],"content":"#![cfg_attr(not(feature = \"auth\"), allow(unused_imports))]\nuse super::SECURITY_NAME;\nuse base64::prelude::*;\nuse futures_util::{future, future::FutureExt};\nuse gotham::{\n\tanyhow,\n\thandler::{Handler, HandlerError, HandlerFuture, NewHandler},\n\thelpers::http::response::{create_empty_response, create_response},\n\thyper::{\n\t\theader::{\n\t\t\tHeaderMap, HeaderValue, CACHE_CONTROL, CONTENT_SECURITY_POLICY, ETAG, IF_NONE_MATCH,\n\t\t\tREFERRER_POLICY, X_CONTENT_TYPE_OPTIONS\n\t\t},\n\t\tBody, Response, StatusCode\n\t},\n\tmime::{APPLICATION_JSON, TEXT_HTML_UTF_8, TEXT_PLAIN_UTF_8},\n\tstate::State\n};\nuse gotham_restful_redoc::Redoc;\nuse openapi_type::{\n\tindexmap::IndexMap,\n\topenapiv3::{APIKeyLocation, OpenAPI, ReferenceOr, SecurityScheme}\n};\nuse parking_lot::RwLock;\nuse sha2::{Digest, Sha256};\nuse std::{panic::RefUnwindSafe, pin::Pin, sync::Arc};\n\n#[cfg(feature = \"auth\")]\nfn get_security(state: &State) -> IndexMap> {\n\tuse crate::AuthSource;\n\tuse gotham::state::FromState;\n\n\tlet source = match AuthSource::try_borrow_from(state) {\n\t\tSome(source) => source,\n\t\tNone => return Default::default()\n\t};\n\n\tlet security_scheme = match source {\n\t\tAuthSource::Cookie(name) => SecurityScheme::APIKey {\n\t\t\tlocation: APIKeyLocation::Cookie,\n\t\t\tname: name.to_string(),\n\t\t\tdescription: None\n\t\t},\n\t\tAuthSource::Header(name) => SecurityScheme::APIKey {\n\t\t\tlocation: APIKeyLocation::Header,\n\t\t\tname: name.to_string(),\n\t\t\tdescription: None\n\t\t},\n\t\tAuthSource::AuthorizationHeader => SecurityScheme::HTTP {\n\t\t\tscheme: \"bearer\".to_owned(),\n\t\t\tbearer_format: Some(\"JWT\".to_owned()),\n\t\t\tdescription: None\n\t\t}\n\t};\n\n\tlet mut security_schemes: IndexMap> = Default::default();\n\tsecurity_schemes.insert(SECURITY_NAME.to_owned(), ReferenceOr::Item(security_scheme));\n\n\tsecurity_schemes\n}\n\n#[cfg(not(feature = \"auth\"))]\nfn get_security(_state: &State) -> IndexMap> {\n\tDefault::default()\n}\n\nfn openapi_string(\n\tstate: &State,\n\topenapi: &Arc>\n) -> Result {\n\tlet openapi = openapi.read();\n\n\tlet mut openapi = openapi.clone();\n\tlet security_schemes = get_security(state);\n\tlet mut components = openapi.components.unwrap_or_default();\n\tcomponents.security_schemes = security_schemes;\n\topenapi.components = Some(components);\n\n\tserde_json::to_string(&openapi)\n}\n\nfn create_openapi_response(state: &State, openapi: &Arc>) -> Response {\n\tmatch openapi_string(state, openapi) {\n\t\tOk(body) => {\n\t\t\tlet mut res = create_response(state, StatusCode::OK, APPLICATION_JSON, body);\n\t\t\tlet headers = res.headers_mut();\n\t\t\theaders.insert(X_CONTENT_TYPE_OPTIONS, HeaderValue::from_static(\"nosniff\"));\n\t\t\tres\n\t\t},\n\t\tErr(e) => {\n\t\t\terror!(\"Unable to handle OpenAPI request due to error: {e}\");\n\t\t\tcreate_response(\n\t\t\t\tstate,\n\t\t\t\tStatusCode::INTERNAL_SERVER_ERROR,\n\t\t\t\tTEXT_PLAIN_UTF_8,\n\t\t\t\t\"\"\n\t\t\t)\n\t\t}\n\t}\n}\n\n#[derive(Clone)]\npub(crate) struct OpenapiSpecHandler {\n\topenapi: Arc>\n}\n\n// safety: the handler only ever aquires a read lock, so this usage of\n// RwLock is, in fact, unwind safe\nimpl RefUnwindSafe for OpenapiSpecHandler {}\n\nimpl OpenapiSpecHandler {\n\tpub(crate) fn new(openapi: Arc>) -> Self {\n\t\tSelf { openapi }\n\t}\n}\n\nimpl NewHandler for OpenapiSpecHandler {\n\ttype Instance = Self;\n\n\tfn new_handler(&self) -> anyhow::Result {\n\t\tOk(self.clone())\n\t}\n}\n\nimpl Handler for OpenapiSpecHandler {\n\tfn handle(self, mut state: State) -> Pin> {\n\t\tlet res = create_openapi_response(&mut state, &self.openapi);\n\t\tfuture::ok((state, res)).boxed()\n\t}\n}\n\n#[derive(Clone)]\npub(crate) struct OpenapiDocHandler {\n\topenapi: Arc>\n}\n\n// safety: the handler only ever aquires a read lock, so this usage of\n// RwLock is, in fact, unwind safe\nimpl RefUnwindSafe for OpenapiDocHandler {}\n\nimpl OpenapiDocHandler {\n\tpub(crate) fn new(openapi: Arc>) -> Self {\n\t\tSelf { openapi }\n\t}\n}\n\nimpl NewHandler for OpenapiDocHandler {\n\ttype Instance = Self;\n\n\tfn new_handler(&self) -> anyhow::Result {\n\t\tOk(self.clone())\n\t}\n}\n\nfn redoc_handler(\n\tstate: &State,\n\topenapi: &Arc>\n) -> Result, HandlerError> {\n\tlet spec = openapi_string(state, openapi)?;\n\tlet Redoc { html, script_hash } = gotham_restful_redoc::html(spec);\n\n\tlet mut etag = Sha256::new();\n\tetag.update(&html);\n\tlet etag = format!(\"\\\"{}\\\"\", BASE64_STANDARD.encode(etag.finalize()));\n\n\tif state\n\t\t.borrow::()\n\t\t.get(IF_NONE_MATCH)\n\t\t.map_or(false, |header| header.as_bytes() == etag.as_bytes())\n\t{\n\t\tlet res = create_empty_response(state, StatusCode::NOT_MODIFIED);\n\t\treturn Ok(res);\n\t}\n\n\tlet mut res = create_response(state, StatusCode::OK, TEXT_HTML_UTF_8, html);\n\tlet headers = res.headers_mut();\n\theaders.insert(\n\t\tCACHE_CONTROL,\n\t\tHeaderValue::from_static(\"public,max-age=2592000\")\n\t);\n\theaders.insert(\n\t\tCONTENT_SECURITY_POLICY,\n\t\tformat!(\n\t\t\t\"default-src 'none';base-uri 'none';script-src 'unsafe-inline' https://cdn.jsdelivr.net 'sha256-{script_hash}' 'strict-dynamic';style-src 'unsafe-inline' https://fonts.googleapis.com;font-src https://fonts.gstatic.com;connect-src 'self';img-src blob: data:\",\n\t\t).parse().unwrap()\n\t);\n\theaders.insert(ETAG, etag.parse().unwrap());\n\theaders.insert(REFERRER_POLICY, HeaderValue::from_static(\"no-referrer\"));\n\theaders.insert(X_CONTENT_TYPE_OPTIONS, HeaderValue::from_static(\"nosniff\"));\n\tOk(res)\n}\n\nimpl Handler for OpenapiDocHandler {\n\tfn handle(self, state: State) -> Pin> {\n\t\tmatch redoc_handler(&state, &self.openapi) {\n\t\t\tOk(res) => future::ok((state, res)).boxed(),\n\t\t\tErr(err) => future::err((state, err)).boxed()\n\t\t}\n\t}\n}\n","traces":[{"line":29,"address":[7822107,7821312],"length":1,"stats":{"Line":2},"fn_name":"get_security"},{"line":33,"address":[7821466,7821350],"length":1,"stats":{"Line":2},"fn_name":null},{"line":34,"address":[7821411],"length":1,"stats":{"Line":1},"fn_name":null},{"line":35,"address":[7821400],"length":1,"stats":{"Line":1},"fn_name":null},{"line":38,"address":[7821429],"length":1,"stats":{"Line":1},"fn_name":null},{"line":41,"address":[7821493],"length":1,"stats":{"Line":0},"fn_name":null},{"line":46,"address":[7821660],"length":1,"stats":{"Line":0},"fn_name":null},{"line":50,"address":[7821803],"length":1,"stats":{"Line":1},"fn_name":null},{"line":51,"address":[7821899,7821828],"length":1,"stats":{"Line":2},"fn_name":null},{"line":56,"address":[7822133],"length":1,"stats":{"Line":1},"fn_name":null},{"line":57,"address":[7822258,7822190],"length":1,"stats":{"Line":2},"fn_name":null},{"line":59,"address":[7822400],"length":1,"stats":{"Line":1},"fn_name":null},{"line":67,"address":[7823375,7822464,7823875],"length":1,"stats":{"Line":2},"fn_name":"openapi_string"},{"line":71,"address":[7822530],"length":1,"stats":{"Line":2},"fn_name":null},{"line":73,"address":[7822660,7822588],"length":1,"stats":{"Line":4},"fn_name":null},{"line":74,"address":[7822688,7822736],"length":1,"stats":{"Line":4},"fn_name":null},{"line":75,"address":[7822744,7822852],"length":1,"stats":{"Line":4},"fn_name":null},{"line":76,"address":[7822868],"length":1,"stats":{"Line":2},"fn_name":null},{"line":77,"address":[7823124],"length":1,"stats":{"Line":2},"fn_name":null},{"line":79,"address":[7823251],"length":1,"stats":{"Line":2},"fn_name":null},{"line":82,"address":[7823904,7824759],"length":1,"stats":{"Line":2},"fn_name":"create_openapi_response"},{"line":83,"address":[7823942],"length":1,"stats":{"Line":2},"fn_name":null},{"line":84,"address":[7823995],"length":1,"stats":{"Line":2},"fn_name":null},{"line":85,"address":[7824018],"length":1,"stats":{"Line":2},"fn_name":null},{"line":86,"address":[7824844,7824153],"length":1,"stats":{"Line":4},"fn_name":null},{"line":87,"address":[7824852],"length":1,"stats":{"Line":2},"fn_name":null},{"line":88,"address":[7825056],"length":1,"stats":{"Line":2},"fn_name":null},{"line":90,"address":[7824172],"length":1,"stats":{"Line":0},"fn_name":null},{"line":91,"address":[7824185,7824621,7824275,7824333],"length":1,"stats":{"Line":0},"fn_name":null},{"line":95,"address":[7824409],"length":1,"stats":{"Line":0},"fn_name":null},{"line":112,"address":[7825088],"length":1,"stats":{"Line":2},"fn_name":null},{"line":120,"address":[7825104],"length":1,"stats":{"Line":2},"fn_name":"new_handler"},{"line":121,"address":[7825113],"length":1,"stats":{"Line":2},"fn_name":null},{"line":126,"address":[7825498,7825152],"length":1,"stats":{"Line":2},"fn_name":"handle"},{"line":127,"address":[7825195],"length":1,"stats":{"Line":2},"fn_name":null},{"line":128,"address":[7825169,7825248],"length":1,"stats":{"Line":4},"fn_name":null},{"line":142,"address":[7825536],"length":1,"stats":{"Line":0},"fn_name":null},{"line":150,"address":[7825552],"length":1,"stats":{"Line":0},"fn_name":"new_handler"},{"line":151,"address":[7825561],"length":1,"stats":{"Line":0},"fn_name":null},{"line":155,"address":[7825600,7826576,7828924],"length":1,"stats":{"Line":0},"fn_name":"redoc_handler"},{"line":159,"address":[7825918,7825647],"length":1,"stats":{"Line":0},"fn_name":null},{"line":160,"address":[7825843,7826001],"length":1,"stats":{"Line":0},"fn_name":null},{"line":162,"address":[7826073],"length":1,"stats":{"Line":0},"fn_name":null},{"line":163,"address":[7826136],"length":1,"stats":{"Line":0},"fn_name":null},{"line":164,"address":[7826417,7826587,7826163],"length":1,"stats":{"Line":0},"fn_name":null},{"line":166,"address":[7826671,7826772,7826817],"length":1,"stats":{"Line":0},"fn_name":null},{"line":168,"address":[7826742],"length":1,"stats":{"Line":0},"fn_name":null},{"line":169,"address":[7826809,7828985,7828960],"length":1,"stats":{"Line":0},"fn_name":"{closure#0}"},{"line":171,"address":[7827045],"length":1,"stats":{"Line":0},"fn_name":null},{"line":172,"address":[7827112],"length":1,"stats":{"Line":0},"fn_name":null},{"line":175,"address":[7826864],"length":1,"stats":{"Line":0},"fn_name":null},{"line":176,"address":[7827339,7827266],"length":1,"stats":{"Line":0},"fn_name":null},{"line":177,"address":[7827454],"length":1,"stats":{"Line":0},"fn_name":null},{"line":178,"address":[7827347],"length":1,"stats":{"Line":0},"fn_name":null},{"line":179,"address":[7827385],"length":1,"stats":{"Line":0},"fn_name":null},{"line":181,"address":[7827959],"length":1,"stats":{"Line":0},"fn_name":null},{"line":182,"address":[7827546],"length":1,"stats":{"Line":0},"fn_name":null},{"line":183,"address":[7827713,7827901],"length":1,"stats":{"Line":0},"fn_name":null},{"line":187,"address":[7828111],"length":1,"stats":{"Line":0},"fn_name":null},{"line":188,"address":[7828375],"length":1,"stats":{"Line":0},"fn_name":null},{"line":189,"address":[7828574],"length":1,"stats":{"Line":0},"fn_name":null},{"line":190,"address":[7828816],"length":1,"stats":{"Line":0},"fn_name":null},{"line":194,"address":[7829056,7829663],"length":1,"stats":{"Line":0},"fn_name":"handle"},{"line":195,"address":[7829073,7829528,7829147],"length":1,"stats":{"Line":0},"fn_name":null},{"line":196,"address":[7829214,7829580],"length":1,"stats":{"Line":0},"fn_name":null},{"line":197,"address":[7829344],"length":1,"stats":{"Line":0},"fn_name":null}],"covered":31,"coverable":66},{"path":["/","home","runner","work","gotham_restful","gotham_restful","src","openapi","mod.rs"],"content":"const SECURITY_NAME: &str = \"authToken\";\n\npub(crate) mod builder;\npub(crate) mod handler;\npub(crate) mod operation;\npub(crate) mod router;\n","traces":[],"covered":0,"coverable":0},{"path":["/","home","runner","work","gotham_restful","gotham_restful","src","openapi","operation.rs"],"content":"use super::SECURITY_NAME;\nuse crate::{response::OrAllTypes, EndpointWithSchema, IntoResponse, RequestBody};\nuse gotham::{hyper::StatusCode, mime::Mime};\nuse openapi_type::{\n\tindexmap::IndexMap,\n\topenapiv3::{\n\t\tMediaType, Operation, Parameter, ParameterData, ParameterSchemaOrContent, ReferenceOr,\n\t\tReferenceOr::Item, RequestBody as OARequestBody, Response, Responses, Schema, SchemaKind,\n\t\tStatusCode as OAStatusCode, Type\n\t},\n\tOpenapiSchema\n};\nuse std::collections::HashMap;\n\nfn new_parameter_data(\n\tname: String,\n\trequired: bool,\n\tschema: ReferenceOr>\n) -> ParameterData {\n\tParameterData {\n\t\tname,\n\t\tdescription: None,\n\t\trequired,\n\t\tdeprecated: None,\n\t\tformat: ParameterSchemaOrContent::Schema(schema.unbox()),\n\t\texample: None,\n\t\texamples: Default::default(),\n\t\texplode: None,\n\t\textensions: Default::default()\n\t}\n}\n\n#[derive(Default)]\nstruct OperationParams {\n\tpath_params: Option,\n\tquery_params: Option\n}\n\nimpl OperationParams {\n\t// TODO shouldn't this be a custom openapi_type::Visitor\n\t// rather than this hacky code?\n\tfn add_path_params(\n\t\tpath_params: Option,\n\t\tparams: &mut Vec>\n\t) {\n\t\tlet path_params = match path_params {\n\t\t\tSome(pp) => pp.schema,\n\t\t\tNone => return\n\t\t};\n\t\tlet path_params = match path_params.schema_kind {\n\t\t\tSchemaKind::Type(Type::Object(ty)) => ty,\n\t\t\t_ => panic!(\"Path Parameters needs to be a plain struct\")\n\t\t};\n\t\tfor (name, schema) in path_params.properties {\n\t\t\tlet required = path_params.required.contains(&name);\n\t\t\tparams.push(Item(Parameter::Path {\n\t\t\t\tparameter_data: new_parameter_data(name, required, schema),\n\t\t\t\tstyle: Default::default()\n\t\t\t}))\n\t\t}\n\t}\n\n\t// TODO shouldn't this be a custom openapi_type::Visitor\n\t// rather than this hacky code?\n\tfn add_query_params(\n\t\tquery_params: Option,\n\t\tparams: &mut Vec>\n\t) {\n\t\tlet query_params = match query_params {\n\t\t\tSome(qp) => qp.schema,\n\t\t\tNone => return\n\t\t};\n\t\tlet query_params = match query_params.schema_kind {\n\t\t\tSchemaKind::Type(Type::Object(ty)) => ty,\n\t\t\t_ => panic!(\"Query Parameters needs to be a plain struct\")\n\t\t};\n\t\tfor (name, schema) in query_params.properties {\n\t\t\tlet required = query_params.required.contains(&name);\n\t\t\tparams.push(Item(Parameter::Query {\n\t\t\t\tparameter_data: new_parameter_data(name, required, schema),\n\t\t\t\tallow_reserved: false,\n\t\t\t\tstyle: Default::default(),\n\t\t\t\tallow_empty_value: None\n\t\t\t}))\n\t\t}\n\t}\n\n\tfn into_params(self) -> Vec> {\n\t\tlet mut params: Vec> = Vec::new();\n\t\tSelf::add_path_params(self.path_params, &mut params);\n\t\tSelf::add_query_params(self.query_params, &mut params);\n\t\tparams\n\t}\n}\n\npub(crate) struct OperationDescription {\n\toperation_id: Option,\n\tdescription: Option,\n\n\taccepted_types: Option>,\n\tresponses: HashMap>,\n\tparams: OperationParams,\n\tbody_schema: Option>,\n\tsupported_types: Option>,\n\trequires_auth: bool\n}\n\nimpl OperationDescription {\n\t/// Create a new operation description for the given endpoint type and schema. If the endpoint\n\t/// does not specify an operation id, the path is used to generate one.\n\tpub(crate) fn new(\n\t\tresponses: HashMap>,\n\t\tpath: &str\n\t) -> Self {\n\t\tlet operation_id = E::operation_id().or_else(|| {\n\t\t\tE::operation_verb()\n\t\t\t\t.map(|verb| format!(\"{verb}_{}\", path.replace(\"/\", \"_\").trim_start_matches('_')))\n\t\t});\n\t\tSelf {\n\t\t\toperation_id,\n\t\t\tdescription: E::description(),\n\n\t\t\taccepted_types: E::Output::accepted_types(),\n\t\t\tresponses,\n\t\t\tparams: Default::default(),\n\t\t\tbody_schema: None,\n\t\t\tsupported_types: None,\n\t\t\trequires_auth: E::wants_auth()\n\t\t}\n\t}\n\n\tpub(crate) fn set_path_params(&mut self, params: OpenapiSchema) {\n\t\tself.params.path_params = Some(params);\n\t}\n\n\tpub(crate) fn set_query_params(&mut self, params: OpenapiSchema) {\n\t\tself.params.query_params = Some(params);\n\t}\n\n\tpub(crate) fn set_body(&mut self, schema: ReferenceOr) {\n\t\tself.body_schema = Some(schema);\n\t\tself.supported_types = Body::supported_types();\n\t}\n\n\tfn schema_to_content(\n\t\ttypes: Vec,\n\t\tschema: ReferenceOr\n\t) -> IndexMap {\n\t\tlet mut content: IndexMap = IndexMap::new();\n\t\tfor ty in types {\n\t\t\tcontent.insert(ty.to_string(), MediaType {\n\t\t\t\tschema: Some(schema.clone()),\n\t\t\t\t..Default::default()\n\t\t\t});\n\t\t}\n\t\tcontent\n\t}\n\n\tpub(crate) fn into_operation(self) -> Operation {\n\t\t// this is unfortunately neccessary to prevent rust from complaining about partially moving self\n\t\tlet (\n\t\t\toperation_id,\n\t\t\tdescription,\n\t\t\taccepted_types,\n\t\t\tresponses,\n\t\t\tparams,\n\t\t\tbody_schema,\n\t\t\tsupported_types,\n\t\t\trequires_auth\n\t\t) = (\n\t\t\tself.operation_id,\n\t\t\tself.description,\n\t\t\tself.accepted_types,\n\t\t\tself.responses,\n\t\t\tself.params,\n\t\t\tself.body_schema,\n\t\t\tself.supported_types,\n\t\t\tself.requires_auth\n\t\t);\n\n\t\tlet responses: IndexMap> = responses\n\t\t\t.into_iter()\n\t\t\t.map(|(code, schema)| {\n\t\t\t\tlet content =\n\t\t\t\t\tSelf::schema_to_content(accepted_types.clone().or_all_types(), schema);\n\t\t\t\t(\n\t\t\t\t\tOAStatusCode::Code(code.as_u16()),\n\t\t\t\t\tItem(Response {\n\t\t\t\t\t\tdescription: code\n\t\t\t\t\t\t\t.canonical_reason()\n\t\t\t\t\t\t\t.map(|d| d.to_string())\n\t\t\t\t\t\t\t.unwrap_or_default(),\n\t\t\t\t\t\tcontent,\n\t\t\t\t\t\t..Default::default()\n\t\t\t\t\t})\n\t\t\t\t)\n\t\t\t})\n\t\t\t.collect();\n\n\t\tlet request_body = body_schema.map(|schema| {\n\t\t\tItem(OARequestBody {\n\t\t\t\tcontent: Self::schema_to_content(supported_types.or_all_types(), schema),\n\t\t\t\trequired: true,\n\t\t\t\t..Default::default()\n\t\t\t})\n\t\t});\n\n\t\tlet mut security = None;\n\t\tif requires_auth {\n\t\t\tlet mut sec = IndexMap::new();\n\t\t\tsec.insert(SECURITY_NAME.to_owned(), Vec::new());\n\t\t\tsecurity = Some(vec![sec]);\n\t\t}\n\n\t\tOperation {\n\t\t\ttags: Vec::new(),\n\t\t\toperation_id,\n\t\t\tdescription,\n\t\t\tparameters: params.into_params(),\n\t\t\trequest_body,\n\t\t\tresponses: Responses {\n\t\t\t\tresponses,\n\t\t\t\t..Default::default()\n\t\t\t},\n\t\t\tdeprecated: false,\n\t\t\tsecurity,\n\t\t\t..Default::default()\n\t\t}\n\t}\n}\n\n#[cfg(test)]\nmod test {\n\tuse super::*;\n\tuse crate::{NoContent, Raw, ResponseSchema};\n\n\t#[test]\n\tfn no_content_schema_to_content() {\n\t\tlet types = NoContent::accepted_types();\n\t\tlet schema = ::schema(StatusCode::NO_CONTENT);\n\t\tlet content =\n\t\t\tOperationDescription::schema_to_content(types.or_all_types(), Item(schema.schema));\n\t\tassert!(content.is_empty());\n\t}\n\n\t#[test]\n\tfn raw_schema_to_content() {\n\t\tlet types = Raw::<&str>::accepted_types();\n\t\tlet schema = as ResponseSchema>::schema(StatusCode::OK);\n\t\tlet content =\n\t\t\tOperationDescription::schema_to_content(types.or_all_types(), Item(schema.schema));\n\t\tassert_eq!(content.len(), 1);\n\t\tlet json = serde_json::to_string(&content.values().nth(0).unwrap()).unwrap();\n\t\tassert_eq!(json, r#\"{\"schema\":{\"type\":\"string\",\"format\":\"binary\"}}\"#);\n\t}\n}\n","traces":[{"line":15,"address":[7758064,7758671,7758625],"length":1,"stats":{"Line":1},"fn_name":"new_parameter_data"},{"line":25,"address":[7758224,7758139],"length":1,"stats":{"Line":2},"fn_name":null},{"line":27,"address":[7758234],"length":1,"stats":{"Line":1},"fn_name":null},{"line":29,"address":[7758305],"length":1,"stats":{"Line":1},"fn_name":null},{"line":42,"address":[7758688,7759914,7760202],"length":1,"stats":{"Line":2},"fn_name":null},{"line":46,"address":[7758728],"length":1,"stats":{"Line":2},"fn_name":null},{"line":47,"address":[7758791],"length":1,"stats":{"Line":1},"fn_name":null},{"line":50,"address":[7758861],"length":1,"stats":{"Line":1},"fn_name":null},{"line":51,"address":[7758947],"length":1,"stats":{"Line":1},"fn_name":null},{"line":54,"address":[7759941,7759245,7759022],"length":1,"stats":{"Line":3},"fn_name":null},{"line":55,"address":[7759511,7759591],"length":1,"stats":{"Line":2},"fn_name":null},{"line":56,"address":[7759806],"length":1,"stats":{"Line":1},"fn_name":null},{"line":57,"address":[7759630],"length":1,"stats":{"Line":1},"fn_name":null},{"line":58,"address":[7759747],"length":1,"stats":{"Line":1},"fn_name":null},{"line":65,"address":[7761752,7762040,7760496],"length":1,"stats":{"Line":2},"fn_name":null},{"line":69,"address":[7760536],"length":1,"stats":{"Line":2},"fn_name":null},{"line":70,"address":[7760599],"length":1,"stats":{"Line":1},"fn_name":null},{"line":73,"address":[7760669],"length":1,"stats":{"Line":1},"fn_name":null},{"line":74,"address":[7760755],"length":1,"stats":{"Line":1},"fn_name":null},{"line":77,"address":[7761779,7760830,7761053],"length":1,"stats":{"Line":3},"fn_name":null},{"line":78,"address":[7761319,7761399],"length":1,"stats":{"Line":2},"fn_name":null},{"line":79,"address":[7761622],"length":1,"stats":{"Line":1},"fn_name":null},{"line":80,"address":[7761438],"length":1,"stats":{"Line":1},"fn_name":null},{"line":82,"address":[7761555],"length":1,"stats":{"Line":1},"fn_name":null},{"line":83,"address":[7761614],"length":1,"stats":{"Line":1},"fn_name":null},{"line":88,"address":[7762336,7762645,7762684],"length":1,"stats":{"Line":2},"fn_name":null},{"line":89,"address":[7762358],"length":1,"stats":{"Line":2},"fn_name":null},{"line":90,"address":[7762452],"length":1,"stats":{"Line":2},"fn_name":null},{"line":91,"address":[7762544],"length":1,"stats":{"Line":2},"fn_name":null},{"line":92,"address":[7762611],"length":1,"stats":{"Line":2},"fn_name":null},{"line":111,"address":[6632607,6635312,6636969,6635205,6637935,6633491,6634313,6636085,6637088,6637861,6632640,6634432,6634387,6635279,6636192,6636159,6633536,6632533,6631760,6637043,6633417],"length":1,"stats":{"Line":8},"fn_name":null},{"line":115,"address":[],"length":0,"stats":{"Line":22},"fn_name":null},{"line":116,"address":[],"length":0,"stats":{"Line":12},"fn_name":null},{"line":117,"address":[],"length":0,"stats":{"Line":22},"fn_name":null},{"line":121,"address":[],"length":0,"stats":{"Line":8},"fn_name":null},{"line":123,"address":[],"length":0,"stats":{"Line":8},"fn_name":null},{"line":125,"address":[],"length":0,"stats":{"Line":8},"fn_name":null},{"line":128,"address":[],"length":0,"stats":{"Line":8},"fn_name":null},{"line":132,"address":[7762736,7762815],"length":1,"stats":{"Line":1},"fn_name":null},{"line":133,"address":[7762857,7762773],"length":1,"stats":{"Line":2},"fn_name":null},{"line":136,"address":[7762880,7762973],"length":1,"stats":{"Line":1},"fn_name":null},{"line":137,"address":[7762917,7763015],"length":1,"stats":{"Line":2},"fn_name":null},{"line":140,"address":[],"length":0,"stats":{"Line":2},"fn_name":null},{"line":141,"address":[],"length":0,"stats":{"Line":2},"fn_name":null},{"line":142,"address":[],"length":0,"stats":{"Line":2},"fn_name":null},{"line":145,"address":[7764333,7763056,7764106],"length":1,"stats":{"Line":3},"fn_name":null},{"line":149,"address":[7763098],"length":1,"stats":{"Line":3},"fn_name":null},{"line":150,"address":[7763269,7763176],"length":1,"stats":{"Line":6},"fn_name":null},{"line":151,"address":[7763796,7763542],"length":1,"stats":{"Line":6},"fn_name":null},{"line":152,"address":[7763618,7763706],"length":1,"stats":{"Line":6},"fn_name":null},{"line":153,"address":[7763716],"length":1,"stats":{"Line":3},"fn_name":null},{"line":156,"address":[7764231],"length":1,"stats":{"Line":3},"fn_name":null},{"line":159,"address":[7766026,7767366,7764368],"length":1,"stats":{"Line":2},"fn_name":null},{"line":161,"address":[7764789,7764435],"length":1,"stats":{"Line":4},"fn_name":null},{"line":162,"address":[7765036],"length":1,"stats":{"Line":2},"fn_name":null},{"line":163,"address":[7765076],"length":1,"stats":{"Line":2},"fn_name":null},{"line":164,"address":[7765116],"length":1,"stats":{"Line":2},"fn_name":null},{"line":165,"address":[7765148],"length":1,"stats":{"Line":2},"fn_name":null},{"line":166,"address":[7765204],"length":1,"stats":{"Line":2},"fn_name":null},{"line":167,"address":[7765237],"length":1,"stats":{"Line":2},"fn_name":null},{"line":168,"address":[7765255],"length":1,"stats":{"Line":2},"fn_name":null},{"line":169,"address":[7765295],"length":1,"stats":{"Line":2},"fn_name":null},{"line":171,"address":[7764515],"length":1,"stats":{"Line":2},"fn_name":null},{"line":172,"address":[7764545],"length":1,"stats":{"Line":2},"fn_name":null},{"line":173,"address":[7764575],"length":1,"stats":{"Line":2},"fn_name":null},{"line":174,"address":[7764605],"length":1,"stats":{"Line":2},"fn_name":null},{"line":175,"address":[7764685],"length":1,"stats":{"Line":2},"fn_name":null},{"line":176,"address":[7764697],"length":1,"stats":{"Line":2},"fn_name":null},{"line":177,"address":[7764749],"length":1,"stats":{"Line":2},"fn_name":null},{"line":178,"address":[7764779],"length":1,"stats":{"Line":2},"fn_name":null},{"line":181,"address":[7765453,7765313],"length":1,"stats":{"Line":4},"fn_name":null},{"line":183,"address":[7768768,7769961,7765445,7768811,7769822],"length":1,"stats":{"Line":6},"fn_name":"{closure#0}"},{"line":185,"address":[7768871,7768934],"length":1,"stats":{"Line":4},"fn_name":null},{"line":187,"address":[7769042,7769100],"length":1,"stats":{"Line":4},"fn_name":null},{"line":188,"address":[7769347],"length":1,"stats":{"Line":2},"fn_name":null},{"line":189,"address":[7769118],"length":1,"stats":{"Line":2},"fn_name":null},{"line":191,"address":[7770000,7770022],"length":1,"stats":{"Line":4},"fn_name":"{closure#0}"},{"line":193,"address":[7769200],"length":1,"stats":{"Line":2},"fn_name":null},{"line":194,"address":[7769296],"length":1,"stats":{"Line":2},"fn_name":null},{"line":200,"address":[7770048,7765523,7770524,7770548],"length":1,"stats":{"Line":3},"fn_name":"{closure#1}"},{"line":201,"address":[7770307,7770070],"length":1,"stats":{"Line":2},"fn_name":null},{"line":202,"address":[7770182,7770086],"length":1,"stats":{"Line":2},"fn_name":null},{"line":204,"address":[7770251],"length":1,"stats":{"Line":1},"fn_name":null},{"line":208,"address":[7765691],"length":1,"stats":{"Line":2},"fn_name":null},{"line":209,"address":[7766415,7765703],"length":1,"stats":{"Line":3},"fn_name":null},{"line":210,"address":[7765729],"length":1,"stats":{"Line":1},"fn_name":null},{"line":211,"address":[7765792,7765865],"length":1,"stats":{"Line":2},"fn_name":null},{"line":212,"address":[7766047],"length":1,"stats":{"Line":1},"fn_name":null},{"line":216,"address":[7765707],"length":1,"stats":{"Line":2},"fn_name":null},{"line":219,"address":[7766522],"length":1,"stats":{"Line":2},"fn_name":null},{"line":221,"address":[7766842],"length":1,"stats":{"Line":2},"fn_name":null}],"covered":91,"coverable":91},{"path":["/","home","runner","work","gotham_restful","gotham_restful","src","openapi","router.rs"],"content":"use super::{\n\tbuilder::OpenapiBuilder,\n\thandler::{OpenapiDocHandler, OpenapiSpecHandler},\n\toperation::OperationDescription\n};\nuse crate::{routing::*, EndpointWithSchema, ResourceWithSchema, ResponseSchema};\nuse gotham::{\n\thyper::{Method, StatusCode},\n\tpipeline::PipelineHandleChain,\n\tprelude::*,\n\trouter::builder::{RouterBuilder, ScopeBuilder}\n};\nuse lazy_regex::regex_replace_all;\nuse openapi_type::OpenapiType;\nuse std::{collections::HashMap, panic::RefUnwindSafe};\n\n/// This trait adds the `openapi_spec` and `openapi_doc` method to an OpenAPI-aware router.\npub trait GetOpenapi {\n\t/// Register a GET route to `path` that returns the OpenAPI specification in JSON format.\n\tfn openapi_spec(&mut self, path: &str);\n\n\t/// Register a GET route to `path` that returns the OpenAPI documentation in HTML format.\n\tfn openapi_doc(&mut self, path: &str);\n}\n\n#[derive(Debug)]\npub struct OpenapiRouter<'a, D> {\n\tpub(crate) router: &'a mut D,\n\tpub(crate) scope: Option<&'a str>,\n\tpub(crate) openapi_builder: &'a mut OpenapiBuilder\n}\n\nmacro_rules! implOpenapiRouter {\n\t($implType:ident) => {\n\t\timpl<'a, 'b, C, P> OpenapiRouter<'a, $implType<'b, C, P>>\n\t\twhere\n\t\t\tC: PipelineHandleChain

+ Copy + Send + Sync + 'static,\n\t\t\tP: RefUnwindSafe + Send + Sync + 'static\n\t\t{\n\t\t\tpub fn scope(&mut self, path: &str, callback: F)\n\t\t\twhere\n\t\t\t\tF: FnOnce(&mut OpenapiRouter<'_, ScopeBuilder<'_, C, P>>)\n\t\t\t{\n\t\t\t\tlet mut openapi_builder = self.openapi_builder.clone();\n\t\t\t\tlet new_scope = self\n\t\t\t\t\t.scope\n\t\t\t\t\t.map(|scope| format!(\"{scope}/{path}\").replace(\"//\", \"/\"));\n\t\t\t\tself.router.scope(path, |router| {\n\t\t\t\t\tlet mut router = OpenapiRouter {\n\t\t\t\t\t\trouter,\n\t\t\t\t\t\tscope: Some(new_scope.as_ref().map(String::as_ref).unwrap_or(path)),\n\t\t\t\t\t\topenapi_builder: &mut openapi_builder\n\t\t\t\t\t};\n\t\t\t\t\tcallback(&mut router);\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\timpl<'a, 'b, C, P> GetOpenapi for OpenapiRouter<'a, $implType<'b, C, P>>\n\t\twhere\n\t\t\tC: PipelineHandleChain

+ Copy + Send + Sync + 'static,\n\t\t\tP: RefUnwindSafe + Send + Sync + 'static\n\t\t{\n\t\t\tfn openapi_spec(&mut self, path: &str) {\n\t\t\t\tself.router\n\t\t\t\t\t.get(path)\n\t\t\t\t\t.to_new_handler(OpenapiSpecHandler::new(\n\t\t\t\t\t\tself.openapi_builder.openapi.clone()\n\t\t\t\t\t));\n\t\t\t}\n\n\t\t\tfn openapi_doc(&mut self, path: &str) {\n\t\t\t\tself.router\n\t\t\t\t\t.get(path)\n\t\t\t\t\t.to_new_handler(OpenapiDocHandler::new(self.openapi_builder.openapi.clone()));\n\t\t\t}\n\t\t}\n\n\t\timpl<'a, 'b, C, P> DrawResourcesWithSchema for OpenapiRouter<'a, $implType<'b, C, P>>\n\t\twhere\n\t\t\tC: PipelineHandleChain

+ Copy + Send + Sync + 'static,\n\t\t\tP: RefUnwindSafe + Send + Sync + 'static\n\t\t{\n\t\t\tfn resource(&mut self, mut path: &str) {\n\t\t\t\tif path.starts_with('/') {\n\t\t\t\t\tpath = &path[1..];\n\t\t\t\t}\n\t\t\t\tR::setup((self, path));\n\t\t\t}\n\t\t}\n\n\t\timpl<'a, 'b, C, P> DrawResourceRoutesWithSchema\n\t\t\tfor (&mut OpenapiRouter<'a, $implType<'b, C, P>>, &str)\n\t\twhere\n\t\t\tC: PipelineHandleChain

+ Copy + Send + Sync + 'static,\n\t\t\tP: RefUnwindSafe + Send + Sync + 'static\n\t\t{\n\t\t\tfn endpoint(&mut self) {\n\t\t\t\tlet mut responses: HashMap = HashMap::new();\n\t\t\t\tfor code in E::Output::status_codes() {\n\t\t\t\t\tresponses.insert(\n\t\t\t\t\t\tcode,\n\t\t\t\t\t\t(self.0).openapi_builder.add_schema(E::Output::schema(code))\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tlet mut path = format!(\"{}/{}\", self.0.scope.unwrap_or_default(), self.1);\n\t\t\t\tlet mut descr = OperationDescription::new::(responses, &path);\n\t\t\t\tif E::has_placeholders() {\n\t\t\t\t\tdescr.set_path_params(E::Placeholders::schema());\n\t\t\t\t}\n\t\t\t\tif E::needs_params() {\n\t\t\t\t\tdescr.set_query_params(E::Params::schema());\n\t\t\t\t}\n\t\t\t\tif E::needs_body() {\n\t\t\t\t\tlet body_schema = (self.0).openapi_builder.add_schema(E::Body::schema());\n\t\t\t\t\tdescr.set_body::(body_schema);\n\t\t\t\t}\n\n\t\t\t\tlet uri: &str = &E::uri();\n\t\t\t\tlet uri =\n\t\t\t\t\tregex_replace_all!(r#\"(^|/):([^/]+)(/|$)\"#, uri, |_, prefix, name, suffix| {\n\t\t\t\t\t\tformat!(\"{prefix}{{{name}}}{suffix}\")\n\t\t\t\t\t});\n\t\t\t\tif !uri.is_empty() {\n\t\t\t\t\tpath = format!(\"{path}/{uri}\");\n\t\t\t\t}\n\n\t\t\t\tlet op = descr.into_operation();\n\t\t\t\tlet mut item = (self.0).openapi_builder.remove_path(&path);\n\t\t\t\tmatch E::http_method() {\n\t\t\t\t\tMethod::GET => item.get = Some(op),\n\t\t\t\t\tMethod::PUT => item.put = Some(op),\n\t\t\t\t\tMethod::POST => item.post = Some(op),\n\t\t\t\t\tMethod::DELETE => item.delete = Some(op),\n\t\t\t\t\tMethod::OPTIONS => item.options = Some(op),\n\t\t\t\t\tMethod::HEAD => item.head = Some(op),\n\t\t\t\t\tMethod::PATCH => item.patch = Some(op),\n\t\t\t\t\tMethod::TRACE => item.trace = Some(op),\n\t\t\t\t\tmethod => {\n\t\t\t\t\t\twarn!(\"Ignoring unsupported method '{method}' in OpenAPI Specification\")\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t\t(self.0).openapi_builder.add_path(path, item);\n\n\t\t\t\t(&mut *(self.0).router, self.1).endpoint::()\n\t\t\t}\n\t\t}\n\t};\n}\n\nimplOpenapiRouter!(RouterBuilder);\nimplOpenapiRouter!(ScopeBuilder);\n","traces":[{"line":40,"address":[6854480,6854813,6854778,6855552,6855850,6855885],"length":1,"stats":{"Line":2},"fn_name":null},{"line":44,"address":[6855653,6854507,6855579,6854581],"length":1,"stats":{"Line":4},"fn_name":null},{"line":45,"address":[6855658,6854586,6854604,6855676],"length":1,"stats":{"Line":4},"fn_name":null},{"line":47,"address":[6854977,6854832,6856192,6854599,6856284,6854924,6856337,6855671],"length":1,"stats":{"Line":5},"fn_name":"{closure#0}<(), (), openapi_supports_scope::openapi_supports_scope::{closure#0}::{closure#0}::{closure#0}::{closure_env#0}>"},{"line":48,"address":[6854664,6856161,6855521,6855904,6855264,6855736],"length":1,"stats":{"Line":4},"fn_name":"{closure#1}<(), (), openapi_supports_scope::openapi_supports_scope::{closure#0}::{closure#0}::{closure#0}::{closure_env#0}>"},{"line":49,"address":[6856096,6855289,6855456,6855929],"length":1,"stats":{"Line":4},"fn_name":null},{"line":51,"address":[6856001,6855299,6855939,6855361],"length":1,"stats":{"Line":4},"fn_name":null},{"line":52,"address":[6855452,6856092],"length":1,"stats":{"Line":2},"fn_name":null},{"line":54,"address":[6856126,6855486],"length":1,"stats":{"Line":2},"fn_name":null},{"line":64,"address":[6405644,6405668,6405488],"length":1,"stats":{"Line":2},"fn_name":"openapi_spec<(borrow_bag::handle::Handle, ())>, borrow_bag::handle::Take>, ()), (gotham::pipeline::Pipeline<(gotham_restful::auth::AuthMiddleware, ())>, ())>"},{"line":65,"address":[6405518,6405617],"length":1,"stats":{"Line":4},"fn_name":null},{"line":67,"address":[6405596],"length":1,"stats":{"Line":2},"fn_name":null},{"line":68,"address":[6405546],"length":1,"stats":{"Line":2},"fn_name":null},{"line":84,"address":[6406112,6405824,6405968,6405680],"length":1,"stats":{"Line":6},"fn_name":"resource<(borrow_bag::handle::Handle, ())>, borrow_bag::handle::Take>, ()), (gotham::pipeline::Pipeline<(gotham_restful::auth::AuthMiddleware, ())>, ()), openapi_specification::CustomResource>"},{"line":85,"address":[6406253,6405848,6405821,6406136,6406109,6405992,6405704,6405965],"length":1,"stats":{"Line":7},"fn_name":null},{"line":86,"address":[6405774,6406062,6406206,6405918],"length":1,"stats":{"Line":1},"fn_name":null},{"line":88,"address":[6405734,6405878,6406022,6406166],"length":1,"stats":{"Line":6},"fn_name":null},{"line":98,"address":[6413216,6431312,6438176,6443745,6443792,6412549,6406984,6425704,6437509,6444416,6418832,6406352,6431936,6418785,6425072,6412592,6425033,6431277,6419464,6437552,6449985],"length":1,"stats":{"Line":9},"fn_name":"endpoint<(borrow_bag::handle::Handle, ())>, borrow_bag::handle::Take>, ()), (gotham::pipeline::Pipeline<(gotham_restful::auth::AuthMiddleware, ())>, ()), openapi_specification::set_image___gotham_restful_endpoint>"},{"line":99,"address":[6425125,6406405,6437605,6443845,6418885,6412645,6431365],"length":1,"stats":{"Line":9},"fn_name":null},{"line":100,"address":[6406622,6412858,6425342,6431514,6406546,6419102,6431578,6437754,6437818,6443994,6444058,6412794,6425266,6419026],"length":1,"stats":{"Line":18},"fn_name":null},{"line":101,"address":[6425648,6438120,6444360,6406928,6413160,6419408,6431880],"length":1,"stats":{"Line":9},"fn_name":null},{"line":103,"address":[6413084,6444284,6431804,6438044,6406848,6425568,6419328],"length":1,"stats":{"Line":9},"fn_name":null},{"line":106,"address":[6438380,6444620,6444727,6432140,6425723,6419483,6425908,6413235,6407003,6438195,6419775,6431955,6407295,6419668,6413527,6444435,6432247,6438487,6407188,6426015,6413420],"length":1,"stats":{"Line":27},"fn_name":null},{"line":107,"address":[6420134,6438621,6426149,6444861,6413661,6432606,6419909,6438846,6445086,6407429,6407654,6426374,6432381,6413886],"length":1,"stats":{"Line":9},"fn_name":null},{"line":108,"address":[6432670,6407621,6407718,6438813,6420198,6426438,6413950,6432573,6420101,6438910,6445053,6445150,6413853,6426341],"length":1,"stats":{"Line":18},"fn_name":null},{"line":109,"address":[6413978,6426458,6420226,6407746,6432690,6438938,6445170],"length":1,"stats":{"Line":4},"fn_name":null},{"line":111,"address":[6432745,6438981,6407789,6407724,6420269,6438916,6445156,6445225,6426444,6414021,6420204,6426513,6413956,6432676],"length":1,"stats":{"Line":18},"fn_name":null},{"line":112,"address":[6426533,6432765,6420289,6445253,6407809,6414041,6439001],"length":1,"stats":{"Line":1},"fn_name":null},{"line":114,"address":[6414096,6432751,6407795,6420275,6432820,6438987,6439056,6445231,6407864,6445296,6426519,6420344,6414027,6426588],"length":1,"stats":{"Line":18},"fn_name":null},{"line":115,"address":[6407896,6414128,6426620,6432852,6445328,6439088,6420376],"length":1,"stats":{"Line":2},"fn_name":null},{"line":116,"address":[6426725,6432957,6407997,6439193,6445433,6414233,6420481],"length":1,"stats":{"Line":2},"fn_name":null},{"line":119,"address":[6420606,6414263,6408122,6420511,6426850,6426755,6432834,6433082,6445310,6414358,6407878,6426602,6420358,6439070,6439318,6408027,6445463,6445558,6439223,6432987,6414110],"length":1,"stats":{"Line":27},"fn_name":null},{"line":121,"address":[8691885,8691785,8691723,8691465,8691760,8692043,8691565,8691440],"length":1,"stats":{"Line":62},"fn_name":"{closure#0}"},{"line":122,"address":[6453747,6455155,6454195,6454707,6455651,6456179,6456595],"length":1,"stats":{"Line":4},"fn_name":null},{"line":124,"address":[6427658,6433281,6439517,6414557,6408930,6420805,6426954,6433186,6427049,6420710,6445757,6445662,6408321,6414462,6433890,6439422,6440126,6446366,6415166,6421414,6408226],"length":1,"stats":{"Line":23},"fn_name":null},{"line":125,"address":[6408646,6414882,6427374,6439842,6446082,6421130,6433606],"length":1,"stats":{"Line":5},"fn_name":null},{"line":128,"address":[6420832,6408943,6439544,6408348,6421427,6415179,6427076,6440139,6414584,6433903,6427671,6445784,6446379,6433308],"length":1,"stats":{"Line":18},"fn_name":null},{"line":129,"address":[6427790,6446387,6427679,6408951,6446498,6434022,6421546,6440147,6409062,6415298,6421435,6433911,6415187,6440258],"length":1,"stats":{"Line":18},"fn_name":null},{"line":130,"address":[6434169,6427937,6421645,6440357,6434121,6446597,6446645,6421693,6409209,6415445,6440405,6409161,6415397,6427889],"length":1,"stats":{"Line":18},"fn_name":null},{"line":131,"address":[6430107,6434429,6440665,6448815,6436339,6442575,6446905,6417615,6415705,6409469,6411379,6421953,6423863,6428197],"length":1,"stats":{"Line":7},"fn_name":null},{"line":132,"address":[6417387,6434665,6436111,6415941,6448587,6423635,6409705,6422189,6429879,6440901,6442347,6447141,6411151,6428433],"length":1,"stats":{"Line":1},"fn_name":null},{"line":133,"address":[6436225,6440783,6422071,6447023,6428315,6409587,6423749,6417501,6411265,6415823,6434547,6442461,6448701,6429993],"length":1,"stats":{"Line":0},"fn_name":null},{"line":134,"address":[6447259,6417273,6409823,6416059,6422307,6411037,6423521,6428551,6429765,6441019,6435997,6434783,6442233,6448473],"length":1,"stats":{"Line":0},"fn_name":null},{"line":135,"address":[6428079,6440547,6442675,6411479,6436439,6448915,6423963,6434311,6421835,6446787,6415587,6417715,6430207,6409351],"length":1,"stats":{"Line":0},"fn_name":null},{"line":136,"address":[6447377,6416177,6448359,6423407,6442119,6417159,6422425,6410923,6429651,6434901,6435883,6409941,6441137,6428669],"length":1,"stats":{"Line":0},"fn_name":null},{"line":137,"address":[6410141,6416377,6428869,6422625,6429429,6416937,6435101,6441337,6410701,6423185,6435661,6447577,6448137,6441897],"length":1,"stats":{"Line":1},"fn_name":null},{"line":138,"address":[6422525,6410041,6441237,6435001,6448245,6428769,6410809,6416277,6423293,6429537,6435769,6442005,6447477,6417045],"length":1,"stats":{"Line":0},"fn_name":null},{"line":139,"address":[6440459,6421747,6427991,6434223,6409263,6446699,6415499],"length":1,"stats":{"Line":0},"fn_name":null},{"line":140,"address":[6447953,6429245,6416586,6422834,6435252,6428031,6441546,6447786,6423001,6416528,6410292,6410517,6421787,6429020,6410350,6434263,6435477,6440499,6435310,6415539,6422776,6409303,6441488,6429078,6441713,6416753,6446739,6447728],"length":1,"stats":{"Line":0},"fn_name":null},{"line":143,"address":[6411631,6424115,6417867,6442827,6449067,6430359,6436591],"length":1,"stats":{"Line":9},"fn_name":null},{"line":145,"address":[6436805,6443041,6449281,6424329,6411845,6418081,6430573],"length":1,"stats":{"Line":9},"fn_name":null}],"covered":44,"coverable":51},{"path":["/","home","runner","work","gotham_restful","gotham_restful","src","response","auth_result.rs"],"content":"use crate::{IntoResponseError, Response};\nuse gotham::{hyper::StatusCode, mime::TEXT_PLAIN_UTF_8};\nuse gotham_restful_derive::ResourceError;\n#[cfg(feature = \"openapi\")]\nuse openapi_type::{OpenapiSchema, OpenapiType};\n\n/// This is an error type that always yields a _403 Forbidden_ response. This type\n/// is best used in combination with [`AuthSuccess`] or [`AuthResult`].\n#[derive(Clone, Debug)]\npub struct AuthError(String);\n\nimpl AuthError {\n\tpub fn new>(msg: T) -> Self {\n\t\tSelf(msg.into())\n\t}\n}\n\nimpl IntoResponseError for AuthError {\n\t// TODO why does this need to be serde_json::Error ?!?\n\ttype Err = serde_json::Error;\n\n\tfn into_response_error(self) -> Result {\n\t\tOk(Response::new(\n\t\t\tStatusCode::FORBIDDEN,\n\t\t\tself.0,\n\t\t\tSome(TEXT_PLAIN_UTF_8)\n\t\t))\n\t}\n\n\t#[cfg(feature = \"openapi\")]\n\tfn status_codes() -> Vec {\n\t\tvec![StatusCode::FORBIDDEN]\n\t}\n\n\t#[cfg(feature = \"openapi\")]\n\tfn schema(code: StatusCode) -> OpenapiSchema {\n\t\tassert_eq!(code, StatusCode::FORBIDDEN);\n\t\t as OpenapiType>::schema()\n\t}\n}\n\n/// This return type can be used to wrap any type implementing [IntoResponse](crate::IntoResponse)\n/// that can only be returned if the client is authenticated. Otherwise, an empty _403 Forbidden_\n/// response will be issued.\n///\n/// Use can look something like this (assuming the `auth` feature is enabled):\n///\n/// ```rust\n/// # #[macro_use] extern crate gotham_restful_derive;\n/// # #[cfg(feature = \"auth\")]\n/// # mod auth_feature_enabled {\n/// # use gotham::state::State;\n/// # use gotham_restful::*;\n/// # use serde::Deserialize;\n/// #\n/// # #[derive(Resource)]\n/// # #[resource(read_all)]\n/// # struct MyResource;\n/// #\n/// # #[derive(Clone, Deserialize)]\n/// # struct MyAuthData { exp : u64 }\n/// #\n/// #[read_all]\n/// fn read_all(auth: AuthStatus) -> AuthSuccess {\n/// \tlet auth_data = auth.ok()?;\n/// \t// do something\n/// \tOk(NoContent::default())\n/// }\n/// # }\n/// ```\npub type AuthSuccess = Result;\n\n/// This is an error type that either yields a _403 Forbidden_ response if produced\n/// from an authentication error, or delegates to another error type. This type is\n/// best used with [`AuthResult`].\n#[derive(Debug, Clone, ResourceError)]\npub enum AuthErrorOrOther {\n\tForbidden(#[from] AuthError),\n\n\t#[status(INTERNAL_SERVER_ERROR)]\n\t#[display(\"{0}\")]\n\tOther(E)\n}\n\nmod private {\n\tuse gotham::handler::HandlerError;\n\tpub trait Sealed {}\n\timpl> Sealed for E {}\n}\n\nimpl From for AuthErrorOrOther\nwhere\n\t// TODO https://github.com/msrd0/gotham_restful/issues/20\n\tF: private::Sealed + Into\n{\n\tfn from(err: F) -> Self {\n\t\tSelf::Other(err.into())\n\t}\n}\n\n/// This return type can be used to wrap any type implementing [IntoResponse](crate::IntoResponse)\n/// that can only be returned if the client is authenticated. Otherwise, an empty _403 Forbidden_\n/// response will be issued.\n///\n/// Use can look something like this (assuming the `auth` feature is enabled):\n///\n/// ```\n/// # #[macro_use] extern crate gotham_restful_derive;\n/// # #[cfg(feature = \"auth\")]\n/// # mod auth_feature_enabled {\n/// # use gotham::state::State;\n/// # use gotham_restful::*;\n/// # use serde::Deserialize;\n/// # use std::io;\n/// #\n/// # #[derive(Resource)]\n/// # #[resource(read_all)]\n/// # struct MyResource;\n/// #\n/// # #[derive(Clone, Deserialize)]\n/// # struct MyAuthData { exp : u64 }\n/// #\n/// #[read_all]\n/// fn read_all(auth: AuthStatus) -> AuthResult {\n/// \tlet auth_data = auth.ok()?;\n/// \t// do something\n/// \tOk(NoContent::default().into())\n/// }\n/// # }\n/// ```\npub type AuthResult = Result>;\n","traces":[{"line":13,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":14,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":22,"address":[6427760],"length":1,"stats":{"Line":0},"fn_name":"into_response_error"},{"line":23,"address":[7829799],"length":1,"stats":{"Line":0},"fn_name":null},{"line":25,"address":[6427777],"length":1,"stats":{"Line":0},"fn_name":null},{"line":26,"address":[8021604],"length":1,"stats":{"Line":0},"fn_name":null},{"line":31,"address":[7829872,7829983],"length":1,"stats":{"Line":1},"fn_name":"status_codes"},{"line":32,"address":[8021816,8021741],"length":1,"stats":{"Line":1},"fn_name":null},{"line":36,"address":[7830000],"length":1,"stats":{"Line":1},"fn_name":"schema"},{"line":38,"address":[7830096],"length":1,"stats":{"Line":1},"fn_name":null},{"line":96,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":97,"address":[],"length":0,"stats":{"Line":0},"fn_name":null}],"covered":4,"coverable":12},{"path":["/","home","runner","work","gotham_restful","gotham_restful","src","response","mod.rs"],"content":"use futures_util::future::{self, BoxFuture, FutureExt};\nuse gotham::{\n\thandler::HandlerError,\n\thyper::{\n\t\theader::{HeaderMap, HeaderName, HeaderValue},\n\t\tBody, StatusCode\n\t},\n\tmime::{Mime, APPLICATION_JSON, STAR_STAR}\n};\n#[cfg(feature = \"openapi\")]\nuse openapi_type::{OpenapiSchema, OpenapiType};\nuse serde::Serialize;\n#[cfg(feature = \"errorlog\")]\nuse std::fmt::Display;\nuse std::{convert::Infallible, fmt::Debug, future::Future, pin::Pin};\n\nmod auth_result;\n#[allow(unreachable_pub)]\npub use auth_result::{AuthError, AuthErrorOrOther, AuthResult, AuthSuccess};\n\nmod no_content;\n#[allow(unreachable_pub)]\npub use no_content::NoContent;\n\nmod raw;\n#[allow(unreachable_pub)]\npub use raw::Raw;\n\nmod redirect;\n#[allow(unreachable_pub)]\npub use redirect::Redirect;\n\nmod result;\n#[allow(unreachable_pub)]\npub use result::IntoResponseError;\n\nmod success;\n#[allow(unreachable_pub)]\npub use success::Success;\n\npub(crate) trait OrAllTypes {\n\tfn or_all_types(self) -> Vec;\n}\n\nimpl OrAllTypes for Option> {\n\tfn or_all_types(self) -> Vec {\n\t\tself.unwrap_or_else(|| vec![STAR_STAR])\n\t}\n}\n\n/// A response, used to create the final gotham response from.\n///\n/// This type is not meant to be used as the return type of endpoint handlers. While it can be\n/// freely used without the `openapi` feature, it is more complicated to use when you enable it,\n/// since this type does not store any schema information. You can attach schema information\n/// like so:\n///\n/// ```rust\n/// # #[cfg(feature = \"openapi\")] mod example {\n/// # use gotham::hyper::StatusCode;\n/// # use gotham_restful::*;\n/// # use openapi_type::*;\n/// fn schema(code: StatusCode) -> OpenapiSchema {\n/// \tassert_eq!(code, StatusCode::ACCEPTED);\n/// \t<()>::schema()\n/// }\n///\n/// fn status_codes() -> Vec {\n/// \tvec![StatusCode::ACCEPTED]\n/// }\n///\n/// #[create(schema = \"schema\", status_codes = \"status_codes\")]\n/// fn create(body: Raw>) {}\n/// # }\n/// ```\n#[derive(Debug)]\npub struct Response {\n\tpub(crate) status: StatusCode,\n\tpub(crate) body: Body,\n\tpub(crate) mime: Option,\n\tpub(crate) headers: HeaderMap\n}\n\nimpl Response {\n\t/// Create a new [Response] from raw data.\n\t#[must_use = \"Creating a response is pointless if you don't use it\"]\n\tpub fn new>(status: StatusCode, body: B, mime: Option) -> Self {\n\t\tSelf {\n\t\t\tstatus,\n\t\t\tbody: body.into(),\n\t\t\tmime,\n\t\t\theaders: Default::default()\n\t\t}\n\t}\n\n\t/// Create a [Response] with mime type json from already serialized data.\n\t#[must_use = \"Creating a response is pointless if you don't use it\"]\n\tpub fn json>(status: StatusCode, body: B) -> Self {\n\t\tSelf {\n\t\t\tstatus,\n\t\t\tbody: body.into(),\n\t\t\tmime: Some(APPLICATION_JSON),\n\t\t\theaders: Default::default()\n\t\t}\n\t}\n\n\t/// Create a _204 No Content_ [Response].\n\t#[must_use = \"Creating a response is pointless if you don't use it\"]\n\tpub fn no_content() -> Self {\n\t\tSelf {\n\t\t\tstatus: StatusCode::NO_CONTENT,\n\t\t\tbody: Body::empty(),\n\t\t\tmime: None,\n\t\t\theaders: Default::default()\n\t\t}\n\t}\n\n\t/// Create an empty _403 Forbidden_ [Response].\n\t#[must_use = \"Creating a response is pointless if you don't use it\"]\n\tpub fn forbidden() -> Self {\n\t\tSelf {\n\t\t\tstatus: StatusCode::FORBIDDEN,\n\t\t\tbody: Body::empty(),\n\t\t\tmime: None,\n\t\t\theaders: Default::default()\n\t\t}\n\t}\n\n\t/// Return the status code of this [Response].\n\tpub fn status(&self) -> StatusCode {\n\t\tself.status\n\t}\n\n\t/// Return the mime type of this [Response].\n\tpub fn mime(&self) -> Option<&Mime> {\n\t\tself.mime.as_ref()\n\t}\n\n\t/// Add an HTTP header to the [Response].\n\tpub fn header(&mut self, name: HeaderName, value: HeaderValue) {\n\t\tself.headers.insert(name, value);\n\t}\n\n\tpub(crate) fn with_headers(mut self, headers: HeaderMap) -> Self {\n\t\tself.headers = headers;\n\t\tself\n\t}\n\n\t#[cfg(test)]\n\tpub(crate) fn full_body(\n\t\tmut self\n\t) -> Result, ::Error> {\n\t\tuse futures_executor::block_on;\n\t\tuse gotham::hyper::body::to_bytes;\n\n\t\tlet bytes: &[u8] = &block_on(to_bytes(&mut self.body))?;\n\t\tOk(bytes.to_vec())\n\t}\n}\n\nimpl IntoResponse for Response {\n\ttype Err = Infallible;\n\n\tfn into_response(self) -> BoxFuture<'static, Result> {\n\t\tfuture::ok(self).boxed()\n\t}\n}\n\n/// This trait needs to be implemented by every type returned from an endpoint to\n/// to provide the response.\npub trait IntoResponse {\n\ttype Err: Into + Send + Sync + 'static;\n\n\t/// Turn this into a response that can be returned to the browser. This api will likely\n\t/// change in the future.\n\tfn into_response(self) -> BoxFuture<'static, Result>;\n\n\t/// Return a list of supported mime types.\n\tfn accepted_types() -> Option> {\n\t\tNone\n\t}\n}\n\n/// Additional details for [IntoResponse] to be used with an OpenAPI-aware router.\n#[cfg(feature = \"openapi\")]\npub trait ResponseSchema {\n\t/// All status codes returned by this response. Returns `[StatusCode::OK]` by default.\n\tfn status_codes() -> Vec {\n\t\tvec![StatusCode::OK]\n\t}\n\n\t/// Return the schema of the response for the given status code. The code may\n\t/// only be one that was previously returned by [Self::status_codes]. The\n\t/// implementation should panic if that is not the case.\n\tfn schema(code: StatusCode) -> OpenapiSchema;\n}\n\n#[cfg(feature = \"openapi\")]\nmod private {\n\tpub trait Sealed {}\n}\n\n/// A trait provided to convert a resource's result to json, and provide an OpenAPI schema to the\n/// router. This trait is implemented for all types that implement [IntoResponse] and\n/// [ResponseSchema].\n#[cfg(feature = \"openapi\")]\npub trait IntoResponseWithSchema: IntoResponse + ResponseSchema + private::Sealed {}\n\n#[cfg(feature = \"openapi\")]\nimpl private::Sealed for R {}\n\n#[cfg(feature = \"openapi\")]\nimpl IntoResponseWithSchema for R {}\n\n/// The default json returned on an 500 Internal Server Error.\n#[derive(Debug, Serialize)]\n#[cfg_attr(feature = \"openapi\", derive(OpenapiType))]\npub(crate) struct ResourceError {\n\t/// This is always `true` and can be used to detect an error response without looking at the\n\t/// HTTP status code.\n\terror: bool,\n\t/// The error message.\n\tmessage: String\n}\n\nimpl From for ResourceError {\n\tfn from(message: T) -> Self {\n\t\tSelf {\n\t\t\terror: true,\n\t\t\tmessage: message.to_string()\n\t\t}\n\t}\n}\n\n#[cfg(feature = \"errorlog\")]\nfn errorlog(e: E) {\n\terror!(\"The handler encountered an error: {e}\");\n}\n\n#[cfg(not(feature = \"errorlog\"))]\nfn errorlog(_e: E) {}\n\nfn handle_error(e: E) -> Pin> + Send>>\nwhere\n\tE: Debug + IntoResponseError\n{\n\tlet msg = format!(\"{e:?}\");\n\tlet res = e.into_response_error();\n\tmatch &res {\n\t\tOk(res) if res.status.is_server_error() => errorlog(msg),\n\t\tErr(err) => {\n\t\t\terrorlog(msg);\n\t\t\terrorlog(format!(\"{err:?}\"));\n\t\t},\n\t\t_ => {}\n\t};\n\tfuture::ready(res).boxed()\n}\n\nimpl IntoResponse for Pin + Send>>\nwhere\n\tRes: IntoResponse + 'static\n{\n\ttype Err = Res::Err;\n\n\tfn into_response(self) -> Pin> + Send>> {\n\t\tself.then(IntoResponse::into_response).boxed()\n\t}\n\n\tfn accepted_types() -> Option> {\n\t\tRes::accepted_types()\n\t}\n}\n\n#[cfg(feature = \"openapi\")]\nimpl ResponseSchema for Pin + Send>>\nwhere\n\tRes: ResponseSchema\n{\n\tfn status_codes() -> Vec {\n\t\tRes::status_codes()\n\t}\n\n\tfn schema(code: StatusCode) -> OpenapiSchema {\n\t\tRes::schema(code)\n\t}\n}\n\n#[cfg(test)]\nmod test {\n\tuse super::*;\n\tuse futures_executor::block_on;\n\tuse thiserror::Error;\n\n\t#[derive(Debug, Default, Deserialize, Serialize)]\n\t#[cfg_attr(feature = \"openapi\", derive(openapi_type::OpenapiType))]\n\tstruct Msg {\n\t\tmsg: String\n\t}\n\n\t#[derive(Debug, Default, Error)]\n\t#[error(\"An Error\")]\n\tstruct MsgError;\n\n\t#[test]\n\tfn result_from_future() {\n\t\tlet nc = NoContent::default();\n\t\tlet res = block_on(nc.into_response()).unwrap();\n\n\t\tlet fut_nc = async move { NoContent::default() }.boxed();\n\t\tlet fut_res = block_on(fut_nc.into_response()).unwrap();\n\n\t\tassert_eq!(res.status, fut_res.status);\n\t\tassert_eq!(res.mime, fut_res.mime);\n\t\tassert_eq!(res.full_body().unwrap(), fut_res.full_body().unwrap());\n\t}\n}\n","traces":[{"line":46,"address":[7804528],"length":1,"stats":{"Line":3},"fn_name":"or_all_types"},{"line":47,"address":[7804536],"length":1,"stats":{"Line":9},"fn_name":null},{"line":87,"address":[6304227,6303840,6304197],"length":1,"stats":{"Line":8},"fn_name":null},{"line":90,"address":[6303903],"length":1,"stats":{"Line":9},"fn_name":null},{"line":92,"address":[6304038],"length":1,"stats":{"Line":9},"fn_name":null},{"line":98,"address":[],"length":0,"stats":{"Line":2},"fn_name":null},{"line":101,"address":[],"length":0,"stats":{"Line":2},"fn_name":null},{"line":102,"address":[],"length":0,"stats":{"Line":2},"fn_name":null},{"line":103,"address":[],"length":0,"stats":{"Line":2},"fn_name":null},{"line":109,"address":[7615328,7615547,7615520],"length":1,"stats":{"Line":2},"fn_name":null},{"line":112,"address":[7615350],"length":1,"stats":{"Line":2},"fn_name":null},{"line":114,"address":[7615364],"length":1,"stats":{"Line":2},"fn_name":null},{"line":120,"address":[7615787,7615760,7615568],"length":1,"stats":{"Line":0},"fn_name":null},{"line":123,"address":[7615590],"length":1,"stats":{"Line":0},"fn_name":null},{"line":125,"address":[7615604],"length":1,"stats":{"Line":0},"fn_name":null},{"line":130,"address":[7615808],"length":1,"stats":{"Line":1},"fn_name":null},{"line":131,"address":[7615813],"length":1,"stats":{"Line":1},"fn_name":null},{"line":135,"address":[7615824],"length":1,"stats":{"Line":1},"fn_name":null},{"line":136,"address":[7615829],"length":1,"stats":{"Line":1},"fn_name":null},{"line":140,"address":[7615856],"length":1,"stats":{"Line":2},"fn_name":null},{"line":141,"address":[7615874],"length":1,"stats":{"Line":2},"fn_name":null},{"line":144,"address":[7616129,7615920],"length":1,"stats":{"Line":2},"fn_name":null},{"line":145,"address":[7616082,7615952],"length":1,"stats":{"Line":4},"fn_name":null},{"line":146,"address":[7616109],"length":1,"stats":{"Line":2},"fn_name":null},{"line":150,"address":[6158400,6158822,6158796],"length":1,"stats":{"Line":1},"fn_name":null},{"line":156,"address":[6158430,6158717,6158487],"length":1,"stats":{"Line":3},"fn_name":null},{"line":157,"address":[6158733],"length":1,"stats":{"Line":2},"fn_name":null},{"line":164,"address":[7616160],"length":1,"stats":{"Line":0},"fn_name":"into_response"},{"line":165,"address":[7616170],"length":1,"stats":{"Line":0},"fn_name":null},{"line":179,"address":[6827296],"length":1,"stats":{"Line":7},"fn_name":"accepted_types>>"},{"line":180,"address":[6827299],"length":1,"stats":{"Line":7},"fn_name":null},{"line":188,"address":[],"length":0,"stats":{"Line":4},"fn_name":null},{"line":189,"address":[],"length":0,"stats":{"Line":4},"fn_name":null},{"line":227,"address":[6354960,6354991],"length":1,"stats":{"Line":2},"fn_name":"from"},{"line":230,"address":[6354984],"length":1,"stats":{"Line":2},"fn_name":null},{"line":236,"address":[],"length":0,"stats":{"Line":1},"fn_name":null},{"line":237,"address":[],"length":0,"stats":{"Line":3},"fn_name":null},{"line":243,"address":[6945376,6946383,6946454],"length":1,"stats":{"Line":1},"fn_name":"handle_error"},{"line":247,"address":[],"length":0,"stats":{"Line":1},"fn_name":null},{"line":248,"address":[],"length":0,"stats":{"Line":2},"fn_name":null},{"line":249,"address":[],"length":0,"stats":{"Line":1},"fn_name":null},{"line":250,"address":[],"length":0,"stats":{"Line":2},"fn_name":null},{"line":251,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":252,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":253,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":255,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":257,"address":[],"length":0,"stats":{"Line":3},"fn_name":null},{"line":266,"address":[],"length":0,"stats":{"Line":1},"fn_name":null},{"line":267,"address":[],"length":0,"stats":{"Line":1},"fn_name":null},{"line":270,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":271,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":280,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":281,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":284,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":285,"address":[],"length":0,"stats":{"Line":0},"fn_name":null}],"covered":40,"coverable":55},{"path":["/","home","runner","work","gotham_restful","gotham_restful","src","response","no_content.rs"],"content":"use super::{handle_error, IntoResponse};\n#[cfg(feature = \"openapi\")]\nuse crate::ResponseSchema;\nuse crate::{IntoResponseError, Response};\nuse futures_util::{future, future::FutureExt};\n#[cfg(feature = \"openapi\")]\nuse gotham::hyper::StatusCode;\nuse gotham::{\n\thyper::header::{HeaderMap, HeaderValue, IntoHeaderName},\n\tmime::Mime\n};\n#[cfg(feature = \"openapi\")]\nuse openapi_type::{OpenapiSchema, OpenapiType};\nuse std::{fmt::Debug, future::Future, pin::Pin};\n\n/// This is the return type of a resource that doesn't actually return something. It will result\n/// in a _204 No Content_ answer by default. You don't need to use this type directly if using\n/// the function attributes:\n///\n/// ```\n/// # #[macro_use] extern crate gotham_restful_derive;\n/// # mod doc_tests_are_broken {\n/// # use gotham::state::State;\n/// # use gotham_restful::*;\n/// #\n/// # #[derive(Resource)]\n/// # #[resource(read_all)]\n/// # struct MyResource;\n/// #\n/// #[read_all]\n/// fn read_all() {\n/// \t// do something\n/// }\n/// # }\n/// ```\n#[derive(Clone, Debug, Default)]\npub struct NoContent {\n\theaders: HeaderMap\n}\n\nimpl From<()> for NoContent {\n\tfn from(_: ()) -> Self {\n\t\tSelf::default()\n\t}\n}\n\nimpl NoContent {\n\t/// Set a custom HTTP header. If a header with this name was set before, its value is being updated.\n\tpub fn header(&mut self, name: K, value: HeaderValue) {\n\t\tself.headers.insert(name, value);\n\t}\n\n\t/// Allow manipulating HTTP headers.\n\tpub fn headers_mut(&mut self) -> &mut HeaderMap {\n\t\t&mut self.headers\n\t}\n}\n\nimpl IntoResponse for NoContent {\n\t// TODO this shouldn't be a serde_json::Error\n\ttype Err = serde_json::Error; // just for easier handling of `Result`\n\n\t/// This will always be a _204 No Content_ together with an empty string.\n\tfn into_response(self) -> Pin> + Send>> {\n\t\tfuture::ok(Response::no_content().with_headers(self.headers)).boxed()\n\t}\n\n\tfn accepted_types() -> Option> {\n\t\tSome(Vec::new())\n\t}\n}\n\n#[cfg(feature = \"openapi\")]\nimpl ResponseSchema for NoContent {\n\tfn status_codes() -> Vec {\n\t\tvec![StatusCode::NO_CONTENT]\n\t}\n\n\t/// Returns the schema of the `()` type.\n\tfn schema(code: StatusCode) -> OpenapiSchema {\n\t\tassert_eq!(code, StatusCode::NO_CONTENT);\n\t\t<()>::schema()\n\t}\n}\n\nimpl IntoResponse for Result\nwhere\n\tE: Debug + IntoResponseError\n{\n\ttype Err = serde_json::Error;\n\n\tfn into_response(\n\t\tself\n\t) -> Pin> + Send>> {\n\t\tmatch self {\n\t\t\tOk(nc) => nc.into_response(),\n\t\t\tErr(e) => handle_error(e)\n\t\t}\n\t}\n\n\tfn accepted_types() -> Option> {\n\t\tNoContent::accepted_types()\n\t}\n}\n\n#[cfg(feature = \"openapi\")]\nimpl ResponseSchema for Result\nwhere\n\tE: Debug + IntoResponseError\n{\n\tfn status_codes() -> Vec {\n\t\tlet mut status_codes = E::status_codes();\n\t\tstatus_codes.push(StatusCode::NO_CONTENT);\n\t\tstatus_codes\n\t}\n\n\tfn schema(code: StatusCode) -> OpenapiSchema {\n\t\tmatch code {\n\t\t\tStatusCode::NO_CONTENT => ::schema(StatusCode::NO_CONTENT),\n\t\t\tcode => E::schema(code)\n\t\t}\n\t}\n}\n\n#[cfg(test)]\nmod test {\n\tuse super::*;\n\tuse futures_executor::block_on;\n\tuse gotham::hyper::{header::ACCESS_CONTROL_ALLOW_ORIGIN, StatusCode};\n\tuse thiserror::Error;\n\n\t#[derive(Debug, Default, Error)]\n\t#[error(\"An Error\")]\n\tstruct MsgError;\n\n\t#[test]\n\tfn no_content_has_empty_response() {\n\t\tlet no_content = NoContent::default();\n\t\tlet res = block_on(no_content.into_response()).expect(\"didn't expect error response\");\n\t\tassert_eq!(res.status, StatusCode::NO_CONTENT);\n\t\tassert_eq!(res.mime, None);\n\t\tassert_eq!(res.full_body().unwrap(), &[] as &[u8]);\n\n\t\t#[cfg(feature = \"openapi\")]\n\t\tassert_eq!(NoContent::status_codes(), vec![StatusCode::NO_CONTENT]);\n\t}\n\n\t#[test]\n\tfn no_content_result() {\n\t\tlet no_content: Result = Ok(NoContent::default());\n\t\tlet res = block_on(no_content.into_response()).expect(\"didn't expect error response\");\n\t\tassert_eq!(res.status, StatusCode::NO_CONTENT);\n\t\tassert_eq!(res.mime, None);\n\t\tassert_eq!(res.full_body().unwrap(), &[] as &[u8]);\n\n\t\t#[cfg(feature = \"openapi\")]\n\t\tassert_eq!(>::status_codes(), vec![\n\t\t\tStatusCode::INTERNAL_SERVER_ERROR,\n\t\t\tStatusCode::NO_CONTENT\n\t\t]);\n\t}\n\n\t#[test]\n\tfn no_content_custom_headers() {\n\t\tlet mut no_content = NoContent::default();\n\t\tno_content.header(ACCESS_CONTROL_ALLOW_ORIGIN, HeaderValue::from_static(\"*\"));\n\t\tlet res = block_on(no_content.into_response()).expect(\"didn't expect error response\");\n\t\tlet cors = res.headers.get(ACCESS_CONTROL_ALLOW_ORIGIN);\n\t\tassert_eq!(cors.map(|value| value.to_str().unwrap()), Some(\"*\"));\n\t}\n}\n","traces":[{"line":42,"address":[6326416],"length":1,"stats":{"Line":0},"fn_name":"from"},{"line":43,"address":[8453964],"length":1,"stats":{"Line":0},"fn_name":null},{"line":49,"address":[],"length":0,"stats":{"Line":1},"fn_name":null},{"line":50,"address":[],"length":0,"stats":{"Line":1},"fn_name":null},{"line":54,"address":[8453984],"length":1,"stats":{"Line":0},"fn_name":null},{"line":64,"address":[7728400,7728673,7728704],"length":1,"stats":{"Line":2},"fn_name":"into_response"},{"line":65,"address":[6326557,6326476],"length":1,"stats":{"Line":4},"fn_name":null},{"line":68,"address":[8454320],"length":1,"stats":{"Line":4},"fn_name":"accepted_types"},{"line":69,"address":[6326797],"length":1,"stats":{"Line":4},"fn_name":null},{"line":75,"address":[7728784,7728895],"length":1,"stats":{"Line":2},"fn_name":"status_codes"},{"line":76,"address":[6326861,6326936],"length":1,"stats":{"Line":2},"fn_name":null},{"line":80,"address":[6326976],"length":1,"stats":{"Line":2},"fn_name":"schema"},{"line":82,"address":[6327072],"length":1,"stats":{"Line":2},"fn_name":null},{"line":92,"address":[6153104],"length":1,"stats":{"Line":1},"fn_name":"into_response"},{"line":95,"address":[],"length":0,"stats":{"Line":2},"fn_name":null},{"line":96,"address":[],"length":0,"stats":{"Line":1},"fn_name":null},{"line":97,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":101,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":102,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":111,"address":[],"length":0,"stats":{"Line":1},"fn_name":null},{"line":112,"address":[],"length":0,"stats":{"Line":1},"fn_name":null},{"line":113,"address":[],"length":0,"stats":{"Line":1},"fn_name":null},{"line":114,"address":[],"length":0,"stats":{"Line":1},"fn_name":null},{"line":117,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":118,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":119,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":120,"address":[],"length":0,"stats":{"Line":0},"fn_name":null}],"covered":17,"coverable":27},{"path":["/","home","runner","work","gotham_restful","gotham_restful","src","response","raw.rs"],"content":"use super::{handle_error, IntoResponse, IntoResponseError};\nuse crate::{types::ResourceType, FromBody, RequestBody, Response};\n#[cfg(feature = \"openapi\")]\nuse crate::{IntoResponseWithSchema, ResponseSchema};\nuse futures_core::future::Future;\nuse futures_util::{future, future::FutureExt};\nuse gotham::{\n\thyper::{\n\t\tbody::{Body, Bytes},\n\t\tStatusCode\n\t},\n\tmime::Mime\n};\n#[cfg(feature = \"openapi\")]\nuse openapi_type::{OpenapiSchema, OpenapiType, Visitor};\nuse serde_json::error::Error as SerdeJsonError;\nuse std::{convert::Infallible, fmt::Debug, pin::Pin};\n\n/// This type can be used both as a raw request body, as well as as a raw response. However, all types\n/// of request bodies are accepted by this type. It is therefore recommended to derive your own type\n/// from [RequestBody] and only use this when you need to return a raw response. This is a usage\n/// example that simply returns its body:\n///\n/// ```rust,no_run\n/// # #[macro_use] extern crate gotham_restful_derive;\n/// # use gotham::router::builder::*;\n/// # use gotham_restful::*;\n/// #[derive(Resource)]\n/// #[resource(create)]\n/// struct ImageResource;\n///\n/// #[create]\n/// fn create(body: Raw>) -> Raw> {\n/// \tbody\n/// }\n/// # fn main() {\n/// # \tgotham::start(\"127.0.0.1:8080\", build_simple_router(|route| {\n/// # \t\troute.resource::(\"img\");\n/// # \t}));\n/// # }\n/// ```\n#[derive(Debug)]\npub struct Raw {\n\tpub raw: T,\n\tpub mime: Mime\n}\n\nimpl Raw {\n\tpub fn new(raw: T, mime: Mime) -> Self {\n\t\tSelf { raw, mime }\n\t}\n}\n\nimpl AsMut for Raw\nwhere\n\tT: AsMut\n{\n\tfn as_mut(&mut self) -> &mut U {\n\t\tself.raw.as_mut()\n\t}\n}\n\nimpl AsRef for Raw\nwhere\n\tT: AsRef\n{\n\tfn as_ref(&self) -> &U {\n\t\tself.raw.as_ref()\n\t}\n}\n\nimpl Clone for Raw {\n\tfn clone(&self) -> Self {\n\t\tSelf {\n\t\t\traw: self.raw.clone(),\n\t\t\tmime: self.mime.clone()\n\t\t}\n\t}\n}\n\nimpl From<&'a [u8]>> FromBody for Raw {\n\ttype Err = Infallible;\n\n\tfn from_body(body: Bytes, mime: Mime) -> Result {\n\t\tOk(Self::new(body.as_ref().into(), mime))\n\t}\n}\n\nimpl RequestBody for Raw where Raw: FromBody + ResourceType {}\n\n#[cfg(feature = \"openapi\")]\nimpl OpenapiType for Raw {\n\tfn visit_type(visitor: &mut V) {\n\t\tvisitor.visit_binary()\n\t}\n}\n\nimpl> IntoResponse for Raw\nwhere\n\tSelf: Send\n{\n\ttype Err = SerdeJsonError; // just for easier handling of `Result, E>`\n\n\tfn into_response(\n\t\tself\n\t) -> Pin> + Send>> {\n\t\tfuture::ok(Response::new(StatusCode::OK, self.raw, Some(self.mime))).boxed()\n\t}\n}\n\n#[cfg(feature = \"openapi\")]\nimpl> ResponseSchema for Raw\nwhere\n\tSelf: Send\n{\n\tfn schema(code: StatusCode) -> OpenapiSchema {\n\t\tassert_eq!(code, StatusCode::OK);\n\t\t::schema()\n\t}\n}\n\nimpl IntoResponse for Result, E>\nwhere\n\tRaw: IntoResponse,\n\tE: Debug + IntoResponseError as IntoResponse>::Err>\n{\n\ttype Err = E::Err;\n\n\tfn into_response(self) -> Pin> + Send>> {\n\t\tmatch self {\n\t\t\tOk(raw) => raw.into_response(),\n\t\t\tErr(e) => handle_error(e)\n\t\t}\n\t}\n}\n\n#[cfg(feature = \"openapi\")]\nimpl ResponseSchema for Result, E>\nwhere\n\tRaw: IntoResponseWithSchema,\n\tE: Debug + IntoResponseError as IntoResponse>::Err>\n{\n\tfn status_codes() -> Vec {\n\t\tlet mut status_codes = E::status_codes();\n\t\tstatus_codes.push(StatusCode::OK);\n\t\tstatus_codes\n\t}\n\n\tfn schema(code: StatusCode) -> OpenapiSchema {\n\t\tmatch code {\n\t\t\tStatusCode::OK => as ResponseSchema>::schema(StatusCode::OK),\n\t\t\tcode => E::schema(code)\n\t\t}\n\t}\n}\n\n#[cfg(test)]\nmod test {\n\tuse super::*;\n\tuse futures_executor::block_on;\n\tuse gotham::mime::TEXT_PLAIN;\n\tuse thiserror::Error;\n\n\t#[derive(Debug, Default, Error)]\n\t#[error(\"An Error\")]\n\tstruct MsgError;\n\n\t#[test]\n\tfn raw_response() {\n\t\tlet msg = \"Test\";\n\t\tlet raw = Raw::new(msg, TEXT_PLAIN);\n\t\tlet res = block_on(raw.into_response()).expect(\"didn't expect error response\");\n\t\tassert_eq!(res.status, StatusCode::OK);\n\t\tassert_eq!(res.mime, Some(TEXT_PLAIN));\n\t\tassert_eq!(res.full_body().unwrap(), msg.as_bytes());\n\n\t\t#[cfg(feature = \"openapi\")]\n\t\tassert_eq!(>::status_codes(), vec![StatusCode::OK]);\n\t}\n\n\t#[test]\n\tfn raw_result() {\n\t\tlet msg = \"Test\";\n\t\tlet raw: Result, MsgError> = Ok(Raw::new(msg, TEXT_PLAIN));\n\t\tlet res = block_on(raw.into_response()).expect(\"didn't expect error response\");\n\t\tassert_eq!(res.status, StatusCode::OK);\n\t\tassert_eq!(res.mime, Some(TEXT_PLAIN));\n\t\tassert_eq!(res.full_body().unwrap(), msg.as_bytes());\n\n\t\t#[cfg(feature = \"openapi\")]\n\t\tassert_eq!(, MsgError>>::status_codes(), vec![\n\t\t\tStatusCode::INTERNAL_SERVER_ERROR,\n\t\t\tStatusCode::OK\n\t\t]);\n\t}\n}\n","traces":[{"line":49,"address":[6827312],"length":1,"stats":{"Line":7},"fn_name":null},{"line":58,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":59,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":67,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":68,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":73,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":75,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":76,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":84,"address":[],"length":0,"stats":{"Line":1},"fn_name":null},{"line":85,"address":[],"length":0,"stats":{"Line":2},"fn_name":null},{"line":93,"address":[6327152],"length":1,"stats":{"Line":4},"fn_name":"visit_type"},{"line":94,"address":[8454693],"length":1,"stats":{"Line":4},"fn_name":null},{"line":104,"address":[6627776],"length":1,"stats":{"Line":5},"fn_name":"into_response<&[u8]>"},{"line":107,"address":[6813719],"length":1,"stats":{"Line":5},"fn_name":null},{"line":116,"address":[],"length":0,"stats":{"Line":3},"fn_name":null},{"line":118,"address":[6566528],"length":1,"stats":{"Line":3},"fn_name":null},{"line":129,"address":[],"length":0,"stats":{"Line":1},"fn_name":null},{"line":130,"address":[],"length":0,"stats":{"Line":2},"fn_name":null},{"line":131,"address":[],"length":0,"stats":{"Line":1},"fn_name":null},{"line":132,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":143,"address":[],"length":0,"stats":{"Line":1},"fn_name":null},{"line":144,"address":[],"length":0,"stats":{"Line":1},"fn_name":null},{"line":145,"address":[],"length":0,"stats":{"Line":1},"fn_name":null},{"line":146,"address":[],"length":0,"stats":{"Line":1},"fn_name":null},{"line":149,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":150,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":151,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":152,"address":[],"length":0,"stats":{"Line":0},"fn_name":null}],"covered":16,"coverable":28},{"path":["/","home","runner","work","gotham_restful","gotham_restful","src","response","redirect.rs"],"content":"use super::{handle_error, IntoResponse};\nuse crate::{IntoResponseError, Response};\n#[cfg(feature = \"openapi\")]\nuse crate::{NoContent, ResponseSchema};\nuse futures_util::future::{BoxFuture, FutureExt, TryFutureExt};\nuse gotham::hyper::{\n\theader::{InvalidHeaderValue, LOCATION},\n\tBody, StatusCode\n};\n#[cfg(feature = \"openapi\")]\nuse openapi_type::OpenapiSchema;\nuse std::{error::Error as StdError, fmt::Debug};\nuse thiserror::Error;\n\n/// This is the return type of a resource that only returns a redirect. It will result\n/// in a _303 See Other_ answer, meaning the redirect will always result in a GET request\n/// on the target.\n///\n/// ```\n/// # #[macro_use] extern crate gotham_restful_derive;\n/// # mod doc_tests_are_broken {\n/// # use gotham::state::State;\n/// # use gotham_restful::*;\n/// #\n/// # #[derive(Resource)]\n/// # #[resource(read_all)]\n/// # struct MyResource;\n/// #\n/// #[read_all]\n/// fn read_all() -> Redirect {\n/// \tRedirect {\n/// \t\tto: \"http://localhost:8080/cool/new/location\".to_owned()\n/// \t}\n/// }\n/// # }\n/// ```\n#[derive(Clone, Debug, Default)]\npub struct Redirect {\n\tpub to: String\n}\n\nimpl IntoResponse for Redirect {\n\ttype Err = InvalidHeaderValue;\n\n\tfn into_response(self) -> BoxFuture<'static, Result> {\n\t\tasync move {\n\t\t\tlet mut res = Response::new(StatusCode::SEE_OTHER, Body::empty(), None);\n\t\t\tres.header(LOCATION, self.to.parse()?);\n\t\t\tOk(res)\n\t\t}\n\t\t.boxed()\n\t}\n}\n\n#[cfg(feature = \"openapi\")]\nimpl ResponseSchema for Redirect {\n\tfn status_codes() -> Vec {\n\t\tvec![StatusCode::SEE_OTHER]\n\t}\n\n\tfn schema(code: StatusCode) -> OpenapiSchema {\n\t\tassert_eq!(code, StatusCode::SEE_OTHER);\n\t\t::schema(StatusCode::NO_CONTENT)\n\t}\n}\n\n// private type due to parent mod\n#[derive(Debug, Error)]\npub enum RedirectError {\n\t#[error(\"{0}\")]\n\tInvalidLocation(#[from] InvalidHeaderValue),\n\t#[error(\"{0}\")]\n\tOther(#[source] E)\n}\n\n#[allow(ambiguous_associated_items)] // an enum variant is not a type. never.\nimpl IntoResponse for Result\nwhere\n\tE: Debug + IntoResponseError,\n\t::Err: StdError + Sync\n{\n\ttype Err = RedirectError<::Err>;\n\n\tfn into_response(self) -> BoxFuture<'static, Result> {\n\t\tmatch self {\n\t\t\tOk(nc) => nc.into_response().map_err(Into::into).boxed(),\n\t\t\tErr(e) => handle_error(e).map_err(RedirectError::Other).boxed()\n\t\t}\n\t}\n}\n\n#[cfg(feature = \"openapi\")]\nimpl ResponseSchema for Result\nwhere\n\tE: Debug + IntoResponseError,\n\t::Err: StdError + Sync\n{\n\tfn status_codes() -> Vec {\n\t\tlet mut status_codes = E::status_codes();\n\t\tstatus_codes.push(StatusCode::SEE_OTHER);\n\t\tstatus_codes\n\t}\n\n\tfn schema(code: StatusCode) -> OpenapiSchema {\n\t\tmatch code {\n\t\t\tStatusCode::SEE_OTHER => ::schema(StatusCode::SEE_OTHER),\n\t\t\tcode => E::schema(code)\n\t\t}\n\t}\n}\n\n#[cfg(test)]\nmod test {\n\tuse super::*;\n\tuse futures_executor::block_on;\n\tuse gotham::hyper::StatusCode;\n\tuse thiserror::Error;\n\n\t#[derive(Debug, Default, Error)]\n\t#[error(\"An Error\")]\n\tstruct MsgError;\n\n\t#[test]\n\tfn redirect_response() {\n\t\tlet redir = Redirect {\n\t\t\tto: \"http://localhost/foo\".to_owned()\n\t\t};\n\t\tlet res = block_on(redir.into_response()).expect(\"didn't expect error response\");\n\t\tassert_eq!(res.status, StatusCode::SEE_OTHER);\n\t\tassert_eq!(res.mime, None);\n\t\tassert_eq!(\n\t\t\tres.headers.get(LOCATION).map(|hdr| hdr.to_str().unwrap()),\n\t\t\tSome(\"http://localhost/foo\")\n\t\t);\n\t\tassert_eq!(res.full_body().unwrap(), &[] as &[u8]);\n\n\t\t#[cfg(feature = \"openapi\")]\n\t\tassert_eq!(Redirect::status_codes(), vec![StatusCode::SEE_OTHER]);\n\t}\n\n\t#[test]\n\tfn redirect_result() {\n\t\tlet redir: Result = Ok(Redirect {\n\t\t\tto: \"http://localhost/foo\".to_owned()\n\t\t});\n\t\tlet res = block_on(redir.into_response()).expect(\"didn't expect error response\");\n\t\tassert_eq!(res.status, StatusCode::SEE_OTHER);\n\t\tassert_eq!(res.mime, None);\n\t\tassert_eq!(\n\t\t\tres.headers.get(LOCATION).map(|hdr| hdr.to_str().unwrap()),\n\t\t\tSome(\"http://localhost/foo\")\n\t\t);\n\t\tassert_eq!(res.full_body().unwrap(), &[] as &[u8]);\n\n\t\t#[cfg(feature = \"openapi\")]\n\t\tassert_eq!(>::status_codes(), vec![\n\t\t\tStatusCode::INTERNAL_SERVER_ERROR,\n\t\t\tStatusCode::SEE_OTHER\n\t\t]);\n\t}\n}\n","traces":[{"line":45,"address":[8528832],"length":1,"stats":{"Line":1},"fn_name":"into_response"},{"line":46,"address":[8529605,8528836,8528880,8528910,8529318,8528967],"length":1,"stats":{"Line":3},"fn_name":"{async_block#0}"},{"line":47,"address":[8850672,8850810],"length":1,"stats":{"Line":4},"fn_name":null},{"line":48,"address":[8528942,8529696,8529356,8529329,8529788,8529131],"length":1,"stats":{"Line":6},"fn_name":null},{"line":49,"address":[8851471],"length":1,"stats":{"Line":2},"fn_name":null},{"line":57,"address":[8529935,8529824],"length":1,"stats":{"Line":1},"fn_name":"status_codes"},{"line":58,"address":[8851565,8851640],"length":1,"stats":{"Line":1},"fn_name":null},{"line":61,"address":[8529952],"length":1,"stats":{"Line":0},"fn_name":"schema"},{"line":63,"address":[8851776],"length":1,"stats":{"Line":0},"fn_name":null},{"line":84,"address":[],"length":0,"stats":{"Line":1},"fn_name":null},{"line":85,"address":[],"length":0,"stats":{"Line":2},"fn_name":null},{"line":86,"address":[],"length":0,"stats":{"Line":1},"fn_name":null},{"line":87,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":98,"address":[],"length":0,"stats":{"Line":1},"fn_name":null},{"line":99,"address":[],"length":0,"stats":{"Line":1},"fn_name":null},{"line":100,"address":[],"length":0,"stats":{"Line":1},"fn_name":null},{"line":101,"address":[],"length":0,"stats":{"Line":1},"fn_name":null},{"line":104,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":105,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":106,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":107,"address":[],"length":0,"stats":{"Line":0},"fn_name":null}],"covered":14,"coverable":21},{"path":["/","home","runner","work","gotham_restful","gotham_restful","src","response","result.rs"],"content":"use super::{handle_error, IntoResponse, ResourceError};\n#[cfg(feature = \"openapi\")]\nuse crate::ResponseSchema;\nuse crate::{Response, ResponseBody, Success};\nuse futures_core::future::Future;\nuse gotham::{\n\tanyhow::Error,\n\thyper::StatusCode,\n\tmime::{Mime, APPLICATION_JSON}\n};\n#[cfg(feature = \"openapi\")]\nuse openapi_type::{OpenapiSchema, OpenapiType};\nuse std::{fmt::Debug, pin::Pin};\n\npub trait IntoResponseError {\n\ttype Err: Debug + Send + 'static;\n\n\tfn into_response_error(self) -> Result;\n\n\t#[cfg(feature = \"openapi\")]\n\tfn status_codes() -> Vec;\n\n\t#[cfg(feature = \"openapi\")]\n\tfn schema(code: StatusCode) -> OpenapiSchema;\n}\n\nimpl IntoResponseError for E\nwhere\n\tE: Into\n{\n\ttype Err = serde_json::Error;\n\n\tfn into_response_error(self) -> Result {\n\t\tlet err: Error = self.into();\n\t\tlet err: ResourceError = err.into();\n\t\tOk(Response::json(\n\t\t\tStatusCode::INTERNAL_SERVER_ERROR,\n\t\t\tserde_json::to_string(&err)?\n\t\t))\n\t}\n\n\t#[cfg(feature = \"openapi\")]\n\tfn status_codes() -> Vec {\n\t\tvec![StatusCode::INTERNAL_SERVER_ERROR]\n\t}\n\n\t#[cfg(feature = \"openapi\")]\n\tfn schema(code: StatusCode) -> OpenapiSchema {\n\t\tassert_eq!(code, StatusCode::INTERNAL_SERVER_ERROR);\n\t\tResourceError::schema()\n\t}\n}\n\nimpl IntoResponse for Result\nwhere\n\tR: ResponseBody,\n\tE: Debug + IntoResponseError\n{\n\ttype Err = E::Err;\n\n\tfn into_response(self) -> Pin> + Send>> {\n\t\tmatch self {\n\t\t\tOk(r) => Success::from(r).into_response(),\n\t\t\tErr(e) => handle_error(e)\n\t\t}\n\t}\n\n\tfn accepted_types() -> Option> {\n\t\tSome(vec![APPLICATION_JSON])\n\t}\n}\n\n#[cfg(feature = \"openapi\")]\nimpl ResponseSchema for Result\nwhere\n\tR: ResponseBody,\n\tE: Debug + IntoResponseError\n{\n\tfn status_codes() -> Vec {\n\t\tlet mut status_codes = E::status_codes();\n\t\tstatus_codes.push(StatusCode::OK);\n\t\tstatus_codes\n\t}\n\n\tfn schema(code: StatusCode) -> OpenapiSchema {\n\t\tmatch code {\n\t\t\tStatusCode::OK => R::schema(),\n\t\t\tcode => E::schema(code)\n\t\t}\n\t}\n}\n\n#[cfg(test)]\nmod test {\n\tuse super::*;\n\tuse crate::response::OrAllTypes;\n\tuse futures_executor::block_on;\n\tuse thiserror::Error;\n\n\t#[derive(Debug, Default, Deserialize, Serialize)]\n\t#[cfg_attr(feature = \"openapi\", derive(openapi_type::OpenapiType))]\n\tstruct Msg {\n\t\tmsg: String\n\t}\n\n\t#[derive(Debug, Default, Error)]\n\t#[error(\"An Error\")]\n\tstruct MsgError;\n\n\t#[test]\n\tfn result_ok() {\n\t\tlet ok: Result = Ok(Msg::default());\n\t\tlet res = block_on(ok.into_response()).expect(\"didn't expect error response\");\n\t\tassert_eq!(res.status, StatusCode::OK);\n\t\tassert_eq!(res.mime, Some(APPLICATION_JSON));\n\t\tassert_eq!(res.full_body().unwrap(), br#\"{\"msg\":\"\"}\"#);\n\t}\n\n\t#[test]\n\tfn result_err() {\n\t\tlet err: Result = Err(MsgError::default());\n\t\tlet res = block_on(err.into_response()).expect(\"didn't expect error response\");\n\t\tassert_eq!(res.status, StatusCode::INTERNAL_SERVER_ERROR);\n\t\tassert_eq!(res.mime, Some(APPLICATION_JSON));\n\t\tassert_eq!(\n\t\t\tres.full_body().unwrap(),\n\t\t\tformat!(r#\"{{\"error\":true,\"message\":\"{}\"}}\"#, MsgError::default()).as_bytes()\n\t\t);\n\t}\n\n\t#[test]\n\tfn success_accepts_json() {\n\t\tassert!(\n\t\t\t>::accepted_types()\n\t\t\t\t.or_all_types()\n\t\t\t\t.contains(&APPLICATION_JSON)\n\t\t)\n\t}\n}\n","traces":[{"line":33,"address":[5720928,5721117],"length":1,"stats":{"Line":2},"fn_name":"into_response_error"},{"line":34,"address":[],"length":0,"stats":{"Line":2},"fn_name":null},{"line":35,"address":[],"length":0,"stats":{"Line":2},"fn_name":null},{"line":36,"address":[],"length":0,"stats":{"Line":4},"fn_name":null},{"line":37,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":38,"address":[],"length":0,"stats":{"Line":6},"fn_name":null},{"line":43,"address":[5720800,5720911],"length":1,"stats":{"Line":3},"fn_name":"status_codes"},{"line":44,"address":[5720813,5720888],"length":1,"stats":{"Line":3},"fn_name":null},{"line":48,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":50,"address":[5721440],"length":1,"stats":{"Line":0},"fn_name":null},{"line":61,"address":[6401264,6401424],"length":1,"stats":{"Line":2},"fn_name":"into_response"},{"line":62,"address":[],"length":0,"stats":{"Line":3},"fn_name":null},{"line":63,"address":[],"length":0,"stats":{"Line":1},"fn_name":null},{"line":64,"address":[],"length":0,"stats":{"Line":1},"fn_name":null},{"line":68,"address":[6401792,6401778,6401584,6401986],"length":1,"stats":{"Line":3},"fn_name":"accepted_types"},{"line":69,"address":[],"length":0,"stats":{"Line":3},"fn_name":null},{"line":79,"address":[],"length":0,"stats":{"Line":2},"fn_name":null},{"line":80,"address":[],"length":0,"stats":{"Line":2},"fn_name":null},{"line":81,"address":[],"length":0,"stats":{"Line":2},"fn_name":null},{"line":82,"address":[],"length":0,"stats":{"Line":2},"fn_name":null},{"line":85,"address":[],"length":0,"stats":{"Line":2},"fn_name":null},{"line":86,"address":[],"length":0,"stats":{"Line":2},"fn_name":null},{"line":87,"address":[],"length":0,"stats":{"Line":2},"fn_name":null},{"line":88,"address":[],"length":0,"stats":{"Line":2},"fn_name":null}],"covered":21,"coverable":24},{"path":["/","home","runner","work","gotham_restful","gotham_restful","src","response","success.rs"],"content":"use super::IntoResponse;\n#[cfg(feature = \"openapi\")]\nuse crate::ResponseSchema;\nuse crate::{Response, ResponseBody};\nuse futures_util::future::{self, FutureExt};\nuse gotham::{\n\thyper::{\n\t\theader::{HeaderMap, HeaderValue, IntoHeaderName},\n\t\tStatusCode\n\t},\n\tmime::{Mime, APPLICATION_JSON}\n};\n#[cfg(feature = \"openapi\")]\nuse openapi_type::OpenapiSchema;\nuse std::{fmt::Debug, future::Future, pin::Pin};\n\n/// This can be returned from a resource when there is no cause of an error.\n///\n/// Usage example:\n///\n/// ```\n/// # #[macro_use] extern crate gotham_restful_derive;\n/// # mod doc_tests_are_broken {\n/// # use gotham::state::State;\n/// # use gotham_restful::*;\n/// # use serde::{Deserialize, Serialize};\n/// #\n/// # #[derive(Resource)]\n/// # #[resource(read_all)]\n/// # struct MyResource;\n/// #\n/// #[derive(Deserialize, Serialize)]\n/// # #[cfg_attr(feature = \"openapi\", derive(openapi_type::OpenapiType))]\n/// struct MyResponse {\n/// \tmessage: &'static str\n/// }\n///\n/// #[read_all]\n/// fn read_all() -> Success {\n/// \tlet res = MyResponse {\n/// \t\tmessage: \"I'm always happy\"\n/// \t};\n/// \tres.into()\n/// }\n/// # }\n/// ```\n#[derive(Clone, Debug, Default)]\npub struct Success {\n\tvalue: T,\n\theaders: HeaderMap\n}\n\nimpl From for Success {\n\tfn from(t: T) -> Self {\n\t\tSelf {\n\t\t\tvalue: t,\n\t\t\theaders: HeaderMap::new()\n\t\t}\n\t}\n}\n\nimpl Success {\n\t/// Set a custom HTTP header. If a header with this name was set before, its value is being updated.\n\tpub fn header(&mut self, name: K, value: HeaderValue) {\n\t\tself.headers.insert(name, value);\n\t}\n\n\t/// Allow manipulating HTTP headers.\n\tpub fn headers_mut(&mut self) -> &mut HeaderMap {\n\t\t&mut self.headers\n\t}\n}\n\nimpl IntoResponse for Success {\n\ttype Err = serde_json::Error;\n\n\tfn into_response(self) -> Pin> + Send>> {\n\t\tlet res = serde_json::to_string(&self.value)\n\t\t\t.map(|body| Response::json(StatusCode::OK, body).with_headers(self.headers));\n\t\tfuture::ready(res).boxed()\n\t}\n\n\tfn accepted_types() -> Option> {\n\t\tSome(vec![APPLICATION_JSON])\n\t}\n}\n\n#[cfg(feature = \"openapi\")]\nimpl ResponseSchema for Success {\n\tfn schema(code: StatusCode) -> OpenapiSchema {\n\t\tassert_eq!(code, StatusCode::OK);\n\t\tT::schema()\n\t}\n}\n\n#[cfg(test)]\nmod test {\n\tuse super::*;\n\tuse crate::response::OrAllTypes;\n\tuse futures_executor::block_on;\n\tuse gotham::hyper::header::ACCESS_CONTROL_ALLOW_ORIGIN;\n\n\t#[derive(Debug, Default, Serialize)]\n\t#[cfg_attr(feature = \"openapi\", derive(openapi_type::OpenapiType))]\n\tstruct Msg {\n\t\tmsg: String\n\t}\n\n\t#[test]\n\tfn success_always_successfull() {\n\t\tlet success: Success = Msg::default().into();\n\t\tlet res = block_on(success.into_response()).expect(\"didn't expect error response\");\n\t\tassert_eq!(res.status, StatusCode::OK);\n\t\tassert_eq!(res.mime, Some(APPLICATION_JSON));\n\t\tassert_eq!(res.full_body().unwrap(), br#\"{\"msg\":\"\"}\"#);\n\t\t#[cfg(feature = \"openapi\")]\n\t\tassert_eq!(>::status_codes(), vec![StatusCode::OK]);\n\t}\n\n\t#[test]\n\tfn success_custom_headers() {\n\t\tlet mut success: Success = Msg::default().into();\n\t\tsuccess.header(ACCESS_CONTROL_ALLOW_ORIGIN, HeaderValue::from_static(\"*\"));\n\t\tlet res = block_on(success.into_response()).expect(\"didn't expect error response\");\n\t\tlet cors = res.headers.get(ACCESS_CONTROL_ALLOW_ORIGIN);\n\t\tassert_eq!(cors.map(|value| value.to_str().unwrap()), Some(\"*\"));\n\t}\n\n\t#[test]\n\tfn success_accepts_json() {\n\t\tassert!(\n\t\t\t>::accepted_types()\n\t\t\t\t.or_all_types()\n\t\t\t\t.contains(&APPLICATION_JSON)\n\t\t)\n\t}\n}\n","traces":[{"line":54,"address":[7580944,7580992,7581088,7581230],"length":1,"stats":{"Line":3},"fn_name":"from"},{"line":57,"address":[],"length":0,"stats":{"Line":3},"fn_name":null},{"line":64,"address":[6444752],"length":1,"stats":{"Line":1},"fn_name":null},{"line":65,"address":[],"length":0,"stats":{"Line":1},"fn_name":null},{"line":69,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":70,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":77,"address":[6445168,6445478,6445499,6445131,6445110,6444800],"length":1,"stats":{"Line":2},"fn_name":"into_response"},{"line":78,"address":[],"length":0,"stats":{"Line":6},"fn_name":null},{"line":79,"address":[],"length":0,"stats":{"Line":9},"fn_name":null},{"line":80,"address":[],"length":0,"stats":{"Line":5},"fn_name":null},{"line":83,"address":[],"length":0,"stats":{"Line":1},"fn_name":null},{"line":84,"address":[],"length":0,"stats":{"Line":1},"fn_name":null},{"line":90,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":92,"address":[],"length":0,"stats":{"Line":0},"fn_name":null}],"covered":10,"coverable":14},{"path":["/","home","runner","work","gotham_restful","gotham_restful","src","routing.rs"],"content":"#[cfg(feature = \"openapi\")]\nuse crate::openapi::{\n\tbuilder::{OpenapiBuilder, OpenapiInfo},\n\trouter::OpenapiRouter\n};\nuse crate::{response::ResourceError, Endpoint, FromBody, IntoResponse, Resource, Response};\n#[cfg(feature = \"cors\")]\nuse gotham::router::route::matcher::AccessControlRequestMethodMatcher;\nuse gotham::{\n\thandler::HandlerError,\n\thelpers::http::response::{create_empty_response, create_response},\n\thyper::{body::to_bytes, header::CONTENT_TYPE, Body, HeaderMap, Method, StatusCode},\n\tmime::{Mime, APPLICATION_JSON},\n\tpipeline::PipelineHandleChain,\n\tprelude::*,\n\trouter::{\n\t\tbuilder::{RouterBuilder, ScopeBuilder},\n\t\troute::matcher::{AcceptHeaderRouteMatcher, ContentTypeHeaderRouteMatcher, RouteMatcher},\n\t\tRouteNonMatch\n\t},\n\tstate::{FromState, State}\n};\n#[cfg(feature = \"openapi\")]\nuse openapi_type::OpenapiType;\nuse std::{any::TypeId, panic::RefUnwindSafe};\n\n/// Allow us to extract an id from a path.\n#[derive(Clone, Copy, Debug, Deserialize, StateData, StaticResponseExtender)]\n#[cfg_attr(feature = \"openapi\", derive(OpenapiType))]\npub struct PathExtractor {\n\tpub id: ID\n}\n\n/// This trait adds the `with_openapi` method to gotham's routing. It turns the default\n/// router into one that will only allow RESTful resources, but record them and generate\n/// an OpenAPI specification on request.\n#[cfg(feature = \"openapi\")]\npub trait WithOpenapi {\n\tfn with_openapi(&mut self, info: OpenapiInfo, block: F)\n\twhere\n\t\tF: FnOnce(OpenapiRouter<'_, D>);\n}\n\n/// This trait adds the `resource` method to gotham's routing. It allows you to register\n/// any RESTful [Resource] with a path.\n#[_private_openapi_trait(DrawResourcesWithSchema)]\npub trait DrawResources {\n\t#[openapi_bound(R: crate::ResourceWithSchema)]\n\t#[non_openapi_bound(R: crate::Resource)]\n\tfn resource(&mut self, path: &str);\n}\n\n/// This trait allows to draw routes within an resource. Use this only inside the\n/// [Resource::setup] method.\n#[_private_openapi_trait(DrawResourceRoutesWithSchema)]\npub trait DrawResourceRoutes {\n\t#[openapi_bound(E: crate::EndpointWithSchema)]\n\t#[non_openapi_bound(E: crate::Endpoint)]\n\tfn endpoint(&mut self);\n}\n\nfn response_from(res: Response, state: &State) -> gotham::hyper::Response {\n\tlet mut r = create_empty_response(state, res.status);\n\tlet headers = r.headers_mut();\n\tif let Some(mime) = res.mime {\n\t\theaders.insert(CONTENT_TYPE, mime.as_ref().parse().unwrap());\n\t}\n\tlet mut last_name = None;\n\tfor (name, value) in res.headers {\n\t\tif name.is_some() {\n\t\t\tlast_name = name;\n\t\t}\n\t\t// this unwrap is safe: the first item will always be Some\n\t\tlet name = last_name.clone().unwrap();\n\t\theaders.insert(name, value);\n\t}\n\n\tlet method = Method::borrow_from(state);\n\tif method != Method::HEAD {\n\t\t*r.body_mut() = res.body;\n\t}\n\n\t#[cfg(feature = \"cors\")]\n\tcrate::cors::handle_cors(state, &mut r);\n\n\tr\n}\n\nasync fn endpoint_handler(\n\tstate: &mut State\n) -> Result, HandlerError>\nwhere\n\tE: Endpoint,\n\t::Err: Into\n{\n\ttrace!(\"entering endpoint_handler\");\n\tlet placeholders = E::Placeholders::take_from(state);\n\t// workaround for E::Placeholders and E::Param being the same type\n\t// when fixed remove `Clone` requirement on endpoint\n\tif TypeId::of::() == TypeId::of::() {\n\t\tstate.put(placeholders.clone());\n\t}\n\tlet params = E::Params::take_from(state);\n\n\tlet body = match E::needs_body() {\n\t\ttrue => {\n\t\t\tlet body = to_bytes(Body::take_from(state)).await?;\n\n\t\t\tlet content_type: Mime = match HeaderMap::borrow_from(state).get(CONTENT_TYPE) {\n\t\t\t\tSome(content_type) => content_type.to_str().unwrap().parse().unwrap(),\n\t\t\t\tNone => {\n\t\t\t\t\tdebug!(\"Missing Content-Type: Returning 415 Response\");\n\t\t\t\t\tlet res = create_empty_response(state, StatusCode::UNSUPPORTED_MEDIA_TYPE);\n\t\t\t\t\treturn Ok(res);\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tmatch E::Body::from_body(body, content_type) {\n\t\t\t\tOk(body) => Some(body),\n\t\t\t\tErr(e) => {\n\t\t\t\t\tdebug!(\"Invalid Body: Returning 400 Response\");\n\t\t\t\t\tlet error: ResourceError = e.into();\n\t\t\t\t\tlet json = serde_json::to_string(&error)?;\n\t\t\t\t\tlet res =\n\t\t\t\t\t\tcreate_response(state, StatusCode::BAD_REQUEST, APPLICATION_JSON, json);\n\t\t\t\t\treturn Ok(res);\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\tfalse => None\n\t};\n\n\tlet out = E::handle(state, placeholders, params, body).await;\n\tlet res = out.into_response().await.map_err(Into::into)?;\n\tdebug!(\"Returning response {res:?}\");\n\tOk(response_from(res, state))\n}\n\n#[derive(Clone)]\nstruct MaybeMatchAcceptHeader {\n\tmatcher: Option\n}\n\nimpl RouteMatcher for MaybeMatchAcceptHeader {\n\tfn is_match(&self, state: &State) -> Result<(), RouteNonMatch> {\n\t\tmatch &self.matcher {\n\t\t\tSome(matcher) => matcher.is_match(state),\n\t\t\tNone => Ok(())\n\t\t}\n\t}\n}\n\nimpl MaybeMatchAcceptHeader {\n\tfn new(types: Option>) -> Self {\n\t\tlet types = match types {\n\t\t\tSome(types) if types.is_empty() => None,\n\t\t\ttypes => types\n\t\t};\n\t\tSelf {\n\t\t\tmatcher: types.map(AcceptHeaderRouteMatcher::new)\n\t\t}\n\t}\n}\n\nimpl From>> for MaybeMatchAcceptHeader {\n\tfn from(types: Option>) -> Self {\n\t\tSelf::new(types)\n\t}\n}\n\n#[derive(Clone)]\nstruct MaybeMatchContentTypeHeader {\n\tmatcher: Option\n}\n\nimpl RouteMatcher for MaybeMatchContentTypeHeader {\n\tfn is_match(&self, state: &State) -> Result<(), RouteNonMatch> {\n\t\tmatch &self.matcher {\n\t\t\tSome(matcher) => matcher.is_match(state),\n\t\t\tNone => Ok(())\n\t\t}\n\t}\n}\n\nimpl MaybeMatchContentTypeHeader {\n\tfn new(types: Option>) -> Self {\n\t\tSelf {\n\t\t\tmatcher: types.map(|types| ContentTypeHeaderRouteMatcher::new(types).allow_no_type())\n\t\t}\n\t}\n}\n\nimpl From>> for MaybeMatchContentTypeHeader {\n\tfn from(types: Option>) -> Self {\n\t\tSelf::new(types)\n\t}\n}\n\nmacro_rules! implDrawResourceRoutes {\n\t($implType:ident) => {\n\t\t#[cfg(feature = \"openapi\")]\n\t\timpl<'a, C, P> WithOpenapi for $implType<'a, C, P>\n\t\twhere\n\t\t\tC: PipelineHandleChain

+ Copy + Send + Sync + 'static,\n\t\t\tP: RefUnwindSafe + Send + Sync + 'static\n\t\t{\n\t\t\tfn with_openapi(&mut self, info: OpenapiInfo, block: F)\n\t\t\twhere\n\t\t\t\tF: FnOnce(OpenapiRouter<'_, $implType<'a, C, P>>)\n\t\t\t{\n\t\t\t\tlet router = OpenapiRouter {\n\t\t\t\t\trouter: self,\n\t\t\t\t\tscope: None,\n\t\t\t\t\topenapi_builder: &mut OpenapiBuilder::new(info)\n\t\t\t\t};\n\t\t\t\tblock(router);\n\t\t\t}\n\t\t}\n\n\t\timpl<'a, C, P> DrawResources for $implType<'a, C, P>\n\t\twhere\n\t\t\tC: PipelineHandleChain

+ Copy + Send + Sync + 'static,\n\t\t\tP: RefUnwindSafe + Send + Sync + 'static\n\t\t{\n\t\t\tfn resource(&mut self, mut path: &str) {\n\t\t\t\tif path.starts_with('/') {\n\t\t\t\t\tpath = &path[1..];\n\t\t\t\t}\n\t\t\t\tR::setup((self, path));\n\t\t\t}\n\t\t}\n\n\t\timpl<'a, C, P> DrawResourceRoutes for (&mut $implType<'a, C, P>, &str)\n\t\twhere\n\t\t\tC: PipelineHandleChain

+ Copy + Send + Sync + 'static,\n\t\t\tP: RefUnwindSafe + Send + Sync + 'static\n\t\t{\n\t\t\tfn endpoint(&mut self) {\n\t\t\t\tlet uri = format!(\"{}/{}\", self.1, E::uri());\n\t\t\t\tdebug!(\"Registering endpoint for {uri}\");\n\t\t\t\tself.0.associate(&uri, |assoc| {\n\t\t\t\t\tassoc\n\t\t\t\t\t\t.request(vec![E::http_method()])\n\t\t\t\t\t\t.add_route_matcher(MaybeMatchAcceptHeader::new(E::Output::accepted_types()))\n\t\t\t\t\t\t.with_path_extractor::()\n\t\t\t\t\t\t.with_query_string_extractor::()\n\t\t\t\t\t\t.to_async_borrowing(endpoint_handler::);\n\n\t\t\t\t\t#[cfg(feature = \"cors\")]\n\t\t\t\t\tif E::http_method() != Method::GET {\n\t\t\t\t\t\tassoc\n\t\t\t\t\t\t\t.options()\n\t\t\t\t\t\t\t.add_route_matcher(AccessControlRequestMethodMatcher::new(\n\t\t\t\t\t\t\t\tE::http_method()\n\t\t\t\t\t\t\t))\n\t\t\t\t\t\t\t.to(crate::cors::cors_preflight_handler);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t};\n}\n\nimplDrawResourceRoutes!(RouterBuilder);\nimplDrawResourceRoutes!(ScopeBuilder);\n","traces":[{"line":62,"address":[7831000,7832442,7830176],"length":1,"stats":{"Line":5},"fn_name":"response_from"},{"line":63,"address":[7830370,7830219],"length":1,"stats":{"Line":10},"fn_name":null},{"line":64,"address":[7830378,7830447],"length":1,"stats":{"Line":10},"fn_name":null},{"line":65,"address":[7830455],"length":1,"stats":{"Line":5},"fn_name":null},{"line":66,"address":[7830780,7830981,7830569],"length":1,"stats":{"Line":4},"fn_name":null},{"line":68,"address":[7830640],"length":1,"stats":{"Line":5},"fn_name":null},{"line":69,"address":[7831881,7831099,7830652],"length":1,"stats":{"Line":10},"fn_name":null},{"line":70,"address":[7831421,7831611,7831353],"length":1,"stats":{"Line":0},"fn_name":null},{"line":71,"address":[7831457],"length":1,"stats":{"Line":0},"fn_name":null},{"line":74,"address":[7831427,7831616],"length":1,"stats":{"Line":0},"fn_name":null},{"line":75,"address":[7831655],"length":1,"stats":{"Line":0},"fn_name":null},{"line":78,"address":[7831910],"length":1,"stats":{"Line":5},"fn_name":null},{"line":79,"address":[7832231,7831939],"length":1,"stats":{"Line":10},"fn_name":null},{"line":80,"address":[7832236,7832008],"length":1,"stats":{"Line":5},"fn_name":null},{"line":84,"address":[7831984],"length":1,"stats":{"Line":5},"fn_name":null},{"line":86,"address":[7832263],"length":1,"stats":{"Line":5},"fn_name":null},{"line":89,"address":[6821840],"length":1,"stats":{"Line":21},"fn_name":"endpoint_handler"},{"line":96,"address":[6822600,6822447,6822511,6822059],"length":1,"stats":{"Line":63},"fn_name":null},{"line":97,"address":[6822579,6822730],"length":1,"stats":{"Line":42},"fn_name":null},{"line":100,"address":[6822742,6822807],"length":1,"stats":{"Line":42},"fn_name":null},{"line":101,"address":[6822907],"length":1,"stats":{"Line":13},"fn_name":null},{"line":103,"address":[6822889,6822989],"length":1,"stats":{"Line":42},"fn_name":null},{"line":105,"address":[6823064,6823001],"length":1,"stats":{"Line":42},"fn_name":null},{"line":106,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":107,"address":[6662236],"length":1,"stats":{"Line":24},"fn_name":null},{"line":109,"address":[6823503,6823648],"length":1,"stats":{"Line":16},"fn_name":null},{"line":110,"address":[6823798],"length":1,"stats":{"Line":8},"fn_name":null},{"line":111,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":112,"address":[6825327,6823750,6825494,6825391],"length":1,"stats":{"Line":0},"fn_name":null},{"line":113,"address":[6825459],"length":1,"stats":{"Line":0},"fn_name":null},{"line":114,"address":[6825634],"length":1,"stats":{"Line":0},"fn_name":null},{"line":118,"address":[6823960],"length":1,"stats":{"Line":8},"fn_name":null},{"line":119,"address":[6824127],"length":1,"stats":{"Line":8},"fn_name":null},{"line":120,"address":[6824184],"length":1,"stats":{"Line":0},"fn_name":null},{"line":121,"address":[6824349,6824440,6824285,6824192],"length":1,"stats":{"Line":0},"fn_name":null},{"line":122,"address":[6824417],"length":1,"stats":{"Line":0},"fn_name":null},{"line":123,"address":[6824919,6824606,6824547],"length":1,"stats":{"Line":0},"fn_name":null},{"line":124,"address":[6824738],"length":1,"stats":{"Line":0},"fn_name":null},{"line":125,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":126,"address":[6825027],"length":1,"stats":{"Line":0},"fn_name":null},{"line":130,"address":[6823070],"length":1,"stats":{"Line":13},"fn_name":null},{"line":133,"address":[6662255],"length":1,"stats":{"Line":64},"fn_name":null},{"line":134,"address":[6662271],"length":1,"stats":{"Line":42},"fn_name":null},{"line":135,"address":[6826823,6826506,6827047,6826765],"length":1,"stats":{"Line":63},"fn_name":null},{"line":136,"address":[6826885,6827169],"length":1,"stats":{"Line":42},"fn_name":null},{"line":145,"address":[7832656],"length":1,"stats":{"Line":6},"fn_name":"is_match"},{"line":146,"address":[7832689],"length":1,"stats":{"Line":6},"fn_name":null},{"line":147,"address":[7832738],"length":1,"stats":{"Line":0},"fn_name":null},{"line":148,"address":[7832718],"length":1,"stats":{"Line":6},"fn_name":null},{"line":154,"address":[7833153,7833223,7832768],"length":1,"stats":{"Line":7},"fn_name":null},{"line":155,"address":[7832790],"length":1,"stats":{"Line":7},"fn_name":null},{"line":156,"address":[7832851,7832998],"length":1,"stats":{"Line":6},"fn_name":null},{"line":157,"address":[7832879],"length":1,"stats":{"Line":5},"fn_name":null},{"line":160,"address":[7833062],"length":1,"stats":{"Line":7},"fn_name":null},{"line":166,"address":[7833248],"length":1,"stats":{"Line":0},"fn_name":"from"},{"line":167,"address":[7833256],"length":1,"stats":{"Line":0},"fn_name":null},{"line":177,"address":[7833280],"length":1,"stats":{"Line":0},"fn_name":"is_match"},{"line":178,"address":[7833313],"length":1,"stats":{"Line":0},"fn_name":null},{"line":179,"address":[7833359],"length":1,"stats":{"Line":0},"fn_name":null},{"line":180,"address":[7833339],"length":1,"stats":{"Line":0},"fn_name":null},{"line":186,"address":[7833392],"length":1,"stats":{"Line":0},"fn_name":null},{"line":188,"address":[7833469,7833456,7833406],"length":1,"stats":{"Line":0},"fn_name":"{closure#0}"},{"line":194,"address":[7833520],"length":1,"stats":{"Line":0},"fn_name":"from"},{"line":195,"address":[7833528],"length":1,"stats":{"Line":0},"fn_name":null},{"line":207,"address":[7613544,7613280,7613525],"length":1,"stats":{"Line":2},"fn_name":"with_openapi<(borrow_bag::handle::Handle, ())>, borrow_bag::handle::Take>, ()), (gotham::pipeline::Pipeline<(gotham_restful::auth::AuthMiddleware, ())>, ()), openapi_specification::openapi_specification::{closure#0}::{closure_env#0}>"},{"line":211,"address":[7613308,7613396],"length":1,"stats":{"Line":4},"fn_name":null},{"line":213,"address":[7613318],"length":1,"stats":{"Line":2},"fn_name":null},{"line":214,"address":[7613327,7613391],"length":1,"stats":{"Line":4},"fn_name":null},{"line":216,"address":[7613431],"length":1,"stats":{"Line":2},"fn_name":null},{"line":225,"address":[6359488],"length":1,"stats":{"Line":5},"fn_name":"resource<(), (), custom_request_body::FooResource>"},{"line":226,"address":[6359512,6359629],"length":1,"stats":{"Line":7},"fn_name":null},{"line":227,"address":[6359582],"length":1,"stats":{"Line":2},"fn_name":null},{"line":229,"address":[6359542],"length":1,"stats":{"Line":5},"fn_name":null},{"line":238,"address":[6362068,6361712],"length":1,"stats":{"Line":31},"fn_name":"endpoint<(), (), custom_request_body::create___gotham_restful_endpoint>"},{"line":239,"address":[6362094,6361814,6361891,6361732],"length":1,"stats":{"Line":62},"fn_name":null},{"line":240,"address":[6362309,6362487,6362251,6362164],"length":1,"stats":{"Line":93},"fn_name":null},{"line":241,"address":[6362376,6362624],"length":1,"stats":{"Line":93},"fn_name":null},{"line":242,"address":[6821076,6821406,6821473,6821280],"length":1,"stats":{"Line":124},"fn_name":null},{"line":243,"address":[6821285,6821194,6821102,6821216,6821313],"length":1,"stats":{"Line":93},"fn_name":null},{"line":244,"address":[6821560,6821445,6821338,6821301],"length":1,"stats":{"Line":62},"fn_name":null},{"line":250,"address":[6821520,6821570],"length":1,"stats":{"Line":31},"fn_name":null},{"line":251,"address":[6821649,6821796,6821749],"length":1,"stats":{"Line":45},"fn_name":null},{"line":253,"address":[6821722],"length":1,"stats":{"Line":15},"fn_name":null},{"line":254,"address":[6821678],"length":1,"stats":{"Line":15},"fn_name":null}],"covered":57,"coverable":84},{"path":["/","home","runner","work","gotham_restful","gotham_restful","src","types.rs"],"content":"use gotham::{\n\thyper::body::Bytes,\n\tmime::{Mime, APPLICATION_JSON}\n};\n#[cfg(feature = \"openapi\")]\nuse openapi_type::OpenapiType;\nuse serde::{de::DeserializeOwned, Serialize};\nuse std::error::Error;\n\n#[cfg(not(feature = \"openapi\"))]\npub trait ResourceType {}\n\n#[cfg(not(feature = \"openapi\"))]\nimpl ResourceType for T {}\n\n#[cfg(feature = \"openapi\")]\npub trait ResourceType: OpenapiType {}\n\n#[cfg(feature = \"openapi\")]\nimpl ResourceType for T {}\n\n/// A type that can be used inside a response body. Implemented for every type that is\n/// serializable with serde. If the `openapi` feature is used, it must also be of type\n/// [OpenapiType].\npub trait ResponseBody: ResourceType + Serialize {}\n\nimpl ResponseBody for T {}\n\n/// This trait should be implemented for every type that can be built from an HTTP request body\n/// plus its media type.\n///\n/// For most use cases it is sufficient to derive this trait, you usually don't need to manually\n/// implement this. Therefore, make sure that the first variable of your struct can be built from\n/// [Bytes], and the second one can be build from [Mime]. If you have any additional variables, they\n/// need to be [Default]. This is an example of such a struct:\n///\n/// ```rust\n/// # use gotham::mime::{self, Mime};\n/// # use gotham_restful::{FromBody, RequestBody};\n/// #[derive(FromBody, RequestBody)]\n/// #[supported_types(mime::IMAGE_GIF, mime::IMAGE_JPEG, mime::IMAGE_PNG)]\n/// struct RawImage {\n/// \tcontent: Vec,\n/// \tcontent_type: Mime\n/// }\n/// ```\npub trait FromBody: Sized {\n\t/// The error type returned by the conversion if it was unsuccessfull. When using the derive\n\t/// macro, there is no way to trigger an error, so [std::convert::Infallible] is used here.\n\t/// However, this might change in the future.\n\ttype Err: Error;\n\n\t/// Perform the conversion.\n\tfn from_body(body: Bytes, content_type: Mime) -> Result;\n}\n\nimpl FromBody for T {\n\ttype Err = serde_json::Error;\n\n\tfn from_body(body: Bytes, _content_type: Mime) -> Result {\n\t\tserde_json::from_slice(&body)\n\t}\n}\n\n/// A type that can be used inside a request body. Implemented for every type that is deserializable\n/// with serde. If the `openapi` feature is used, it must also be of type [OpenapiType].\n///\n/// If you want a non-deserializable type to be used as a request body, e.g. because you'd like to\n/// get the raw data, you can derive it for your own type. All you need is to have a type implementing\n/// [FromBody] and optionally a list of supported media types:\n///\n/// ```rust\n/// # use gotham::mime::{self, Mime};\n/// # use gotham_restful::{FromBody, RequestBody};\n/// #[derive(FromBody, RequestBody)]\n/// #[supported_types(mime::IMAGE_GIF, mime::IMAGE_JPEG, mime::IMAGE_PNG)]\n/// struct RawImage {\n/// \tcontent: Vec,\n/// \tcontent_type: Mime\n/// }\n/// ```\npub trait RequestBody: ResourceType + FromBody {\n\t/// Return all types that are supported as content types. Use `None` if all types are supported.\n\tfn supported_types() -> Option> {\n\t\tNone\n\t}\n}\n\nimpl RequestBody for T {\n\tfn supported_types() -> Option> {\n\t\tSome(vec![APPLICATION_JSON])\n\t}\n}\n","traces":[{"line":60,"address":[],"length":0,"stats":{"Line":2},"fn_name":null},{"line":61,"address":[6927758,6927817],"length":1,"stats":{"Line":4},"fn_name":null},{"line":84,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":85,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":90,"address":[],"length":0,"stats":{"Line":1},"fn_name":null},{"line":91,"address":[],"length":0,"stats":{"Line":1},"fn_name":null}],"covered":4,"coverable":6},{"path":["/","home","runner","work","gotham_restful","gotham_restful","tests","async_methods.rs"],"content":"use gotham::{\n\thyper::{HeaderMap, Method},\n\tmime::{APPLICATION_JSON, TEXT_PLAIN},\n\tprelude::*,\n\trouter::build_simple_router,\n\tstate::State,\n\ttest::TestServer\n};\nuse gotham_restful::*;\n#[cfg(feature = \"openapi\")]\nuse openapi_type::OpenapiType;\nuse serde::Deserialize;\nuse tokio::time::{sleep, Duration};\n\nmod util {\n\tinclude!(\"util/mod.rs\");\n}\nuse util::{test_delete_response, test_get_response, test_post_response, test_put_response};\n\n#[derive(Resource)]\n#[resource(\n\tread_all, read, search, create, update_all, update, delete_all, delete, state_test\n)]\nstruct FooResource;\n\n#[derive(Deserialize)]\n#[cfg_attr(feature = \"openapi\", derive(OpenapiType))]\n#[allow(dead_code)]\nstruct FooBody {\n\tdata: String\n}\n\n#[derive(Clone, Deserialize, StateData, StaticResponseExtender)]\n#[cfg_attr(feature = \"openapi\", derive(OpenapiType))]\n#[allow(dead_code)]\nstruct FooSearch {\n\tquery: String\n}\n\nconst READ_ALL_RESPONSE: &[u8] = b\"1ARwwSPVyOKpJKrYwqGgECPVWDl1BqajAAj7g7WJ3e\";\n#[read_all]\nasync fn read_all() -> Raw<&'static [u8]> {\n\tRaw::new(READ_ALL_RESPONSE, TEXT_PLAIN)\n}\n\nconst READ_RESPONSE: &[u8] = b\"FEReHoeBKU17X2bBpVAd1iUvktFL43CDu0cFYHdaP9\";\n#[read]\nasync fn read(_id: u64) -> Raw<&'static [u8]> {\n\tRaw::new(READ_RESPONSE, TEXT_PLAIN)\n}\n\nconst SEARCH_RESPONSE: &[u8] = b\"AWqcQUdBRHXKh3at4u79mdupOAfEbnTcx71ogCVF0E\";\n#[search]\nasync fn search(_body: FooSearch) -> Raw<&'static [u8]> {\n\tRaw::new(SEARCH_RESPONSE, TEXT_PLAIN)\n}\n\nconst CREATE_RESPONSE: &[u8] = b\"y6POY7wOMAB0jBRBw0FJT7DOpUNbhmT8KdpQPLkI83\";\n#[create]\nasync fn create(_body: FooBody) -> Raw<&'static [u8]> {\n\tRaw::new(CREATE_RESPONSE, TEXT_PLAIN)\n}\n\nconst UPDATE_ALL_RESPONSE: &[u8] = b\"QlbYg8gHE9OQvvk3yKjXJLTSXlIrg9mcqhfMXJmQkv\";\n#[update_all]\nasync fn update_all(_body: FooBody) -> Raw<&'static [u8]> {\n\tRaw::new(UPDATE_ALL_RESPONSE, TEXT_PLAIN)\n}\n\nconst UPDATE_RESPONSE: &[u8] = b\"qGod55RUXkT1lgPO8h0uVM6l368O2S0GrwENZFFuRu\";\n#[update]\nasync fn update(_id: u64, _body: FooBody) -> Raw<&'static [u8]> {\n\tRaw::new(UPDATE_RESPONSE, TEXT_PLAIN)\n}\n\nconst DELETE_ALL_RESPONSE: &[u8] = b\"Y36kZ749MRk2Nem4BedJABOZiZWPLOtiwLfJlGTwm5\";\n#[delete_all]\nasync fn delete_all() -> Raw<&'static [u8]> {\n\tRaw::new(DELETE_ALL_RESPONSE, TEXT_PLAIN)\n}\n\nconst DELETE_RESPONSE: &[u8] = b\"CwRzBrKErsVZ1N7yeNfjZuUn1MacvgBqk4uPOFfDDq\";\n#[delete]\nasync fn delete(_id: u64) -> Raw<&'static [u8]> {\n\tRaw::new(DELETE_RESPONSE, TEXT_PLAIN)\n}\n\nconst STATE_TEST_RESPONSE: &[u8] = b\"xxJbxOuwioqR5DfzPuVqvaqRSfpdNQGluIvHU4n1LM\";\n#[endpoint(method = \"Method::GET\", uri = \"state_test\")]\nasync fn state_test(state: &mut State) -> Raw<&'static [u8]> {\n\tsleep(Duration::from_nanos(1)).await;\n\tstate.borrow::();\n\tsleep(Duration::from_nanos(1)).await;\n\tRaw::new(STATE_TEST_RESPONSE, TEXT_PLAIN)\n}\n\n#[test]\nfn async_methods() {\n\tlet _ = pretty_env_logger::try_init_timed();\n\n\tlet server = TestServer::new(build_simple_router(|router| {\n\t\trouter.resource::(\"foo\");\n\t}))\n\t.unwrap();\n\n\ttest_get_response(&server, \"http://localhost/foo\", READ_ALL_RESPONSE);\n\ttest_get_response(&server, \"http://localhost/foo/1\", READ_RESPONSE);\n\ttest_get_response(\n\t\t&server,\n\t\t\"http://localhost/foo/search?query=hello+world\",\n\t\tSEARCH_RESPONSE\n\t);\n\ttest_post_response(\n\t\t&server,\n\t\t\"http://localhost/foo\",\n\t\tr#\"{\"data\":\"hello world\"}\"#,\n\t\tAPPLICATION_JSON,\n\t\tCREATE_RESPONSE\n\t);\n\ttest_put_response(\n\t\t&server,\n\t\t\"http://localhost/foo\",\n\t\tr#\"{\"data\":\"hello world\"}\"#,\n\t\tAPPLICATION_JSON,\n\t\tUPDATE_ALL_RESPONSE\n\t);\n\ttest_put_response(\n\t\t&server,\n\t\t\"http://localhost/foo/1\",\n\t\tr#\"{\"data\":\"hello world\"}\"#,\n\t\tAPPLICATION_JSON,\n\t\tUPDATE_RESPONSE\n\t);\n\ttest_delete_response(&server, \"http://localhost/foo\", DELETE_ALL_RESPONSE);\n\ttest_delete_response(&server, \"http://localhost/foo/1\", DELETE_RESPONSE);\n\ttest_get_response(\n\t\t&server,\n\t\t\"http://localhost/foo/state_test\",\n\t\tSTATE_TEST_RESPONSE\n\t);\n}\n","traces":[],"covered":0,"coverable":0},{"path":["/","home","runner","work","gotham_restful","gotham_restful","tests","cors_handling.rs"],"content":"#![cfg(feature = \"cors\")]\nuse gotham::{\n\thyper::{body::Body, client::connect::Connect, header::*, StatusCode},\n\tmime::TEXT_PLAIN,\n\tpipeline::{new_pipeline, single_pipeline},\n\trouter::build_router,\n\ttest::{Server, TestRequest, TestServer}\n};\nuse gotham_restful::{\n\tcors::{Headers, Origin},\n\tread_all, update_all, CorsConfig, DrawResources, Raw, Resource\n};\n\n#[derive(Resource)]\n#[resource(read_all, update_all)]\nstruct FooResource;\n\n#[read_all]\nfn read_all() {}\n\n#[update_all]\nfn update_all(_body: Raw>) {}\n\nfn test_server(cfg: CorsConfig) -> TestServer {\n\tlet (chain, pipeline) = single_pipeline(new_pipeline().add(cfg).build());\n\tTestServer::new(build_router(chain, pipeline, |router| {\n\t\trouter.resource::(\"/foo\")\n\t}))\n\t.unwrap()\n}\n\nfn test_response(\n\treq: TestRequest,\n\torigin: Option<&str>,\n\tvary: Option<&str>,\n\tcredentials: bool\n) where\n\tTS: Server + 'static,\n\tC: Connect + Clone + Send + Sync + 'static\n{\n\tlet res = req\n\t\t.with_header(ORIGIN, \"http://example.org\".parse().unwrap())\n\t\t.perform()\n\t\t.unwrap();\n\tassert_eq!(res.status(), StatusCode::NO_CONTENT);\n\tlet headers = res.headers();\n\tprintln!(\n\t\t\"{}\",\n\t\theaders\n\t\t\t.keys()\n\t\t\t.map(|name| name.as_str())\n\t\t\t.collect::>()\n\t\t\t.join(\",\")\n\t);\n\tassert_eq!(\n\t\theaders\n\t\t\t.get(ACCESS_CONTROL_ALLOW_ORIGIN)\n\t\t\t.and_then(|value| value.to_str().ok())\n\t\t\t.as_deref(),\n\t\torigin\n\t);\n\tassert_eq!(\n\t\theaders\n\t\t\t.get(VARY)\n\t\t\t.and_then(|value| value.to_str().ok())\n\t\t\t.as_deref(),\n\t\tvary\n\t);\n\tassert_eq!(\n\t\theaders\n\t\t\t.get(ACCESS_CONTROL_ALLOW_CREDENTIALS)\n\t\t\t.and_then(|value| value.to_str().ok())\n\t\t\t.map(|value| value == \"true\")\n\t\t\t.unwrap_or(false),\n\t\tcredentials\n\t);\n\tassert!(headers.get(ACCESS_CONTROL_MAX_AGE).is_none());\n}\n\nfn test_preflight(\n\tserver: &TestServer,\n\tmethod: &str,\n\torigin: Option<&str>,\n\tvary: &str,\n\tcredentials: bool,\n\tmax_age: u64\n) {\n\tlet res = server\n\t\t.client()\n\t\t.options(\"http://example.org/foo\")\n\t\t.with_header(ACCESS_CONTROL_REQUEST_METHOD, method.parse().unwrap())\n\t\t.with_header(ORIGIN, \"http://example.org\".parse().unwrap())\n\t\t.perform()\n\t\t.unwrap();\n\tassert_eq!(res.status(), StatusCode::NO_CONTENT);\n\tlet headers = res.headers();\n\tprintln!(\n\t\t\"{}\",\n\t\theaders\n\t\t\t.keys()\n\t\t\t.map(|name| name.as_str())\n\t\t\t.collect::>()\n\t\t\t.join(\",\")\n\t);\n\tassert_eq!(\n\t\theaders\n\t\t\t.get(ACCESS_CONTROL_ALLOW_METHODS)\n\t\t\t.and_then(|value| value.to_str().ok())\n\t\t\t.as_deref(),\n\t\tSome(method)\n\t);\n\tassert_eq!(\n\t\theaders\n\t\t\t.get(ACCESS_CONTROL_ALLOW_ORIGIN)\n\t\t\t.and_then(|value| value.to_str().ok())\n\t\t\t.as_deref(),\n\t\torigin\n\t);\n\tassert_eq!(\n\t\theaders\n\t\t\t.get(VARY)\n\t\t\t.and_then(|value| value.to_str().ok())\n\t\t\t.as_deref(),\n\t\tSome(vary)\n\t);\n\tassert_eq!(\n\t\theaders\n\t\t\t.get(ACCESS_CONTROL_ALLOW_CREDENTIALS)\n\t\t\t.and_then(|value| value.to_str().ok())\n\t\t\t.map(|value| value == \"true\")\n\t\t\t.unwrap_or(false),\n\t\tcredentials\n\t);\n\tassert_eq!(\n\t\theaders\n\t\t\t.get(ACCESS_CONTROL_MAX_AGE)\n\t\t\t.and_then(|value| value.to_str().ok())\n\t\t\t.and_then(|value| value.parse().ok()),\n\t\tSome(max_age)\n\t);\n}\n\nfn test_preflight_headers(\n\tserver: &TestServer,\n\tmethod: &str,\n\trequest_headers: Option<&str>,\n\tallowed_headers: Option<&str>,\n\tvary: &str\n) {\n\tlet client = server.client();\n\tlet mut res = client\n\t\t.options(\"http://example.org/foo\")\n\t\t.with_header(ACCESS_CONTROL_REQUEST_METHOD, method.parse().unwrap())\n\t\t.with_header(ORIGIN, \"http://example.org\".parse().unwrap());\n\tif let Some(hdr) = request_headers {\n\t\tres = res.with_header(ACCESS_CONTROL_REQUEST_HEADERS, hdr.parse().unwrap());\n\t}\n\tlet res = res.perform().unwrap();\n\tassert_eq!(res.status(), StatusCode::NO_CONTENT);\n\tlet headers = res.headers();\n\tprintln!(\n\t\t\"{}\",\n\t\theaders\n\t\t\t.keys()\n\t\t\t.map(|name| name.as_str())\n\t\t\t.collect::>()\n\t\t\t.join(\",\")\n\t);\n\tif let Some(hdr) = allowed_headers {\n\t\tassert_eq!(\n\t\t\theaders\n\t\t\t\t.get(ACCESS_CONTROL_ALLOW_HEADERS)\n\t\t\t\t.and_then(|value| value.to_str().ok())\n\t\t\t\t.as_deref(),\n\t\t\tSome(hdr)\n\t\t)\n\t} else {\n\t\tassert!(!headers.contains_key(ACCESS_CONTROL_ALLOW_HEADERS));\n\t}\n\tassert_eq!(\n\t\theaders\n\t\t\t.get(VARY)\n\t\t\t.and_then(|value| value.to_str().ok())\n\t\t\t.as_deref(),\n\t\tSome(vary)\n\t);\n}\n\n#[test]\nfn cors_origin_none() {\n\tlet cfg = Default::default();\n\tlet server = test_server(cfg);\n\n\ttest_preflight(\n\t\t&server,\n\t\t\"PUT\",\n\t\tNone,\n\t\t\"access-control-request-method\",\n\t\tfalse,\n\t\t0\n\t);\n\n\ttest_response(\n\t\tserver.client().get(\"http://example.org/foo\"),\n\t\tNone,\n\t\tNone,\n\t\tfalse\n\t);\n\ttest_response(\n\t\tserver\n\t\t\t.client()\n\t\t\t.put(\"http://example.org/foo\", Body::empty(), TEXT_PLAIN),\n\t\tNone,\n\t\tNone,\n\t\tfalse\n\t);\n}\n\n#[test]\nfn cors_origin_star() {\n\tlet cfg = CorsConfig {\n\t\torigin: Origin::Star,\n\t\t..Default::default()\n\t};\n\tlet server = test_server(cfg);\n\n\ttest_preflight(\n\t\t&server,\n\t\t\"PUT\",\n\t\tSome(\"*\"),\n\t\t\"access-control-request-method\",\n\t\tfalse,\n\t\t0\n\t);\n\n\ttest_response(\n\t\tserver.client().get(\"http://example.org/foo\"),\n\t\tSome(\"*\"),\n\t\tNone,\n\t\tfalse\n\t);\n\ttest_response(\n\t\tserver\n\t\t\t.client()\n\t\t\t.put(\"http://example.org/foo\", Body::empty(), TEXT_PLAIN),\n\t\tSome(\"*\"),\n\t\tNone,\n\t\tfalse\n\t);\n}\n\n#[test]\nfn cors_origin_single() {\n\tlet cfg = CorsConfig {\n\t\torigin: Origin::Single(\"https://foo.com\".to_owned()),\n\t\t..Default::default()\n\t};\n\tlet server = test_server(cfg);\n\n\ttest_preflight(\n\t\t&server,\n\t\t\"PUT\",\n\t\tSome(\"https://foo.com\"),\n\t\t\"access-control-request-method\",\n\t\tfalse,\n\t\t0\n\t);\n\n\ttest_response(\n\t\tserver.client().get(\"http://example.org/foo\"),\n\t\tSome(\"https://foo.com\"),\n\t\tNone,\n\t\tfalse\n\t);\n\ttest_response(\n\t\tserver\n\t\t\t.client()\n\t\t\t.put(\"http://example.org/foo\", Body::empty(), TEXT_PLAIN),\n\t\tSome(\"https://foo.com\"),\n\t\tNone,\n\t\tfalse\n\t);\n}\n\n#[test]\nfn cors_origin_copy() {\n\tlet cfg = CorsConfig {\n\t\torigin: Origin::Copy,\n\t\t..Default::default()\n\t};\n\tlet server = test_server(cfg);\n\n\ttest_preflight(\n\t\t&server,\n\t\t\"PUT\",\n\t\tSome(\"http://example.org\"),\n\t\t\"access-control-request-method,origin\",\n\t\tfalse,\n\t\t0\n\t);\n\n\ttest_response(\n\t\tserver.client().get(\"http://example.org/foo\"),\n\t\tSome(\"http://example.org\"),\n\t\tSome(\"origin\"),\n\t\tfalse\n\t);\n\ttest_response(\n\t\tserver\n\t\t\t.client()\n\t\t\t.put(\"http://example.org/foo\", Body::empty(), TEXT_PLAIN),\n\t\tSome(\"http://example.org\"),\n\t\tSome(\"origin\"),\n\t\tfalse\n\t);\n}\n\n#[test]\nfn cors_headers_none() {\n\tlet cfg = Default::default();\n\tlet server = test_server(cfg);\n\n\ttest_preflight_headers(&server, \"PUT\", None, None, \"access-control-request-method\");\n\ttest_preflight_headers(\n\t\t&server,\n\t\t\"PUT\",\n\t\tSome(\"Content-Type\"),\n\t\tNone,\n\t\t\"access-control-request-method\"\n\t);\n}\n\n#[test]\nfn cors_headers_list() {\n\tlet cfg = CorsConfig {\n\t\theaders: Headers::List(vec![CONTENT_TYPE]),\n\t\t..Default::default()\n\t};\n\tlet server = test_server(cfg);\n\n\ttest_preflight_headers(\n\t\t&server,\n\t\t\"PUT\",\n\t\tNone,\n\t\tSome(\"content-type\"),\n\t\t\"access-control-request-method\"\n\t);\n\ttest_preflight_headers(\n\t\t&server,\n\t\t\"PUT\",\n\t\tSome(\"content-type\"),\n\t\tSome(\"content-type\"),\n\t\t\"access-control-request-method\"\n\t);\n}\n\n#[test]\nfn cors_headers_copy() {\n\tlet cfg = CorsConfig {\n\t\theaders: Headers::Copy,\n\t\t..Default::default()\n\t};\n\tlet server = test_server(cfg);\n\n\ttest_preflight_headers(\n\t\t&server,\n\t\t\"PUT\",\n\t\tNone,\n\t\tNone,\n\t\t\"access-control-request-method,access-control-request-headers\"\n\t);\n\ttest_preflight_headers(\n\t\t&server,\n\t\t\"PUT\",\n\t\tSome(\"content-type\"),\n\t\tSome(\"content-type\"),\n\t\t\"access-control-request-method,access-control-request-headers\"\n\t);\n}\n\n#[test]\nfn cors_credentials() {\n\tlet cfg = CorsConfig {\n\t\torigin: Origin::None,\n\t\tcredentials: true,\n\t\t..Default::default()\n\t};\n\tlet server = test_server(cfg);\n\n\ttest_preflight(\n\t\t&server,\n\t\t\"PUT\",\n\t\tNone,\n\t\t\"access-control-request-method\",\n\t\ttrue,\n\t\t0\n\t);\n\n\ttest_response(\n\t\tserver.client().get(\"http://example.org/foo\"),\n\t\tNone,\n\t\tNone,\n\t\ttrue\n\t);\n\ttest_response(\n\t\tserver\n\t\t\t.client()\n\t\t\t.put(\"http://example.org/foo\", Body::empty(), TEXT_PLAIN),\n\t\tNone,\n\t\tNone,\n\t\ttrue\n\t);\n}\n\n#[test]\nfn cors_max_age() {\n\tlet cfg = CorsConfig {\n\t\torigin: Origin::None,\n\t\tmax_age: 31536000,\n\t\t..Default::default()\n\t};\n\tlet server = test_server(cfg);\n\n\ttest_preflight(\n\t\t&server,\n\t\t\"PUT\",\n\t\tNone,\n\t\t\"access-control-request-method\",\n\t\tfalse,\n\t\t31536000\n\t);\n\n\ttest_response(\n\t\tserver.client().get(\"http://example.org/foo\"),\n\t\tNone,\n\t\tNone,\n\t\tfalse\n\t);\n\ttest_response(\n\t\tserver\n\t\t\t.client()\n\t\t\t.put(\"http://example.org/foo\", Body::empty(), TEXT_PLAIN),\n\t\tNone,\n\t\tNone,\n\t\tfalse\n\t);\n}\n","traces":[],"covered":0,"coverable":0},{"path":["/","home","runner","work","gotham_restful","gotham_restful","tests","custom_request_body.rs"],"content":"use gotham::{\n\thyper::header::CONTENT_TYPE,\n\tmime::{Mime, TEXT_PLAIN},\n\trouter::builder::*,\n\ttest::TestServer\n};\nuse gotham_restful::{create, DrawResources, FromBody, Raw, RequestBody, Resource};\n\nconst RESPONSE: &[u8] = b\"This is the only valid response.\";\n\n#[derive(Resource)]\n#[resource(create)]\nstruct FooResource;\n\n#[derive(FromBody, RequestBody)]\n#[supported_types(TEXT_PLAIN)]\nstruct Foo {\n\tcontent: Vec,\n\tcontent_type: Mime\n}\n\n#[create]\nfn create(body: Foo) -> Raw> {\n\tRaw::new(body.content, body.content_type)\n}\n\n#[test]\nfn custom_request_body() {\n\tlet server = TestServer::new(build_simple_router(|router| {\n\t\trouter.resource::(\"foo\");\n\t}))\n\t.unwrap();\n\n\tlet res = server\n\t\t.client()\n\t\t.post(\"http://localhost/foo\", RESPONSE, TEXT_PLAIN)\n\t\t.perform()\n\t\t.unwrap();\n\tassert_eq!(\n\t\tres.headers().get(CONTENT_TYPE).unwrap().to_str().unwrap(),\n\t\t\"text/plain\"\n\t);\n\tlet res = res.read_body().unwrap();\n\tlet body: &[u8] = res.as_ref();\n\tassert_eq!(body, RESPONSE);\n}\n","traces":[],"covered":0,"coverable":0},{"path":["/","home","runner","work","gotham_restful","gotham_restful","tests","openapi_specification.rs"],"content":"#![cfg(all(feature = \"auth\", feature = \"openapi\"))]\n#![allow(clippy::approx_constant)]\n\n#[macro_use]\nextern crate pretty_assertions;\n\nuse gotham::{\n\thyper::{Method, StatusCode},\n\tmime::{IMAGE_PNG, TEXT_PLAIN_UTF_8},\n\tpipeline::{new_pipeline, single_pipeline},\n\tprelude::*,\n\trouter::build_router,\n\ttest::TestServer\n};\nuse gotham_restful::*;\nuse openapi_type::{OpenapiSchema, OpenapiType, Visitor};\nuse serde::{Deserialize, Serialize};\n\n#[allow(dead_code)]\nmod util {\n\tinclude!(\"util/mod.rs\");\n}\nuse util::test_openapi_response;\n\nconst IMAGE_RESPONSE : &[u8] = b\"iVBORw0KGgoAAAANSUhEUgAAAAEAAAABAQMAAAAl21bKAAAAA1BMVEUA/wA0XsCoAAAAAXRSTlN/gFy0ywAAAApJREFUeJxjYgAAAAYAAzY3fKgAAAAASUVORK5CYII=\";\n\n#[derive(Resource)]\n#[resource(get_image, set_image)]\nstruct ImageResource;\n\n#[derive(FromBody, RequestBody)]\n#[supported_types(IMAGE_PNG)]\nstruct Image(Vec);\n\n#[read(operation_id = \"getImage\")]\nfn get_image(_id: u64) -> Raw<&'static [u8]> {\n\tRaw::new(IMAGE_RESPONSE, \"image/png;base64\".parse().unwrap())\n}\n\n#[update(operation_id = \"setImage\")]\nfn set_image(_id: u64, _image: Image) {}\n\n#[derive(Resource)]\n#[resource(read_secret, search_secret)]\nstruct SecretResource;\n\n#[derive(Deserialize, Clone)]\nstruct AuthData {\n\tsub: String,\n\tiat: u64,\n\texp: u64\n}\n\ntype AuthStatus = gotham_restful::AuthStatus;\n\n#[derive(OpenapiType, Serialize)]\nstruct Secret {\n\tcode: f32\n}\n\n#[derive(OpenapiType, Serialize)]\nstruct Secrets {\n\tsecrets: Vec\n}\n\n#[derive(Clone, Deserialize, OpenapiType, StateData, StaticResponseExtender)]\nstruct SecretQuery {\n\tdate: String,\n\thour: Option,\n\tminute: Option\n}\n\n/// This endpoint gives access to the secret.\n///\n/// You need to be authenticated to call this endpoint.\n#[read]\nfn read_secret(auth: AuthStatus, _id: String) -> AuthSuccess {\n\tauth.ok()?;\n\tOk(Secret { code: 4.2 })\n}\n\n#[search]\nfn search_secret(auth: AuthStatus, _query: SecretQuery) -> AuthSuccess {\n\tauth.ok()?;\n\tOk(Secrets {\n\t\tsecrets: vec![Secret { code: 4.2 }, Secret { code: 3.14 }]\n\t})\n}\n\n#[derive(Resource)]\n#[resource(coffee_read_all)]\nstruct CoffeeResource;\n\nfn teapot_status_codes() -> Vec {\n\tvec![StatusCode::IM_A_TEAPOT]\n}\n\nfn teapot_schema(code: StatusCode) -> OpenapiSchema {\n\tassert_eq!(code, StatusCode::IM_A_TEAPOT);\n\n\tstruct Binary;\n\n\timpl OpenapiType for Binary {\n\t\tfn visit_type(visitor: &mut V) {\n\t\t\tvisitor.visit_binary();\n\t\t}\n\t}\n\n\tBinary::schema()\n}\n\n#[read_all(status_codes = \"teapot_status_codes\", schema = \"teapot_schema\")]\nfn coffee_read_all() -> Response {\n\tResponse::new(\n\t\tStatusCode::IM_A_TEAPOT,\n\t\t\"Sorry, this is just your fancy grandma's teapot. Can't make coffee.\",\n\t\tSome(TEXT_PLAIN_UTF_8)\n\t)\n}\n\n#[derive(Resource)]\n#[resource(custom_read_with, custom_patch)]\nstruct CustomResource;\n\n#[derive(Clone, Deserialize, OpenapiType, StateData, StaticResponseExtender)]\nstruct ReadWithPath {\n\tfrom: String,\n\tid: u64\n}\n\n#[endpoint(method = \"Method::GET\", uri = \"read/:from/with/:id\")]\nfn custom_read_with(_path: ReadWithPath) {}\n\n#[endpoint(method = \"Method::PATCH\", uri = \"\", body = true)]\nfn custom_patch(_body: String) {}\n\n#[test]\nfn openapi_specification() {\n\tlet info = OpenapiInfo {\n\t\ttitle: \"This is just a test\".to_owned(),\n\t\tversion: \"1.2.3\".to_owned(),\n\t\turls: vec![\"http://localhost:12345/api/v1\".to_owned()]\n\t};\n\tlet auth: AuthMiddleware = AuthMiddleware::new(\n\t\tAuthSource::AuthorizationHeader,\n\t\tAuthValidation::default(),\n\t\tStaticAuthHandler::from_array(b\"zlBsA2QXnkmpe0QTh8uCvtAEa4j33YAc\")\n\t);\n\tlet (chain, pipelines) = single_pipeline(new_pipeline().add(auth).build());\n\tlet server = TestServer::new(build_router(chain, pipelines, |router| {\n\t\trouter.with_openapi(info, |mut router| {\n\t\t\t// the leading slash tests that the spec doesn't contain '//img' nonsense\n\t\t\trouter.resource::(\"/img\");\n\t\t\trouter.resource::(\"secret\");\n\t\t\trouter.resource::(\"coffee\");\n\t\t\trouter.resource::(\"custom\");\n\t\t\trouter.openapi_spec(\"openapi\");\n\t\t});\n\t}))\n\t.unwrap();\n\n\ttest_openapi_response(\n\t\t&server,\n\t\t\"http://localhost/openapi\",\n\t\t\"tests/openapi_specification.json\"\n\t);\n}\n","traces":[],"covered":0,"coverable":0},{"path":["/","home","runner","work","gotham_restful","gotham_restful","tests","openapi_supports_scope.rs"],"content":"#![cfg(feature = \"openapi\")]\n\n#[macro_use]\nextern crate pretty_assertions;\n\nuse gotham::{mime::TEXT_PLAIN, router::builder::*, test::TestServer};\nuse gotham_restful::*;\n\n#[allow(dead_code)]\nmod util {\n\tinclude!(\"util/mod.rs\");\n}\nuse util::{test_get_response, test_openapi_response};\n\nconst RESPONSE: &[u8] = b\"This is the only valid response.\";\n\n#[derive(Resource)]\n#[resource(read_all)]\nstruct FooResource;\n\n#[read_all]\nfn read_all() -> Raw<&'static [u8]> {\n\tRaw::new(RESPONSE, TEXT_PLAIN)\n}\n\n#[test]\nfn openapi_supports_scope() {\n\tlet info = OpenapiInfo {\n\t\ttitle: \"Test\".to_owned(),\n\t\tversion: \"1.2.3\".to_owned(),\n\t\turls: Vec::new()\n\t};\n\tlet server = TestServer::new(build_simple_router(|router| {\n\t\trouter.with_openapi(info, |mut router| {\n\t\t\trouter.openapi_spec(\"openapi\");\n\t\t\trouter.resource::(\"foo1\");\n\t\t\trouter.scope(\"/bar\", |router| {\n\t\t\t\trouter.resource::(\"foo2\");\n\t\t\t\trouter.scope(\"/baz\", |router| {\n\t\t\t\t\trouter.resource::(\"foo3\");\n\t\t\t\t})\n\t\t\t});\n\t\t\trouter.resource::(\"foo4\");\n\t\t});\n\t}))\n\t.unwrap();\n\n\ttest_get_response(&server, \"http://localhost/foo1\", RESPONSE);\n\ttest_get_response(&server, \"http://localhost/bar/foo2\", RESPONSE);\n\ttest_get_response(&server, \"http://localhost/bar/baz/foo3\", RESPONSE);\n\ttest_get_response(&server, \"http://localhost/foo4\", RESPONSE);\n\ttest_openapi_response(\n\t\t&server,\n\t\t\"http://localhost/openapi\",\n\t\t\"tests/openapi_supports_scope.json\"\n\t);\n}\n","traces":[],"covered":0,"coverable":0},{"path":["/","home","runner","work","gotham_restful","gotham_restful","tests","resource_error.rs"],"content":"use gotham_restful::ResourceError;\n\n#[derive(ResourceError)]\nenum Error {\n\t#[display(\"I/O Error: {0}\")]\n\tIoError(#[from] std::io::Error),\n\n\t#[status(INTERNAL_SERVER_ERROR)]\n\t#[display(\"Internal Server Error: {0}\")]\n\tInternalServerError(String)\n}\n\n#[allow(deprecated)]\nmod resource_error {\n\tuse super::Error;\n\tuse gotham::{hyper::StatusCode, mime::APPLICATION_JSON};\n\tuse gotham_restful::IntoResponseError;\n\n\t#[test]\n\tfn io_error() {\n\t\tlet err = Error::IoError(std::io::Error::last_os_error());\n\t\tlet res = err.into_response_error().unwrap();\n\t\tassert_eq!(res.status(), StatusCode::INTERNAL_SERVER_ERROR);\n\t\tassert_eq!(res.mime(), Some(&APPLICATION_JSON));\n\t}\n\n\t#[test]\n\tfn internal_server_error() {\n\t\tlet err = Error::InternalServerError(\"Brocken\".to_owned());\n\t\tassert_eq!(&format!(\"{err}\"), \"Internal Server Error: Brocken\");\n\n\t\tlet res = err.into_response_error().unwrap();\n\t\tassert_eq!(res.status(), StatusCode::INTERNAL_SERVER_ERROR);\n\t\tassert_eq!(res.mime(), None); // TODO shouldn't this be a json error message?\n\t}\n}\n","traces":[],"covered":0,"coverable":0},{"path":["/","home","runner","work","gotham_restful","gotham_restful","tests","sync_methods.rs"],"content":"use gotham::{\n\tmime::{APPLICATION_JSON, TEXT_PLAIN},\n\tprelude::*,\n\trouter::build_simple_router,\n\ttest::TestServer\n};\nuse gotham_restful::*;\n#[cfg(feature = \"openapi\")]\nuse openapi_type::OpenapiType;\nuse serde::Deserialize;\n\nmod util {\n\tinclude!(\"util/mod.rs\");\n}\nuse util::{test_delete_response, test_get_response, test_post_response, test_put_response};\n\n#[derive(Resource)]\n#[resource(read_all, read, search, create, update_all, update, delete_all, delete)]\nstruct FooResource;\n\n#[derive(Deserialize)]\n#[cfg_attr(feature = \"openapi\", derive(OpenapiType))]\n#[allow(dead_code)]\nstruct FooBody {\n\tdata: String\n}\n\n#[derive(Clone, Deserialize, StateData, StaticResponseExtender)]\n#[cfg_attr(feature = \"openapi\", derive(OpenapiType))]\n#[allow(dead_code)]\nstruct FooSearch {\n\tquery: String\n}\n\nconst READ_ALL_RESPONSE: &[u8] = b\"1ARwwSPVyOKpJKrYwqGgECPVWDl1BqajAAj7g7WJ3e\";\n#[read_all]\nfn read_all() -> Raw<&'static [u8]> {\n\tRaw::new(READ_ALL_RESPONSE, TEXT_PLAIN)\n}\n\nconst READ_RESPONSE: &[u8] = b\"FEReHoeBKU17X2bBpVAd1iUvktFL43CDu0cFYHdaP9\";\n#[read]\nfn read(_id: u64) -> Raw<&'static [u8]> {\n\tRaw::new(READ_RESPONSE, TEXT_PLAIN)\n}\n\nconst SEARCH_RESPONSE: &[u8] = b\"AWqcQUdBRHXKh3at4u79mdupOAfEbnTcx71ogCVF0E\";\n#[search]\nfn search(_body: FooSearch) -> Raw<&'static [u8]> {\n\tRaw::new(SEARCH_RESPONSE, TEXT_PLAIN)\n}\n\nconst CREATE_RESPONSE: &[u8] = b\"y6POY7wOMAB0jBRBw0FJT7DOpUNbhmT8KdpQPLkI83\";\n#[create]\nfn create(_body: FooBody) -> Raw<&'static [u8]> {\n\tRaw::new(CREATE_RESPONSE, TEXT_PLAIN)\n}\n\nconst UPDATE_ALL_RESPONSE: &[u8] = b\"QlbYg8gHE9OQvvk3yKjXJLTSXlIrg9mcqhfMXJmQkv\";\n#[update_all]\nfn update_all(_body: FooBody) -> Raw<&'static [u8]> {\n\tRaw::new(UPDATE_ALL_RESPONSE, TEXT_PLAIN)\n}\n\nconst UPDATE_RESPONSE: &[u8] = b\"qGod55RUXkT1lgPO8h0uVM6l368O2S0GrwENZFFuRu\";\n#[update]\nfn update(_id: u64, _body: FooBody) -> Raw<&'static [u8]> {\n\tRaw::new(UPDATE_RESPONSE, TEXT_PLAIN)\n}\n\nconst DELETE_ALL_RESPONSE: &[u8] = b\"Y36kZ749MRk2Nem4BedJABOZiZWPLOtiwLfJlGTwm5\";\n#[delete_all]\nfn delete_all() -> Raw<&'static [u8]> {\n\tRaw::new(DELETE_ALL_RESPONSE, TEXT_PLAIN)\n}\n\nconst DELETE_RESPONSE: &[u8] = b\"CwRzBrKErsVZ1N7yeNfjZuUn1MacvgBqk4uPOFfDDq\";\n#[delete]\nfn delete(_id: u64) -> Raw<&'static [u8]> {\n\tRaw::new(DELETE_RESPONSE, TEXT_PLAIN)\n}\n\n#[test]\nfn sync_methods() {\n\tlet _ = pretty_env_logger::try_init_timed();\n\n\tlet server = TestServer::new(build_simple_router(|router| {\n\t\trouter.resource::(\"foo\");\n\t}))\n\t.unwrap();\n\n\ttest_get_response(&server, \"http://localhost/foo\", READ_ALL_RESPONSE);\n\ttest_get_response(&server, \"http://localhost/foo/1\", READ_RESPONSE);\n\ttest_get_response(\n\t\t&server,\n\t\t\"http://localhost/foo/search?query=hello+world\",\n\t\tSEARCH_RESPONSE\n\t);\n\ttest_post_response(\n\t\t&server,\n\t\t\"http://localhost/foo\",\n\t\tr#\"{\"data\":\"hello world\"}\"#,\n\t\tAPPLICATION_JSON,\n\t\tCREATE_RESPONSE\n\t);\n\ttest_put_response(\n\t\t&server,\n\t\t\"http://localhost/foo\",\n\t\tr#\"{\"data\":\"hello world\"}\"#,\n\t\tAPPLICATION_JSON,\n\t\tUPDATE_ALL_RESPONSE\n\t);\n\ttest_put_response(\n\t\t&server,\n\t\t\"http://localhost/foo/1\",\n\t\tr#\"{\"data\":\"hello world\"}\"#,\n\t\tAPPLICATION_JSON,\n\t\tUPDATE_RESPONSE\n\t);\n\ttest_delete_response(&server, \"http://localhost/foo\", DELETE_ALL_RESPONSE);\n\ttest_delete_response(&server, \"http://localhost/foo/1\", DELETE_RESPONSE);\n}\n","traces":[],"covered":0,"coverable":0},{"path":["/","home","runner","work","gotham_restful","gotham_restful","tests","trybuild_ui.rs"],"content":"use trybuild::TestCases;\n\n#[test]\n#[ignore]\nfn trybuild_ui() {\n\tlet t = TestCases::new();\n\tt.compile_fail(\"tests/ui/endpoint/*.rs\");\n\tt.compile_fail(\"tests/ui/from_body/*.rs\");\n\tt.compile_fail(\"tests/ui/resource/*.rs\");\n}\n","traces":[],"covered":0,"coverable":0},{"path":["/","home","runner","work","gotham_restful","gotham_restful","tests","ui","endpoint","async_state.rs"],"content":"#[macro_use]\nextern crate gotham_restful;\nuse gotham::state::State;\n\n#[derive(Resource)]\n#[resource(read_all)]\nstruct FooResource;\n\n#[read_all]\nasync fn read_all(state: &State) {}\n\nfn main() {}\n","traces":[],"covered":0,"coverable":0},{"path":["/","home","runner","work","gotham_restful","gotham_restful","tests","ui","endpoint","auth_data_non_clone.rs"],"content":"use gotham_restful::*;\nuse serde::Deserialize;\n\n#[derive(Resource)]\n#[resource(read_all)]\nstruct FooResource;\n\n#[derive(Deserialize)]\nstruct AuthData {\n\tiat: u64,\n\texp: u64\n}\n\n#[read_all]\nasync fn read_all(auth: AuthStatus) -> Result {\n\tauth.ok()?;\n\tOk(NoContent::default())\n}\n\nfn main() {}\n","traces":[],"covered":0,"coverable":0},{"path":["/","home","runner","work","gotham_restful","gotham_restful","tests","ui","endpoint","custom_method_invalid_expr.rs"],"content":"#[macro_use]\nextern crate gotham_restful;\n\n#[derive(Resource)]\n#[resource(read_all)]\nstruct FooResource;\n\n#[endpoint(method = \"I like pizza\", uri = \"custom_read\")]\nasync fn read_all() {}\n\nfn main() {}\n","traces":[],"covered":0,"coverable":0},{"path":["/","home","runner","work","gotham_restful","gotham_restful","tests","ui","endpoint","custom_method_invalid_type.rs"],"content":"#[macro_use]\nextern crate gotham_restful;\n\n#[derive(Resource)]\n#[resource(read_all)]\nstruct FooResource;\n\n#[endpoint(method = \"String::new()\", uri = \"custom_read\")]\nasync fn read_all() {}\n\nfn main() {}\n","traces":[],"covered":0,"coverable":0},{"path":["/","home","runner","work","gotham_restful","gotham_restful","tests","ui","endpoint","custom_method_missing.rs"],"content":"#[macro_use]\nextern crate gotham_restful;\n\n#[derive(Resource)]\n#[resource(read_all)]\nstruct FooResource;\n\n#[endpoint(uri = \"custom_read\")]\nasync fn read_all() {}\n\nfn main() {}\n","traces":[],"covered":0,"coverable":0},{"path":["/","home","runner","work","gotham_restful","gotham_restful","tests","ui","endpoint","custom_uri_missing.rs"],"content":"#[macro_use]\nextern crate gotham_restful;\n\n#[derive(Resource)]\n#[resource(read_all)]\nstruct FooResource;\n\n#[endpoint(method = \"gotham_restful::gotham::hyper::Method::GET\")]\nasync fn read_all() {}\n\nfn main() {}\n","traces":[],"covered":0,"coverable":0},{"path":["/","home","runner","work","gotham_restful","gotham_restful","tests","ui","endpoint","dynamic_schema_missing_schema.rs"],"content":"#[macro_use]\nextern crate gotham_restful;\n\nuse gotham::hyper::StatusCode;\n\n#[derive(Resource)]\n#[resource(read_all)]\nstruct FooResource;\n\nfn status_codes() -> Vec {\n\tunimplemented!()\n}\n\n#[read_all(status_codes = \"status_codes\")]\nasync fn read_all() {}\n\nfn main() {}\n","traces":[],"covered":0,"coverable":0},{"path":["/","home","runner","work","gotham_restful","gotham_restful","tests","ui","endpoint","dynamic_schema_missing_status_codes.rs"],"content":"#[macro_use]\nextern crate gotham_restful;\n\nuse gotham::hyper::StatusCode;\nuse gotham_restful::private::OpenapiSchema;\n\n#[derive(Resource)]\n#[resource(read_all)]\nstruct FooResource;\n\nfn schema(_: StatusCode) -> OpenapiSchema {\n\tunimplemented!()\n}\n\n#[read_all(schema = \"schema\")]\nasync fn read_all() {}\n\nfn main() {}\n","traces":[],"covered":0,"coverable":0},{"path":["/","home","runner","work","gotham_restful","gotham_restful","tests","ui","endpoint","dynamic_schema_wrong_type.rs"],"content":"#[macro_use]\nextern crate gotham_restful;\n\n#[derive(Resource)]\n#[resource(read_all)]\nstruct FooResource;\n\nfn schema(_: u16) -> String {\n\tunimplemented!()\n}\n\nfn status_codes() -> Vec {\n\tunimplemented!()\n}\n\n#[read_all(schema = \"schema\", status_codes = \"status_codes\")]\nasync fn read_all() {}\n\nfn main() {}\n","traces":[],"covered":0,"coverable":0},{"path":["/","home","runner","work","gotham_restful","gotham_restful","tests","ui","endpoint","invalid_attribute.rs"],"content":"#[macro_use]\nextern crate gotham_restful;\n\n#[derive(Resource)]\n#[resource(read_all)]\nstruct FooResource;\n\n#[read_all(FooResource)]\nfn read_all() {}\n\nfn main() {}\n","traces":[],"covered":0,"coverable":0},{"path":["/","home","runner","work","gotham_restful","gotham_restful","tests","ui","endpoint","invalid_body_ty.rs"],"content":"#[macro_use]\nextern crate gotham_restful;\nuse gotham_restful::gotham::hyper::Method;\n\n#[derive(Resource)]\n#[resource(endpoint)]\nstruct FooResource;\n\n#[derive(Debug)]\nstruct FooBody {\n\tfoo: String\n}\n\n#[endpoint(method = \"Method::GET\", uri = \"\", body = true)]\nfn endpoint(_: FooBody) {\n\tunimplemented!()\n}\n\nfn main() {}\n","traces":[],"covered":0,"coverable":0},{"path":["/","home","runner","work","gotham_restful","gotham_restful","tests","ui","endpoint","invalid_params_ty.rs"],"content":"#[macro_use]\nextern crate gotham_restful;\nuse gotham_restful::gotham::hyper::Method;\n\n#[derive(Resource)]\n#[resource(endpoint)]\nstruct FooResource;\n\n#[derive(Debug)]\nstruct FooParams {\n\tfoo: String\n}\n\n#[endpoint(method = \"Method::GET\", uri = \"\", params = true)]\nfn endpoint(_: FooParams) {\n\tunimplemented!()\n}\n\nfn main() {}\n","traces":[],"covered":0,"coverable":0},{"path":["/","home","runner","work","gotham_restful","gotham_restful","tests","ui","endpoint","invalid_placeholders_ty.rs"],"content":"#[macro_use]\nextern crate gotham_restful;\nuse gotham_restful::gotham::hyper::Method;\n\n#[derive(Resource)]\n#[resource(endpoint)]\nstruct FooResource;\n\n#[derive(Debug)]\nstruct FooPlaceholders {\n\tfoo: String\n}\n\n#[endpoint(method = \"Method::GET\", uri = \":foo\")]\nfn endpoint(_: FooPlaceholders) {\n\tunimplemented!()\n}\n\nfn main() {}\n","traces":[],"covered":0,"coverable":0},{"path":["/","home","runner","work","gotham_restful","gotham_restful","tests","ui","endpoint","invalid_return_type.rs"],"content":"#[macro_use]\nextern crate gotham_restful;\nuse gotham_restful::gotham::hyper::Method;\n\n#[derive(Resource)]\n#[resource(endpoint)]\nstruct FooResource;\n\nstruct FooResponse;\n\n#[endpoint(method = \"Method::GET\", uri = \"\")]\nfn endpoint() -> FooResponse {\n\tunimplemented!()\n}\n\nfn main() {}\n","traces":[],"covered":0,"coverable":0},{"path":["/","home","runner","work","gotham_restful","gotham_restful","tests","ui","endpoint","non_custom_body_attribute.rs"],"content":"#[macro_use]\nextern crate gotham_restful;\n\n#[derive(Resource)]\n#[resource(read_all)]\nstruct FooResource;\n\n#[read_all(body = false)]\nasync fn read_all() {}\n\nfn main() {}\n","traces":[],"covered":0,"coverable":0},{"path":["/","home","runner","work","gotham_restful","gotham_restful","tests","ui","endpoint","non_custom_method_attribute.rs"],"content":"#[macro_use]\nextern crate gotham_restful;\n\n#[derive(Resource)]\n#[resource(read_all)]\nstruct FooResource;\n\n#[read_all(method = \"gotham_restful::gotham::hyper::Method::GET\")]\nasync fn read_all() {}\n\nfn main() {}\n","traces":[],"covered":0,"coverable":0},{"path":["/","home","runner","work","gotham_restful","gotham_restful","tests","ui","endpoint","non_custom_params_attribute.rs"],"content":"#[macro_use]\nextern crate gotham_restful;\n\n#[derive(Resource)]\n#[resource(read_all)]\nstruct FooResource;\n\n#[read_all(params = true)]\nasync fn read_all() {}\n\nfn main() {}\n","traces":[],"covered":0,"coverable":0},{"path":["/","home","runner","work","gotham_restful","gotham_restful","tests","ui","endpoint","non_custom_uri_attribute.rs"],"content":"#[macro_use]\nextern crate gotham_restful;\n\n#[derive(Resource)]\n#[resource(read_all)]\nstruct FooResource;\n\n#[read_all(uri = \"custom_read\")]\nasync fn read_all() {}\n\nfn main() {}\n","traces":[],"covered":0,"coverable":0},{"path":["/","home","runner","work","gotham_restful","gotham_restful","tests","ui","endpoint","self.rs"],"content":"#[macro_use]\nextern crate gotham_restful;\n\n#[derive(Resource)]\n#[resource(read_all)]\nstruct FooResource;\n\n#[read_all]\nfn read_all(self) {}\n\nfn main() {}\n","traces":[],"covered":0,"coverable":0},{"path":["/","home","runner","work","gotham_restful","gotham_restful","tests","ui","endpoint","too_few_args.rs"],"content":"#[macro_use]\nextern crate gotham_restful;\n\n#[derive(Resource)]\n#[resource(read)]\nstruct FooResource;\n\n#[read]\nfn read() {}\n\nfn main() {}\n","traces":[],"covered":0,"coverable":0},{"path":["/","home","runner","work","gotham_restful","gotham_restful","tests","ui","endpoint","too_many_args.rs"],"content":"#[macro_use]\nextern crate gotham_restful;\n\n#[derive(Resource)]\n#[resource(read_all)]\nstruct FooResource;\n\n#[read_all]\nfn read_all(_id: u64) {}\n\nfn main() {}\n","traces":[],"covered":0,"coverable":0},{"path":["/","home","runner","work","gotham_restful","gotham_restful","tests","ui","endpoint","unknown_attribute.rs"],"content":"#[macro_use]\nextern crate gotham_restful;\n\n#[derive(Resource)]\n#[resource(read_all)]\nstruct FooResource;\n\n#[read_all(pineapple = \"on pizza\")]\nfn read_all() {}\n\nfn main() {}\n","traces":[],"covered":0,"coverable":0},{"path":["/","home","runner","work","gotham_restful","gotham_restful","tests","ui","endpoint","unsafe.rs"],"content":"#[macro_use]\nextern crate gotham_restful;\n\n#[derive(Resource)]\n#[resource(read_all)]\nstruct FooResource;\n\n#[read_all]\nunsafe fn read_all() {}\n\nfn main() {}\n","traces":[],"covered":0,"coverable":0},{"path":["/","home","runner","work","gotham_restful","gotham_restful","tests","ui","endpoint","wants_auth_non_bool.rs"],"content":"#[macro_use]\nextern crate gotham_restful;\n\n#[derive(Resource)]\n#[resource(read_all)]\nstruct FooResource;\n\n#[read_all(wants_auth = \"yes, please\")]\nasync fn read_all() {}\n\nfn main() {}\n","traces":[],"covered":0,"coverable":0},{"path":["/","home","runner","work","gotham_restful","gotham_restful","tests","ui","from_body","enum.rs"],"content":"#[macro_use]\nextern crate gotham_restful;\n\n#[derive(FromBody)]\nenum FromBodyEnum {\n\tSomeVariant(Vec),\n\tOtherVariant(String)\n}\n\nfn main() {}\n","traces":[],"covered":0,"coverable":0},{"path":["/","home","runner","work","gotham_restful","gotham_restful","tests","ui","resource","unknown_method.rs"],"content":"#[macro_use]\nextern crate gotham_restful;\n\n#[derive(Resource)]\n#[resource(read_any)]\nstruct FooResource;\n\n#[read_all]\nfn read_all() {}\n\nfn main() {}\n","traces":[],"covered":0,"coverable":0},{"path":["/","home","runner","work","gotham_restful","gotham_restful","tests","util","mod.rs"],"content":"use gotham::{\n\thyper::Body,\n\ttest::TestServer\n};\nuse log::info;\nuse gotham::mime::Mime;\n#[allow(unused_imports)]\nuse std::{fs::File, io::{Read, Write}, str};\n\npub fn test_get_response(server : &TestServer, path : &str, expected : &[u8])\n{\n\tinfo!(\"GET {path}\");\n\tlet res = server.client().get(path).perform().unwrap().read_body().unwrap();\n\tlet body : &[u8] = res.as_ref();\n\tassert_eq!(body, expected);\n}\n\npub fn test_post_response(server : &TestServer, path : &str, body : B, mime : Mime, expected : &[u8])\nwhere\n\tB : Into\n{\n\tinfo!(\"POST {path}\");\n\tlet res = server.client().post(path, body, mime).perform().unwrap().read_body().unwrap();\n\tlet body : &[u8] = res.as_ref();\n\tassert_eq!(body, expected);\n}\n\npub fn test_put_response(server : &TestServer, path : &str, body : B, mime : Mime, expected : &[u8])\nwhere\n\tB : Into\n{\n\tinfo!(\"PUT {path}\");\n\tlet res = server.client().put(path, body, mime).perform().unwrap().read_body().unwrap();\n\tlet body : &[u8] = res.as_ref();\n\tassert_eq!(body, expected);\n}\n\npub fn test_delete_response(server : &TestServer, path : &str, expected : &[u8])\n{\n\tinfo!(\"DELETE {path}\");\n\tlet res = server.client().delete(path).perform().unwrap().read_body().unwrap();\n\tlet body : &[u8] = res.as_ref();\n\tassert_eq!(body, expected);\n}\n\n#[cfg(feature = \"openapi\")]\npub fn test_openapi_response(server : &TestServer, path : &str, output_file : &str)\n{\n\tinfo!(\"GET {path}\");\n\tlet res = server.client().get(path).perform().unwrap().read_body().unwrap();\n\tlet body: serde_json::Value = serde_json::from_slice(&res).unwrap();\n\n\tlet mut file = File::open(output_file).unwrap();\n\tlet expected: serde_json::Value = serde_json::from_reader(&mut file).unwrap();\n\n\t//eprintln!(\"{body}\");\n\tassert_eq!(body, expected);\n}\n","traces":[],"covered":0,"coverable":0}]} \ No newline at end of file