actix_web_pagination/
parse.rs

1use super::pagination::Pagination;
2use super::pagination_config::PaginationConfig;
3
4use actix_web::dev;
5use actix_web::web;
6use actix_web::FromRequest;
7use actix_web::HttpRequest;
8use futures_util::future;
9
10impl FromRequest for Pagination {
11    type Error = actix_web::Error;
12
13    type Future = future::Ready<actix_web::Result<Self>>;
14
15    type Config = ();
16
17    fn from_request(req: &HttpRequest, _payload: &mut dev::Payload) -> Self::Future {
18        future::ready(Pagination::parse(req))
19    }
20}
21
22impl Pagination {
23    pub(crate) fn parse(req: &HttpRequest) -> actix_web::Result<Pagination> {
24        let config = req
25            .app_data_resolved()
26            .unwrap_or(&PaginationConfig::DEFAULT);
27
28        let mut it = config.pagination();
29        form_urlencoded::parse(req.query_string().as_bytes()).for_each(|(k, v)| match k {
30            _ if k == config.page_name => it.page = config.parse_page(&v) as _,
31            _ if k == config.per_page_name => it.per_page = config.parse_per_page(&v) as _,
32            _ => {}
33        });
34
35        Ok(it)
36    }
37}
38
39trait HttpRequestExt {
40    fn app_data_resolved<T: 'static>(&self) -> Option<&T>;
41}
42
43impl HttpRequestExt for HttpRequest {
44    fn app_data_resolved<T: 'static>(&self) -> Option<&T> {
45        self.app_data()
46            .or_else(|| self.app_data::<web::Data<T>>().map(|it| it.as_ref()))
47    }
48}