Skip to main content

Storage

Struct Storage 

Source
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

Source

pub fn id(&self) -> StorageId

Source

pub fn info(&self) -> &StorageInfo

Storage information (cached, call refresh() to update).

Source

pub async fn refresh(&mut self) -> Result<(), Error>

Refresh storage info from device (updates free space, etc.).

Source

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
Source

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);
}
Source

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.

Source

pub async fn list_objects_recursive_native( &self, parent: Option<ObjectHandle>, ) -> Result<Vec<ObjectInfo>, Error>

List objects recursively using native MTP recursive listing.

Source

pub async fn list_objects_recursive_manual( &self, parent: Option<ObjectHandle>, ) -> Result<Vec<ObjectInfo>, Error>

List objects recursively using manual folder traversal.

Source

pub async fn get_object_info( &self, handle: ObjectHandle, ) -> Result<ObjectInfo, Error>

Get object metadata by handle.

Source

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().

Source

pub async fn download_partial( &self, handle: ObjectHandle, offset: u64, size: u32, ) -> Result<Vec<u8>, Error>

Download a partial file (byte range).

Source

pub async fn download_thumbnail( &self, handle: ObjectHandle, ) -> Result<Vec<u8>, Error>

Source

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);
}
Source

pub async fn upload<S>( &self, parent: Option<ObjectHandle>, info: NewObjectInfo, data: S, ) -> Result<ObjectHandle, Error>
where S: Stream<Item = Result<Bytes, Error>> + Unpin,

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 size
  • data - Stream of data chunks to upload
Source

pub async fn upload_with_progress<S, F>( &self, parent: Option<ObjectHandle>, info: NewObjectInfo, data: S, on_progress: F, ) -> Result<ObjectHandle, Error>
where S: Stream<Item = Result<Bytes, Error>> + Unpin, F: FnMut(Progress) -> ControlFlow<()>,

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.

Source

pub async fn create_folder( &self, parent: Option<ObjectHandle>, name: &str, ) -> Result<ObjectHandle, Error>

Source

pub async fn delete(&self, handle: ObjectHandle) -> Result<(), Error>

Source

pub async fn move_object( &self, handle: ObjectHandle, new_parent: ObjectHandle, new_storage: Option<StorageId>, ) -> Result<(), Error>

Move an object to a different folder.

Source

pub async fn copy_object( &self, handle: ObjectHandle, new_parent: ObjectHandle, new_storage: Option<StorageId>, ) -> Result<ObjectHandle, Error>

Source

pub async fn rename( &self, handle: ObjectHandle, new_name: &str, ) -> Result<(), Error>

Rename an object (file or folder).

Not all devices support renaming. Use MtpDevice::supports_rename() to check if this operation is available.

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.