///|
pub struct OffsetPageInfo {
offset : Int
limit : Int
total : Int
has_previous_page : Bool
has_next_page : Bool
} derive(Debug, Eq)
///|
pub struct OffsetPage {
rows : Array[PageRow]
info : OffsetPageInfo
} derive(Debug, Eq)
///|
pub fn OffsetPage::rows(self : OffsetPage) -> Array[PageRow] {
self.rows.copy()
}
///|
pub fn OffsetPage::info(self : OffsetPage) -> OffsetPageInfo {
self.info
}
///|
pub fn OffsetPageInfo::offset(self : OffsetPageInfo) -> Int {
self.offset
}
///|
pub fn OffsetPageInfo::limit(self : OffsetPageInfo) -> Int {
self.limit
}
///|
pub fn OffsetPageInfo::total(self : OffsetPageInfo) -> Int {
self.total
}
///|
pub fn OffsetPageInfo::has_previous_page(self : OffsetPageInfo) -> Bool {
self.has_previous_page
}
///|
pub fn OffsetPageInfo::has_next_page(self : OffsetPageInfo) -> Bool {
self.has_next_page
}
///|
/// Compatibility mode for APIs that expose numeric pages. It shares sort and
/// limit validation but cannot guarantee mutation stability like keyset mode.
pub fn paginate_offset(
input : Array[PageRow],
sort : Array[SortField],
offset : Int,
limit : Int,
limits? : PageLimits = page_limits(),
) -> Result[OffsetPage, PageError] {
if offset < 0 {
return Err(
page_error(InvalidOffset, "offset", "offset must not be negative"),
)
}
if limit < 1 || limit > limits.max_size {
return Err(
page_error(
InvalidPageSize,
"limit",
"offset page size exceeds configured bounds",
),
)
}
let sorted = match sort_rows(input, sort, limits~) {
Ok(rows) => rows
Err(error) => return Err(error)
}
let start = if offset > sorted.length() { sorted.length() } else { offset }
let end = if start + limit > sorted.length() {
sorted.length()
} else {
start + limit
}
Ok({
rows: sorted[start:end].to_owned(),
info: {
offset: start,
limit,
total: sorted.length(),
has_previous_page: start > 0,
has_next_page: end < sorted.length(),
},
})
}