tina-core 0.0.2

Tina platform
Documentation
//! 分页

use crate::tina::server::session::Session;

/// 分布扩展
pub trait PageRequestExt {
    /// 对象
    type Target;
    /// 最大记录数
    fn max_records(session: &Session) -> Self::Target;
    /// 最小记录数
    fn min_records(session: &Session) -> Self::Target;
    /// 最大页数
    fn max_page_no(session: &Session) -> Self::Target;
    /// 最小页数
    fn min_page_no(session: &Session) -> Self::Target;
    /// 用于export的PageRequest
    fn export(session: &Session) -> Self::Target;
    /// 最大记录数
    fn with_max_records(self, session: &Session) -> Self::Target;
    /// 最小记录数
    fn with_min_records(self, session: &Session) -> Self::Target;
    /// 最大页数
    fn with_max_page_no(self, session: &Session) -> Self::Target;
    /// 最小页数
    fn with_min_page_no(self, session: &Session) -> Self::Target;
    /// 用于export的PageRequest
    fn with_export(self, session: &Session) -> Self::Target;
}

/// Page元素扩展
pub trait PageExt<T> {
    /// 第一个
    fn first(&self) -> Option<&T>;
    /// 第一个(可变)
    fn first_mut(&mut self) -> Option<&mut T>;
    /// 提取第一个
    fn take_first(&mut self) -> Option<T>;
    /// 转换为第一个元素
    fn into_first(self) -> Option<T>;
    /// 最后一个
    fn last(&self) -> Option<&T>;
    /// 最后一个(可变)
    fn last_mut(&mut self) -> Option<&mut T>;
    /// 提取最后一个
    fn take_last(&mut self) -> Option<T>;
    /// 转换为最后一个元素
    fn into_last(self) -> Option<T>;
    /// 从列表构建(带总数)
    fn from_records_with_total(records: Vec<T>, page_num: u64, page_size: u64, total: u64) -> Self
    where
        Self: Sized;
    /// 从列表构建(不带总数)
    fn from_records_without_total(records: Vec<T>, page_num: u64, page_size: u64) -> Self
    where
        Self: Sized;
}

/// Page元素转换
pub trait PageExtMap<T, U> {
    /// 转换成的Page
    type MapTo;
    /// 转换元素
    fn map<F: Fn(T) -> U + Copy + Clone>(self, f: F) -> Self::MapTo;
}

#[cfg(all(feature = "rbatis", feature = "rbs"))]
mod rbatis {
    use rbatis::sql::{Page, PageRequest};

    use crate::tina::{constant::Constants, data::AppResult, server::session::Session};

    use super::{PageExt, PageExtMap, PageRequestExt};

    impl PageRequestExt for PageRequest {
        type Target = AppResult<PageRequest>;

        fn max_records(session: &Session) -> Self::Target {
            let application = session.get_application();
            let server_config = application.get_server_config()?;
            let mut page = PageRequest::new(1, server_config.max_query_rows);
            page.search_count = false;
            Ok(page)
        }

        fn min_records(_session: &Session) -> Self::Target {
            let mut page = PageRequest::new(1, 1);
            page.search_count = false;
            Ok(page)
        }

        fn max_page_no(_session: &Session) -> Self::Target {
            let mut page = PageRequest::new(u64::MAX, Constants::DEFAULT_PAGE_SIZE);
            page.search_count = false;
            Ok(page)
        }

        fn min_page_no(_session: &Session) -> Self::Target {
            let mut page = PageRequest::new(1, Constants::DEFAULT_PAGE_SIZE);
            page.search_count = false;
            Ok(page)
        }

        fn export(session: &Session) -> Self::Target {
            let mut page = PageRequest::max_records(session)?;
            page.search_count = true;
            Ok(page)
        }

        fn with_max_records(mut self, session: &Session) -> Self::Target {
            let application = session.get_application();
            let server_config = application.get_server_config()?;
            self.page_size = server_config.max_query_rows;
            Ok(self)
        }

        fn with_min_records(mut self, _session: &Session) -> Self::Target {
            self.page_size = 1;
            Ok(self)
        }

        fn with_max_page_no(mut self, _session: &Session) -> Self::Target {
            self.page_no = u64::MAX;
            Ok(self)
        }

        fn with_min_page_no(mut self, _session: &Session) -> Self::Target {
            self.page_no = 1;
            Ok(self)
        }

        fn with_export(self, session: &Session) -> Self::Target {
            Self::export(session)
        }
    }

    impl<T> PageExt<T> for Page<T> {
        fn first(&self) -> Option<&T> {
            match self.records.is_empty() {
                true => None,
                false => self.records.first(),
            }
        }

        fn first_mut(&mut self) -> Option<&mut T> {
            match self.records.is_empty() {
                true => None,
                false => self.records.first_mut(),
            }
        }

        fn take_first(&mut self) -> Option<T> {
            match self.records.is_empty() {
                true => None,
                false => Some(self.records.remove(0)),
            }
        }

        fn into_first(mut self) -> Option<T> {
            match self.records.is_empty() {
                true => None,
                false => Some(self.records.remove(0)),
            }
        }

        fn last(&self) -> Option<&T> {
            match self.records.is_empty() {
                true => None,
                false => self.records.last(),
            }
        }

        fn last_mut(&mut self) -> Option<&mut T> {
            match self.records.is_empty() {
                true => None,
                false => self.records.last_mut(),
            }
        }

        fn take_last(&mut self) -> Option<T> {
            match self.records.is_empty() {
                true => None,
                false => Some(self.records.remove(self.records.len() - 1)),
            }
        }

        fn into_last(mut self) -> Option<T> {
            match self.records.is_empty() {
                true => None,
                false => Some(self.records.remove(self.records.len() - 1)),
            }
        }

        fn from_records_with_total(records: Vec<T>, page_num: u64, page_size: u64, total: u64) -> Self
        where
            Self: Sized,
        {
            let add = match total % page_size > 0 {
                true => 1,
                false => 0,
            };
            let pages = (total / page_size) + add;
            Self {
                records,
                total,
                pages,
                page_no: page_num,
                page_size,
                search_count: true,
            }
        }

        fn from_records_without_total(records: Vec<T>, page_num: u64, page_size: u64) -> Self
        where
            Self: Sized,
        {
            let len = records.len() as u64;
            let pages = match len >= page_size {
                true => page_num + 1,
                false => page_num,
            };
            let total = match len >= page_size {
                true => page_num * page_size + 1,
                false => {
                    let page_index = match page_num > 0 {
                        true => page_num - 1,
                        false => 0,
                    };
                    page_index * page_size + len
                }
            };
            Self {
                records,
                total,
                pages,
                page_no: page_num,
                page_size,
                search_count: false,
            }
        }
    }

    impl<T, U> PageExtMap<T, U> for Page<T> {
        type MapTo = Page<U>;

        fn map<F: Fn(T) -> U + Copy + Clone>(self, f: F) -> Self::MapTo {
            Self::MapTo {
                records: self.records.into_iter().map(f).collect(),
                total: self.total,
                pages: self.pages,
                page_no: self.page_no,
                page_size: self.page_size,
                search_count: self.search_count,
            }
        }
    }
}