feat: add cache and gtk benches comparison

This commit is contained in:
Paul Delafosse 2022-05-12 23:12:06 +02:00
parent e40fbfa916
commit 8de66cc58e
5 changed files with 190 additions and 45 deletions

35
src/cache.rs Normal file
View 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())
}
}

View file

@ -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()

View file

@ -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>;