Skip to content

Commit 82f4ca2

Browse files
committed
Add reconstructed ListBlobs marker as an experimental feature
1 parent c14ade2 commit 82f4ca2

File tree

3 files changed

+52
-0
lines changed

3 files changed

+52
-0
lines changed

object_store/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ aws = ["cloud", "md-5"]
6767
http = ["cloud"]
6868
tls-webpki-roots = ["reqwest?/rustls-tls-webpki-roots"]
6969
integration = []
70+
experimental-azure-list-offset = []
7071

7172
[dev-dependencies] # In alphabetical order
7273
futures-test = "0.3"

object_store/src/azure/client.rs

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -559,6 +559,19 @@ impl GetClient for AzureClient {
559559
}
560560
}
561561

562+
#[cfg(feature = "experimental-azure-list-offset")]
563+
fn marker_for_offset(offset: &str, is_emulator: bool) -> String {
564+
if is_emulator {
565+
return offset.to_string();
566+
} else {
567+
let encoded_part = BASE64_STANDARD.encode(
568+
&format!("{:06}!{} !000028!9999-12-31T23:59:59.9999999Z!", offset.len() + 1, offset)
569+
).replace("=", "-");
570+
let length_string = format!("{}", encoded_part.len());
571+
return format!("{}!{}!{}", length_string.len(), length_string, encoded_part);
572+
}
573+
}
574+
562575
#[async_trait]
563576
impl ListClient for AzureClient {
564577
/// Make an Azure List request <https://docs.microsoft.com/en-us/rest/api/storageservices/list-blobs>
@@ -569,6 +582,7 @@ impl ListClient for AzureClient {
569582
token: Option<&str>,
570583
offset: Option<&str>,
571584
) -> Result<(ListResult, Option<String>)> {
585+
#[cfg(not(feature = "experimental-azure-list-offset"))]
572586
assert!(offset.is_none()); // Not yet supported
573587

574588
let credential = self.get_credential().await?;
@@ -586,6 +600,22 @@ impl ListClient for AzureClient {
586600
query.push(("delimiter", DELIMITER))
587601
}
588602

603+
#[cfg(feature = "experimental-azure-list-offset")]
604+
let token_string = match (token, offset) {
605+
(Some(token), _) => {
606+
Some(token.to_string())
607+
}
608+
(None, Some(offset)) => {
609+
Some(marker_for_offset(offset, self.config.is_emulator))
610+
}
611+
(None, None) => {
612+
None
613+
}
614+
};
615+
616+
#[cfg(feature = "experimental-azure-list-offset")]
617+
let token = token_string.as_deref();
618+
589619
if let Some(token) = token {
590620
query.push(("marker", token))
591621
}
@@ -967,4 +997,16 @@ mod tests {
967997
let _delegated_key_response_internal: UserDelegationKey =
968998
quick_xml::de::from_str(S).unwrap();
969999
}
1000+
1001+
#[cfg(feature = "experimental-azure-list-offset")]
1002+
#[test]
1003+
fn test_marker_for_offset() {
1004+
// BlobStorage
1005+
let marker = marker_for_offset("file.txt", false);
1006+
assert_eq!(marker, "2!72!MDAwMDA5IWZpbGUudHh0ICEwMDAwMjghOTk5OS0xMi0zMVQyMzo1OTo1OS45OTk5OTk5WiE-");
1007+
1008+
// Azurite
1009+
let marker = marker_for_offset("file.txt", true);
1010+
assert_eq!(marker, "file.txt");
1011+
}
9701012
}

object_store/src/azure/mod.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,15 @@ impl ObjectStore for MicrosoftAzure {
123123
self.client.list(prefix)
124124
}
125125

126+
#[cfg(feature = "experimental-azure-list-offset")]
127+
fn list_with_offset(
128+
&self,
129+
prefix: Option<&Path>,
130+
offset: &Path,
131+
) -> BoxStream<'_, Result<ObjectMeta>> {
132+
self.client.list_with_offset(prefix, offset)
133+
}
134+
126135
async fn list_with_delimiter(&self, prefix: Option<&Path>) -> Result<ListResult> {
127136
self.client.list_with_delimiter(prefix).await
128137
}

0 commit comments

Comments
 (0)