///|
/// Validated page request. `cursor` is interpreted as an exclusive boundary.
pub struct PageRequest {
mode : PageMode
limit : Int
cursor : String?
} derive(Debug, Eq)
///|
/// Limits applied before decoding cursors or sorting untrusted input.
pub struct PageLimits {
default_size : Int
max_size : Int
max_sort_fields : Int
max_cursor_chars : Int
max_rows : Int
} derive(Debug, Eq)
///|
pub fn page_limits(
default_size? : Int = 20,
max_size? : Int = 100,
max_sort_fields? : Int = 8,
max_cursor_chars? : Int = 4096,
max_rows? : Int = 100000,
) -> PageLimits {
let safe_max = if max_size < 1 { 1 } else { max_size }
{
default_size: if default_size < 1 {
1
} else if default_size > safe_max {
safe_max
} else {
default_size
},
max_size: safe_max,
max_sort_fields: if max_sort_fields < 1 {
1
} else {
max_sort_fields
},
max_cursor_chars: if max_cursor_chars < 32 {
32
} else {
max_cursor_chars
},
max_rows: if max_rows < 1 {
1
} else {
max_rows
},
}
}
///|
pub fn first_page(
limit? : Int = 0,
after? : String? = None,
limits? : PageLimits = page_limits(),
) -> Result[PageRequest, PageError] {
make_page_request(ForwardPage, limit, after, limits)
}
///|
pub fn last_page(
limit? : Int = 0,
before? : String? = None,
limits? : PageLimits = page_limits(),
) -> Result[PageRequest, PageError] {
make_page_request(BackwardPage, limit, before, limits)
}
///|
fn make_page_request(
mode : PageMode,
requested : Int,
cursor : String?,
limits : PageLimits,
) -> Result[PageRequest, PageError] {
let limit = if requested == 0 { limits.default_size } else { requested }
if limit < 1 || limit > limits.max_size {
return Err(
page_error(
InvalidPageSize,
"limit",
"page size must be positive and not exceed configured maximum",
),
)
}
match cursor {
Some(value) =>
if value.to_array().length() > limits.max_cursor_chars {
return Err(
page_error(
CursorTooLong,
"cursor",
"cursor exceeds configured character limit",
),
)
}
None => ()
}
Ok({ mode, limit, cursor })
}
///|
pub fn PageRequest::mode(self : PageRequest) -> PageMode {
self.mode
}
///|
pub fn PageRequest::limit(self : PageRequest) -> Int {
self.limit
}
///|
pub fn PageRequest::cursor(self : PageRequest) -> String? {
self.cursor
}
///|
pub fn PageLimits::default_size(self : PageLimits) -> Int {
self.default_size
}
///|
pub fn PageLimits::max_size(self : PageLimits) -> Int {
self.max_size
}
///|
pub fn PageLimits::max_sort_fields(self : PageLimits) -> Int {
self.max_sort_fields
}
///|
pub fn PageLimits::max_cursor_chars(self : PageLimits) -> Int {
self.max_cursor_chars
}
///|
pub fn PageLimits::max_rows(self : PageLimits) -> Int {
self.max_rows
}