fix(odm): resolve pagination Clippy failures

This commit is contained in:
overtrue
2026-09-05 11:54:29 +08:00
parent e1f8cb9b89
commit 7b74dfddb0
2 changed files with 25 additions and 25 deletions
@@ -283,19 +283,19 @@ pub struct FetchRequest {
#[derive(Clone, Copy, Debug, PartialEq, Eq, thiserror::Error)] #[derive(Clone, Copy, Debug, PartialEq, Eq, thiserror::Error)]
pub enum ListPageError { pub enum ListPageError {
#[error("truncated listing has no continuation token")] #[error("truncated listing has no continuation token")]
MissingToken, Missing,
#[error("truncated listing has an empty continuation token")] #[error("truncated listing has an empty continuation token")]
EmptyToken, Empty,
#[error("truncated listing repeats a continuation token")] #[error("truncated listing repeats a continuation token")]
RepeatedToken, Repeated,
} }
pub(crate) fn validate_list_page(is_truncated: bool, token: Option<&str>, next_token: Option<&str>) -> Result<(), ListPageError> { pub(crate) fn validate_list_page(is_truncated: bool, token: Option<&str>, next_token: Option<&str>) -> Result<(), ListPageError> {
if is_truncated { if is_truncated {
match next_token { match next_token {
None => return Err(ListPageError::MissingToken), None => return Err(ListPageError::Missing),
Some("") => return Err(ListPageError::EmptyToken), Some("") => return Err(ListPageError::Empty),
Some(next) if Some(next) == token => return Err(ListPageError::RepeatedToken), Some(next) if Some(next) == token => return Err(ListPageError::Repeated),
Some(_) => {} Some(_) => {}
} }
} }
@@ -424,7 +424,7 @@ impl ListThroughMerger {
validate_list_page(is_truncated, token.as_deref(), next_token.as_deref())?; validate_list_page(is_truncated, token.as_deref(), next_token.as_deref())?;
// Also reject a cycle through an earlier page in this bounded fetch. // Also reject a cycle through an earlier page in this bounded fetch.
if is_truncated && state.pages.iter().any(|page| page.token == next_token) { if is_truncated && state.pages.iter().any(|page| page.token == next_token) {
return Err(ListPageError::RepeatedToken); return Err(ListPageError::Repeated);
} }
state.more = is_truncated; state.more = is_truncated;
state.pages.push(FetchedPage { state.pages.push(FetchedPage {
@@ -667,11 +667,11 @@ mod tests {
let Some(suffix) = key.strip_prefix(prefix) else { let Some(suffix) = key.strip_prefix(prefix) else {
continue; continue;
}; };
if let Some(delimiter) = delimiter.filter(|delimiter| !delimiter.is_empty()) { if let Some(delimiter) = delimiter.filter(|delimiter| !delimiter.is_empty())
if let Some((directory, _)) = suffix.split_once(delimiter) { && let Some((directory, _)) = suffix.split_once(delimiter)
namespace.insert(format!("{prefix}{directory}{delimiter}"), true); {
continue; namespace.insert(format!("{prefix}{directory}{delimiter}"), true);
} continue;
} }
namespace.insert(key.clone(), false); namespace.insert(key.clone(), false);
} }
@@ -765,9 +765,9 @@ mod tests {
for side in [MergeSide::Local, MergeSide::Source] { for side in [MergeSide::Local, MergeSide::Source] {
for entries in [vec![], vec![ListEntryKey::object("a")]] { for entries in [vec![], vec![ListEntryKey::object("a")]] {
for (next, expected) in [ for (next, expected) in [
(None, Err(ListPageError::MissingToken)), (None, Err(ListPageError::Missing)),
(Some(""), Err(ListPageError::EmptyToken)), (Some(""), Err(ListPageError::Empty)),
(Some("stuck"), Err(ListPageError::RepeatedToken)), (Some("stuck"), Err(ListPageError::Repeated)),
(Some("advances"), Ok(())), (Some("advances"), Ok(())),
] { ] {
let resume = ListThroughToken::new( let resume = ListThroughToken::new(
@@ -815,7 +815,7 @@ mod tests {
); );
assert_eq!( assert_eq!(
merger.push_page(MergeSide::Source, vec![], true, Some("stuck".into())), merger.push_page(MergeSide::Source, vec![], true, Some("stuck".into())),
Err(ListPageError::RepeatedToken) Err(ListPageError::Repeated)
); );
} }
@@ -868,7 +868,7 @@ mod tests {
.expect("first page advances"); .expect("first page advances");
assert_eq!( assert_eq!(
merger.push_page(MergeSide::Source, vec![], true, Some("first".into())), merger.push_page(MergeSide::Source, vec![], true, Some("first".into())),
Err(ListPageError::RepeatedToken) Err(ListPageError::Repeated)
); );
} }
@@ -884,7 +884,7 @@ mod tests {
assert_eq!(merger.next_fetch().expect("source refill is required").token.as_deref(), Some("stuck")); assert_eq!(merger.next_fetch().expect("source refill is required").token.as_deref(), Some("stuck"));
assert_eq!( assert_eq!(
merger.push_page(MergeSide::Source, vec![], true, Some("stuck".into())), merger.push_page(MergeSide::Source, vec![], true, Some("stuck".into())),
Err(ListPageError::RepeatedToken) Err(ListPageError::Repeated)
); );
merger.disable_source(); merger.disable_source();
let outcome = merger.finish(); let outcome = merger.finish();
@@ -1338,16 +1338,16 @@ mod tests {
.list_objects_v2(None, None, 10) .list_objects_v2(None, None, 10)
.await .await
.expect_err("truncated page without token is corrupt"); .expect_err("truncated page without token is corrupt");
assert!(matches!(err, SourceError::InvalidPagination(ListPageError::MissingToken)), "{err:?}"); assert!(matches!(err, SourceError::InvalidPagination(ListPageError::Missing)), "{err:?}");
} }
#[tokio::test] #[tokio::test]
async fn list_page_validates_s3_cursor_progress_before_mapping_entries() { async fn list_page_validates_s3_cursor_progress_before_mapping_entries() {
for contents in ["", "<Contents><Key>data/a</Key><Size>1</Size></Contents>"] { for contents in ["", "<Contents><Key>data/a</Key><Size>1</Size></Contents>"] {
for (truncated, next, expected) in [ for (truncated, next, expected) in [
(true, None, Some(ListPageError::MissingToken)), (true, None, Some(ListPageError::Missing)),
(true, Some(""), Some(ListPageError::EmptyToken)), (true, Some(""), Some(ListPageError::Empty)),
(true, Some("stuck"), Some(ListPageError::RepeatedToken)), (true, Some("stuck"), Some(ListPageError::Repeated)),
(true, Some("opaque-next"), None), (true, Some("opaque-next"), None),
(false, None, None), (false, None, None),
(false, Some("stuck"), None), (false, Some("stuck"), None),
@@ -1420,9 +1420,9 @@ mod tests {
#[tokio::test] #[tokio::test]
async fn list_page_validates_non_s3_provider_cursors_at_the_common_boundary() { async fn list_page_validates_non_s3_provider_cursors_at_the_common_boundary() {
for (next, expected) in [ for (next, expected) in [
(None, ListPageError::MissingToken), (None, ListPageError::Missing),
(Some(""), ListPageError::EmptyToken), (Some(""), ListPageError::Empty),
(Some("stuck"), ListPageError::RepeatedToken), (Some("stuck"), ListPageError::Repeated),
] { ] {
let mut client = prefix_client(Some("data/".into())); let mut client = prefix_client(Some("data/".into()));
client.backend = Box::new(ListOnlyBackend(SourcePage { client.backend = Box::new(ListOnlyBackend(SourcePage {