Struct RawDir
struct RawDir<'buf, Fd: AsFd> { ... }
A directory iterator implemented with getdents.
Note: This implementation does not handle growing the buffer. If this
functionality is necessary, you'll need to drop the current iterator,
resize the buffer, and then re-create the iterator. The iterator is
guaranteed to continue where it left off provided the file descriptor isn't
changed. See the example in RawDir::new.
Implementations
impl<'buf, Fd: AsFd> RawDir<'buf, Fd>
fn next(self: &mut Self) -> Option<Result<RawDirEntry<'_>>>Identical to
Iterator::nextexcept thatIterator::Itemborrows from self.Note: this interface will be broken to implement a stdlib iterator API with GAT support once one becomes available.
fn is_buffer_empty(self: &Self) -> boolReturns true if the internal buffer is empty and will be refilled when calling
next.
impl<'buf, Fd: AsFd> RawDir<'buf, Fd>
fn new(fd: Fd, buf: &'buf mut [MaybeUninit<u8>]) -> SelfCreate a new iterator from the given file descriptor and buffer.
Note: the buffer size may be trimmed to accommodate alignment requirements.
Examples
Simple but non-portable
These examples are non-portable, because file systems may not have a maximum file name length. If you can make assumptions that bound this length, then these examples may suffice.
Using the heap:
# use MaybeUninit; # use ; # use cstr; let fd = openat .unwrap; let mut buf = Vecwith_capacity; let mut iter = new; while let Some = iter.nextUsing the stack:
# use MaybeUninit; # use ; # use cstr; let fd = openat .unwrap; let mut buf = ; let mut iter = new; while let Some = iter.nextPortable
Heap allocated growing buffer for supporting directory entries with arbitrarily large file names:
# // The `ignore` above can be removed when we can depend on Rust 1.65. # use std::mem::MaybeUninit; # use rustix::fs::{CWD, Mode, OFlags, openat, RawDir}; # use rustix::io::Errno; # use rustix::cstr; let fd = openat( CWD, cstr!("."), OFlags::RDONLY | OFlags::DIRECTORY | OFlags::CLOEXEC, Mode::empty(), ) .unwrap(); let mut buf = Vec::with_capacity(8192); 'read: loop { 'resize: { let mut iter = RawDir::new(&fd, buf.spare_capacity_mut()); while let Some(entry) = iter.next() { let entry = match entry { Err(Errno::INVAL) => break 'resize, r => r.unwrap(), }; dbg!(&entry); } break 'read; } let new_capacity = buf.capacity() * 2; buf.reserve(new_capacity); }
impl<'buf, Fd> Freeze for RawDir<'buf, Fd>
impl<'buf, Fd> RefUnwindSafe for RawDir<'buf, Fd>
impl<'buf, Fd> Send for RawDir<'buf, Fd>
impl<'buf, Fd> Sync for RawDir<'buf, Fd>
impl<'buf, Fd> Unpin for RawDir<'buf, Fd>
impl<'buf, Fd> UnsafeUnpin for RawDir<'buf, Fd>
impl<'buf, Fd> UnwindSafe for RawDir<'buf, Fd>
impl<T> Any for RawDir<'buf, Fd>
fn type_id(self: &Self) -> TypeId
impl<T> Borrow for RawDir<'buf, Fd>
fn borrow(self: &Self) -> &T
impl<T> BorrowMut for RawDir<'buf, Fd>
fn borrow_mut(self: &mut Self) -> &mut T
impl<T> From for RawDir<'buf, Fd>
fn from(t: T) -> TReturns the argument unchanged.
impl<T, U> Into for RawDir<'buf, Fd>
fn into(self: Self) -> UCalls
U::from(self).That is, this conversion is whatever the implementation of
[From]<T> for Uchooses to do.
impl<T, U> TryFrom for RawDir<'buf, Fd>
fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>
impl<T, U> TryInto for RawDir<'buf, Fd>
fn try_into(self: Self) -> Result<U, <U as TryFrom<T>>::Error>