refactor(blahd): use NonZero/u32 for page length

This avoids platform-dependent `usize` in configuration and webapi.
This commit is contained in:
oxalica 2024-09-23 17:58:10 -04:00
parent 82f69eb96a
commit 1e8c16888c
2 changed files with 19 additions and 15 deletions

View file

@ -1,3 +1,4 @@
use std::num::NonZero;
use std::path::PathBuf;
use anyhow::{ensure, Context};
@ -283,7 +284,11 @@ pub trait TransactionOps {
.map_err(Into::into)
}
fn list_public_rooms(&self, start_rid: Id, page_len: usize) -> Result<Vec<RoomMetadata>> {
fn list_public_rooms(
&self,
start_rid: Id,
page_len: NonZero<u32>,
) -> Result<Vec<RoomMetadata>> {
// Attribute check must be written in the SQL literal so the query planer
// can successfully pick the conditional index.
const _: () = assert!(RoomAttrs::PUBLIC_READABLE.bits() == 1);
@ -312,7 +317,7 @@ pub trait TransactionOps {
&self,
uid: i64,
start_rid: Id,
page_len: usize,
page_len: NonZero<u32>,
) -> Result<Vec<RoomMetadata>> {
prepare_cached_and_bind!(
self.conn(),
@ -344,7 +349,7 @@ pub trait TransactionOps {
&self,
uid: i64,
start_rid: Id,
page_len: usize,
page_len: NonZero<u32>,
) -> Result<Vec<RoomMetadata>> {
prepare_cached_and_bind!(
self.conn(),
@ -385,7 +390,7 @@ pub trait TransactionOps {
rid: Id,
after_cid: Id,
before_cid: Id,
page_len: usize,
page_len: NonZero<u32>,
) -> Result<Vec<WithMsgId<SignedChatMsg>>> {
prepare_cached_and_bind!(
self.conn(),

View file

@ -1,4 +1,4 @@
use std::num::NonZeroUsize;
use std::num::NonZero;
use std::sync::Arc;
use std::time::{Duration, SystemTime};
@ -47,7 +47,7 @@ pub struct ServerConfig {
pub base_url: Url,
#[serde_inline_default(1024.try_into().expect("not zero"))]
pub max_page_len: NonZeroUsize,
pub max_page_len: NonZero<u32>,
#[serde_inline_default(4096)] // 4KiB
pub max_request_len: usize,
@ -220,7 +220,7 @@ struct ListRoomParams {
// Workaround: serde(flatten) breaks deserialization
// See: https://github.com/nox/serde_urlencoded/issues/33
skip_token: Option<Id>,
top: Option<NonZeroUsize>,
top: Option<NonZero<u32>>,
}
#[derive(Debug, Clone, Copy, Deserialize)]
@ -260,8 +260,8 @@ async fn room_list(
}
})?;
let skip_token =
(rooms.len() == page_len).then(|| rooms.last().expect("page must not be empty").rid);
let skip_token = (rooms.len() as u32 == page_len.get())
.then(|| rooms.last().expect("page must not be empty").rid);
Ok(Json(RoomList { rooms, skip_token }))
}
@ -354,18 +354,17 @@ struct Pagination {
/// A opaque token from previous response to fetch the next page.
skip_token: Option<Id>,
/// Maximum page size.
top: Option<NonZeroUsize>,
top: Option<NonZero<u32>>,
/// Only return items before (excluding) this token.
/// Useful for `room_msg_list` to pass `last_seen_cid` without over-fetching.
until_token: Option<Id>,
}
impl Pagination {
fn effective_page_len(&self, st: &AppState) -> usize {
fn effective_page_len(&self, st: &AppState) -> NonZero<u32> {
self.top
.unwrap_or(usize::MAX.try_into().expect("not zero"))
.unwrap_or(u32::MAX.try_into().expect("not zero"))
.min(st.config.max_page_len)
.get()
}
}
@ -544,8 +543,8 @@ fn query_room_msgs(
pagination.skip_token.unwrap_or(Id::MAX),
page_len,
)?;
let skip_token =
(msgs.len() == page_len).then(|| msgs.last().expect("page must not be empty").cid);
let skip_token = (msgs.len() as u32 == page_len.get())
.then(|| msgs.last().expect("page must not be empty").cid);
Ok((msgs, skip_token))
}