mirror of
https://github.com/narrrl/proton-sdk-rs.git
synced 2026-11-03 16:41:26 +01:00
enumeration returns NodeUids (enumerate_folder_children_node_uids / enumerate_trash_node_uids), caller materializes via enumerate_nodes. noise dropped: BOM/deps/kt-enum-order/cs-account-refactor
This commit is contained in:
1 parent
5685923034
commit
e15f2d3111
4 files changed
+37
-53
No files matched your search
+3
-2
@@ -6,8 +6,8 @@ gitignored, so this file is the only durable record of what we last reviewed.
|
|||||||
|
|
||||||
- **Upstream**: https://github.com/ProtonDriveApps/sdk
|
- **Upstream**: https://github.com/ProtonDriveApps/sdk
|
||||||
- **Reconciled subtree**: `client/cs/sdk/src`
|
- **Reconciled subtree**: `client/cs/sdk/src`
|
||||||
- **Pinned**: `fb4173ab823a62c1c9f5a11d1b8320d4ce0ea4dc`
|
- **Pinned**: `36430318919c30fac42ec8577036a6d6e9de916f`
|
||||||
- **Date**: 2026-06-25
|
- **Date**: 2026-06-26
|
||||||
|
|
||||||
## Workflow
|
## Workflow
|
||||||
|
|
||||||
@@ -22,3 +22,4 @@ gitignored, so this file is the only durable record of what we last reviewed.
|
|||||||
| date | from → to | ported | notes |
|
| date | from → to | ported | notes |
|
||||||
|------|-----------|--------|-------|
|
|------|-----------|--------|-------|
|
||||||
| 2026-06-25 | initial pin `fb4173ab` | — | baseline; delta reviewed, 0 behavioral changes outstanding |
|
| 2026-06-25 | initial pin `fb4173ab` | — | baseline; delta reviewed, 0 behavioral changes outstanding |
|
||||||
|
| 2026-06-26 | `fb4173ab` → `36430318` | `36430318` | ported: enumeration returns `NodeUid`s (`enumerate_folder_children_node_uids` / `enumerate_trash_node_uids`), caller materializes via `enumerate_nodes`. noise dropped: BOM/deps/kt-enum-order/cs-account-refactor |
|
||||||
@@ -55,7 +55,8 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
);
|
);
|
||||||
|
|
||||||
eprintln!("[*] enumerating children ...");
|
eprintln!("[*] enumerating children ...");
|
||||||
let children = client.enumerate_folder_children(&root.uid).await?;
|
let child_uids = client.enumerate_folder_children_node_uids(&root.uid).await?;
|
||||||
|
let children = client.enumerate_nodes(&child_uids).await?;
|
||||||
eprintln!("[+] {} children:", children.len());
|
eprintln!("[+] {} children:", children.len());
|
||||||
for c in &children {
|
for c in &children {
|
||||||
eprintln!(" - {:?} [{:?}] {}", c.name, c.kind, c.uid);
|
eprintln!(" - {:?} [{:?}] {}", c.name, c.kind, c.uid);
|
||||||
|
|||||||
@@ -227,12 +227,21 @@ impl ProtonDriveClient {
|
|||||||
Ok(Some(node))
|
Ok(Some(node))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Enumerate the (non-trashed) children of a folder.
|
/// Enumerate the [`NodeUid`]s of a folder's (non-trashed) children.
|
||||||
pub async fn enumerate_folder_children(&self, folder_uid: &NodeUid) -> Result<Vec<Node>> {
|
///
|
||||||
let mut timer = self.telemetry.start("enumerate_folder_children");
|
/// Mirrors C# `FolderOperations.EnumerateChildrenAsync` (renamed to
|
||||||
let folder_key = self.folder_node_key(folder_uid).await?;
|
/// `EnumerateFolderChildrenNodeUidsAsync` on the client): enumeration now
|
||||||
|
/// only lists uids — it does not fetch the folder key, link details, or
|
||||||
|
/// decrypt anything. Callers materialize the nodes they care about via
|
||||||
|
/// [`enumerate_nodes`](Self::enumerate_nodes), avoiding per-child decryption
|
||||||
|
/// of the whole listing.
|
||||||
|
pub async fn enumerate_folder_children_node_uids(
|
||||||
|
&self,
|
||||||
|
folder_uid: &NodeUid,
|
||||||
|
) -> Result<Vec<NodeUid>> {
|
||||||
|
let mut timer = self.telemetry.start("enumerate_folder_children_node_uids");
|
||||||
|
|
||||||
let mut nodes = Vec::new();
|
let mut uids = Vec::new();
|
||||||
let mut anchor: Option<LinkId> = None;
|
let mut anchor: Option<LinkId> = None;
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
@@ -249,20 +258,8 @@ impl ProtonDriveClient {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
let details = self
|
for link_id in page.link_ids {
|
||||||
.get_link_details(&folder_uid.volume_id, &page.link_ids)
|
uids.push(NodeUid::new(folder_uid.volume_id.clone(), link_id));
|
||||||
.await?;
|
|
||||||
|
|
||||||
for child in &details.links {
|
|
||||||
match self
|
|
||||||
.build_node(&folder_uid.volume_id, child, &folder_key)
|
|
||||||
.await
|
|
||||||
{
|
|
||||||
Ok(node) => nodes.push(node),
|
|
||||||
Err(e) => {
|
|
||||||
tracing::warn!(link_id = %child.link.id, error = %e, "skipping undecryptable child");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if !page.more_results_exist {
|
if !page.more_results_exist {
|
||||||
@@ -274,9 +271,9 @@ impl ProtonDriveClient {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
timer.attr("node_count", nodes.len());
|
timer.attr("node_count", uids.len());
|
||||||
timer.success();
|
timer.success();
|
||||||
Ok(nodes)
|
Ok(uids)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Fetch decrypted metadata for many nodes in one pass.
|
/// Fetch decrypted metadata for many nodes in one pass.
|
||||||
@@ -314,17 +311,17 @@ impl ProtonDriveClient {
|
|||||||
Ok(nodes)
|
Ok(nodes)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Enumerate the trashed nodes of the main volume.
|
/// Enumerate the [`NodeUid`]s of the main volume's trashed nodes.
|
||||||
///
|
///
|
||||||
/// Mirrors C# `VolumeOperations.EnumerateTrashAsync`: page the trash listing
|
/// Mirrors C# `VolumeOperations.EnumerateTrashAsync` (renamed to
|
||||||
/// (`GET volumes/{vid}/trash`), which groups trashed links by share, then
|
/// `EnumerateTrashNodeUidsAsync` on the client): page the trash listing
|
||||||
/// decrypt each group's links against their resolved parent keys. As with
|
/// (`GET volumes/{vid}/trash`), which groups trashed links by share, and
|
||||||
/// other enumeration paths, a node that fails to decrypt is logged and
|
/// emit a [`NodeUid`] per link. Enumeration no longer fetches share keys or
|
||||||
/// skipped rather than aborting the listing.
|
/// decrypts — callers materialize via [`enumerate_nodes`](Self::enumerate_nodes).
|
||||||
pub async fn enumerate_trash(&self) -> Result<Vec<Node>> {
|
pub async fn enumerate_trash_node_uids(&self) -> Result<Vec<NodeUid>> {
|
||||||
let volume_id = self.main_volume_id().await?;
|
let volume_id = self.main_volume_id().await?;
|
||||||
|
|
||||||
let mut nodes = Vec::new();
|
let mut uids = Vec::new();
|
||||||
let mut page = 0_usize;
|
let mut page = 0_usize;
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
@@ -334,25 +331,9 @@ impl ProtonDriveClient {
|
|||||||
|
|
||||||
let mut count = 0_usize;
|
let mut count = 0_usize;
|
||||||
for group in &response.trash_by_share {
|
for group in &response.trash_by_share {
|
||||||
count += group.link_ids.len();
|
for link_id in &group.link_ids {
|
||||||
for chunk in group.link_ids.chunks(MAX_BATCH_COUNT) {
|
count += 1;
|
||||||
let details = self.get_link_details(&volume_id, chunk).await?;
|
uids.push(NodeUid::new(volume_id.clone(), link_id.clone()));
|
||||||
for detail in &details.links {
|
|
||||||
let parent_key =
|
|
||||||
match self.resolve_parent_key(&volume_id, &detail.link).await {
|
|
||||||
Ok(key) => key,
|
|
||||||
Err(e) => {
|
|
||||||
tracing::warn!(link_id = %detail.link.id, error = %e, "skipping trashed node: parent key unavailable");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
match self.build_node(&volume_id, detail, &parent_key).await {
|
|
||||||
Ok(node) => nodes.push(node),
|
|
||||||
Err(e) => {
|
|
||||||
tracing::warn!(link_id = %detail.link.id, error = %e, "skipping undecryptable trashed node");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -363,7 +344,7 @@ impl ProtonDriveClient {
|
|||||||
page += 1;
|
page += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(nodes)
|
Ok(uids)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The main volume id, resolved via My Files.
|
/// The main volume id, resolved via My Files.
|
||||||
|
|||||||
@@ -24,7 +24,8 @@
|
|||||||
//!
|
//!
|
||||||
//! let drive = ProtonDriveClient::new(&session, b"mailbox-password".to_vec());
|
//! let drive = ProtonDriveClient::new(&session, b"mailbox-password".to_vec());
|
||||||
//! let root = drive.get_my_files_folder().await?;
|
//! let root = drive.get_my_files_folder().await?;
|
||||||
//! for child in drive.enumerate_folder_children(&root.uid).await? {
|
//! let child_uids = drive.enumerate_folder_children_node_uids(&root.uid).await?;
|
||||||
|
//! for child in drive.enumerate_nodes(&child_uids).await? {
|
||||||
//! println!("{} ({:?})", child.name, child.kind);
|
//! println!("{} ({:?})", child.name, child.kind);
|
||||||
//! }
|
//! }
|
||||||
//! # Ok(())
|
//! # Ok(())
|
||||||
|
|||||||
Reference in new issue
Block a user