pub struct Storage { /* private fields */ }Expand description
A storage location on an MTP device.
Storage holds an Arc<MtpDeviceInner> so it can outlive the original
MtpDevice and be used from multiple tasks.
Implementations§
Source§impl Storage
impl Storage
pub fn id(&self) -> StorageId
Sourcepub fn info(&self) -> &StorageInfo
pub fn info(&self) -> &StorageInfo
Storage information (cached, call refresh() to update).
Sourcepub async fn refresh(&mut self) -> Result<(), Error>
pub async fn refresh(&mut self) -> Result<(), Error>
Refresh storage info from device (updates free space, etc.).
Sourcepub async fn list_objects(
&self,
parent: Option<ObjectHandle>,
) -> Result<Vec<ObjectInfo>, Error>
pub async fn list_objects( &self, parent: Option<ObjectHandle>, ) -> Result<Vec<ObjectInfo>, Error>
List objects in a folder (None = root), returning all results at once.
For progress reporting during large listings, use
list_objects_stream() instead.
This method handles various device quirks:
- Android devices: parent=0 returns ALL objects, so we use parent=0xFFFFFFFF instead
- Samsung devices: return InvalidObjectHandle for parent=0, so we fall back to recursive
- Fuji devices: return all objects for root, so we filter by parent handle
Sourcepub async fn list_objects_stream(
&self,
parent: Option<ObjectHandle>,
) -> Result<ObjectListing, Error>
pub async fn list_objects_stream( &self, parent: Option<ObjectHandle>, ) -> Result<ObjectListing, Error>
List objects in a folder as a streaming ObjectListing.
Returns immediately after GetObjectHandles completes (one USB round-trip).
The total count is then known via ObjectListing::total(), and each call
to ObjectListing::next() fetches one object’s metadata from USB.
This enables progress reporting (e.g., “Loading 42 of 500…”) during
what would otherwise be a single blocking list_objects() call.
Handles the same device quirks as list_objects().
§Example
let mut listing = storage.list_objects_stream(None).await?;
println!("Found {} items", listing.total());
while let Some(result) = listing.next().await {
let info = result?;
println!("[{}/{}] {}", listing.fetched(), listing.total(), info.filename);
}Sourcepub async fn list_objects_recursive(
&self,
parent: Option<ObjectHandle>,
) -> Result<Vec<ObjectInfo>, Error>
pub async fn list_objects_recursive( &self, parent: Option<ObjectHandle>, ) -> Result<Vec<ObjectInfo>, Error>
List objects recursively.
This method automatically detects Android devices and uses manual traversal
for them, since Android’s MTP implementation doesn’t support the native
ObjectHandle::ALL recursive listing.
For non-Android devices, it tries native recursive listing first and falls back to manual traversal if the results look incomplete.
Sourcepub async fn list_objects_recursive_native(
&self,
parent: Option<ObjectHandle>,
) -> Result<Vec<ObjectInfo>, Error>
pub async fn list_objects_recursive_native( &self, parent: Option<ObjectHandle>, ) -> Result<Vec<ObjectInfo>, Error>
List objects recursively using native MTP recursive listing.
Sourcepub async fn list_objects_recursive_manual(
&self,
parent: Option<ObjectHandle>,
) -> Result<Vec<ObjectInfo>, Error>
pub async fn list_objects_recursive_manual( &self, parent: Option<ObjectHandle>, ) -> Result<Vec<ObjectInfo>, Error>
List objects recursively using manual folder traversal.
Sourcepub async fn get_object_info(
&self,
handle: ObjectHandle,
) -> Result<ObjectInfo, Error>
pub async fn get_object_info( &self, handle: ObjectHandle, ) -> Result<ObjectInfo, Error>
Get object metadata by handle.
Sourcepub async fn download(&self, handle: ObjectHandle) -> Result<Vec<u8>, Error>
pub async fn download(&self, handle: ObjectHandle) -> Result<Vec<u8>, Error>
Download a file and return all bytes.
For small to medium files where you want all the data in memory.
For large files or streaming to disk, use download_stream().
Sourcepub async fn download_partial(
&self,
handle: ObjectHandle,
offset: u64,
size: u32,
) -> Result<Vec<u8>, Error>
pub async fn download_partial( &self, handle: ObjectHandle, offset: u64, size: u32, ) -> Result<Vec<u8>, Error>
Download a partial file (byte range).
pub async fn download_thumbnail( &self, handle: ObjectHandle, ) -> Result<Vec<u8>, Error>
Sourcepub async fn download_stream(
&self,
handle: ObjectHandle,
) -> Result<FileDownload, Error>
pub async fn download_stream( &self, handle: ObjectHandle, ) -> Result<FileDownload, Error>
Download a file as a stream (true USB streaming).
Unlike download(), this method yields data chunks
directly from USB as they arrive, without buffering the entire file
in memory. Ideal for large files or when piping data to disk.
§Important
The MTP session is locked while the download is active. You must consume the entire download (or drop it) before calling other storage methods.
§Example
let mut download = storage.download_stream(handle).await?;
println!("Downloading {} bytes...", download.size());
let mut file = tokio::fs::File::create("output.bin").await?;
while let Some(chunk) = download.next_chunk().await {
let bytes = chunk?;
file.write_all(&bytes).await?;
println!("Progress: {:.1}%", download.progress() * 100.0);
}Sourcepub async fn upload<S>(
&self,
parent: Option<ObjectHandle>,
info: NewObjectInfo,
data: S,
) -> Result<ObjectHandle, Error>
pub async fn upload<S>( &self, parent: Option<ObjectHandle>, info: NewObjectInfo, data: S, ) -> Result<ObjectHandle, Error>
Upload a file from a stream.
The stream is consumed and all data is buffered before sending (MTP protocol requires knowing the total size upfront).
§Arguments
parent- Parent folder handle (None for root)info- Object metadata including filename and sizedata- Stream of data chunks to upload
Sourcepub async fn upload_with_progress<S, F>(
&self,
parent: Option<ObjectHandle>,
info: NewObjectInfo,
data: S,
on_progress: F,
) -> Result<ObjectHandle, Error>
pub async fn upload_with_progress<S, F>( &self, parent: Option<ObjectHandle>, info: NewObjectInfo, data: S, on_progress: F, ) -> Result<ObjectHandle, Error>
Upload a file with progress callback.
Progress is reported as data is read from the stream. Return
ControlFlow::Break(()) from the callback to cancel the upload.
pub async fn create_folder( &self, parent: Option<ObjectHandle>, name: &str, ) -> Result<ObjectHandle, Error>
pub async fn delete(&self, handle: ObjectHandle) -> Result<(), Error>
Sourcepub async fn move_object(
&self,
handle: ObjectHandle,
new_parent: ObjectHandle,
new_storage: Option<StorageId>,
) -> Result<(), Error>
pub async fn move_object( &self, handle: ObjectHandle, new_parent: ObjectHandle, new_storage: Option<StorageId>, ) -> Result<(), Error>
Move an object to a different folder.