This commit is contained in:
Claude committed 2026-10-11 11:39:25 +00:00
commit 14679de823
1 file changed
+22 -2
+22 -2
View File
@@ -59,6 +59,12 @@ fn photo_arg(s: &Session, p: &Value, c: &str) -> crate::Result<PhotoId> {
}
}
// Catalog queries also run in the 32-bit web build. A narrowing cast wraps
// an out-of-range offset to zero, returning the first page instead of no photos.
fn pagination_usize(value: u64) -> usize {
usize::try_from(value).unwrap_or(usize::MAX)
}
pub fn specs() -> Vec<CommandSpec> {
vec![
cmd!(query "catalog.query", "Query Photos", [], None, "{filter?: Filter, sort?: Sort, offset?, limit?} — omit filter to list the current view", always, |s, p| {
@@ -69,8 +75,8 @@ pub fn specs() -> Vec<CommandSpec> {
} else {
s.visible_cloned()
};
let off = p.get("offset").and_then(Value::as_u64).unwrap_or(0) as usize;
let lim = p.get("limit").and_then(Value::as_u64).unwrap_or(200) as usize;
let off = pagination_usize(p.get("offset").and_then(Value::as_u64).unwrap_or(0));
let lim = pagination_usize(p.get("limit").and_then(Value::as_u64).unwrap_or(200));
let items: Vec<Value> = ids.iter().skip(off).take(lim).filter_map(|id| s.catalog.photo(*id)).map(|p| photo_summary(p)).collect();
Ok(json!({"total": ids.len(), "photos": items}))
}),
@@ -237,3 +243,17 @@ pub fn specs() -> Vec<CommandSpec> {
}),
]
}
#[cfg(test)]
mod pagination_tests {
use super::*;
#[test]
fn offsets_and_limits_saturate_instead_of_wrapping_on_wasm() {
assert_eq!(pagination_usize(0), 0);
assert_eq!(pagination_usize(200), 200);
assert_eq!(pagination_usize(u64::MAX), usize::MAX);
#[cfg(target_pointer_width = "32")]
assert_eq!(pagination_usize(u64::from(u32::MAX) + 1), usize::MAX);
}
}