feat: add cache and gtk benches comparison
This commit is contained in:
parent
e40fbfa916
commit
8de66cc58e
5 changed files with 190 additions and 45 deletions
35
src/cache.rs
Normal file
35
src/cache.rs
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
use once_cell::sync::Lazy;
|
||||
use std::collections::BTreeMap;
|
||||
use std::path::PathBuf;
|
||||
use std::sync::Mutex;
|
||||
|
||||
pub(crate) static CACHE: Lazy<Cache> = Lazy::new(Cache::default);
|
||||
|
||||
#[derive(Default)]
|
||||
pub(crate) struct Cache(Mutex<BTreeMap<String, BTreeMap<(String, u16, u16), PathBuf>>>);
|
||||
|
||||
impl Cache {
|
||||
pub fn insert(&self, theme: &str, size: u16, scale: u16, icon_name: &str, icon_path: &PathBuf) {
|
||||
let mut theme_map = self.0.lock().unwrap();
|
||||
|
||||
match theme_map.get_mut(theme) {
|
||||
Some(icon_map) => {
|
||||
icon_map.insert((icon_name.to_string(), size, scale), icon_path.clone());
|
||||
}
|
||||
None => {
|
||||
let mut icon_map = BTreeMap::new();
|
||||
icon_map.insert((icon_name.to_string(), size, scale), icon_path.clone());
|
||||
theme_map.insert(theme.to_string(), icon_map);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get(&self, theme: &str, size: u16, scale: u16, icon_name: &str) -> Option<PathBuf> {
|
||||
let theme_map = self.0.lock().unwrap();
|
||||
|
||||
theme_map
|
||||
.get(theme)
|
||||
.map(|icon_map| icon_map.get(&(icon_name.to_string(), size, scale)))
|
||||
.and_then(|path| path.cloned())
|
||||
}
|
||||
}
|
||||
162
src/lib.rs
162
src/lib.rs
|
|
@ -1,12 +1,47 @@
|
|||
//! # freedesktop-incons
|
||||
//!
|
||||
//! This crate provides a [freedesktop icon](https://specifications.freedesktop.org/icon-theme-spec/icon-theme-spec-latest.html#implementation_notes) lookup implementation.
|
||||
//!
|
||||
//! It exposes a single [`lookup`] function to find icon based on their, `name`, `theme`, `size` and `scale`.
|
||||
//!
|
||||
//! ## Example
|
||||
//!
|
||||
//! **Simple lookup:**
|
||||
//!
|
||||
//! The following snippet get an icon from the default 'hicolor' theme
|
||||
//! with the default scale (`1`) and the default size (`24`).
|
||||
//!
|
||||
//! ```rust
|
||||
//! # fn main() {
|
||||
//! use freedesktop_icons::lookup;
|
||||
//!
|
||||
//! let icon = lookup("firefox").find();
|
||||
//! # }
|
||||
//!```
|
||||
//!
|
||||
//! **Complex lookup:**
|
||||
//!
|
||||
//! If you have specific requirement for your lookup you can use the provided builder functions:
|
||||
//!
|
||||
//! ```rust
|
||||
//! # fn main() {
|
||||
//! use freedesktop_icons::lookup;
|
||||
//!
|
||||
//! let icon = lookup("firefox")
|
||||
//! .with_size(48)
|
||||
//! .with_scale(2)
|
||||
//! .with_theme("Arc")
|
||||
//! .find();
|
||||
//! # }
|
||||
//!```
|
||||
use crate::cache::CACHE;
|
||||
use crate::theme::{try_build_icon_path, THEMES};
|
||||
use std::path::PathBuf;
|
||||
|
||||
pub mod theme;
|
||||
|
||||
pub fn lookup(name: &str) -> LookupBuilder {
|
||||
LookupBuilder::new(name)
|
||||
}
|
||||
mod cache;
|
||||
mod theme;
|
||||
|
||||
/// The lookup builder struct, holding all the lookup query parameters.
|
||||
pub struct LookupBuilder<'a> {
|
||||
name: &'a str,
|
||||
scale: u16,
|
||||
|
|
@ -14,22 +49,86 @@ pub struct LookupBuilder<'a> {
|
|||
theme: Option<&'a str>,
|
||||
}
|
||||
|
||||
/// Build an icon lookup for the given icon name.
|
||||
///
|
||||
/// ## Example
|
||||
/// ```rust
|
||||
/// # fn main() {
|
||||
/// use freedesktop_icons::lookup;
|
||||
///
|
||||
/// let icon = lookup("firefox").find();
|
||||
/// # }
|
||||
pub fn lookup(name: &str) -> LookupBuilder {
|
||||
LookupBuilder::new(name)
|
||||
}
|
||||
|
||||
impl<'a> LookupBuilder<'a> {
|
||||
/// Restrict the lookup to the given icon size.
|
||||
///
|
||||
/// ## Example
|
||||
/// ```rust
|
||||
/// # fn main() {
|
||||
/// use freedesktop_icons::lookup;
|
||||
///
|
||||
/// let icon = lookup("firefox")
|
||||
/// .with_size(48)
|
||||
/// .find();
|
||||
/// # }
|
||||
pub fn with_size(mut self, scale: u16) -> Self {
|
||||
self.scale = scale;
|
||||
self
|
||||
}
|
||||
|
||||
/// Restrict the lookup to the given scale.
|
||||
///
|
||||
/// ## Example
|
||||
/// ```rust
|
||||
/// # fn main() {
|
||||
/// use freedesktop_icons::lookup;
|
||||
///
|
||||
/// let icon = lookup("firefox")
|
||||
/// .with_scale(2)
|
||||
/// .find();
|
||||
/// # }
|
||||
pub fn with_scale(mut self, size: u16) -> Self {
|
||||
self.size = size;
|
||||
self
|
||||
}
|
||||
|
||||
/// Add the given theme to the current lookup :
|
||||
/// ## Example
|
||||
/// ```rust
|
||||
/// # fn main() {
|
||||
/// use freedesktop_icons::lookup;
|
||||
///
|
||||
/// let icon = lookup("firefox")
|
||||
/// .with_theme("Papirus")
|
||||
/// .find();
|
||||
/// # }
|
||||
pub fn with_theme<'b: 'a>(mut self, theme: &'b str) -> Self {
|
||||
self.theme = Some(theme);
|
||||
self
|
||||
}
|
||||
|
||||
/// Execute the current lookup
|
||||
/// if no icon is found in the current theme fallback to
|
||||
/// `/usr/shar/hicolor` theme and then to `/usr/share/pixmaps`.
|
||||
pub fn find(self) -> Option<PathBuf> {
|
||||
// Lookup for an icon in the given theme and fallback to 'hicolor' default theme
|
||||
let icon = self
|
||||
.theme
|
||||
.and_then(|theme| self.lookup_in_theme(theme))
|
||||
.or_else(|| self.lookup_in_theme("hicolor"));
|
||||
|
||||
// Return the icon if found
|
||||
if icon.is_some() {
|
||||
return icon;
|
||||
};
|
||||
|
||||
// Last chance
|
||||
try_build_icon_path(self.name, "/usr/share/pixmaps")
|
||||
}
|
||||
|
||||
fn new<'b: 'a>(name: &'b str) -> Self {
|
||||
Self {
|
||||
name,
|
||||
|
|
@ -39,37 +138,26 @@ impl<'a> LookupBuilder<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn find_one(self) -> Option<PathBuf> {
|
||||
let name = self.name;
|
||||
let size = self.size;
|
||||
let scale = self.scale;
|
||||
|
||||
// We have a theme name, lookup -> fallback - exit
|
||||
if let Some(theme) = self.theme.and_then(|theme| THEMES.get(theme)) {
|
||||
let icon = theme.try_get_icon(name, size, scale);
|
||||
if icon.is_some() {
|
||||
return icon;
|
||||
}
|
||||
|
||||
// hicolor fallback
|
||||
if let Some(fallback) = THEMES.get("hicolor") {
|
||||
let icon = fallback.try_get_icon(name, size, scale);
|
||||
if icon.is_some() {
|
||||
return icon;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// No theme let's look everywhere
|
||||
for theme in THEMES.values() {
|
||||
let icon = theme.try_get_icon(name, size, scale);
|
||||
if icon.is_some() {
|
||||
return icon;
|
||||
}
|
||||
}
|
||||
// Recursively lookup for icon in the given theme and its parents
|
||||
fn lookup_in_theme(&self, theme: &str) -> Option<PathBuf> {
|
||||
let cached = CACHE.get(theme, self.size, self.scale, self.name);
|
||||
if cached.is_some() {
|
||||
return cached;
|
||||
}
|
||||
|
||||
// Last chance
|
||||
try_build_icon_path(name, "/usr/share/pixmaps")
|
||||
THEMES.get(theme).and_then(|icon_theme| {
|
||||
icon_theme
|
||||
.try_get_icon(self.name, self.size, self.scale)
|
||||
.or_else(|| {
|
||||
icon_theme
|
||||
.inherits()
|
||||
.and_then(|parent| self.lookup_in_theme(parent))
|
||||
})
|
||||
.map(|icon| {
|
||||
CACHE.insert(theme, self.size, self.scale, self.name, &icon);
|
||||
icon
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -81,7 +169,7 @@ mod test {
|
|||
|
||||
#[test]
|
||||
fn simple_lookup() {
|
||||
let firefox = lookup("firefox").find_one();
|
||||
let firefox = lookup("firefox").find();
|
||||
assert_that!(firefox).is_some();
|
||||
}
|
||||
|
||||
|
|
@ -97,7 +185,7 @@ mod test {
|
|||
.with_size(16)
|
||||
.with_scale(1)
|
||||
.with_theme("Papirus")
|
||||
.find_one();
|
||||
.find();
|
||||
|
||||
assert_that!(wireshark).is_some().is_equal_to(lin_wireshark)
|
||||
}
|
||||
|
|
@ -108,7 +196,7 @@ mod test {
|
|||
.with_size(16)
|
||||
.with_scale(1)
|
||||
.with_theme("Papirus")
|
||||
.find_one();
|
||||
.find();
|
||||
|
||||
assert_that!(archlinux_logo)
|
||||
.is_some()
|
||||
|
|
|
|||
|
|
@ -7,10 +7,10 @@ use std::collections::BTreeMap;
|
|||
use std::fmt::{Debug, Formatter};
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
pub mod directories;
|
||||
mod directories;
|
||||
pub mod error;
|
||||
pub mod parse;
|
||||
pub mod paths;
|
||||
mod parse;
|
||||
mod paths;
|
||||
|
||||
type Result<T> = std::result::Result<T, ThemeError>;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue