• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

Covertness / coap-rs / 25931059598

15 May 2026 05:11PM UTC coverage: 84.871% (-0.4%) from 85.288%
25931059598

Pull #130

github

web-flow
Merge 936cb4815 into 094b60c74
Pull Request #130: Fix all Clippy warnings and enforce Clippy in CI

480 of 567 new or added lines in 19 files covered. (84.66%)

3 existing lines in 2 files now uncovered.

1251 of 1474 relevant lines covered (84.87%)

3.86 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

86.67
/src/router/handler.rs
1
use crate::router::{
2
    extract::FromRequest, macros::all_the_tuples, request::Request, response::IntoResponse,
3
};
4
use std::{future::Future, pin::Pin};
5

6
/// Trait for request handlers.
7
///
8
/// # Generics
9
///
10
/// - `T`: The type of parameters extracted from the request (e.g. path parameters, query parameters, etc.).
11
/// - `S`: The type of the router shared state that can be accessed by the handler.
12
pub trait Handler<T, S>: Clone + Send + Sync + 'static {
13
    /// The type of future calling this handler returns.
14
    type Future: Future<Output = Request> + Send + 'static;
15

16
    /// Call the handler with the given request.
17
    fn call(self, req: Request, state: S) -> Self::Future;
18
}
19

20
impl<S, F, Fut, Res> Handler<(), S> for F
21
where
22
    F: FnOnce() -> Fut + Clone + Send + Sync + 'static,
23
    Fut: Future<Output = Res> + Send,
24
    Res: IntoResponse + 'static,
25
{
26
    type Future = Pin<Box<dyn Future<Output = Request> + Send>>;
27

28
    fn call(self, mut req: Request, _state: S) -> Self::Future {
2✔
29
        Box::pin(async move {
6✔
30
            let result = self().await.into_response();
4✔
31
            result.fill_response(&mut req);
2✔
32
            req
2✔
33
        })
34
    }
35
}
36

37
/// A wrapper struct to allow cloning of handlers that implement the `Handler` trait.
38
pub struct HandlerWrapper<T, S, H: Handler<T, S>> {
39
    handler: H,
40
    _marker: std::marker::PhantomData<(T, S)>,
41
}
42

43
impl<T, S, H> HandlerWrapper<T, S, H>
44
where
45
    H: Handler<T, S> + 'static,
46
    T: 'static,
47
{
48
    /// Creates a new `HandlerWrapper` from a handler that implements the `Handler` trait.
NEW
49
    pub fn new(handler: H) -> Self {
×
50
        Self {
51
            handler,
52
            _marker: std::marker::PhantomData,
53
        }
54
    }
55
}
56

57
impl<T, S, H> Clone for HandlerWrapper<T, S, H>
58
where
59
    H: Handler<T, S> + Clone,
60
{
61
    fn clone(&self) -> Self {
14✔
62
        Self {
63
            handler: self.handler.clone(),
14✔
64
            _marker: std::marker::PhantomData,
65
        }
66
    }
67
}
68

69
/// Type-erased trait for [handlers](Handler) (no `T` parameter)
70
pub trait BoxableHandler<S>: Send + Sync + 'static {
71
    /// Call the handler with the given request and state.
72
    fn call(&self, req: Request, state: S) -> Pin<Box<dyn Future<Output = Request> + Send>>;
73

74
    /// Clone the handler into a boxed trait object.
75
    fn clone_box(&self) -> Box<dyn BoxableHandler<S>>;
76
}
77

78
// Enable cloning of boxed handlers
79
impl<S: 'static> Clone for Box<dyn BoxableHandler<S>> {
80
    fn clone(&self) -> Self {
2✔
81
        self.clone_box()
2✔
82
    }
83
}
84

85
impl<T, S, H> BoxableHandler<S> for HandlerWrapper<T, S, H>
86
where
87
    T: Sync + Send + 'static,
88
    S: Send + Sync + 'static,
89
    H: Handler<T, S> + Clone + Send + Sync + 'static,
90
{
91
    fn call(&self, req: Request, state: S) -> Pin<Box<dyn Future<Output = Request> + Send>> {
14✔
92
        let clone = self.clone();
14✔
93
        Box::pin(H::call(clone.handler, req, state))
28✔
94
    }
95
    fn clone_box(&self) -> Box<dyn BoxableHandler<S>> {
13✔
96
        Box::new(self.clone())
13✔
97
    }
98
}
99

100
/// Type alias for a boxed, type-erased [`Handler`].
101
pub type BoxedHandler<S> = Box<dyn BoxableHandler<S>>;
102

103
// Macro to implement Handler for tuples of parameters extracted from the request
104
macro_rules! impl_handler {
105
    (
106
        [$($ty:ident),*], $last:ident
107
    ) => {
108
        #[allow(non_snake_case, unused_mut)]
109
        impl<$($ty,)* $last, S, F, Fut, Res> Handler<($($ty,)* $last,), S> for F
110
        where
111
            S: Send + Sync + 'static,
112
            F: FnOnce($($ty,)* $last,) -> Fut + Clone + Send + Sync + 'static,
113
            Fut: Future<Output = Res> + Send,
114
            Res: IntoResponse,
115
            $( $ty: FromRequest<S> + Send, )*
116
            $last: FromRequest<S> + Send,
117
        {
118
            type Future = Pin<Box<dyn Future<Output = Request> + Send>>;
119

120
            fn call(self, mut req: Request, state: S) -> Self::Future {
12✔
121
                Box::pin(async move {
36✔
122
                    $(
123
                        let $ty = match $ty::from_request(&req, &state).await {
14✔
124
                            Ok(value) => value,
7✔
125
                            Err(rejection) => {
1✔
126
                                rejection.into_response().fill_response(&mut req);
2✔
127
                                return req;
1✔
128
                            }
129
                        };
130
                    )*
131

132
                    let $last = match $last::from_request( &req, &state).await {
24✔
133
                        Ok(value) => value,
12✔
NEW
134
                        Err(rejection) => {
×
NEW
135
                            rejection.into_response().fill_response(&mut req);
×
NEW
136
                            return req;
×
137
                        }
138
                    };
139

140
                    let response = self($($ty,)* $last,).await;
24✔
141
                    response.into_response().fill_response(&mut req);
12✔
142
                    req
12✔
143
                })
144
            }
145
        }
146
    };
147
}
148

149
all_the_tuples!(impl_handler);
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc