Skip to content

Commit b322453

Browse files
committed
feat: relax handler bounds, add more utility impls
1 parent ef5ea89 commit b322453

File tree

9 files changed

+113
-105
lines changed

9 files changed

+113
-105
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ Here's a quick example that can do the following:
2929
```rust
3030
use axum::{Router, response::IntoResponse};
3131
use axum_codec::{
32-
handler::IntoCodecResponse,
32+
response::IntoCodecResponse,
3333
routing::{get, post},
3434
Codec,
3535
extract::Accept,

examples/aide-validator/src/main.rs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
use std::sync::Arc;
22

33
use aide::axum::ApiRouter;
4-
use axum::{extract::State, response::IntoResponse, Extension};
4+
use axum::{extract::State, Extension};
55
use axum_codec::{
6-
handler::IntoCodecResponse,
76
routing::{get, post},
8-
Codec,
7+
Codec, IntoCodecResponse,
98
};
109

1110
#[axum_codec::apply(encode, decode)]
@@ -37,7 +36,7 @@ async fn state(State(state): State<String>) -> Codec<Greeting> {
3736
Codec(Greeting { message: state })
3837
}
3938

40-
async fn openapi(Extension(api): Extension<Arc<aide::openapi::OpenApi>>) -> impl IntoResponse {
39+
async fn openapi(Extension(api): Extension<Arc<aide::openapi::OpenApi>>) -> impl IntoCodecResponse {
4140
axum::Json(api)
4241
}
4342

@@ -49,7 +48,7 @@ async fn main() {
4948
.api_route("/me", get(me).into())
5049
.api_route("/greet", post(greet).into())
5150
.api_route("/state", get(state).into())
52-
.route("/openapi.json", axum::routing::get(openapi))
51+
.route("/openapi.json", get(openapi))
5352
.finish_api(&mut api)
5453
.layer(Extension(Arc::new(api)))
5554
.with_state("Hello, world!".to_string());

examples/basic/src/main.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,8 @@ use axum::{
33
Router,
44
};
55
use axum_codec::{
6-
handler::IntoCodecResponse,
76
routing::{get, post},
8-
Codec,
7+
Codec, IntoCodecResponse,
98
};
109

1110
#[axum_codec::apply(encode, decode)]

macros/src/lib.rs

Lines changed: 0 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -253,17 +253,6 @@ mod __private {
253253
});
254254
}
255255

256-
#[cfg(feature = "aide")]
257-
{
258-
if !constraints.is_empty() {
259-
constraints.extend(quote! { + });
260-
}
261-
262-
constraints.extend(quote! {
263-
schemars::JsonSchema
264-
});
265-
}
266-
267256
#[cfg(feature = "validator")]
268257
{
269258
if !constraints.is_empty() {
@@ -350,17 +339,6 @@ mod __private {
350339
});
351340
}
352341

353-
#[cfg(feature = "aide")]
354-
{
355-
if !constraints.is_empty() {
356-
constraints.extend(quote! { + });
357-
}
358-
359-
constraints.extend(quote! {
360-
schemars::JsonSchema
361-
});
362-
}
363-
364342
codec_trait.extend(constraints.clone());
365343
codec_impl.extend(constraints);
366344

src/handler.rs

Lines changed: 15 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -6,46 +6,7 @@ use axum::{
66
response::{IntoResponse, Response},
77
};
88

9-
use crate::{Accept, Codec, CodecEncode, ContentType};
10-
11-
#[cfg(not(feature = "aide"))]
12-
pub trait IntoCodecResponse {
13-
fn into_codec_response(self, content_type: ContentType) -> Response;
14-
}
15-
16-
#[cfg(feature = "aide")]
17-
pub trait IntoCodecResponse: schemars::JsonSchema {
18-
fn into_codec_response(self, content_type: ContentType) -> Response;
19-
}
20-
21-
#[cfg(not(feature = "aide"))]
22-
impl<R> IntoCodecResponse for R
23-
where
24-
R: IntoResponse,
25-
{
26-
fn into_codec_response(self, _content_type: ContentType) -> Response {
27-
self.into_response()
28-
}
29-
}
30-
31-
#[cfg(feature = "aide")]
32-
impl<R> IntoCodecResponse for R
33-
where
34-
R: IntoResponse + schemars::JsonSchema,
35-
{
36-
fn into_codec_response(self, _content_type: ContentType) -> Response {
37-
self.into_response()
38-
}
39-
}
40-
41-
impl<D> IntoCodecResponse for Codec<D>
42-
where
43-
D: CodecEncode,
44-
{
45-
fn into_codec_response(self, content_type: ContentType) -> Response {
46-
self.to_response(content_type)
47-
}
48-
}
9+
use crate::{Accept, IntoCodecResponse};
4910

5011
#[cfg(not(feature = "aide"))]
5112
pub trait Input {}
@@ -114,30 +75,38 @@ where
11475
#[cfg(feature = "aide")]
11576
impl<H, I, D> aide::OperationOutput for CodecHandlerFn<H, I, D>
11677
where
117-
Codec<D>: aide::OperationOutput,
78+
D: aide::OperationOutput,
11879
{
119-
type Inner = <Codec<D> as aide::OperationOutput>::Inner;
80+
type Inner = D;
12081

12182
fn operation_response(
12283
ctx: &mut aide::gen::GenContext,
12384
operation: &mut aide::openapi::Operation,
12485
) -> Option<aide::openapi::Response> {
125-
<Codec<D> as aide::OperationOutput>::operation_response(ctx, operation)
86+
D::operation_response(ctx, operation)
12687
}
12788

12889
fn inferred_responses(
12990
ctx: &mut aide::gen::GenContext,
13091
operation: &mut aide::openapi::Operation,
13192
) -> Vec<(Option<u16>, aide::openapi::Response)> {
132-
<Codec<D> as aide::OperationOutput>::inferred_responses(ctx, operation)
93+
D::inferred_responses(ctx, operation)
13394
}
13495
}
13596

13697
#[cfg(feature = "aide")]
137-
impl<F, I, D> aide::operation::OperationHandler<I, Codec<D>> for CodecHandlerFn<F, I, D>
98+
impl<F, I, D> aide::operation::OperationHandler<I, crate::Codec<D>> for CodecHandlerFn<F, I, D>
99+
where
100+
I: aide::OperationInput,
101+
D: schemars::JsonSchema,
102+
{
103+
}
104+
105+
#[cfg(feature = "aide")]
106+
impl<F, I, D> aide::operation::OperationHandler<I, D> for CodecHandlerFn<F, I, D>
138107
where
139108
I: aide::OperationInput,
140-
Codec<D>: aide::OperationOutput,
109+
D: aide::OperationOutput,
141110
{
142111
}
143112

src/lib.rs

Lines changed: 3 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ mod encode;
99
pub mod extract;
1010
pub mod handler;
1111
mod rejection;
12+
pub mod response;
1213
pub mod routing;
1314

1415
use core::{
@@ -18,7 +19,7 @@ use core::{
1819

1920
pub use {
2021
content::ContentType, decode::CodecDecode, encode::CodecEncode, extract::Accept,
21-
handler::CodecHandler, rejection::CodecRejection,
22+
handler::CodecHandler, rejection::CodecRejection, response::IntoCodecResponse,
2223
};
2324

2425
use axum::{
@@ -44,7 +45,6 @@ pub mod __private {
4445

4546
pub use axum_codec_macros as macros;
4647

47-
use handler::IntoCodecResponse;
4848
#[cfg(feature = "macros")]
4949
pub use macros::apply;
5050

@@ -166,20 +166,6 @@ where
166166
}
167167
}
168168

169-
#[cfg(feature = "aide")]
170-
impl<T> schemars::JsonSchema for Codec<T>
171-
where
172-
T: schemars::JsonSchema,
173-
{
174-
fn schema_name() -> String {
175-
T::schema_name()
176-
}
177-
178-
fn json_schema(gen: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema {
179-
T::json_schema(gen)
180-
}
181-
}
182-
183169
#[cfg(feature = "aide")]
184170
impl<T> aide::operation::OperationInput for Codec<T>
185171
where
@@ -202,7 +188,7 @@ impl<T> aide::operation::OperationOutput for Codec<T>
202188
where
203189
T: schemars::JsonSchema,
204190
{
205-
type Inner = <axum::Json<T> as aide::operation::OperationOutput>::Inner;
191+
type Inner = T;
206192

207193
fn operation_response(
208194
ctx: &mut aide::gen::GenContext,

src/rejection.rs

Lines changed: 33 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use axum::{extract::rejection::BytesRejection, response::Response};
22

3-
use crate::{handler::IntoCodecResponse, ContentType};
3+
use crate::{ContentType, IntoCodecResponse};
44

55
/// Rejection used for [`Codec`](crate::Codec).
66
///
@@ -47,13 +47,21 @@ impl IntoCodecResponse for CodecRejection {
4747
}
4848

4949
#[cfg(feature = "aide")]
50-
impl schemars::JsonSchema for CodecRejection {
51-
fn schema_name() -> String {
52-
Message::schema_name()
50+
impl aide::OperationOutput for CodecRejection {
51+
type Inner = Message;
52+
53+
fn operation_response(
54+
ctx: &mut aide::gen::GenContext,
55+
operation: &mut aide::openapi::Operation,
56+
) -> Option<aide::openapi::Response> {
57+
axum::Json::<Message>::operation_response(ctx, operation)
5358
}
5459

55-
fn json_schema(gen: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema {
56-
Message::json_schema(gen)
60+
fn inferred_responses(
61+
ctx: &mut aide::gen::GenContext,
62+
operation: &mut aide::openapi::Operation,
63+
) -> Vec<(Option<u16>, aide::openapi::Response)> {
64+
axum::Json::<Message>::inferred_responses(ctx, operation)
5765
}
5866
}
5967

@@ -77,6 +85,25 @@ pub struct Message {
7785
pub content: String,
7886
}
7987

88+
#[cfg(feature = "aide")]
89+
impl aide::OperationOutput for Message {
90+
type Inner = Self;
91+
92+
fn operation_response(
93+
ctx: &mut aide::gen::GenContext,
94+
operation: &mut aide::openapi::Operation,
95+
) -> Option<aide::openapi::Response> {
96+
axum::Json::<Self>::operation_response(ctx, operation)
97+
}
98+
99+
fn inferred_responses(
100+
ctx: &mut aide::gen::GenContext,
101+
operation: &mut aide::openapi::Operation,
102+
) -> Vec<(Option<u16>, aide::openapi::Response)> {
103+
axum::Json::<Self>::inferred_responses(ctx, operation)
104+
}
105+
}
106+
80107
impl CodecRejection {
81108
/// Consumes the rejection and returns a pretty [`Message`] representing the error.
82109
///

src/response.rs

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
use axum::response::{IntoResponse, Response};
2+
3+
use crate::{Codec, CodecEncode, ContentType};
4+
5+
#[cfg(not(feature = "aide"))]
6+
pub trait IntoCodecResponse {
7+
fn into_codec_response(self, content_type: ContentType) -> Response;
8+
}
9+
10+
#[cfg(feature = "aide")]
11+
pub trait IntoCodecResponse: aide::OperationOutput {
12+
fn into_codec_response(self, content_type: ContentType) -> Response;
13+
}
14+
15+
#[cfg(not(feature = "aide"))]
16+
impl<R> IntoCodecResponse for R
17+
where
18+
R: IntoResponse,
19+
{
20+
fn into_codec_response(self, _content_type: ContentType) -> Response {
21+
self.into_response()
22+
}
23+
}
24+
25+
#[cfg(feature = "aide")]
26+
impl<R> IntoCodecResponse for R
27+
where
28+
R: IntoResponse + aide::OperationOutput,
29+
{
30+
fn into_codec_response(self, _content_type: ContentType) -> Response {
31+
self.into_response()
32+
}
33+
}
34+
35+
#[cfg(not(feature = "aide"))]
36+
impl<D> IntoCodecResponse for Codec<D>
37+
where
38+
D: CodecEncode,
39+
{
40+
fn into_codec_response(self, content_type: ContentType) -> Response {
41+
self.to_response(content_type)
42+
}
43+
}
44+
45+
#[cfg(feature = "aide")]
46+
impl<D> IntoCodecResponse for Codec<D>
47+
where
48+
D: CodecEncode,
49+
Self: aide::OperationOutput,
50+
{
51+
fn into_codec_response(self, content_type: ContentType) -> Response {
52+
self.to_response(content_type)
53+
}
54+
}

src/routing.rs

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ use std::convert::Infallible;
33
use axum::routing;
44

55
use crate::{
6-
handler::{CodecHandlerFn, Input, IntoCodecResponse},
7-
CodecHandler,
6+
handler::{CodecHandlerFn, Input},
7+
CodecHandler, IntoCodecResponse,
88
};
99

1010
/// A light wrapper around axum's [`MethodRouter`](axum::routing::MethodRouter) (or [`ApiMethodRouter`](aide::axum::routing::ApiMethodRouter) if the `aide` feature is enabled).
@@ -98,7 +98,6 @@ macro_rules! method_router_chain_method {
9898
H: CodecHandler<T, I, D, S> + Clone + Send + Sync + 'static,
9999
I: Input + Send + 'static,
100100
D: IntoCodecResponse + Send + 'static,
101-
crate::Codec<D>: aide::OperationOutput,
102101
S: Clone + Send + Sync + 'static,
103102
T: 'static,
104103
{
@@ -113,7 +112,6 @@ macro_rules! method_router_chain_method {
113112
H: CodecHandler<T, I, D, S> + Clone + Send + Sync + 'static,
114113
I: Input + Send + 'static,
115114
D: IntoCodecResponse + Send + 'static,
116-
crate::Codec<D>: aide::OperationOutput,
117115
S: Clone + Send + Sync + 'static,
118116
T: 'static,
119117
F: FnOnce(aide::transform::TransformOperation) -> aide::transform::TransformOperation,
@@ -164,7 +162,6 @@ macro_rules! method_router_top_level {
164162
H: CodecHandler<T, I, D, S> + Clone + Send + Sync + 'static,
165163
I: Input + Send + 'static,
166164
D: IntoCodecResponse + Send + 'static,
167-
crate::Codec<D>: aide::OperationOutput,
168165
S: Clone + Send + Sync + 'static,
169166
T: 'static,
170167
{
@@ -180,7 +177,6 @@ macro_rules! method_router_top_level {
180177
H: CodecHandler<T, I, D, S> + Clone + Send + Sync + 'static,
181178
I: Input + Send + 'static,
182179
D: IntoCodecResponse + Send + Sync + 'static,
183-
crate::Codec<D>: aide::OperationOutput,
184180
S: Clone + Send + Sync + 'static,
185181
T: 'static,
186182
F: FnOnce(aide::transform::TransformOperation) -> aide::transform::TransformOperation,

0 commit comments

Comments
 (0)