Merge pull request #1298 from Cheong-Lau/rustc-hash

perf: use `rustc-hash` for `HashMap` and `HashSet`
This commit is contained in:
Jeremy Soller 2025-10-28 15:07:48 -06:00 committed by GitHub
commit 5863671217
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
11 changed files with 68 additions and 68 deletions

1
Cargo.lock generated
View file

@ -1496,6 +1496,7 @@ dependencies = [
"recently-used-xbel", "recently-used-xbel",
"regex", "regex",
"rust-embed", "rust-embed",
"rustc-hash 2.1.1",
"serde", "serde",
"shlex", "shlex",
"slotmap", "slotmap",

View file

@ -29,6 +29,7 @@ notify-rust = { version = "4", optional = true }
open = "5.3.2" open = "5.3.2"
paste = "1.0" paste = "1.0"
regex = "1" regex = "1"
rustc-hash = "2.1"
serde = { version = "1", features = ["serde_derive"] } serde = { version = "1", features = ["serde_derive"] }
shlex = { version = "1.3" } shlex = { version = "1.3" }
tempfile = "3" tempfile = "3"

View file

@ -48,10 +48,11 @@ use notify_debouncer_full::{
DebouncedEvent, Debouncer, RecommendedCache, new_debouncer, DebouncedEvent, Debouncer, RecommendedCache, new_debouncer,
notify::{self, RecommendedWatcher}, notify::{self, RecommendedWatcher},
}; };
use rustc_hash::{FxHashMap, FxHashSet};
use slotmap::Key as SlotMapKey; use slotmap::Key as SlotMapKey;
use std::{ use std::{
any::TypeId, any::TypeId,
collections::{BTreeMap, BTreeSet, HashMap, HashSet, VecDeque}, collections::{BTreeMap, BTreeSet, HashMap, VecDeque},
env, fmt, fs, env, fmt, fs,
future::Future, future::Future,
io, io,
@ -68,6 +69,7 @@ use trash::TrashItem;
use wayland_client::{Proxy, protocol::wl_output::WlOutput}; use wayland_client::{Proxy, protocol::wl_output::WlOutput};
use crate::{ use crate::{
FxOrderMap,
clipboard::{ClipboardCopy, ClipboardKind, ClipboardPaste}, clipboard::{ClipboardCopy, ClipboardKind, ClipboardPaste},
config::{ config::{
AppTheme, Config, DesktopConfig, Favorite, IconSizes, TIME_CONFIG_ID, TabConfig, AppTheme, Config, DesktopConfig, Favorite, IconSizes, TIME_CONFIG_ID, TabConfig,
@ -676,17 +678,17 @@ pub struct App {
dialog_pages: DialogPages, dialog_pages: DialogPages,
dialog_text_input: widget::Id, dialog_text_input: widget::Id,
key_binds: HashMap<KeyBind, Action>, key_binds: HashMap<KeyBind, Action>,
margin: HashMap<window::Id, (f32, f32, f32, f32)>, margin: FxHashMap<window::Id, (f32, f32, f32, f32)>,
mime_app_cache: MimeAppCache, mime_app_cache: MimeAppCache,
modifiers: Modifiers, modifiers: Modifiers,
mounter_items: HashMap<MounterKey, MounterItems>, mounter_items: FxHashMap<MounterKey, MounterItems>,
must_save_sort_names: bool, must_save_sort_names: bool,
network_drive_connecting: Option<(MounterKey, String)>, network_drive_connecting: Option<(MounterKey, String)>,
network_drive_input: String, network_drive_input: String,
#[cfg(feature = "notify")] #[cfg(feature = "notify")]
notification_opt: Option<Arc<Mutex<notify_rust::NotificationHandle>>>, notification_opt: Option<Arc<Mutex<notify_rust::NotificationHandle>>>,
#[cfg(all(feature = "wayland", feature = "desktop-applet"))] #[cfg(all(feature = "wayland", feature = "desktop-applet"))]
overlap: HashMap<String, (window::Id, Rectangle)>, overlap: FxHashMap<String, (window::Id, Rectangle)>,
pending_operation_id: u64, pending_operation_id: u64,
pending_operations: BTreeMap<u64, (Operation, Controller)>, pending_operations: BTreeMap<u64, (Operation, Controller)>,
progress_operations: BTreeSet<u64>, progress_operations: BTreeSet<u64>,
@ -696,17 +698,17 @@ pub struct App {
search_id: widget::Id, search_id: widget::Id,
size: Option<Size>, size: Option<Size>,
#[cfg(all(feature = "wayland", feature = "desktop-applet"))] #[cfg(all(feature = "wayland", feature = "desktop-applet"))]
layer_sizes: HashMap<window::Id, Size>, layer_sizes: FxHashMap<window::Id, Size>,
#[cfg(all(feature = "wayland", feature = "desktop-applet"))] #[cfg(all(feature = "wayland", feature = "desktop-applet"))]
surface_ids: HashMap<WlOutput, WindowId>, surface_ids: FxHashMap<WlOutput, WindowId>,
#[cfg(all(feature = "wayland", feature = "desktop-applet"))] #[cfg(all(feature = "wayland", feature = "desktop-applet"))]
surface_names: HashMap<WindowId, String>, surface_names: FxHashMap<WindowId, String>,
toasts: widget::toaster::Toasts<Message>, toasts: widget::toaster::Toasts<Message>,
watcher_opt: Option<( watcher_opt: Option<(
Debouncer<RecommendedWatcher, RecommendedCache>, Debouncer<RecommendedWatcher, RecommendedCache>,
HashSet<PathBuf>, FxHashSet<PathBuf>,
)>, )>,
windows: HashMap<window::Id, WindowKind>, windows: FxHashMap<window::Id, WindowKind>,
nav_dnd_hover: Option<(Location, Instant)>, nav_dnd_hover: Option<(Location, Instant)>,
tab_dnd_hover: Option<(Entity, Instant)>, tab_dnd_hover: Option<(Entity, Instant)>,
nav_drag_id: DragId, nav_drag_id: DragId,
@ -731,7 +733,7 @@ impl App {
// Associate all paths to its MIME type // Associate all paths to its MIME type
// This allows handling paths as groups if possible, such as launching a single video // This allows handling paths as groups if possible, such as launching a single video
// player that is passed every path. // player that is passed every path.
let mut groups: HashMap<Mime, Vec<PathBuf>> = HashMap::new(); let mut groups: FxHashMap<Mime, Vec<PathBuf>> = FxHashMap::default();
let mut all_archives = true; let mut all_archives = true;
let supported_archive_types = crate::archive::SUPPORTED_ARCHIVE_TYPES let supported_archive_types = crate::archive::SUPPORTED_ARCHIVE_TYPES
.iter() .iter()
@ -948,7 +950,7 @@ impl App {
#[cfg(all(feature = "wayland", feature = "desktop-applet"))] #[cfg(all(feature = "wayland", feature = "desktop-applet"))]
fn handle_overlap(&mut self) { fn handle_overlap(&mut self) {
let mut overlaps: HashMap<_, _> = self let mut overlaps: FxHashMap<_, _> = self
.windows .windows
.keys() .keys()
.map(|k| (*k, (0., 0., 0., 0.))) .map(|k| (*k, (0., 0., 0., 0.)))
@ -1609,7 +1611,7 @@ impl App {
fn update_watcher(&mut self) -> Task<Message> { fn update_watcher(&mut self) -> Task<Message> {
if let Some((mut watcher, old_paths)) = self.watcher_opt.take() { if let Some((mut watcher, old_paths)) = self.watcher_opt.take() {
let mut new_paths = HashSet::new(); let mut new_paths = FxHashSet::default();
for entity in self.tab_model.iter() { for entity in self.tab_model.iter() {
if let Some(tab) = self.tab_model.data::<Tab>(entity) { if let Some(tab) = self.tab_model.data::<Tab>(entity) {
if let Some(path) = tab.location.path_opt() { if let Some(path) = tab.location.path_opt() {
@ -1978,7 +1980,7 @@ impl App {
fn get_apps_for_mime(&self, mime_type: &Mime) -> Vec<(&MimeApp, MimeAppMatch)> { fn get_apps_for_mime(&self, mime_type: &Mime) -> Vec<(&MimeApp, MimeAppMatch)> {
let mut results = Vec::new(); let mut results = Vec::new();
let mut dedupe = HashSet::new(); let mut dedupe = FxHashSet::default();
// start with exact matches // start with exact matches
for mime_app in self.mime_app_cache.get(mime_type) { for mime_app in self.mime_app_cache.get(mime_type) {
@ -2160,17 +2162,17 @@ impl Application for App {
dialog_pages: DialogPages::new(), dialog_pages: DialogPages::new(),
dialog_text_input: widget::Id::new("Dialog Text Input"), dialog_text_input: widget::Id::new("Dialog Text Input"),
key_binds, key_binds,
margin: HashMap::new(), margin: FxHashMap::default(),
mime_app_cache: MimeAppCache::new(), mime_app_cache: MimeAppCache::new(),
modifiers: Modifiers::empty(), modifiers: Modifiers::empty(),
mounter_items: HashMap::new(), mounter_items: FxHashMap::default(),
must_save_sort_names: false, must_save_sort_names: false,
network_drive_connecting: None, network_drive_connecting: None,
network_drive_input: String::new(), network_drive_input: String::new(),
#[cfg(feature = "notify")] #[cfg(feature = "notify")]
notification_opt: None, notification_opt: None,
#[cfg(all(feature = "wayland", feature = "desktop-applet"))] #[cfg(all(feature = "wayland", feature = "desktop-applet"))]
overlap: HashMap::new(), overlap: FxHashMap::default(),
pending_operation_id: 0, pending_operation_id: 0,
pending_operations: BTreeMap::new(), pending_operations: BTreeMap::new(),
progress_operations: BTreeSet::new(), progress_operations: BTreeSet::new(),
@ -2180,12 +2182,12 @@ impl Application for App {
search_id: widget::Id::new("File Search"), search_id: widget::Id::new("File Search"),
size: None, size: None,
#[cfg(all(feature = "wayland", feature = "desktop-applet"))] #[cfg(all(feature = "wayland", feature = "desktop-applet"))]
surface_ids: HashMap::new(), surface_ids: FxHashMap::default(),
#[cfg(all(feature = "wayland", feature = "desktop-applet"))] #[cfg(all(feature = "wayland", feature = "desktop-applet"))]
surface_names: HashMap::new(), surface_names: FxHashMap::default(),
toasts: widget::toaster::Toasts::new(Message::CloseToast), toasts: widget::toaster::Toasts::new(Message::CloseToast),
watcher_opt: None, watcher_opt: None,
windows: HashMap::new(), windows: FxHashMap::default(),
nav_dnd_hover: None, nav_dnd_hover: None,
tab_dnd_hover: None, tab_dnd_hover: None,
nav_drag_id: DragId::new(), nav_drag_id: DragId::new(),
@ -2193,7 +2195,7 @@ impl Application for App {
auto_scroll_speed: None, auto_scroll_speed: None,
file_dialog_opt: None, file_dialog_opt: None,
#[cfg(all(feature = "wayland", feature = "desktop-applet"))] #[cfg(all(feature = "wayland", feature = "desktop-applet"))]
layer_sizes: HashMap::new(), layer_sizes: FxHashMap::default(),
}; };
let mut commands = vec![app.update_config()]; let mut commands = vec![app.update_config()];
@ -3264,7 +3266,7 @@ impl Application for App {
Message::NotifyWatcher(mut watcher_wrapper) => match watcher_wrapper.watcher_opt.take() Message::NotifyWatcher(mut watcher_wrapper) => match watcher_wrapper.watcher_opt.take()
{ {
Some(watcher) => { Some(watcher) => {
self.watcher_opt = Some((watcher, HashSet::new())); self.watcher_opt = Some((watcher, FxHashSet::default()));
return self.update_watcher(); return self.update_watcher();
} }
None => { None => {
@ -4744,8 +4746,8 @@ impl Application for App {
Message::SaveSortNames => { Message::SaveSortNames => {
self.must_save_sort_names = false; self.must_save_sort_names = false;
if let Some(state_handler) = self.state_handler.as_ref() { if let Some(state_handler) = self.state_handler.as_ref() {
if let Err(err) = if let Err(err) = state_handler
state_handler.set::<ordermap::OrderMap<String, (HeadingOptions, bool)>>( .set::<FxOrderMap<String, (HeadingOptions, bool)>>(
"sort_names", "sort_names",
self.state.sort_names.clone(), self.state.sort_names.clone(),
) )

View file

@ -8,10 +8,10 @@ use cosmic::{
iced::Subscription, iced::Subscription,
theme, theme,
}; };
use ordermap::OrderMap;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::{ use crate::{
FxOrderMap,
app::App, app::App,
tab::{HeadingOptions, Location, View}, tab::{HeadingOptions, Location, View},
}; };
@ -115,13 +115,13 @@ pub enum TypeToSearch {
#[derive(Clone, CosmicConfigEntry, Debug, Deserialize, Eq, PartialEq, Serialize)] #[derive(Clone, CosmicConfigEntry, Debug, Deserialize, Eq, PartialEq, Serialize)]
#[serde(default)] #[serde(default)]
pub struct State { pub struct State {
pub sort_names: ordermap::OrderMap<String, (HeadingOptions, bool)>, pub sort_names: FxOrderMap<String, (HeadingOptions, bool)>,
} }
impl Default for State { impl Default for State {
fn default() -> Self { fn default() -> Self {
Self { Self {
sort_names: OrderMap::from_iter(dirs::download_dir().into_iter().map(|dir| { sort_names: FxOrderMap::from_iter(dirs::download_dir().into_iter().map(|dir| {
( (
Location::Path(dir).normalize().to_string(), Location::Path(dir).normalize().to_string(),
(HeadingOptions::Modified, false), (HeadingOptions::Modified, false),

View file

@ -26,9 +26,10 @@ use notify_debouncer_full::{
notify::{self, RecommendedWatcher}, notify::{self, RecommendedWatcher},
}; };
use recently_used_xbel::update_recently_used; use recently_used_xbel::update_recently_used;
use rustc_hash::{FxHashMap, FxHashSet};
use std::{ use std::{
any::TypeId, any::TypeId,
collections::{HashMap, HashSet, VecDeque}, collections::{HashMap, VecDeque},
env, fmt, fs, env, fmt, fs,
num::NonZeroU16, num::NonZeroU16,
path::PathBuf, path::PathBuf,
@ -513,7 +514,7 @@ struct App {
filter_selected: Option<usize>, filter_selected: Option<usize>,
filename_id: widget::Id, filename_id: widget::Id,
modifiers: Modifiers, modifiers: Modifiers,
mounter_items: HashMap<MounterKey, MounterItems>, mounter_items: FxHashMap<MounterKey, MounterItems>,
nav_model: segmented_button::SingleSelectModel, nav_model: segmented_button::SingleSelectModel,
result_opt: Option<DialogResult>, result_opt: Option<DialogResult>,
search_id: widget::Id, search_id: widget::Id,
@ -521,7 +522,7 @@ struct App {
key_binds: HashMap<KeyBind, Action>, key_binds: HashMap<KeyBind, Action>,
watcher_opt: Option<( watcher_opt: Option<(
Debouncer<RecommendedWatcher, RecommendedCache>, Debouncer<RecommendedWatcher, RecommendedCache>,
HashSet<PathBuf>, FxHashSet<PathBuf>,
)>, )>,
auto_scroll_speed: Option<i16>, auto_scroll_speed: Option<i16>,
} }
@ -875,7 +876,7 @@ impl App {
fn update_watcher(&mut self) -> Task<Message> { fn update_watcher(&mut self) -> Task<Message> {
if let Some((mut watcher, old_paths)) = self.watcher_opt.take() { if let Some((mut watcher, old_paths)) = self.watcher_opt.take() {
let mut new_paths = HashSet::new(); let mut new_paths = FxHashSet::default();
if let Some(path) = &self.tab.location.path_opt() { if let Some(path) = &self.tab.location.path_opt() {
new_paths.insert(path.to_path_buf()); new_paths.insert(path.to_path_buf());
} }
@ -985,7 +986,7 @@ impl Application for App {
filter_selected: None, filter_selected: None,
filename_id: widget::Id::new("Dialog Filename"), filename_id: widget::Id::new("Dialog Filename"),
modifiers: Modifiers::empty(), modifiers: Modifiers::empty(),
mounter_items: HashMap::new(), mounter_items: FxHashMap::default(),
nav_model: segmented_button::ModelBuilder::default().build(), nav_model: segmented_button::ModelBuilder::default().build(),
result_opt: None, result_opt: None,
search_id: widget::Id::new("Dialog File Search"), search_id: widget::Id::new("Dialog File Search"),
@ -1532,7 +1533,7 @@ impl Application for App {
Message::NotifyWatcher(mut watcher_wrapper) => match watcher_wrapper.watcher_opt.take() Message::NotifyWatcher(mut watcher_wrapper) => match watcher_wrapper.watcher_opt.take()
{ {
Some(watcher) => { Some(watcher) => {
self.watcher_opt = Some((watcher, HashSet::new())); self.watcher_opt = Some((watcher, FxHashSet::default()));
return self.update_watcher(); return self.update_watcher();
} }
None => { None => {

View file

@ -27,6 +27,8 @@ pub mod tab;
mod thumbnail_cacher; mod thumbnail_cacher;
mod thumbnailer; mod thumbnailer;
pub(crate) type FxOrderMap<K, V> = ordermap::OrderMap<K, V, rustc_hash::FxBuildHasher>;
pub(crate) fn err_str<T: ToString>(err: T) -> String { pub(crate) fn err_str<T: ToString>(err: T) -> String {
err.to_string() err.to_string()
} }

View file

@ -5,9 +5,9 @@
use cosmic::desktop; use cosmic::desktop;
use cosmic::widget; use cosmic::widget;
pub use mime_guess::Mime; pub use mime_guess::Mime;
use rustc_hash::FxHashMap;
use std::{ use std::{
cmp::Ordering, cmp::Ordering,
collections::HashMap,
env, env,
ffi::OsStr, ffi::OsStr,
fs, io, fs, io,
@ -221,8 +221,8 @@ fn filename_eq(path_opt: &Option<PathBuf>, filename: &str) -> bool {
pub struct MimeAppCache { pub struct MimeAppCache {
apps: Vec<MimeApp>, apps: Vec<MimeApp>,
cache: HashMap<Mime, Vec<MimeApp>>, cache: FxHashMap<Mime, Vec<MimeApp>>,
icons: HashMap<Mime, Vec<widget::icon::Handle>>, icons: FxHashMap<Mime, Vec<widget::icon::Handle>>,
terminals: Vec<MimeApp>, terminals: Vec<MimeApp>,
} }
@ -230,8 +230,8 @@ impl MimeAppCache {
pub fn new() -> Self { pub fn new() -> Self {
let mut mime_app_cache = Self { let mut mime_app_cache = Self {
apps: Vec::new(), apps: Vec::new(),
cache: HashMap::new(), cache: FxHashMap::default(),
icons: HashMap::new(), icons: FxHashMap::default(),
terminals: Vec::new(), terminals: Vec::new(),
}; };
mime_app_cache.reload(); mime_app_cache.reload();

View file

@ -2,8 +2,8 @@
use cosmic::widget::icon; use cosmic::widget::icon;
use mime_guess::Mime; use mime_guess::Mime;
use rustc_hash::FxHashMap;
use std::{ use std::{
collections::HashMap,
fs, fs,
path::Path, path::Path,
sync::{LazyLock, Mutex}, sync::{LazyLock, Mutex},
@ -18,14 +18,14 @@ struct MimeIconKey {
} }
struct MimeIconCache { struct MimeIconCache {
cache: HashMap<MimeIconKey, Option<icon::Handle>>, cache: FxHashMap<MimeIconKey, Option<icon::Handle>>,
shared_mime_info: xdg_mime::SharedMimeInfo, shared_mime_info: xdg_mime::SharedMimeInfo,
} }
impl MimeIconCache { impl MimeIconCache {
pub fn new() -> Self { pub fn new() -> Self {
Self { Self {
cache: HashMap::new(), cache: FxHashMap::default(),
shared_mime_info: xdg_mime::SharedMimeInfo::new(), shared_mime_info: xdg_mime::SharedMimeInfo::new(),
} }
} }

View file

@ -49,7 +49,7 @@ use icu::{
use image::ImageDecoder; use image::ImageDecoder;
use jxl_oxide::integration::JxlDecoder; use jxl_oxide::integration::JxlDecoder;
use mime_guess::{Mime, mime}; use mime_guess::{Mime, mime};
use ordermap::OrderMap; use rustc_hash::FxHashMap;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::{ use std::{
borrow::Cow, borrow::Cow,
@ -73,6 +73,7 @@ use trash::TrashItemSize;
use walkdir::WalkDir; use walkdir::WalkDir;
use crate::{ use crate::{
FxOrderMap,
app::{Action, PreviewItem, PreviewKind}, app::{Action, PreviewItem, PreviewKind},
clipboard::{ClipboardCopy, ClipboardKind, ClipboardPaste}, clipboard::{ClipboardCopy, ClipboardKind, ClipboardPaste},
config::{DesktopConfig, ICON_SCALE_MAX, ICON_SIZE_GRID, IconSizes, TabConfig, ThumbCfg}, config::{DesktopConfig, ICON_SCALE_MAX, ICON_SIZE_GRID, IconSizes, TabConfig, ThumbCfg},
@ -100,9 +101,9 @@ const THUMBNAIL_SIZE: u32 = (ICON_SIZE_GRID as u32) * (ICON_SCALE_MAX as u32);
pub static THUMB_SEMAPHORE: LazyLock<tokio::sync::Semaphore> = pub static THUMB_SEMAPHORE: LazyLock<tokio::sync::Semaphore> =
LazyLock::new(|| tokio::sync::Semaphore::const_new(num_cpus::get())); LazyLock::new(|| tokio::sync::Semaphore::const_new(num_cpus::get()));
pub(crate) static SORT_OPTION_FALLBACK: LazyLock<HashMap<String, (HeadingOptions, bool)>> = pub(crate) static SORT_OPTION_FALLBACK: LazyLock<FxHashMap<String, (HeadingOptions, bool)>> =
LazyLock::new(|| { LazyLock::new(|| {
HashMap::from_iter(dirs::download_dir().into_iter().map(|dir| { FxHashMap::from_iter(dirs::download_dir().into_iter().map(|dir| {
( (
Location::Path(dir).normalize().to_string(), Location::Path(dir).normalize().to_string(),
(HeadingOptions::Modified, false), (HeadingOptions::Modified, false),
@ -131,8 +132,8 @@ static MODE_NAMES: LazyLock<Vec<String>> = LazyLock::new(|| {
] ]
}); });
static SPECIAL_DIRS: LazyLock<HashMap<PathBuf, &'static str>> = LazyLock::new(|| { static SPECIAL_DIRS: LazyLock<FxHashMap<PathBuf, &'static str>> = LazyLock::new(|| {
let mut special_dirs = HashMap::new(); let mut special_dirs = FxHashMap::default();
if let Some(dir) = dirs::document_dir() { if let Some(dir) = dirs::document_dir() {
special_dirs.insert(dir, "folder-documents"); special_dirs.insert(dir, "folder-documents");
} }
@ -534,25 +535,17 @@ pub enum FsKind {
pub fn fs_kind(metadata: &Metadata) -> FsKind { pub fn fs_kind(metadata: &Metadata) -> FsKind {
//TODO: method to reload remote filesystems dynamically //TODO: method to reload remote filesystems dynamically
//TODO: fix for https://github.com/eminence/procfs/issues/262 //TODO: fix for https://github.com/eminence/procfs/issues/262
static DEVICES: LazyLock<HashMap<u64, FsKind>> = LazyLock::new(|| { static DEVICES: LazyLock<FxHashMap<u64, FsKind>> = LazyLock::new(|| {
let mut devices = HashMap::new(); let mut devices = FxHashMap::default();
match procfs::process::Process::myself() { match procfs::process::Process::myself() {
Ok(process) => match process.mountinfo() { Ok(process) => match process.mountinfo() {
Ok(mount_infos) => { Ok(mount_infos) => {
for mount_info in mount_infos.iter() { devices = FxHashMap::from_iter(mount_infos.iter().filter_map(|mount_info| {
let mut parts = mount_info.majmin.split(':'); let mut parts = mount_info.majmin.split(':');
let Some(major_str) = parts.next() else { let major_str = parts.next()?;
continue; let minor_str = parts.next()?;
}; let major = major_str.parse::<libc::c_uint>().ok()?;
let Some(minor_str) = parts.next() else { let minor = minor_str.parse::<libc::c_uint>().ok()?;
continue;
};
let Ok(major) = major_str.parse::<libc::c_uint>() else {
continue;
};
let Ok(minor) = minor_str.parse::<libc::c_uint>() else {
continue;
};
let dev = libc::makedev(major, minor); let dev = libc::makedev(major, minor);
//TODO: make sure this list is exhaustive //TODO: make sure this list is exhaustive
let kind = match mount_info.fs_type.as_str() { let kind = match mount_info.fs_type.as_str() {
@ -561,8 +554,8 @@ pub fn fs_kind(metadata: &Metadata) -> FsKind {
"fuse.gvfsd-fuse" => FsKind::Gvfs, "fuse.gvfsd-fuse" => FsKind::Gvfs,
_ => FsKind::Local, _ => FsKind::Local,
}; };
devices.insert(dev, kind); Some((dev, kind))
} }));
} }
Err(err) => { Err(err) => {
log::warn!("failed to get mount info: {err}"); log::warn!("failed to get mount info: {err}");
@ -2524,7 +2517,7 @@ impl Tab {
location: Location, location: Location,
config: TabConfig, config: TabConfig,
thumb_config: ThumbCfg, thumb_config: ThumbCfg,
sorting_options: Option<&OrderMap<String, (HeadingOptions, bool)>>, sorting_options: Option<&FxOrderMap<String, (HeadingOptions, bool)>>,
scrollable_id: widget::Id, scrollable_id: widget::Id,
window_id: Option<window::Id>, window_id: Option<window::Id>,
) -> Self { ) -> Self {

View file

@ -1,7 +1,7 @@
use image::DynamicImage; use image::DynamicImage;
use md5::{Digest, Md5}; use md5::{Digest, Md5};
use rustc_hash::FxHashMap;
use std::{ use std::{
collections::HashMap,
error::Error, error::Error,
fs::{self, File}, fs::{self, File},
io::{self, BufReader, BufWriter}, io::{self, BufReader, BufWriter},
@ -143,7 +143,7 @@ impl ThumbnailCacher {
let mut reader = decoder.read_info()?; let mut reader = decoder.read_info()?;
let (width, height, color_type, bit_depth, mut text_chunks) = { let (width, height, color_type, bit_depth, mut text_chunks) = {
let info = reader.info(); let info = reader.info();
let text_chunks: HashMap<String, String> = info let text_chunks: FxHashMap<String, String> = info
.uncompressed_latin1_text .uncompressed_latin1_text
.clone() .clone()
.into_iter() .into_iter()

View file

@ -2,8 +2,8 @@
// SPDX-License-Identifier: GPL-3.0-only // SPDX-License-Identifier: GPL-3.0-only
use mime_guess::Mime; use mime_guess::Mime;
use rustc_hash::FxHashMap;
use std::{ use std::{
collections::HashMap,
fs, fs,
path::Path, path::Path,
process, process,
@ -56,13 +56,13 @@ impl Thumbnailer {
} }
pub struct ThumbnailerCache { pub struct ThumbnailerCache {
cache: HashMap<Mime, Vec<Thumbnailer>>, cache: FxHashMap<Mime, Vec<Thumbnailer>>,
} }
impl ThumbnailerCache { impl ThumbnailerCache {
pub fn new() -> Self { pub fn new() -> Self {
let mut thumbnailer_cache = Self { let mut thumbnailer_cache = Self {
cache: HashMap::new(), cache: FxHashMap::default(),
}; };
thumbnailer_cache.reload(); thumbnailer_cache.reload();
thumbnailer_cache thumbnailer_cache