opendal/services/obs/
lister.rs1use std::sync::Arc;
19
20use bytes::Buf;
21use quick_xml::de;
22
23use super::core::*;
24use super::error::parse_error;
25use crate::raw::*;
26use crate::EntryMode;
27use crate::Metadata;
28use crate::Result;
29
30pub struct ObsLister {
31 core: Arc<ObsCore>,
32 path: String,
33 delimiter: &'static str,
34 limit: Option<usize>,
35}
36
37impl ObsLister {
38 pub fn new(core: Arc<ObsCore>, path: &str, recursive: bool, limit: Option<usize>) -> Self {
39 let delimiter = if recursive { "" } else { "/" };
40
41 Self {
42 core,
43 path: path.to_string(),
44 delimiter,
45 limit,
46 }
47 }
48}
49
50impl oio::PageList for ObsLister {
51 async fn next_page(&self, ctx: &mut oio::PageContext) -> Result<()> {
52 let resp = self
53 .core
54 .obs_list_objects(&self.path, &ctx.token, self.delimiter, self.limit)
55 .await?;
56
57 if resp.status() != http::StatusCode::OK {
58 return Err(parse_error(resp));
59 }
60
61 let bs = resp.into_body();
62
63 let output: ListObjectsOutput =
64 de::from_reader(bs.reader()).map_err(new_xml_deserialize_error)?;
65
66 ctx.done = match output.next_marker.as_ref() {
70 None => true,
71 Some(next_marker) => next_marker.is_empty(),
72 };
73 ctx.token = output.next_marker.clone().unwrap_or_default();
74
75 let common_prefixes = output.common_prefixes;
76
77 for prefix in common_prefixes {
78 let de = oio::Entry::new(
79 &build_rel_path(&self.core.root, &prefix.prefix),
80 Metadata::new(EntryMode::DIR),
81 );
82
83 ctx.entries.push_back(de);
84 }
85
86 for object in output.contents {
87 let mut path = build_rel_path(&self.core.root, &object.key);
88 if path.is_empty() {
89 path = "/".to_string();
90 }
91
92 let meta = Metadata::new(EntryMode::from_path(&path)).with_content_length(object.size);
93
94 let de = oio::Entry::with(path, meta);
95
96 ctx.entries.push_back(de);
97 }
98
99 Ok(())
100 }
101}