restrepo 0.5.12

A collection of components for building restful webservices with actix-web
Documentation
use serde::Deserialize;

/// Query parameters to implement pagination
/// Example
/// ```
/// use actix_web::{Error, http::StatusCode, Responder, web::Query};
/// use restrepo::server::PaginationConfig;
///
/// async fn handler(pagination: Query<PaginationConfig>) -> impl Responder {
///     format!("Return page #{} with {} entries",
///         pagination.page().unwrap_or_default(),
///         pagination.page_size().unwrap_or_default()
///     )
/// }
/// ```
#[derive(Debug, Deserialize)]
pub struct PaginationConfig {
    page: Option<u32>,
    page_size: Option<u32>,
}

impl PaginationConfig {
    /// Helper method for use with SQL statements. Calculates the number of entries to skip.
    /// If no query parameters were provided, this will return 0.
    pub fn offset(&self) -> u32 {
        self.page_size.unwrap_or_default() * (self.page.unwrap_or(1) - 1)
    }

    /// Helper method for use with SQL statements. Returns the requested maximum number of entries.
    /// If no query parameters were provided, this will return 0.
    pub fn limit(&self) -> u32 {
        self.page_size.unwrap_or_default()
    }

    pub fn page(&self) -> Option<u32> {
        self.page
    }

    pub fn page_size(&self) -> Option<u32> {
        self.page_size
    }
}

#[cfg(test)]
mod tests {
    use actix_web::{
        App, Responder,
        web::{Bytes, Query, get},
    };

    use super::*;

    async fn test_handler(pagination: Query<PaginationConfig>) -> impl Responder {
        format!("{},{}", pagination.limit(), pagination.offset())
    }

    #[test]
    fn test_unset_pagination_config() {
        let pc = PaginationConfig {
            page: None,
            page_size: None,
        };
        assert_eq!(pc.limit(), 0);
        assert_eq!(pc.offset(), 0)
    }

    #[test]
    fn test_pagination_config() {
        let pc = PaginationConfig {
            page: Some(2),
            page_size: Some(40),
        };
        assert_eq!(pc.limit(), pc.offset());
    }

    #[actix_web::test]
    async fn test_pagination_config_as_query_parameters() {
        let test_app =
            actix_web::test::init_service(App::new().route("/", get().to(test_handler))).await;
        let req_pagination = actix_web::test::TestRequest::get()
            .uri("/?page=2&page_size=40")
            .to_request();
        let req_no_pagination = actix_web::test::TestRequest::get().uri("/").to_request();
        let result_pagination =
            actix_web::test::call_and_read_body(&test_app, req_pagination).await;
        let result_no_pagination =
            actix_web::test::call_and_read_body(&test_app, req_no_pagination).await;
        assert_eq!(result_pagination, Bytes::from_static(b"40,40"));
        assert_eq!(result_no_pagination, Bytes::from_static(b"0,0"));
    }
}