pub struct DirEntry { /* private fields */ }Expand description
A struct representing a directory entry with minimal memory overhead.
This struct is designed for high-performance file system traversal and analysis. It holds metadata and a path to a file or directory, optimised for size and efficient access to its components.
The struct’s memory footprint is
- Path: 16 bytes,
Box<CStr>, retaining compatibility for use in libc but converting to&[u8]trivially(as deref) - File type: 1-byte enum representing the entry’s type (file, directory, etc.).
- Inode: 8-byte integer for the file’s unique inode number.
- Depth: 4-byte integer indicating the entry’s depth from the root.
- File name index: 8-byte integer pointing to the start of the file name within the path buffer.
- is traversible cache: 1 byte
Cell<Option<bool>>an Implementation detail that avoids recalling stat on symlinks
§Examples
use fdf::fs::DirEntry;
use std::path::Path;
use std::fs::File;
use std::io::Write;
use std::sync::Arc;
// Create a temporary directory for the test
let temp_dir = std::env::temp_dir();
let file_path = temp_dir.join("test_file.txt");
// Create a file inside the temporary directory
let mut file = File::create(&file_path).expect("Failed to create file");
writeln!(file, "Hello, world!").expect("Failed to write to file");
// Create a DirEntry from the temporary file path
let entry = DirEntry::new(&file_path).unwrap();
assert!(entry.is_regular_file());
assert_eq!(entry.file_name(), b"test_file.txt");Implementations§
Source§impl DirEntry
impl DirEntry
Sourcepub fn is_executable(&self) -> bool
pub fn is_executable(&self) -> bool
Checks if the entry is an executable file.
This is a costly operation as it performs an access system call.
§Examples
use fdf::fs::DirEntry;
use std::fs::{self, File};
use std::os::unix::fs::PermissionsExt;
use std::sync::Arc;
let temp_dir = std::env::temp_dir();
let exe_path = temp_dir.join("my_executable");
File::create(&exe_path).unwrap().set_permissions(fs::Permissions::from_mode(0o755)).unwrap();
let entry = DirEntry::new(&exe_path).unwrap();
assert!(entry.is_executable());
let non_exe_path = temp_dir.join("my_file");
File::create(&non_exe_path).unwrap();
let non_exe_entry = DirEntry::new(&non_exe_path).unwrap();
assert!(!non_exe_entry.is_executable());
fs::remove_file(exe_path).unwrap();
fs::remove_file(non_exe_path).unwrap();Sourcepub const fn as_ptr(&self) -> *const c_char
pub const fn as_ptr(&self) -> *const c_char
Returns a raw pointer to the underlying C string.
This provides access to the null-terminated C string representation of the file path for use with FFI functions.
Sourcepub const fn is_block_device(&self) -> bool
pub const fn is_block_device(&self) -> bool
Cost free check for block devices
pub fn to_string_lossy(&self) -> Cow<'_, str>
Sourcepub const fn as_str(&self) -> Result<&str, Utf8Error>
pub const fn as_str(&self) -> Result<&str, Utf8Error>
Returns the underlying bytes as a UTF-8 string slice if valid.
§Errors
Returns Err if the bytes are not valid UTF-8.
Sourcepub const fn is_char_device(&self) -> bool
pub const fn is_char_device(&self) -> bool
Cost free check for character devices
Sourcepub const fn is_regular_file(&self) -> bool
pub const fn is_regular_file(&self) -> bool
Cost free check for regular files
Sourcepub const fn is_unknown(&self) -> bool
pub const fn is_unknown(&self) -> bool
Cost free check for unknown file types
Sourcepub const fn is_symlink(&self) -> bool
pub const fn is_symlink(&self) -> bool
Cost free check for symlinks
Sourcepub fn is_empty(&self) -> bool
pub fn is_empty(&self) -> bool
Checks if the entry is empty.
For files, it checks if the size is zero. For directories, it checks if there are no entries.
This is a costly operation as it requires system calls (stat or getdents/readdir).
§Examples
use fdf::fs::DirEntry;
use std::fs::{self, File};
use std::io::Write;
use std::sync::Arc;
let temp_dir = std::env::temp_dir();
// Check an empty file.
let empty_file_path = temp_dir.join("empty.txt");
File::create(&empty_file_path).unwrap();
let empty_entry = DirEntry::new(&empty_file_path).unwrap();
assert!(empty_entry.is_empty());
// Check a non-empty file.
let non_empty_file_path = temp_dir.join("not_empty.txt");
File::create(&non_empty_file_path).unwrap().write_all(b"Hello").unwrap();
let non_empty_entry = DirEntry::new(&non_empty_file_path).unwrap();
assert!(!non_empty_entry.is_empty());
// Check an empty directory.
let empty_dir_path = temp_dir.join("empty_dir");
fs::create_dir(&empty_dir_path).unwrap();
let empty_dir_entry = DirEntry::new(&empty_dir_path).unwrap();
assert!(empty_dir_entry.is_empty());
fs::remove_file(empty_file_path).unwrap();
fs::remove_file(non_empty_file_path).unwrap();
fs::remove_dir(empty_dir_path).unwrap();Sourcepub const fn as_cstr(&self) -> &CStr
pub const fn as_cstr(&self) -> &CStr
Returns the full path of this directory entry as a CStr.
This function provides direct access to the underlying null-terminated C string representing the entry’s absolute or relative path (depending on how it was created).
The returned reference is valid for the lifetime of the DirEntry and does not allocate.
§Examples
use fdf::fs::DirEntry;
use std::fs::File;
use std::io::Write;
use std::os::unix::ffi::OsStrExt;
// Create a temporary file
let tmp = std::env::temp_dir().join("as_cstr_test.txt");
File::create(&tmp).unwrap().write_all(b"data").unwrap();
// Create a DirEntry from the file path
let entry = DirEntry::new(&tmp).unwrap();
// Retrieve full path as a CStr
let cstr = entry.as_cstr();
// It should match the full path string plus null terminator
let expected = std::ffi::CString::new(tmp.as_os_str().as_bytes()).unwrap();
assert_eq!(cstr.to_bytes_with_nul(), expected.to_bytes_with_nul());
// The CStr can be converted back to &str (if valid UTF-8)
let path_str = cstr.to_str().unwrap();
assert!(path_str.ends_with("as_cstr_test.txt"));
std::fs::remove_file(tmp).unwrap();Sourcepub fn file_name_cstr(&self) -> &CStr
pub fn file_name_cstr(&self) -> &CStr
Returns the file name component of the entry as a CStr.
This slice is a view into the internal path buffer and includes the null terminator. It is guaranteed to be valid UTF-8 if and only if the file name is UTF-8.
Useful within the openat calls
§Examples
use fdf::fs::DirEntry;
use std::fs::File;
use std::io::Write;
// Create a temporary file
let tmp = std::env::temp_dir().join("file_name_cstr_test.txt");
File::create(&tmp).unwrap().write_all(b"abc").unwrap();
// Build DirEntry
let entry = DirEntry::new(&tmp).unwrap();
// Extract file name as CStr
let cstr = entry.file_name_cstr();
// It should match the file name plus null terminator
assert_eq!(cstr.to_bytes_with_nul(), b"file_name_cstr_test.txt\0");
// We can also convert it to a &str
assert_eq!(cstr.to_str().unwrap(), "file_name_cstr_test.txt");
std::fs::remove_file(tmp).unwrap();use fdf::fs::DirEntry;
use std::fs::File;
// File name with spaces
let tmp = std::env::temp_dir().join("some name.txt");
File::create(&tmp).unwrap();
let entry = DirEntry::new(&tmp).unwrap();
let name = entry.file_name_cstr();
assert_eq!(name.to_str().unwrap(), "some name.txt");
std::fs::remove_file(tmp).unwrap();
let root_dir=DirEntry::new("/");
assert!(root_dir.is_err() || root_dir.is_ok_and(|x| x.file_name_cstr()==c"/"));
Sourcepub fn file_name(&self) -> &[u8] ⓘ
pub fn file_name(&self) -> &[u8] ⓘ
Returns the name of the file (as bytes, no null terminator)
( Returns / or . when they are the entry)
use fdf::fs::DirEntry;
use std::fs::File;
// File name with spaces
let tmp = std::env::temp_dir().join("some name.txt");
File::create(&tmp).unwrap();
let entry = DirEntry::new(&tmp).unwrap();
let name = entry.file_name();
assert_eq!(name, b"some name.txt");
std::fs::remove_file(tmp).unwrap();
let root_dir=DirEntry::new("/");
assert!(root_dir.is_err() || root_dir.is_ok_and(|x| x.file_name()==b"/"));
// if on certain systems, root dir requires permissions, so we have to be careful (esp android)
let dot_dir=DirEntry::new(".");
assert!(dot_dir.is_ok_and(|x| x.file_name()==b"."));
Sourcepub fn to_inner(self) -> Box<CStr>
pub fn to_inner(self) -> Box<CStr>
Takes the value of the path and gives the raw representation as a boxed Cstr
Sourcepub fn to_full_path(&self) -> Result<Self>
pub fn to_full_path(&self) -> Result<Self>
Converts a directory entry to a full, canonical path, resolving all symlinks
This is a costly operation as it involves a system call (realpath).
If the filetype is a symlink, it invokes a stat call to find the realtype, otherwise stat is not called.
§Errors
Returns an Err
It can be one of the following,
FileType::AccessDenied, (EACCESS)
FileType::TooManySymbolicLinks, ( ELOOP)
FileType::InvalidPath (ENOENT)
(There may be more, this documentation is not complete) TODO!
§Examples
these tests are broken on macos because of funky stuff with mac’s privacy/security settings.
use fdf::fs::DirEntry;
use std::path::Path;
use std::fs;
use std::sync::Arc;
use std::os::unix::ffi::OsStrExt as _;
use std::os::unix::fs::symlink;
let temp_dir = std::env::temp_dir();
let target_path = temp_dir.join("target_file_full_path.txt");
fs::File::create(&target_path).unwrap();
let symlink_path = temp_dir.join("link_to_target_full_path.txt");
symlink(&target_path, &symlink_path).unwrap();
// Create a DirEntry from the symlink path
let entry = DirEntry::new(&symlink_path).unwrap();
assert!(entry.is_symlink());
// Canonicalise the path
let full_entry = entry.to_full_path().unwrap();
// The full path of the canonicalised entry should match the target path.
assert_eq!(full_entry.as_bytes(), target_path.as_os_str().as_bytes());
fs::remove_file(&symlink_path).unwrap();
fs::remove_file(&target_path).unwrap();
Sourcepub fn parent(&self) -> Option<&[u8]>
pub fn parent(&self) -> Option<&[u8]>
Returns the parent path as byte slice, or None if at root.
§Examples
Basic usage with a temporary directory and file:
use fdf::fs::DirEntry;
use std::fs::File;
use std::os::unix::ffi::OsStrExt;
let tmp = std::env::temp_dir().join("fdf_parent_test_dir");
let _ = std::fs::remove_dir_all(&tmp);
std::fs::create_dir_all(&tmp).unwrap();
let file_path = tmp.join("file.txt");
File::create(&file_path).unwrap();
let entry = DirEntry::new(&file_path).unwrap();
assert_eq!(entry.parent().unwrap(), tmp.as_os_str().as_bytes());
std::fs::remove_file(&file_path).unwrap();
std::fs::remove_dir_all(&tmp).unwrap();Root path yields None for parent (guarded to avoid failing on unusual systems):
dot entries return an empty byte slice, mirroring semantics from stdlib.
use fdf::fs::DirEntry;
let root = DirEntry::new("/");
if let Ok(e) = root {
assert!(e.parent().is_none());
}
let dot=DirEntry::new(".");
if let Ok(dotentry)=dot{
let parent=dotentry.parent();
assert!(dotentry.parent().is_some_and(|x| x.is_empty()));
}
Sourcepub fn is_readable(&self) -> bool
pub fn is_readable(&self) -> bool
Checks if the file or directory is readable by the current process.
This uses the access system call with R_OK to check read permissions
without actually opening the file. It follows symlinks.
§Returns
true if the current process has read permission, false otherwise.
false if the file doesn’t exist or on permission errors.
Sourcepub fn is_writable(&self) -> bool
pub fn is_writable(&self) -> bool
Checks if the file or directory is writable by the current process.
This uses the access system call with W_OK to check write permissions
without actually opening the file. It follows symlinks.
§Returns
true if the current process has write permission, false otherwise.
false if the file doesn’t exist or on permission errors.
Sourcepub fn exists(&self) -> bool
pub fn exists(&self) -> bool
Checks if the file exists.
This makes a system call to check file existence.
Sourcepub fn get_lstatat(&self, fd: &FileDes) -> Result<stat>
pub fn get_lstatat(&self, fd: &FileDes) -> Result<stat>
Gets file metadata using lstatat for a file relative to a directory file descriptor.
This function uses fstatat with AT_SYMLINK_NOFOLLOW to get metadata without
following symbolic links, similar to lstat but relative to a directory fd.
§Arguments
fd - Directory file descriptor to use as the base for relative path resolution
§Returns
A stat structure containing file metadata on success.
§Errors
Returns DirEntryError::IOError if the stat operation fails
Sourcepub fn get_lstat(&self) -> Result<stat>
pub fn get_lstat(&self) -> Result<stat>
Gets file status information without following symlinks.
This performs an lstat system call to retrieve metadata about the file,
including type, permissions, size, and timestamps. Unlike stat,
lstat returns information about the symlink itself rather than the target.
§Errors
Returns an error if:
- The file doesn’t exist
- Permission is denied
- The path is invalid
- System call fails for any other reason
Returns DirEntryError::IOError if the stat operation fails
A stat structure containing file metadata on success.
Sourcepub fn get_stat(&self) -> Result<stat>
pub fn get_stat(&self) -> Result<stat>
Gets file status information by following symlinks.
This performs a stat system call to retrieve metadata about the file,
including type, permissions, size, and timestamps. Unlike lstat,
stat follows symbolic links and returns information about the target file
rather than the link itself.
§Errors
Returns an error if:
- The file doesn’t exist
- Permission is denied
- The path is invalid
- A symlink target doesn’t exist
- System call fails for any other reason
§Returns DirEntryError::IOError if the stat operation fails
A stat structure containing file metadata on success.
Sourcepub fn get_statat(&self, fd: &FileDes) -> Result<stat>
pub fn get_statat(&self, fd: &FileDes) -> Result<stat>
Gets file metadata using statat for a file relative to a directory file descriptor.
This function uses fstatat with AT_SYMLINK_FOLLOW to get metadata by
following symbolic links, similar to stat but relative to a directory fd.
§Arguments
fd - Directory file descriptor to use as the base for relative path resolution
§Returns
A stat structure containing file metadata on success.
§Errors
Returns DirEntryError::IOError if the stat operation fails
Sourcepub const fn as_bytes(&self) -> &[u8] ⓘ
pub const fn as_bytes(&self) -> &[u8] ⓘ
Cost free conversion to bytes (because it is already is bytes)
Sourcepub const fn len(&self) -> usize
pub const fn len(&self) -> usize
Returns the length of the path string in bytes.
The length excludes the internal null terminator, so it matches what you’d expect from a regular Rust string slice length.
§Examples
use fdf::fs::DirEntry;
use std::fs::File;
let tmp = std::env::temp_dir().join("test_file.txt");
File::create(&tmp).unwrap();
let entry = DirEntry::new(&tmp).unwrap();
// Length matches the path string without null terminator
assert_eq!(entry.len(), tmp.as_os_str().len());
std::fs::remove_file(tmp).unwrap();Sourcepub const fn file_type(&self) -> FileType
pub const fn file_type(&self) -> FileType
Returns the file type of the file (eg directory, regular file, etc)
Sourcepub const fn depth(&self) -> usize
pub const fn depth(&self) -> usize
Returns the depth relative to the start directory, this is cost free
Sourcepub const fn ino(&self) -> u64
pub const fn ino(&self) -> u64
Returns the inode number of the file, cost free check
This is a unique identifier for the file on the filesystem, it is not the same as the file name or path, it is a number that identifies the file on the
Sourcepub const fn file_name_index(&self) -> usize
pub const fn file_name_index(&self) -> usize
Returns the length of the base path (eg /home/user/ is 6 ‘/home/’) and ‘/’ is 0
Sourcepub fn is_traversible(&self) -> bool
pub fn is_traversible(&self) -> bool
Checks if the file is a directory or symlink (but internally a directory)
Checks if the file is hidden (e.g., .gitignore, .config).
A file is considered hidden if its filename (not the full path) starts with a dot (‘.’) character.
Useful for filtering out hidden files in directory listings.
§Examples
use fdf::fs::DirEntry;
use std::fs::File;
use std::io::Write;
// Create a temporary hidden file
let tmp = std::env::temp_dir().join(".hidden_file.txt");
File::create(&tmp).unwrap().write_all(b"content").unwrap();
// Build DirEntry
let entry = DirEntry::new(&tmp).unwrap();
// Check if it's hidden
assert!(entry.is_hidden());
std::fs::remove_file(tmp).unwrap();use fdf::fs::DirEntry;
use std::fs::File;
// Regular non-hidden file
let tmp = std::env::temp_dir().join("visible_file.txt");
File::create(&tmp).unwrap();
let entry = DirEntry::new(&tmp).unwrap();
assert!(!entry.is_hidden());
std::fs::remove_file(tmp).unwrap();use fdf::fs::DirEntry;
use std::fs::File;
// File with multiple dots but not hidden
let tmp = std::env::temp_dir().join("backup.old.txt");
File::create(&tmp).unwrap();
let entry = DirEntry::new(&tmp).unwrap();
assert!(!entry.is_hidden());
std::fs::remove_file(tmp).unwrap();use fdf::fs::DirEntry;
use std::fs::File;
// Edge case: just a dot
let tmp = std::env::temp_dir().join(".helo");
File::create(&tmp).unwrap();
let entry = DirEntry::new(&tmp).unwrap();
assert!(entry.is_hidden());
std::fs::remove_file(tmp).unwrap();Sourcepub fn dirname(&self) -> &[u8] ⓘ
pub fn dirname(&self) -> &[u8] ⓘ
Returns the directory name of the file (as bytes)
use fdf::fs::DirEntry;
use std::fs::File;
use std::io::Write;
// Test 1: Regular file path with directory structure
let tmp = std::env::temp_dir().join("test_dir/file.txt");
if let Some(parent) = tmp.parent() {
std::fs::create_dir_all(parent).unwrap();
}
File::create(&tmp).unwrap();
let entry = DirEntry::new(&tmp).unwrap();
assert_eq!(entry.dirname(), b"test_dir");
std::fs::remove_file(&tmp).unwrap();
std::fs::remove_dir_all(tmp.parent().unwrap()).unwrap();
let root_dir=DirEntry::new("/");
assert!(root_dir.is_err() || root_dir.is_ok_and(|x| x.dirname()==b"/"));
Sourcepub fn extension(&self) -> Option<&[u8]>
pub fn extension(&self) -> Option<&[u8]>
Extracts the extension of the file name, if any.
The extension is defined as the substring after the last dot (.) character
in the file name, excluding cases where the dot is the final character.
§Examples
use fdf::fs::DirEntry;
use std::env::temp_dir;
let tmp=std::env::temp_dir();
let file_test=tmp.join("file.txt");
std::fs::File::create(&file_test).unwrap();
let path = DirEntry::new(&file_test).unwrap();
assert_eq!(path.extension(), Some(b"txt".as_ref()));
std::fs::remove_file(&file_test).unwrap();
let root_dir=DirEntry::new("/");
assert!(root_dir.is_err() || root_dir.is_ok_and(|path| path.extension().is_none()));Sourcepub fn new<T: AsRef<OsStr>>(path: T) -> Result<Self>
pub fn new<T: AsRef<OsStr>>(path: T) -> Result<Self>
Creates a new DirEntry from the given path.
This constructor attempts to resolve metadata for the provided path using
a lstat call. If successful, it initialises a DirEntry with the path,
file type, inode, and some derived metadata such as depth and file name index.
§Examples
use fdf::fs::DirEntry;
use std::env;
// Use the system temporary directory
let tmp = env::temp_dir();
// Create a DirEntry from the temporary directory path
let entry = DirEntry::new(tmp)?;
println!("inode: {}", entry.ino());
Ok(())
}§Errors
The following returns an DirEntryError::IOError error when the file doesn’t exist:
use fdf::{fs::DirEntry, DirEntryError};
use std::fs;
// Verify the path doesn't exist first
let nonexistent_path = "/definitely/not/a/real/file/lalalalalalalalalalalal";
assert!(!fs::metadata(nonexistent_path).is_ok());
// This will return an DirEntry::IOError because the file does not exist
let result = DirEntry::new(nonexistent_path);
match result {
Ok(_) => panic!("this should never happen!"),
Err(DirEntryError::IOError(_)) => {}, // Expected error
Err(_) => panic!("Expected error, got different error"),
}
Sourcepub fn modified_time(&self) -> Result<DateTime<Utc>>
pub fn modified_time(&self) -> Result<DateTime<Utc>>
Returns the last modification time of the file in UTC.
This method performs an lstat system call to retrieve metadata for the entry.
Unlike stat, it does not follow symbolic links. If the entry is a symlink,
the modification time of the link itself is returned rather than that of its target.
§Errors
Returns an Err if:
- The
lstatcall fails (for example, due to insufficient permissions or an invalid path). - The timestamp retrieved from the OS cannot be represented as a valid
DateTime<Utc>.
§Notes
The timestamp is constructed using seconds (st_mtime) and nanoseconds (st_mtimensec)
from the underlying stat structure. These values are cast to u32 internally
to match the expected type for chrono::DateTime::from_timestamp.
§Examples
use fdf::fs::DirEntry;
use chrono::Utc;
let entry = DirEntry::new("/tmp/example.txt").unwrap();
let modified = entry.modified_time().unwrap();
println!("Last modified at: {}", modified.with_timezone(&Utc));Sourcepub fn file_size(&self) -> Result<u64>
pub fn file_size(&self) -> Result<u64>
Gets the file size in bytes.
This method retrieves the file size by calling get_lstat() and extracting
the st_size field from the stat structure. Unlike get_stat(), this
method does not follow symbolic links - it returns the size of the symlink
itself rather than the target file.
§Errors
Returns an error if:
- The file doesn’t exist
- Permission is denied
- The path is invalid
- The lstat system call fails for any other reason
§Returns
The size of the file in bytes as an u64. For symbolic links, this returns
the length of the symlink path itself, not the target file size.
Sourcepub fn readdir(&self) -> Result<ReadDir>
pub fn readdir(&self) -> Result<ReadDir>
Returns an iterator over directory entries using the readdir API.
This provides a higher-level, more portable interface for directory iteration
compared to getdents. Suitable for most use cases where maximum performance
isn’t critical.
§Errors
Returns Err if:
- The entry is not a directory
- Permission restrictions prevent reading the directory
- The directory has been removed or become inaccessible
- Any other system error occurs during directory opening/reading
§Examples
use fdf::fs::DirEntry;
use std::fs::{self, File};
use std::io::Write;
use std::sync::Arc;
// Create a temporary directory with test files
let temp_dir = std::env::temp_dir().join("test_readdir");
fs::create_dir(&temp_dir).unwrap();
// Create test files
File::create(temp_dir.join("file1.txt")).unwrap().write_all(b"test").unwrap();
File::create(temp_dir.join("file2.txt")).unwrap().write_all(b"test").unwrap();
fs::create_dir(temp_dir.join("subdir")).unwrap();
// Create DirEntry for the temporary directory
let entry = DirEntry::new(&temp_dir).unwrap();
// Use readdir to iterate through directory contents
let mut entries: Vec<_> = entry.readdir().unwrap().collect();
entries.sort_by_key(|e| e.file_name().to_vec());
// Should contain 3 entries: 2 files and 1 directory
assert_eq!(entries.len(), 3);
assert!(entries.iter().any(|e| e.file_name() == b"file1.txt"));
assert!(entries.iter().any(|e| e.file_name() == b"file2.txt"));
assert!(entries.iter().any(|e| e.file_name() == b"subdir"));
fs::remove_dir_all(&temp_dir).unwrap();Sourcepub fn getdents(&self) -> Result<GetDents>
pub fn getdents(&self) -> Result<GetDents>
Low-level directory iterator using the getdents64 system call.
This method provides high-performance directory scanning by using a large buffer
(typically ~4.1KB) to minimise system calls. It’s Linux-specific and generally
faster than readdir for bulk directory operations.
§Errors
Returns Err if:
- The entry is not a directory
- Permission restrictions prevent reading the directory
- The directory file descriptor cannot be opened
- Buffer allocation fails
- Any other system error occurs during the
getdentsoperation
§Platform Specificity
This method is only available on Linux targets due to its dependence on
the getdents64 system call.
§Examples
use fdf::fs::DirEntry;
use std::fs::{self, File};
use std::io::Write;
use std::sync::Arc;
// Create a temporary directory with test files
let temp_dir = std::env::temp_dir().join("test_getdents");
fs::create_dir(&temp_dir).unwrap();
// Create test files
File::create(temp_dir.join("file1.txt")).unwrap().write_all(b"test").unwrap();
File::create(temp_dir.join("file2.txt")).unwrap().write_all(b"test").unwrap();
fs::create_dir(temp_dir.join("subdir")).unwrap();
// Create DirEntry for the temporary directory
let entry= DirEntry::new(&temp_dir).unwrap();
// Use getdents to iterate through directory contents
let mut entries: Vec<_> = entry.getdents().unwrap().collect();
entries.sort_by_key(|e| e.file_name().to_vec());
// Should contain 3 entries: 2 files and 1 directory
assert_eq!(entries.len(), 3);
assert!(entries.iter().any(|e| e.file_name() == b"file1.txt"));
assert!(entries.iter().any(|e| e.file_name() == b"file2.txt"));
assert!(entries.iter().any(|e| e.file_name() == b"subdir"));
// Clean up
fs::remove_dir_all(&temp_dir).unwrap();Methods from Deref<Target = [u8]>§
1.23.0pub fn is_ascii(&self) -> bool
pub fn is_ascii(&self) -> bool
Checks if all bytes in this slice are within the ASCII range.
An empty slice returns true.
pub fn as_ascii(&self) -> Option<&[AsciiChar]>
🔬This is a nightly-only experimental API. (ascii_char)
pub fn as_ascii(&self) -> Option<&[AsciiChar]>
ascii_char)If this slice is_ascii, returns it as a slice of
ASCII characters, otherwise returns None.
pub unsafe fn as_ascii_unchecked(&self) -> &[AsciiChar]
🔬This is a nightly-only experimental API. (ascii_char)
pub unsafe fn as_ascii_unchecked(&self) -> &[AsciiChar]
ascii_char)Converts this slice of bytes into a slice of ASCII characters, without checking whether they’re valid.
§Safety
Every byte in the slice must be in 0..=127, or else this is UB.
1.23.0pub fn eq_ignore_ascii_case(&self, other: &[u8]) -> bool
pub fn eq_ignore_ascii_case(&self, other: &[u8]) -> bool
Checks that two slices are an ASCII case-insensitive match.
Same as to_ascii_lowercase(a) == to_ascii_lowercase(b),
but without allocating and copying temporaries.
1.60.0pub fn escape_ascii(&self) -> EscapeAscii<'_>
pub fn escape_ascii(&self) -> EscapeAscii<'_>
Returns an iterator that produces an escaped version of this slice, treating it as an ASCII string.
§Examples
let s = b"0\t\r\n'\"\\\x9d";
let escaped = s.escape_ascii().to_string();
assert_eq!(escaped, "0\\t\\r\\n\\'\\\"\\\\\\x9d");1.80.0pub fn trim_ascii_start(&self) -> &[u8] ⓘ
pub fn trim_ascii_start(&self) -> &[u8] ⓘ
Returns a byte slice with leading ASCII whitespace bytes removed.
‘Whitespace’ refers to the definition used by
u8::is_ascii_whitespace.
§Examples
assert_eq!(b" \t hello world\n".trim_ascii_start(), b"hello world\n");
assert_eq!(b" ".trim_ascii_start(), b"");
assert_eq!(b"".trim_ascii_start(), b"");1.80.0pub fn trim_ascii_end(&self) -> &[u8] ⓘ
pub fn trim_ascii_end(&self) -> &[u8] ⓘ
Returns a byte slice with trailing ASCII whitespace bytes removed.
‘Whitespace’ refers to the definition used by
u8::is_ascii_whitespace.
§Examples
assert_eq!(b"\r hello world\n ".trim_ascii_end(), b"\r hello world");
assert_eq!(b" ".trim_ascii_end(), b"");
assert_eq!(b"".trim_ascii_end(), b"");1.80.0pub fn trim_ascii(&self) -> &[u8] ⓘ
pub fn trim_ascii(&self) -> &[u8] ⓘ
Returns a byte slice with leading and trailing ASCII whitespace bytes removed.
‘Whitespace’ refers to the definition used by
u8::is_ascii_whitespace.
§Examples
assert_eq!(b"\r hello world\n ".trim_ascii(), b"hello world");
assert_eq!(b" ".trim_ascii(), b"");
assert_eq!(b"".trim_ascii(), b"");1.0.0pub fn is_empty(&self) -> bool
pub fn is_empty(&self) -> bool
Returns true if the slice has a length of 0.
§Examples
let a = [1, 2, 3];
assert!(!a.is_empty());
let b: &[i32] = &[];
assert!(b.is_empty());1.0.0pub fn first(&self) -> Option<&T>
pub fn first(&self) -> Option<&T>
Returns the first element of the slice, or None if it is empty.
§Examples
let v = [10, 40, 30];
assert_eq!(Some(&10), v.first());
let w: &[i32] = &[];
assert_eq!(None, w.first());1.5.0pub fn split_first(&self) -> Option<(&T, &[T])>
pub fn split_first(&self) -> Option<(&T, &[T])>
Returns the first and all the rest of the elements of the slice, or None if it is empty.
§Examples
let x = &[0, 1, 2];
if let Some((first, elements)) = x.split_first() {
assert_eq!(first, &0);
assert_eq!(elements, &[1, 2]);
}1.5.0pub fn split_last(&self) -> Option<(&T, &[T])>
pub fn split_last(&self) -> Option<(&T, &[T])>
Returns the last and all the rest of the elements of the slice, or None if it is empty.
§Examples
let x = &[0, 1, 2];
if let Some((last, elements)) = x.split_last() {
assert_eq!(last, &2);
assert_eq!(elements, &[0, 1]);
}1.0.0pub fn last(&self) -> Option<&T>
pub fn last(&self) -> Option<&T>
Returns the last element of the slice, or None if it is empty.
§Examples
let v = [10, 40, 30];
assert_eq!(Some(&30), v.last());
let w: &[i32] = &[];
assert_eq!(None, w.last());1.77.0pub fn first_chunk<const N: usize>(&self) -> Option<&[T; N]>
pub fn first_chunk<const N: usize>(&self) -> Option<&[T; N]>
Returns an array reference to the first N items in the slice.
If the slice is not at least N in length, this will return None.
§Examples
let u = [10, 40, 30];
assert_eq!(Some(&[10, 40]), u.first_chunk::<2>());
let v: &[i32] = &[10];
assert_eq!(None, v.first_chunk::<2>());
let w: &[i32] = &[];
assert_eq!(Some(&[]), w.first_chunk::<0>());1.77.0pub fn split_first_chunk<const N: usize>(&self) -> Option<(&[T; N], &[T])>
pub fn split_first_chunk<const N: usize>(&self) -> Option<(&[T; N], &[T])>
Returns an array reference to the first N items in the slice and the remaining slice.
If the slice is not at least N in length, this will return None.
§Examples
let x = &[0, 1, 2];
if let Some((first, elements)) = x.split_first_chunk::<2>() {
assert_eq!(first, &[0, 1]);
assert_eq!(elements, &[2]);
}
assert_eq!(None, x.split_first_chunk::<4>());1.77.0pub fn split_last_chunk<const N: usize>(&self) -> Option<(&[T], &[T; N])>
pub fn split_last_chunk<const N: usize>(&self) -> Option<(&[T], &[T; N])>
Returns an array reference to the last N items in the slice and the remaining slice.
If the slice is not at least N in length, this will return None.
§Examples
let x = &[0, 1, 2];
if let Some((elements, last)) = x.split_last_chunk::<2>() {
assert_eq!(elements, &[0]);
assert_eq!(last, &[1, 2]);
}
assert_eq!(None, x.split_last_chunk::<4>());1.77.0pub fn last_chunk<const N: usize>(&self) -> Option<&[T; N]>
pub fn last_chunk<const N: usize>(&self) -> Option<&[T; N]>
Returns an array reference to the last N items in the slice.
If the slice is not at least N in length, this will return None.
§Examples
let u = [10, 40, 30];
assert_eq!(Some(&[40, 30]), u.last_chunk::<2>());
let v: &[i32] = &[10];
assert_eq!(None, v.last_chunk::<2>());
let w: &[i32] = &[];
assert_eq!(Some(&[]), w.last_chunk::<0>());1.0.0pub fn get<I>(&self, index: I) -> Option<&<I as SliceIndex<[T]>>::Output>where
I: SliceIndex<[T]>,
pub fn get<I>(&self, index: I) -> Option<&<I as SliceIndex<[T]>>::Output>where
I: SliceIndex<[T]>,
Returns a reference to an element or subslice depending on the type of index.
- If given a position, returns a reference to the element at that
position or
Noneif out of bounds. - If given a range, returns the subslice corresponding to that range,
or
Noneif out of bounds.
§Examples
let v = [10, 40, 30];
assert_eq!(Some(&40), v.get(1));
assert_eq!(Some(&[10, 40][..]), v.get(0..2));
assert_eq!(None, v.get(3));
assert_eq!(None, v.get(0..4));1.0.0pub unsafe fn get_unchecked<I>(
&self,
index: I,
) -> &<I as SliceIndex<[T]>>::Outputwhere
I: SliceIndex<[T]>,
pub unsafe fn get_unchecked<I>(
&self,
index: I,
) -> &<I as SliceIndex<[T]>>::Outputwhere
I: SliceIndex<[T]>,
Returns a reference to an element or subslice, without doing bounds checking.
For a safe alternative see get.
§Safety
Calling this method with an out-of-bounds index is undefined behavior even if the resulting reference is not used.
You can think of this like .get(index).unwrap_unchecked(). It’s UB
to call .get_unchecked(len), even if you immediately convert to a
pointer. And it’s UB to call .get_unchecked(..len + 1),
.get_unchecked(..=len), or similar.
§Examples
let x = &[1, 2, 4];
unsafe {
assert_eq!(x.get_unchecked(1), &2);
}1.0.0pub fn as_ptr(&self) -> *const T
pub fn as_ptr(&self) -> *const T
Returns a raw pointer to the slice’s buffer.
The caller must ensure that the slice outlives the pointer this function returns, or else it will end up dangling.
The caller must also ensure that the memory the pointer (non-transitively) points to
is never written to (except inside an UnsafeCell) using this pointer or any pointer
derived from it. If you need to mutate the contents of the slice, use as_mut_ptr.
Modifying the container referenced by this slice may cause its buffer to be reallocated, which would also make any pointers to it invalid.
§Examples
let x = &[1, 2, 4];
let x_ptr = x.as_ptr();
unsafe {
for i in 0..x.len() {
assert_eq!(x.get_unchecked(i), &*x_ptr.add(i));
}
}1.48.0pub fn as_ptr_range(&self) -> Range<*const T>
pub fn as_ptr_range(&self) -> Range<*const T>
Returns the two raw pointers spanning the slice.
The returned range is half-open, which means that the end pointer points one past the last element of the slice. This way, an empty slice is represented by two equal pointers, and the difference between the two pointers represents the size of the slice.
See as_ptr for warnings on using these pointers. The end pointer
requires extra caution, as it does not point to a valid element in the
slice.
This function is useful for interacting with foreign interfaces which use two pointers to refer to a range of elements in memory, as is common in C++.
It can also be useful to check if a pointer to an element refers to an element of this slice:
let a = [1, 2, 3];
let x = &a[1] as *const _;
let y = &5 as *const _;
assert!(a.as_ptr_range().contains(&x));
assert!(!a.as_ptr_range().contains(&y));1.94.0pub fn as_array<const N: usize>(&self) -> Option<&[T; N]>
pub fn as_array<const N: usize>(&self) -> Option<&[T; N]>
Gets a reference to the underlying array.
If N is not exactly equal to the length of self, then this method returns None.
1.0.0pub fn iter(&self) -> Iter<'_, T>
pub fn iter(&self) -> Iter<'_, T>
Returns an iterator over the slice.
The iterator yields all items from start to end.
§Examples
let x = &[1, 2, 4];
let mut iterator = x.iter();
assert_eq!(iterator.next(), Some(&1));
assert_eq!(iterator.next(), Some(&2));
assert_eq!(iterator.next(), Some(&4));
assert_eq!(iterator.next(), None);1.0.0pub fn windows(&self, size: usize) -> Windows<'_, T>
pub fn windows(&self, size: usize) -> Windows<'_, T>
Returns an iterator over all contiguous windows of length
size. The windows overlap. If the slice is shorter than
size, the iterator returns no values.
§Panics
Panics if size is zero.
§Examples
let slice = ['l', 'o', 'r', 'e', 'm'];
let mut iter = slice.windows(3);
assert_eq!(iter.next().unwrap(), &['l', 'o', 'r']);
assert_eq!(iter.next().unwrap(), &['o', 'r', 'e']);
assert_eq!(iter.next().unwrap(), &['r', 'e', 'm']);
assert!(iter.next().is_none());If the slice is shorter than size:
let slice = ['f', 'o', 'o'];
let mut iter = slice.windows(4);
assert!(iter.next().is_none());Because the Iterator trait cannot represent the required lifetimes,
there is no windows_mut analog to windows;
[0,1,2].windows_mut(2).collect() would violate the rules of references
(though a LendingIterator analog is possible). You can sometimes use
Cell::as_slice_of_cells in
conjunction with windows instead:
use std::cell::Cell;
let mut array = ['R', 'u', 's', 't', ' ', '2', '0', '1', '5'];
let slice = &mut array[..];
let slice_of_cells: &[Cell<char>] = Cell::from_mut(slice).as_slice_of_cells();
for w in slice_of_cells.windows(3) {
Cell::swap(&w[0], &w[2]);
}
assert_eq!(array, ['s', 't', ' ', '2', '0', '1', '5', 'u', 'R']);1.0.0pub fn chunks(&self, chunk_size: usize) -> Chunks<'_, T>
pub fn chunks(&self, chunk_size: usize) -> Chunks<'_, T>
Returns an iterator over chunk_size elements of the slice at a time, starting at the
beginning of the slice.
The chunks are slices and do not overlap. If chunk_size does not divide the length of the
slice, then the last chunk will not have length chunk_size.
See chunks_exact for a variant of this iterator that returns chunks of always exactly
chunk_size elements, and rchunks for the same iterator but starting at the end of the
slice.
If your chunk_size is a constant, consider using as_chunks instead, which will
give references to arrays of exactly that length, rather than slices.
§Panics
Panics if chunk_size is zero.
§Examples
let slice = ['l', 'o', 'r', 'e', 'm'];
let mut iter = slice.chunks(2);
assert_eq!(iter.next().unwrap(), &['l', 'o']);
assert_eq!(iter.next().unwrap(), &['r', 'e']);
assert_eq!(iter.next().unwrap(), &['m']);
assert!(iter.next().is_none());1.31.0pub fn chunks_exact(&self, chunk_size: usize) -> ChunksExact<'_, T>
pub fn chunks_exact(&self, chunk_size: usize) -> ChunksExact<'_, T>
Returns an iterator over chunk_size elements of the slice at a time, starting at the
beginning of the slice.
The chunks are slices and do not overlap. If chunk_size does not divide the length of the
slice, then the last up to chunk_size-1 elements will be omitted and can be retrieved
from the remainder function of the iterator.
Due to each chunk having exactly chunk_size elements, the compiler can often optimize the
resulting code better than in the case of chunks.
See chunks for a variant of this iterator that also returns the remainder as a smaller
chunk, and rchunks_exact for the same iterator but starting at the end of the slice.
If your chunk_size is a constant, consider using as_chunks instead, which will
give references to arrays of exactly that length, rather than slices.
§Panics
Panics if chunk_size is zero.
§Examples
let slice = ['l', 'o', 'r', 'e', 'm'];
let mut iter = slice.chunks_exact(2);
assert_eq!(iter.next().unwrap(), &['l', 'o']);
assert_eq!(iter.next().unwrap(), &['r', 'e']);
assert!(iter.next().is_none());
assert_eq!(iter.remainder(), &['m']);1.88.0pub unsafe fn as_chunks_unchecked<const N: usize>(&self) -> &[[T; N]]
pub unsafe fn as_chunks_unchecked<const N: usize>(&self) -> &[[T; N]]
Splits the slice into a slice of N-element arrays,
assuming that there’s no remainder.
This is the inverse operation to as_flattened.
As this is unsafe, consider whether you could use as_chunks or
as_rchunks instead, perhaps via something like
if let (chunks, []) = slice.as_chunks() or
let (chunks, []) = slice.as_chunks() else { unreachable!() };.
§Safety
This may only be called when
- The slice splits exactly into
N-element chunks (akaself.len() % N == 0). N != 0.
§Examples
let slice: &[char] = &['l', 'o', 'r', 'e', 'm', '!'];
let chunks: &[[char; 1]] =
// SAFETY: 1-element chunks never have remainder
unsafe { slice.as_chunks_unchecked() };
assert_eq!(chunks, &[['l'], ['o'], ['r'], ['e'], ['m'], ['!']]);
let chunks: &[[char; 3]] =
// SAFETY: The slice length (6) is a multiple of 3
unsafe { slice.as_chunks_unchecked() };
assert_eq!(chunks, &[['l', 'o', 'r'], ['e', 'm', '!']]);
// These would be unsound:
// let chunks: &[[_; 5]] = slice.as_chunks_unchecked() // The slice length is not a multiple of 5
// let chunks: &[[_; 0]] = slice.as_chunks_unchecked() // Zero-length chunks are never allowed1.88.0pub fn as_chunks<const N: usize>(&self) -> (&[[T; N]], &[T])
pub fn as_chunks<const N: usize>(&self) -> (&[[T; N]], &[T])
Splits the slice into a slice of N-element arrays,
starting at the beginning of the slice,
and a remainder slice with length strictly less than N.
The remainder is meaningful in the division sense. Given
let (chunks, remainder) = slice.as_chunks(), then:
chunks.len()equalsslice.len() / N,remainder.len()equalsslice.len() % N, andslice.len()equalschunks.len() * N + remainder.len().
You can flatten the chunks back into a slice-of-T with as_flattened.
§Panics
Panics if N is zero.
Note that this check is against a const generic parameter, not a runtime value, and thus a particular monomorphization will either always panic or it will never panic.
§Examples
let slice = ['l', 'o', 'r', 'e', 'm'];
let (chunks, remainder) = slice.as_chunks();
assert_eq!(chunks, &[['l', 'o'], ['r', 'e']]);
assert_eq!(remainder, &['m']);If you expect the slice to be an exact multiple, you can combine
let-else with an empty slice pattern:
let slice = ['R', 'u', 's', 't'];
let (chunks, []) = slice.as_chunks::<2>() else {
panic!("slice didn't have even length")
};
assert_eq!(chunks, &[['R', 'u'], ['s', 't']]);1.88.0pub fn as_rchunks<const N: usize>(&self) -> (&[T], &[[T; N]])
pub fn as_rchunks<const N: usize>(&self) -> (&[T], &[[T; N]])
Splits the slice into a slice of N-element arrays,
starting at the end of the slice,
and a remainder slice with length strictly less than N.
The remainder is meaningful in the division sense. Given
let (remainder, chunks) = slice.as_rchunks(), then:
remainder.len()equalsslice.len() % N,chunks.len()equalsslice.len() / N, andslice.len()equalschunks.len() * N + remainder.len().
You can flatten the chunks back into a slice-of-T with as_flattened.
§Panics
Panics if N is zero.
Note that this check is against a const generic parameter, not a runtime value, and thus a particular monomorphization will either always panic or it will never panic.
§Examples
let slice = ['l', 'o', 'r', 'e', 'm'];
let (remainder, chunks) = slice.as_rchunks();
assert_eq!(remainder, &['l']);
assert_eq!(chunks, &[['o', 'r'], ['e', 'm']]);1.94.0pub fn array_windows<const N: usize>(&self) -> ArrayWindows<'_, T, N>
pub fn array_windows<const N: usize>(&self) -> ArrayWindows<'_, T, N>
Returns an iterator over overlapping windows of N elements of a slice,
starting at the beginning of the slice.
This is the const generic equivalent of windows.
If N is greater than the size of the slice, it will return no windows.
§Panics
Panics if N is zero.
Note that this check is against a const generic parameter, not a runtime value, and thus a particular monomorphization will either always panic or it will never panic.
§Examples
let slice = [0, 1, 2, 3];
let mut iter = slice.array_windows();
assert_eq!(iter.next().unwrap(), &[0, 1]);
assert_eq!(iter.next().unwrap(), &[1, 2]);
assert_eq!(iter.next().unwrap(), &[2, 3]);
assert!(iter.next().is_none());1.31.0pub fn rchunks(&self, chunk_size: usize) -> RChunks<'_, T>
pub fn rchunks(&self, chunk_size: usize) -> RChunks<'_, T>
Returns an iterator over chunk_size elements of the slice at a time, starting at the end
of the slice.
The chunks are slices and do not overlap. If chunk_size does not divide the length of the
slice, then the last chunk will not have length chunk_size.
See rchunks_exact for a variant of this iterator that returns chunks of always exactly
chunk_size elements, and chunks for the same iterator but starting at the beginning
of the slice.
If your chunk_size is a constant, consider using as_rchunks instead, which will
give references to arrays of exactly that length, rather than slices.
§Panics
Panics if chunk_size is zero.
§Examples
let slice = ['l', 'o', 'r', 'e', 'm'];
let mut iter = slice.rchunks(2);
assert_eq!(iter.next().unwrap(), &['e', 'm']);
assert_eq!(iter.next().unwrap(), &['o', 'r']);
assert_eq!(iter.next().unwrap(), &['l']);
assert!(iter.next().is_none());1.31.0pub fn rchunks_exact(&self, chunk_size: usize) -> RChunksExact<'_, T>
pub fn rchunks_exact(&self, chunk_size: usize) -> RChunksExact<'_, T>
Returns an iterator over chunk_size elements of the slice at a time, starting at the
end of the slice.
The chunks are slices and do not overlap. If chunk_size does not divide the length of the
slice, then the last up to chunk_size-1 elements will be omitted and can be retrieved
from the remainder function of the iterator.
Due to each chunk having exactly chunk_size elements, the compiler can often optimize the
resulting code better than in the case of rchunks.
See rchunks for a variant of this iterator that also returns the remainder as a smaller
chunk, and chunks_exact for the same iterator but starting at the beginning of the
slice.
If your chunk_size is a constant, consider using as_rchunks instead, which will
give references to arrays of exactly that length, rather than slices.
§Panics
Panics if chunk_size is zero.
§Examples
let slice = ['l', 'o', 'r', 'e', 'm'];
let mut iter = slice.rchunks_exact(2);
assert_eq!(iter.next().unwrap(), &['e', 'm']);
assert_eq!(iter.next().unwrap(), &['o', 'r']);
assert!(iter.next().is_none());
assert_eq!(iter.remainder(), &['l']);1.77.0pub fn chunk_by<F>(&self, pred: F) -> ChunkBy<'_, T, F>
pub fn chunk_by<F>(&self, pred: F) -> ChunkBy<'_, T, F>
Returns an iterator over the slice producing non-overlapping runs of elements using the predicate to separate them.
The predicate is called for every pair of consecutive elements,
meaning that it is called on slice[0] and slice[1],
followed by slice[1] and slice[2], and so on.
§Examples
let slice = &[1, 1, 1, 3, 3, 2, 2, 2];
let mut iter = slice.chunk_by(|a, b| a == b);
assert_eq!(iter.next(), Some(&[1, 1, 1][..]));
assert_eq!(iter.next(), Some(&[3, 3][..]));
assert_eq!(iter.next(), Some(&[2, 2, 2][..]));
assert_eq!(iter.next(), None);This method can be used to extract the sorted subslices:
let slice = &[1, 1, 2, 3, 2, 3, 2, 3, 4];
let mut iter = slice.chunk_by(|a, b| a <= b);
assert_eq!(iter.next(), Some(&[1, 1, 2, 3][..]));
assert_eq!(iter.next(), Some(&[2, 3][..]));
assert_eq!(iter.next(), Some(&[2, 3, 4][..]));
assert_eq!(iter.next(), None);1.0.0pub fn split_at(&self, mid: usize) -> (&[T], &[T])
pub fn split_at(&self, mid: usize) -> (&[T], &[T])
Divides one slice into two at an index.
The first will contain all indices from [0, mid) (excluding
the index mid itself) and the second will contain all
indices from [mid, len) (excluding the index len itself).
§Panics
Panics if mid > len. For a non-panicking alternative see
split_at_checked.
§Examples
let v = ['a', 'b', 'c'];
{
let (left, right) = v.split_at(0);
assert_eq!(left, []);
assert_eq!(right, ['a', 'b', 'c']);
}
{
let (left, right) = v.split_at(2);
assert_eq!(left, ['a', 'b']);
assert_eq!(right, ['c']);
}
{
let (left, right) = v.split_at(3);
assert_eq!(left, ['a', 'b', 'c']);
assert_eq!(right, []);
}1.79.0pub unsafe fn split_at_unchecked(&self, mid: usize) -> (&[T], &[T])
pub unsafe fn split_at_unchecked(&self, mid: usize) -> (&[T], &[T])
Divides one slice into two at an index, without doing bounds checking.
The first will contain all indices from [0, mid) (excluding
the index mid itself) and the second will contain all
indices from [mid, len) (excluding the index len itself).
For a safe alternative see split_at.
§Safety
Calling this method with an out-of-bounds index is undefined behavior
even if the resulting reference is not used. The caller has to ensure that
0 <= mid <= self.len().
§Examples
let v = ['a', 'b', 'c'];
unsafe {
let (left, right) = v.split_at_unchecked(0);
assert_eq!(left, []);
assert_eq!(right, ['a', 'b', 'c']);
}
unsafe {
let (left, right) = v.split_at_unchecked(2);
assert_eq!(left, ['a', 'b']);
assert_eq!(right, ['c']);
}
unsafe {
let (left, right) = v.split_at_unchecked(3);
assert_eq!(left, ['a', 'b', 'c']);
assert_eq!(right, []);
}1.80.0pub fn split_at_checked(&self, mid: usize) -> Option<(&[T], &[T])>
pub fn split_at_checked(&self, mid: usize) -> Option<(&[T], &[T])>
Divides one slice into two at an index, returning None if the slice is
too short.
If mid ≤ len returns a pair of slices where the first will contain all
indices from [0, mid) (excluding the index mid itself) and the
second will contain all indices from [mid, len) (excluding the index
len itself).
Otherwise, if mid > len, returns None.
§Examples
let v = [1, -2, 3, -4, 5, -6];
{
let (left, right) = v.split_at_checked(0).unwrap();
assert_eq!(left, []);
assert_eq!(right, [1, -2, 3, -4, 5, -6]);
}
{
let (left, right) = v.split_at_checked(2).unwrap();
assert_eq!(left, [1, -2]);
assert_eq!(right, [3, -4, 5, -6]);
}
{
let (left, right) = v.split_at_checked(6).unwrap();
assert_eq!(left, [1, -2, 3, -4, 5, -6]);
assert_eq!(right, []);
}
assert_eq!(None, v.split_at_checked(7));1.0.0pub fn split<F>(&self, pred: F) -> Split<'_, T, F>
pub fn split<F>(&self, pred: F) -> Split<'_, T, F>
Returns an iterator over subslices separated by elements that match
pred. The matched element is not contained in the subslices.
§Examples
let slice = [10, 40, 33, 20];
let mut iter = slice.split(|num| num % 3 == 0);
assert_eq!(iter.next().unwrap(), &[10, 40]);
assert_eq!(iter.next().unwrap(), &[20]);
assert!(iter.next().is_none());If the first element is matched, an empty slice will be the first item returned by the iterator. Similarly, if the last element in the slice is matched, an empty slice will be the last item returned by the iterator:
let slice = [10, 40, 33];
let mut iter = slice.split(|num| num % 3 == 0);
assert_eq!(iter.next().unwrap(), &[10, 40]);
assert_eq!(iter.next().unwrap(), &[]);
assert!(iter.next().is_none());If two matched elements are directly adjacent, an empty slice will be present between them:
let slice = [10, 6, 33, 20];
let mut iter = slice.split(|num| num % 3 == 0);
assert_eq!(iter.next().unwrap(), &[10]);
assert_eq!(iter.next().unwrap(), &[]);
assert_eq!(iter.next().unwrap(), &[20]);
assert!(iter.next().is_none());1.51.0pub fn split_inclusive<F>(&self, pred: F) -> SplitInclusive<'_, T, F>
pub fn split_inclusive<F>(&self, pred: F) -> SplitInclusive<'_, T, F>
Returns an iterator over subslices separated by elements that match
pred. The matched element is contained in the end of the previous
subslice as a terminator.
§Examples
let slice = [10, 40, 33, 20];
let mut iter = slice.split_inclusive(|num| num % 3 == 0);
assert_eq!(iter.next().unwrap(), &[10, 40, 33]);
assert_eq!(iter.next().unwrap(), &[20]);
assert!(iter.next().is_none());If the last element of the slice is matched, that element will be considered the terminator of the preceding slice. That slice will be the last item returned by the iterator.
let slice = [3, 10, 40, 33];
let mut iter = slice.split_inclusive(|num| num % 3 == 0);
assert_eq!(iter.next().unwrap(), &[3]);
assert_eq!(iter.next().unwrap(), &[10, 40, 33]);
assert!(iter.next().is_none());1.27.0pub fn rsplit<F>(&self, pred: F) -> RSplit<'_, T, F>
pub fn rsplit<F>(&self, pred: F) -> RSplit<'_, T, F>
Returns an iterator over subslices separated by elements that match
pred, starting at the end of the slice and working backwards.
The matched element is not contained in the subslices.
§Examples
let slice = [11, 22, 33, 0, 44, 55];
let mut iter = slice.rsplit(|num| *num == 0);
assert_eq!(iter.next().unwrap(), &[44, 55]);
assert_eq!(iter.next().unwrap(), &[11, 22, 33]);
assert_eq!(iter.next(), None);As with split(), if the first or last element is matched, an empty
slice will be the first (or last) item returned by the iterator.
let v = &[0, 1, 1, 2, 3, 5, 8];
let mut it = v.rsplit(|n| *n % 2 == 0);
assert_eq!(it.next().unwrap(), &[]);
assert_eq!(it.next().unwrap(), &[3, 5]);
assert_eq!(it.next().unwrap(), &[1, 1]);
assert_eq!(it.next().unwrap(), &[]);
assert_eq!(it.next(), None);1.0.0pub fn splitn<F>(&self, n: usize, pred: F) -> SplitN<'_, T, F>
pub fn splitn<F>(&self, n: usize, pred: F) -> SplitN<'_, T, F>
Returns an iterator over subslices separated by elements that match
pred, limited to returning at most n items. The matched element is
not contained in the subslices.
The last element returned, if any, will contain the remainder of the slice.
§Examples
Print the slice split once by numbers divisible by 3 (i.e., [10, 40],
[20, 60, 50]):
let v = [10, 40, 30, 20, 60, 50];
for group in v.splitn(2, |num| *num % 3 == 0) {
println!("{group:?}");
}1.0.0pub fn rsplitn<F>(&self, n: usize, pred: F) -> RSplitN<'_, T, F>
pub fn rsplitn<F>(&self, n: usize, pred: F) -> RSplitN<'_, T, F>
Returns an iterator over subslices separated by elements that match
pred limited to returning at most n items. This starts at the end of
the slice and works backwards. The matched element is not contained in
the subslices.
The last element returned, if any, will contain the remainder of the slice.
§Examples
Print the slice split once, starting from the end, by numbers divisible
by 3 (i.e., [50], [10, 40, 30, 20]):
let v = [10, 40, 30, 20, 60, 50];
for group in v.rsplitn(2, |num| *num % 3 == 0) {
println!("{group:?}");
}pub fn split_once<F>(&self, pred: F) -> Option<(&[T], &[T])>
🔬This is a nightly-only experimental API. (slice_split_once)
pub fn split_once<F>(&self, pred: F) -> Option<(&[T], &[T])>
slice_split_once)Splits the slice on the first element that matches the specified predicate.
If any matching elements are present in the slice, returns the prefix
before the match and suffix after. The matching element itself is not
included. If no elements match, returns None.
§Examples
#![feature(slice_split_once)]
let s = [1, 2, 3, 2, 4];
assert_eq!(s.split_once(|&x| x == 2), Some((
&[1][..],
&[3, 2, 4][..]
)));
assert_eq!(s.split_once(|&x| x == 0), None);pub fn rsplit_once<F>(&self, pred: F) -> Option<(&[T], &[T])>
🔬This is a nightly-only experimental API. (slice_split_once)
pub fn rsplit_once<F>(&self, pred: F) -> Option<(&[T], &[T])>
slice_split_once)Splits the slice on the last element that matches the specified predicate.
If any matching elements are present in the slice, returns the prefix
before the match and suffix after. The matching element itself is not
included. If no elements match, returns None.
§Examples
#![feature(slice_split_once)]
let s = [1, 2, 3, 2, 4];
assert_eq!(s.rsplit_once(|&x| x == 2), Some((
&[1, 2, 3][..],
&[4][..]
)));
assert_eq!(s.rsplit_once(|&x| x == 0), None);1.0.0pub fn contains(&self, x: &T) -> boolwhere
T: PartialEq,
pub fn contains(&self, x: &T) -> boolwhere
T: PartialEq,
Returns true if the slice contains an element with the given value.
This operation is O(n).
Note that if you have a sorted slice, binary_search may be faster.
§Examples
let v = [10, 40, 30];
assert!(v.contains(&30));
assert!(!v.contains(&50));If you do not have a &T, but some other value that you can compare
with one (for example, String implements PartialEq<str>), you can
use iter().any:
let v = [String::from("hello"), String::from("world")]; // slice of `String`
assert!(v.iter().any(|e| e == "hello")); // search with `&str`
assert!(!v.iter().any(|e| e == "hi"));1.0.0pub fn starts_with(&self, needle: &[T]) -> boolwhere
T: PartialEq,
pub fn starts_with(&self, needle: &[T]) -> boolwhere
T: PartialEq,
Returns true if needle is a prefix of the slice or equal to the slice.
§Examples
let v = [10, 40, 30];
assert!(v.starts_with(&[10]));
assert!(v.starts_with(&[10, 40]));
assert!(v.starts_with(&v));
assert!(!v.starts_with(&[50]));
assert!(!v.starts_with(&[10, 50]));Always returns true if needle is an empty slice:
let v = &[10, 40, 30];
assert!(v.starts_with(&[]));
let v: &[u8] = &[];
assert!(v.starts_with(&[]));1.0.0pub fn ends_with(&self, needle: &[T]) -> boolwhere
T: PartialEq,
pub fn ends_with(&self, needle: &[T]) -> boolwhere
T: PartialEq,
Returns true if needle is a suffix of the slice or equal to the slice.
§Examples
let v = [10, 40, 30];
assert!(v.ends_with(&[30]));
assert!(v.ends_with(&[40, 30]));
assert!(v.ends_with(&v));
assert!(!v.ends_with(&[50]));
assert!(!v.ends_with(&[50, 30]));Always returns true if needle is an empty slice:
let v = &[10, 40, 30];
assert!(v.ends_with(&[]));
let v: &[u8] = &[];
assert!(v.ends_with(&[]));1.51.0pub fn strip_prefix<P>(&self, prefix: &P) -> Option<&[T]>
pub fn strip_prefix<P>(&self, prefix: &P) -> Option<&[T]>
Returns a subslice with the prefix removed.
If the slice starts with prefix, returns the subslice after the prefix, wrapped in Some.
If prefix is empty, simply returns the original slice. If prefix is equal to the
original slice, returns an empty slice.
If the slice does not start with prefix, returns None.
§Examples
let v = &[10, 40, 30];
assert_eq!(v.strip_prefix(&[10]), Some(&[40, 30][..]));
assert_eq!(v.strip_prefix(&[10, 40]), Some(&[30][..]));
assert_eq!(v.strip_prefix(&[10, 40, 30]), Some(&[][..]));
assert_eq!(v.strip_prefix(&[50]), None);
assert_eq!(v.strip_prefix(&[10, 50]), None);
let prefix : &str = "he";
assert_eq!(b"hello".strip_prefix(prefix.as_bytes()),
Some(b"llo".as_ref()));1.51.0pub fn strip_suffix<P>(&self, suffix: &P) -> Option<&[T]>
pub fn strip_suffix<P>(&self, suffix: &P) -> Option<&[T]>
Returns a subslice with the suffix removed.
If the slice ends with suffix, returns the subslice before the suffix, wrapped in Some.
If suffix is empty, simply returns the original slice. If suffix is equal to the
original slice, returns an empty slice.
If the slice does not end with suffix, returns None.
§Examples
let v = &[10, 40, 30];
assert_eq!(v.strip_suffix(&[30]), Some(&[10, 40][..]));
assert_eq!(v.strip_suffix(&[40, 30]), Some(&[10][..]));
assert_eq!(v.strip_suffix(&[10, 40, 30]), Some(&[][..]));
assert_eq!(v.strip_suffix(&[50]), None);
assert_eq!(v.strip_suffix(&[50, 30]), None);pub fn strip_circumfix<S, P>(&self, prefix: &P, suffix: &S) -> Option<&[T]>
🔬This is a nightly-only experimental API. (strip_circumfix)
pub fn strip_circumfix<S, P>(&self, prefix: &P, suffix: &S) -> Option<&[T]>
strip_circumfix)Returns a subslice with the prefix and suffix removed.
If the slice starts with prefix and ends with suffix, returns the subslice after the
prefix and before the suffix, wrapped in Some.
If the slice does not start with prefix or does not end with suffix, returns None.
§Examples
#![feature(strip_circumfix)]
let v = &[10, 50, 40, 30];
assert_eq!(v.strip_circumfix(&[10], &[30]), Some(&[50, 40][..]));
assert_eq!(v.strip_circumfix(&[10], &[40, 30]), Some(&[50][..]));
assert_eq!(v.strip_circumfix(&[10, 50], &[40, 30]), Some(&[][..]));
assert_eq!(v.strip_circumfix(&[50], &[30]), None);
assert_eq!(v.strip_circumfix(&[10], &[40]), None);
assert_eq!(v.strip_circumfix(&[], &[40, 30]), Some(&[10, 50][..]));
assert_eq!(v.strip_circumfix(&[10, 50], &[]), Some(&[40, 30][..]));pub fn trim_prefix<P>(&self, prefix: &P) -> &[T]
🔬This is a nightly-only experimental API. (trim_prefix_suffix)
pub fn trim_prefix<P>(&self, prefix: &P) -> &[T]
trim_prefix_suffix)Returns a subslice with the optional prefix removed.
If the slice starts with prefix, returns the subslice after the prefix. If prefix
is empty or the slice does not start with prefix, simply returns the original slice.
If prefix is equal to the original slice, returns an empty slice.
§Examples
#![feature(trim_prefix_suffix)]
let v = &[10, 40, 30];
// Prefix present - removes it
assert_eq!(v.trim_prefix(&[10]), &[40, 30][..]);
assert_eq!(v.trim_prefix(&[10, 40]), &[30][..]);
assert_eq!(v.trim_prefix(&[10, 40, 30]), &[][..]);
// Prefix absent - returns original slice
assert_eq!(v.trim_prefix(&[50]), &[10, 40, 30][..]);
assert_eq!(v.trim_prefix(&[10, 50]), &[10, 40, 30][..]);
let prefix : &str = "he";
assert_eq!(b"hello".trim_prefix(prefix.as_bytes()), b"llo".as_ref());pub fn trim_suffix<P>(&self, suffix: &P) -> &[T]
🔬This is a nightly-only experimental API. (trim_prefix_suffix)
pub fn trim_suffix<P>(&self, suffix: &P) -> &[T]
trim_prefix_suffix)Returns a subslice with the optional suffix removed.
If the slice ends with suffix, returns the subslice before the suffix. If suffix
is empty or the slice does not end with suffix, simply returns the original slice.
If suffix is equal to the original slice, returns an empty slice.
§Examples
#![feature(trim_prefix_suffix)]
let v = &[10, 40, 30];
// Suffix present - removes it
assert_eq!(v.trim_suffix(&[30]), &[10, 40][..]);
assert_eq!(v.trim_suffix(&[40, 30]), &[10][..]);
assert_eq!(v.trim_suffix(&[10, 40, 30]), &[][..]);
// Suffix absent - returns original slice
assert_eq!(v.trim_suffix(&[50]), &[10, 40, 30][..]);
assert_eq!(v.trim_suffix(&[50, 30]), &[10, 40, 30][..]);1.0.0pub fn binary_search(&self, x: &T) -> Result<usize, usize>where
T: Ord,
pub fn binary_search(&self, x: &T) -> Result<usize, usize>where
T: Ord,
Binary searches this slice for a given element. If the slice is not sorted, the returned result is unspecified and meaningless.
If the value is found then Result::Ok is returned, containing the
index of the matching element. If there are multiple matches, then any
one of the matches could be returned. The index is chosen
deterministically, but is subject to change in future versions of Rust.
If the value is not found then Result::Err is returned, containing
the index where a matching element could be inserted while maintaining
sorted order.
See also binary_search_by, binary_search_by_key, and partition_point.
§Examples
Looks up a series of four elements. The first is found, with a
uniquely determined position; the second and third are not
found; the fourth could match any position in [1, 4].
let s = [0, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55];
assert_eq!(s.binary_search(&13), Ok(9));
assert_eq!(s.binary_search(&4), Err(7));
assert_eq!(s.binary_search(&100), Err(13));
let r = s.binary_search(&1);
assert!(match r { Ok(1..=4) => true, _ => false, });If you want to find that whole range of matching items, rather than
an arbitrary matching one, that can be done using partition_point:
let s = [0, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55];
let low = s.partition_point(|x| x < &1);
assert_eq!(low, 1);
let high = s.partition_point(|x| x <= &1);
assert_eq!(high, 5);
let r = s.binary_search(&1);
assert!((low..high).contains(&r.unwrap()));
assert!(s[..low].iter().all(|&x| x < 1));
assert!(s[low..high].iter().all(|&x| x == 1));
assert!(s[high..].iter().all(|&x| x > 1));
// For something not found, the "range" of equal items is empty
assert_eq!(s.partition_point(|x| x < &11), 9);
assert_eq!(s.partition_point(|x| x <= &11), 9);
assert_eq!(s.binary_search(&11), Err(9));If you want to insert an item to a sorted vector, while maintaining
sort order, consider using partition_point:
let mut s = vec![0, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55];
let num = 42;
let idx = s.partition_point(|&x| x <= num);
// If `num` is unique, `s.partition_point(|&x| x < num)` (with `<`) is equivalent to
// `s.binary_search(&num).unwrap_or_else(|x| x)`, but using `<=` will allow `insert`
// to shift less elements.
s.insert(idx, num);
assert_eq!(s, [0, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 42, 55]);1.0.0pub fn binary_search_by<'a, F>(&'a self, f: F) -> Result<usize, usize>
pub fn binary_search_by<'a, F>(&'a self, f: F) -> Result<usize, usize>
Binary searches this slice with a comparator function.
The comparator function should return an order code that indicates
whether its argument is Less, Equal or Greater the desired
target.
If the slice is not sorted or if the comparator function does not
implement an order consistent with the sort order of the underlying
slice, the returned result is unspecified and meaningless.
If the value is found then Result::Ok is returned, containing the
index of the matching element. If there are multiple matches, then any
one of the matches could be returned. The index is chosen
deterministically, but is subject to change in future versions of Rust.
If the value is not found then Result::Err is returned, containing
the index where a matching element could be inserted while maintaining
sorted order.
See also binary_search, binary_search_by_key, and partition_point.
§Examples
Looks up a series of four elements. The first is found, with a
uniquely determined position; the second and third are not
found; the fourth could match any position in [1, 4].
let s = [0, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55];
let seek = 13;
assert_eq!(s.binary_search_by(|probe| probe.cmp(&seek)), Ok(9));
let seek = 4;
assert_eq!(s.binary_search_by(|probe| probe.cmp(&seek)), Err(7));
let seek = 100;
assert_eq!(s.binary_search_by(|probe| probe.cmp(&seek)), Err(13));
let seek = 1;
let r = s.binary_search_by(|probe| probe.cmp(&seek));
assert!(match r { Ok(1..=4) => true, _ => false, });1.10.0pub fn binary_search_by_key<'a, B, F>(
&'a self,
b: &B,
f: F,
) -> Result<usize, usize>
pub fn binary_search_by_key<'a, B, F>( &'a self, b: &B, f: F, ) -> Result<usize, usize>
Binary searches this slice with a key extraction function.
Assumes that the slice is sorted by the key, for instance with
sort_by_key using the same key extraction function.
If the slice is not sorted by the key, the returned result is
unspecified and meaningless.
If the value is found then Result::Ok is returned, containing the
index of the matching element. If there are multiple matches, then any
one of the matches could be returned. The index is chosen
deterministically, but is subject to change in future versions of Rust.
If the value is not found then Result::Err is returned, containing
the index where a matching element could be inserted while maintaining
sorted order.
See also binary_search, binary_search_by, and partition_point.
§Examples
Looks up a series of four elements in a slice of pairs sorted by
their second elements. The first is found, with a uniquely
determined position; the second and third are not found; the
fourth could match any position in [1, 4].
let s = [(0, 0), (2, 1), (4, 1), (5, 1), (3, 1),
(1, 2), (2, 3), (4, 5), (5, 8), (3, 13),
(1, 21), (2, 34), (4, 55)];
assert_eq!(s.binary_search_by_key(&13, |&(a, b)| b), Ok(9));
assert_eq!(s.binary_search_by_key(&4, |&(a, b)| b), Err(7));
assert_eq!(s.binary_search_by_key(&100, |&(a, b)| b), Err(13));
let r = s.binary_search_by_key(&1, |&(a, b)| b);
assert!(match r { Ok(1..=4) => true, _ => false, });1.30.0pub unsafe fn align_to<U>(&self) -> (&[T], &[U], &[T])
pub unsafe fn align_to<U>(&self) -> (&[T], &[U], &[T])
Transmutes the slice to a slice of another type, ensuring alignment of the types is maintained.
This method splits the slice into three distinct slices: prefix, correctly aligned middle slice of a new type, and the suffix slice. The middle part will be as big as possible under the given alignment constraint and element size.
This method has no purpose when either input element T or output element U are
zero-sized and will return the original slice without splitting anything.
§Safety
This method is essentially a transmute with respect to the elements in the returned
middle slice, so all the usual caveats pertaining to transmute::<T, U> also apply here.
§Examples
Basic usage:
unsafe {
let bytes: [u8; 7] = [1, 2, 3, 4, 5, 6, 7];
let (prefix, shorts, suffix) = bytes.align_to::<u16>();
// less_efficient_algorithm_for_bytes(prefix);
// more_efficient_algorithm_for_aligned_shorts(shorts);
// less_efficient_algorithm_for_bytes(suffix);
}pub fn as_simd<const LANES: usize>(&self) -> (&[T], &[Simd<T, LANES>], &[T])
🔬This is a nightly-only experimental API. (portable_simd)
pub fn as_simd<const LANES: usize>(&self) -> (&[T], &[Simd<T, LANES>], &[T])
portable_simd)Splits a slice into a prefix, a middle of aligned SIMD types, and a suffix.
This is a safe wrapper around slice::align_to, so inherits the same
guarantees as that method.
§Panics
This will panic if the size of the SIMD type is different from
LANES times that of the scalar.
At the time of writing, the trait restrictions on Simd<T, LANES> keeps
that from ever happening, as only power-of-two numbers of lanes are
supported. It’s possible that, in the future, those restrictions might
be lifted in a way that would make it possible to see panics from this
method for something like LANES == 3.
§Examples
#![feature(portable_simd)]
use core::simd::prelude::*;
let short = &[1, 2, 3];
let (prefix, middle, suffix) = short.as_simd::<4>();
assert_eq!(middle, []); // Not enough elements for anything in the middle
// They might be split in any possible way between prefix and suffix
let it = prefix.iter().chain(suffix).copied();
assert_eq!(it.collect::<Vec<_>>(), vec![1, 2, 3]);
fn basic_simd_sum(x: &[f32]) -> f32 {
use std::ops::Add;
let (prefix, middle, suffix) = x.as_simd();
let sums = f32x4::from_array([
prefix.iter().copied().sum(),
0.0,
0.0,
suffix.iter().copied().sum(),
]);
let sums = middle.iter().copied().fold(sums, f32x4::add);
sums.reduce_sum()
}
let numbers: Vec<f32> = (1..101).map(|x| x as _).collect();
assert_eq!(basic_simd_sum(&numbers[1..99]), 4949.0);1.82.0pub fn is_sorted(&self) -> boolwhere
T: PartialOrd,
pub fn is_sorted(&self) -> boolwhere
T: PartialOrd,
Checks if the elements of this slice are sorted.
That is, for each element a and its following element b, a <= b must hold. If the
slice yields exactly zero or one element, true is returned.
Note that if Self::Item is only PartialOrd, but not Ord, the above definition
implies that this function returns false if any two consecutive items are not
comparable.
§Examples
let empty: [i32; 0] = [];
assert!([1, 2, 2, 9].is_sorted());
assert!(![1, 3, 2, 4].is_sorted());
assert!([0].is_sorted());
assert!(empty.is_sorted());
assert!(![0.0, 1.0, f32::NAN].is_sorted());1.82.0pub fn is_sorted_by<'a, F>(&'a self, compare: F) -> bool
pub fn is_sorted_by<'a, F>(&'a self, compare: F) -> bool
Checks if the elements of this slice are sorted using the given comparator function.
Instead of using PartialOrd::partial_cmp, this function uses the given compare
function to determine whether two elements are to be considered in sorted order.
§Examples
assert!([1, 2, 2, 9].is_sorted_by(|a, b| a <= b));
assert!(![1, 2, 2, 9].is_sorted_by(|a, b| a < b));
assert!([0].is_sorted_by(|a, b| true));
assert!([0].is_sorted_by(|a, b| false));
let empty: [i32; 0] = [];
assert!(empty.is_sorted_by(|a, b| false));
assert!(empty.is_sorted_by(|a, b| true));1.82.0pub fn is_sorted_by_key<'a, F, K>(&'a self, f: F) -> bool
pub fn is_sorted_by_key<'a, F, K>(&'a self, f: F) -> bool
Checks if the elements of this slice are sorted using the given key extraction function.
Instead of comparing the slice’s elements directly, this function compares the keys of the
elements, as determined by f. Apart from that, it’s equivalent to is_sorted; see its
documentation for more information.
§Examples
assert!(["c", "bb", "aaa"].is_sorted_by_key(|s| s.len()));
assert!(![-2i32, -1, 0, 3].is_sorted_by_key(|n| n.abs()));1.52.0pub fn partition_point<P>(&self, pred: P) -> usize
pub fn partition_point<P>(&self, pred: P) -> usize
Returns the index of the partition point according to the given predicate (the index of the first element of the second partition).
The slice is assumed to be partitioned according to the given predicate.
This means that all elements for which the predicate returns true are at the start of the slice
and all elements for which the predicate returns false are at the end.
For example, [7, 15, 3, 5, 4, 12, 6] is partitioned under the predicate x % 2 != 0
(all odd numbers are at the start, all even at the end).
If this slice is not partitioned, the returned result is unspecified and meaningless, as this method performs a kind of binary search.
See also binary_search, binary_search_by, and binary_search_by_key.
§Examples
let v = [1, 2, 3, 3, 5, 6, 7];
let i = v.partition_point(|&x| x < 5);
assert_eq!(i, 4);
assert!(v[..i].iter().all(|&x| x < 5));
assert!(v[i..].iter().all(|&x| !(x < 5)));If all elements of the slice match the predicate, including if the slice is empty, then the length of the slice will be returned:
let a = [2, 4, 8];
assert_eq!(a.partition_point(|x| x < &100), a.len());
let a: [i32; 0] = [];
assert_eq!(a.partition_point(|x| x < &100), 0);If you want to insert an item to a sorted vector, while maintaining sort order:
let mut s = vec![0, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55];
let num = 42;
let idx = s.partition_point(|&x| x <= num);
s.insert(idx, num);
assert_eq!(s, [0, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 42, 55]);pub fn element_offset(&self, element: &T) -> Option<usize>
🔬This is a nightly-only experimental API. (substr_range)
pub fn element_offset(&self, element: &T) -> Option<usize>
substr_range)Returns the index that an element reference points to.
Returns None if element does not point to the start of an element within the slice.
This method is useful for extending slice iterators like slice::split.
Note that this uses pointer arithmetic and does not compare elements.
To find the index of an element via comparison, use
.iter().position() instead.
§Panics
Panics if T is zero-sized.
§Examples
Basic usage:
#![feature(substr_range)]
let nums: &[u32] = &[1, 7, 1, 1];
let num = &nums[2];
assert_eq!(num, &1);
assert_eq!(nums.element_offset(num), Some(2));Returning None with an unaligned element:
#![feature(substr_range)]
let arr: &[[u32; 2]] = &[[0, 1], [2, 3]];
let flat_arr: &[u32] = arr.as_flattened();
let ok_elm: &[u32; 2] = flat_arr[0..2].try_into().unwrap();
let weird_elm: &[u32; 2] = flat_arr[1..3].try_into().unwrap();
assert_eq!(ok_elm, &[0, 1]);
assert_eq!(weird_elm, &[1, 2]);
assert_eq!(arr.element_offset(ok_elm), Some(0)); // Points to element 0
assert_eq!(arr.element_offset(weird_elm), None); // Points between element 0 and 1pub fn subslice_range(&self, subslice: &[T]) -> Option<Range<usize>>
🔬This is a nightly-only experimental API. (substr_range)
pub fn subslice_range(&self, subslice: &[T]) -> Option<Range<usize>>
substr_range)Returns the range of indices that a subslice points to.
Returns None if subslice does not point within the slice or if it is not aligned with the
elements in the slice.
This method does not compare elements. Instead, this method finds the location in the slice that
subslice was obtained from. To find the index of a subslice via comparison, instead use
.windows().position().
This method is useful for extending slice iterators like slice::split.
Note that this may return a false positive (either Some(0..0) or Some(self.len()..self.len()))
if subslice has a length of zero and points to the beginning or end of another, separate, slice.
§Panics
Panics if T is zero-sized.
§Examples
Basic usage:
#![feature(substr_range)]
let nums = &[0, 5, 10, 0, 0, 5];
let mut iter = nums
.split(|t| *t == 0)
.map(|n| nums.subslice_range(n).unwrap());
assert_eq!(iter.next(), Some(0..0));
assert_eq!(iter.next(), Some(1..3));
assert_eq!(iter.next(), Some(4..4));
assert_eq!(iter.next(), Some(5..6));pub fn as_slice(&self) -> &[T]
🔬This is a nightly-only experimental API. (str_as_str)
pub fn as_slice(&self) -> &[T]
str_as_str)Returns the same slice &[T].
This method is redundant when used directly on &[T], but
it helps dereferencing other “container” types to slices,
for example Box<[T]> or Arc<[T]>.
1.79.0pub fn utf8_chunks(&self) -> Utf8Chunks<'_>
pub fn utf8_chunks(&self) -> Utf8Chunks<'_>
Creates an iterator over the contiguous valid UTF-8 ranges of this slice, and the non-UTF-8 fragments in between.
See the Utf8Chunk type for documentation of the items yielded by this iterator.
§Examples
This function formats arbitrary but mostly-UTF-8 bytes into Rust source
code in the form of a C-string literal (c"...").
use std::fmt::Write as _;
pub fn cstr_literal(bytes: &[u8]) -> String {
let mut repr = String::new();
repr.push_str("c\"");
for chunk in bytes.utf8_chunks() {
for ch in chunk.valid().chars() {
// Escapes \0, \t, \r, \n, \\, \', \", and uses \u{...} for non-printable characters.
write!(repr, "{}", ch.escape_debug()).unwrap();
}
for byte in chunk.invalid() {
write!(repr, "\\x{:02X}", byte).unwrap();
}
}
repr.push('"');
repr
}
fn main() {
let lit = cstr_literal(b"\xferris the \xf0\x9f\xa6\x80\x07");
let expected = stringify!(c"\xFErris the 🦀\u{7}");
assert_eq!(lit, expected);
}1.0.0pub fn to_vec(&self) -> Vec<T>where
T: Clone,
pub fn to_vec(&self) -> Vec<T>where
T: Clone,
Copies self into a new Vec.
§Examples
let s = [10, 40, 30];
let x = s.to_vec();
// Here, `s` and `x` can be modified independently.pub fn to_vec_in<A>(&self, alloc: A) -> Vec<T, A>
🔬This is a nightly-only experimental API. (allocator_api)
pub fn to_vec_in<A>(&self, alloc: A) -> Vec<T, A>
allocator_api)Copies self into a new Vec with an allocator.
§Examples
#![feature(allocator_api)]
use std::alloc::System;
let s = [10, 40, 30];
let x = s.to_vec_in(System);
// Here, `s` and `x` can be modified independently.1.0.0pub fn concat<Item>(&self) -> <[T] as Concat<Item>>::Output ⓘ
pub fn concat<Item>(&self) -> <[T] as Concat<Item>>::Output ⓘ
Flattens a slice of T into a single value Self::Output.
§Examples
assert_eq!(["hello", "world"].concat(), "helloworld");
assert_eq!([[1, 2], [3, 4]].concat(), [1, 2, 3, 4]);1.3.0pub fn join<Separator>(
&self,
sep: Separator,
) -> <[T] as Join<Separator>>::Output ⓘ
pub fn join<Separator>( &self, sep: Separator, ) -> <[T] as Join<Separator>>::Output ⓘ
Flattens a slice of T into a single value Self::Output, placing a
given separator between each.
§Examples
assert_eq!(["hello", "world"].join(" "), "hello world");
assert_eq!([[1, 2], [3, 4]].join(&0), [1, 2, 0, 3, 4]);
assert_eq!([[1, 2], [3, 4]].join(&[0, 0][..]), [1, 2, 0, 0, 3, 4]);1.0.0pub fn connect<Separator>(
&self,
sep: Separator,
) -> <[T] as Join<Separator>>::Output ⓘ
👎Deprecated since 1.3.0: renamed to join
pub fn connect<Separator>( &self, sep: Separator, ) -> <[T] as Join<Separator>>::Output ⓘ
Flattens a slice of T into a single value Self::Output, placing a
given separator between each.
§Examples
assert_eq!(["hello", "world"].connect(" "), "hello world");
assert_eq!([[1, 2], [3, 4]].connect(&0), [1, 2, 0, 3, 4]);1.23.0pub fn to_ascii_uppercase(&self) -> Vec<u8> ⓘ
pub fn to_ascii_uppercase(&self) -> Vec<u8> ⓘ
Returns a vector containing a copy of this slice where each byte is mapped to its ASCII upper case equivalent.
ASCII letters ‘a’ to ‘z’ are mapped to ‘A’ to ‘Z’, but non-ASCII letters are unchanged.
To uppercase the value in-place, use make_ascii_uppercase.
1.23.0pub fn to_ascii_lowercase(&self) -> Vec<u8> ⓘ
pub fn to_ascii_lowercase(&self) -> Vec<u8> ⓘ
Returns a vector containing a copy of this slice where each byte is mapped to its ASCII lower case equivalent.
ASCII letters ‘A’ to ‘Z’ are mapped to ‘a’ to ‘z’, but non-ASCII letters are unchanged.
To lowercase the value in-place, use make_ascii_lowercase.
Trait Implementations§
Auto Trait Implementations§
impl !Freeze for DirEntry
impl !RefUnwindSafe for DirEntry
impl Send for DirEntry
impl !Sync for DirEntry
impl Unpin for DirEntry
impl UnwindSafe for DirEntry
Blanket Implementations§
§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
§unsafe fn clone_to_uninit(&self, dest: *mut u8)
unsafe fn clone_to_uninit(&self, dest: *mut u8)
clone_to_uninit)Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more