treewide: replace std hashers with rustc_hash alternatives; fix clippy

Signed-off-by: NotAShelf <raf@notashelf.dev>
Change-Id: I766c36cb53d3d7f9e85b91a67c4131a66a6a6964
This commit is contained in:
raf 2026-03-19 22:34:30 +03:00
commit c6efd3661f
Signed by: NotAShelf
GPG key ID: 29D95B64378DB4BF
53 changed files with 343 additions and 394 deletions

View file

@ -4,12 +4,10 @@
//! Plugins can extend Pinakes by implementing one or more of the provided
//! traits.
use std::{
collections::HashMap,
path::{Path, PathBuf},
};
use std::path::{Path, PathBuf};
use async_trait::async_trait;
use rustc_hash::FxHashMap;
use serde::{Deserialize, Serialize};
use thiserror::Error;
@ -74,7 +72,7 @@ pub struct PluginContext {
pub cache_dir: PathBuf,
/// Plugin configuration from manifest
pub config: HashMap<String, serde_json::Value>,
pub config: FxHashMap<String, serde_json::Value>,
/// Capabilities granted to the plugin
pub capabilities: Capabilities,
@ -160,7 +158,7 @@ pub struct PluginMetadata {
pub struct HealthStatus {
pub healthy: bool,
pub message: Option<String>,
pub metrics: HashMap<String, f64>,
pub metrics: FxHashMap<String, f64>,
}
/// Trait for plugins that provide custom media type support
@ -227,7 +225,7 @@ pub struct ExtractedMetadata {
pub bitrate_kbps: Option<u32>,
/// Custom metadata fields specific to this file type
pub custom_fields: HashMap<String, serde_json::Value>,
pub custom_fields: FxHashMap<String, serde_json::Value>,
/// Tags extracted from the file
pub tags: Vec<String>,
@ -301,14 +299,14 @@ pub struct SearchIndexItem {
pub content: Option<String>,
pub tags: Vec<String>,
pub media_type: String,
pub metadata: HashMap<String, serde_json::Value>,
pub metadata: FxHashMap<String, serde_json::Value>,
}
/// Search query
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SearchQuery {
pub query_text: String,
pub filters: HashMap<String, serde_json::Value>,
pub filters: FxHashMap<String, serde_json::Value>,
pub limit: usize,
pub offset: usize,
}
@ -360,7 +358,7 @@ pub enum EventType {
pub struct Event {
pub event_type: EventType,
pub timestamp: String,
pub data: HashMap<String, serde_json::Value>,
pub data: FxHashMap<String, serde_json::Value>,
}
/// Trait for plugins that provide UI themes
@ -387,7 +385,7 @@ pub struct ThemeDefinition {
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Theme {
pub id: String,
pub colors: HashMap<String, String>,
pub fonts: HashMap<String, String>,
pub colors: FxHashMap<String, String>,
pub fonts: FxHashMap<String, String>,
pub custom_css: Option<String>,
}

View file

@ -1,7 +1,8 @@
//! Plugin manifest parsing and validation
use std::{collections::HashMap, path::Path};
use std::path::Path;
use rustc_hash::FxHashMap;
use serde::{Deserialize, Serialize};
use thiserror::Error;
@ -23,7 +24,7 @@ pub struct PluginManifest {
pub capabilities: ManifestCapabilities,
#[serde(default)]
pub config: HashMap<String, toml::Value>,
pub config: FxHashMap<String, toml::Value>,
/// UI pages provided by this plugin
#[serde(default)]
@ -49,8 +50,8 @@ pub struct UiSection {
/// CSS custom property overrides provided by this plugin.
/// Keys are property names (e.g. `--accent-color`), values are CSS values.
/// The host applies these to `document.documentElement` on startup.
#[serde(default, skip_serializing_if = "HashMap::is_empty")]
pub theme_extensions: HashMap<String, String>,
#[serde(default, skip_serializing_if = "FxHashMap::is_empty")]
pub theme_extensions: FxHashMap<String, String>,
}
impl UiSection {
@ -709,7 +710,7 @@ gap = 16
"/api/v1/media".to_string(),
"/api/plugins/my-plugin/data".to_string(),
],
theme_extensions: HashMap::new(),
theme_extensions: FxHashMap::default(),
};
assert!(section.validate().is_ok());
}
@ -720,7 +721,7 @@ gap = 16
pages: vec![],
widgets: vec![],
required_endpoints: vec!["/not-api/something".to_string()],
theme_extensions: HashMap::new(),
theme_extensions: FxHashMap::default(),
};
assert!(section.validate().is_err());
}
@ -731,7 +732,7 @@ gap = 16
pages: vec![],
widgets: vec![],
required_endpoints: vec!["/api/ok".to_string(), "no-slash".to_string()],
theme_extensions: HashMap::new(),
theme_extensions: FxHashMap::default(),
};
let err = section.validate().unwrap_err();
assert!(

View file

@ -49,8 +49,7 @@
//! Array indices use the same notation: `"items.0.title"`.
//! ```
use std::collections::HashMap;
use rustc_hash::FxHashMap;
use serde::{Deserialize, Serialize};
use thiserror::Error;
@ -133,12 +132,12 @@ pub struct UiPage {
pub root_element: UiElement,
/// Named data sources available to this page
#[serde(default, skip_serializing_if = "HashMap::is_empty")]
pub data_sources: HashMap<String, DataSource>,
#[serde(default, skip_serializing_if = "FxHashMap::is_empty")]
pub data_sources: FxHashMap<String, DataSource>,
/// Named actions available to this page (referenced by `ActionRef::Name`)
#[serde(default, skip_serializing_if = "HashMap::is_empty")]
pub actions: HashMap<String, ActionDefinition>,
#[serde(default, skip_serializing_if = "FxHashMap::is_empty")]
pub actions: FxHashMap<String, ActionDefinition>,
}
impl UiPage {
@ -204,8 +203,8 @@ impl UiPage {
/// Validates that there are no cycles in Transform data source dependencies
fn validate_no_cycles(&self) -> SchemaResult<()> {
let mut visited = std::collections::HashSet::new();
let mut stack = std::collections::HashSet::new();
let mut visited = rustc_hash::FxHashSet::default();
let mut stack = rustc_hash::FxHashSet::default();
for name in self.data_sources.keys() {
Self::dfs_check_cycles(self, name, &mut visited, &mut stack)?;
@ -218,8 +217,8 @@ impl UiPage {
fn dfs_check_cycles(
&self,
name: &str,
visited: &mut std::collections::HashSet<String>,
stack: &mut std::collections::HashSet<String>,
visited: &mut rustc_hash::FxHashSet<String>,
stack: &mut rustc_hash::FxHashSet<String>,
) -> SchemaResult<()> {
if stack.contains(name) {
return Err(SchemaError::ValidationError(format!(
@ -1451,8 +1450,8 @@ pub struct ActionDefinition {
pub path: String,
/// Action parameters (merged with form data on submit)
#[serde(default, skip_serializing_if = "HashMap::is_empty")]
pub params: HashMap<String, serde_json::Value>,
#[serde(default, skip_serializing_if = "FxHashMap::is_empty")]
pub params: FxHashMap<String, serde_json::Value>,
/// Success message
#[serde(skip_serializing_if = "Option::is_none")]
@ -1509,7 +1508,7 @@ impl Default for ActionDefinition {
Self {
method: default_http_method(),
path: String::new(),
params: HashMap::new(),
params: FxHashMap::default(),
success_message: None,
error_message: None,
navigate_to: None,
@ -1543,8 +1542,8 @@ pub enum DataSource {
path: String,
/// Query parameters
#[serde(default, skip_serializing_if = "HashMap::is_empty")]
params: HashMap<String, Expression>,
#[serde(default, skip_serializing_if = "FxHashMap::is_empty")]
params: FxHashMap<String, Expression>,
/// Polling interval in seconds (0 = no polling)
#[serde(default)]
@ -1839,7 +1838,7 @@ mod tests {
let valid = DataSource::Endpoint {
method: HttpMethod::Get,
path: "/api/test".to_string(),
params: HashMap::new(),
params: FxHashMap::default(),
poll_interval: 0,
transform: None,
};
@ -1848,7 +1847,7 @@ mod tests {
let invalid = DataSource::Endpoint {
method: HttpMethod::Get,
path: "api/test".to_string(),
params: HashMap::new(),
params: FxHashMap::default(),
poll_interval: 0,
transform: None,
};
@ -1898,8 +1897,8 @@ mod tests {
page_size: 0,
row_actions: vec![],
},
data_sources: HashMap::new(),
actions: HashMap::new(),
data_sources: FxHashMap::default(),
actions: FxHashMap::default(),
};
let refs = page.referenced_data_sources();
@ -1918,8 +1917,8 @@ mod tests {
columns: 13,
gap: 16,
},
data_sources: HashMap::new(),
actions: HashMap::new(),
data_sources: FxHashMap::default(),
actions: FxHashMap::default(),
};
assert!(page.validate().is_err());
@ -1937,8 +1936,8 @@ mod tests {
content: TextContent::Static("Title".to_string()),
id: None,
},
data_sources: HashMap::new(),
actions: HashMap::new(),
data_sources: FxHashMap::default(),
actions: FxHashMap::default(),
};
assert!(page.validate().is_err());
@ -2005,7 +2004,7 @@ mod tests {
let bad = DataSource::Endpoint {
method: HttpMethod::Get,
path: "/not-api/something".to_string(),
params: HashMap::new(),
params: FxHashMap::default(),
poll_interval: 0,
transform: None,
};
@ -2017,7 +2016,7 @@ mod tests {
let bad = DataSource::Endpoint {
method: HttpMethod::Get,
path: "/api/v1/../admin".to_string(),
params: HashMap::new(),
params: FxHashMap::default(),
poll_interval: 0,
transform: None,
};
@ -2078,7 +2077,7 @@ mod tests {
#[test]
fn test_link_validation_rejects_unsafe_href() {
use std::collections::HashMap as HM;
use rustc_hash::FxHashMap as HM;
let page = UiPage {
id: "p".to_string(),
title: "P".to_string(),
@ -2089,15 +2088,15 @@ mod tests {
href: "javascript:alert(1)".to_string(),
external: false,
},
data_sources: HM::new(),
actions: HM::new(),
data_sources: HM::default(),
actions: HM::default(),
};
assert!(page.validate().is_err());
}
#[test]
fn test_reserved_route_rejected() {
use std::collections::HashMap as HM;
use rustc_hash::FxHashMap as HM;
let page = UiPage {
id: "search-page".to_string(),
title: "Search".to_string(),
@ -2108,8 +2107,8 @@ mod tests {
gap: 0,
padding: None,
},
data_sources: HM::new(),
actions: HM::new(),
data_sources: HM::default(),
actions: HM::default(),
};
let err = page.validate().unwrap_err();
assert!(

View file

@ -343,7 +343,7 @@ impl SchemaValidator {
#[cfg(test)]
mod tests {
use std::collections::HashMap;
use rustc_hash::FxHashMap;
use super::*;
use crate::UiElement;
@ -359,8 +359,8 @@ mod tests {
gap: 0,
padding: None,
},
data_sources: HashMap::new(),
actions: HashMap::new(),
data_sources: FxHashMap::default(),
actions: FxHashMap::default(),
}
}

View file

@ -1,7 +1,6 @@
//! WASM bridge types and helpers for plugin communication
use std::collections::HashMap;
use rustc_hash::FxHashMap;
use serde::{Deserialize, Serialize};
/// Memory allocation info for passing data between host and plugin
@ -93,7 +92,7 @@ pub struct LogMessage {
pub level: LogLevel,
pub target: String,
pub message: String,
pub fields: HashMap<String, String>,
pub fields: FxHashMap<String, String>,
}
/// HTTP request parameters
@ -101,7 +100,7 @@ pub struct LogMessage {
pub struct HttpRequest {
pub method: String,
pub url: String,
pub headers: HashMap<String, String>,
pub headers: FxHashMap<String, String>,
pub body: Option<Vec<u8>>,
}
@ -109,7 +108,7 @@ pub struct HttpRequest {
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct HttpResponse {
pub status: u16,
pub headers: HashMap<String, String>,
pub headers: FxHashMap<String, String>,
pub body: Vec<u8>,
}