improv: significant memory and cpu usage reduction
This commit is contained in:
parent
4578b5fa25
commit
3dd7647411
7 changed files with 200 additions and 127 deletions
|
|
@ -1,34 +1,114 @@
|
|||
use crate::theme::directories::{Directory, DirectoryType};
|
||||
use crate::theme::Theme;
|
||||
use ini::Properties;
|
||||
|
||||
fn icon_theme_section(file: &str) -> impl Iterator<Item = (&str, &str)> + '_ {
|
||||
ini_core::Parser::new(file)
|
||||
.skip_while(|item| *item != ini_core::Item::Section("Icon Theme"))
|
||||
.take_while(|item| match item {
|
||||
ini_core::Item::Section(value) => *value == "Icon Theme",
|
||||
_ => true,
|
||||
})
|
||||
.filter_map(|item| {
|
||||
if let ini_core::Item::Property(key, value) = item {
|
||||
Some((key, value?))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
enum DirectorySection<'a> {
|
||||
Property(&'a str, &'a str),
|
||||
EndSection,
|
||||
Section(&'a str),
|
||||
}
|
||||
|
||||
fn sections(file: &str) -> impl Iterator<Item = DirectorySection> {
|
||||
ini_core::Parser::new(file).filter_map(move |item| match item {
|
||||
ini_core::Item::Property(key, Some(value)) => Some(DirectorySection::Property(key, value)),
|
||||
ini_core::Item::Section(section) => Some(DirectorySection::Section(section)),
|
||||
ini_core::Item::SectionEnd => Some(DirectorySection::EndSection),
|
||||
_ => None,
|
||||
})
|
||||
}
|
||||
|
||||
impl Theme {
|
||||
pub(super) fn get_all_directories(&self) -> impl Iterator<Item = Directory> {
|
||||
self.directories()
|
||||
.into_iter()
|
||||
.filter_map(|name| self.get_directory(name))
|
||||
.chain(
|
||||
self.scaled_directories()
|
||||
.into_iter()
|
||||
.filter_map(|name| self.get_directory(name)),
|
||||
)
|
||||
pub(super) fn get_all_directories<'a>(
|
||||
&'a self,
|
||||
file: &'a str,
|
||||
) -> impl Iterator<Item = Directory<'a>> + 'a {
|
||||
let mut iterator = sections(file);
|
||||
|
||||
std::iter::from_fn(move || {
|
||||
let mut name = "";
|
||||
let mut size = None;
|
||||
let mut max_size = None;
|
||||
let mut min_size = None;
|
||||
let mut threshold = None;
|
||||
let mut scale = None;
|
||||
// let mut context = None;
|
||||
let mut dtype = DirectoryType::default();
|
||||
|
||||
#[allow(clippy::while_let_on_iterator)]
|
||||
while let Some(event) = iterator.next() {
|
||||
match event {
|
||||
DirectorySection::Property(key, value) => {
|
||||
if name.is_empty() || name == "Icon Theme" {
|
||||
continue;
|
||||
}
|
||||
|
||||
match key {
|
||||
"Size" => size = str::parse(value).ok(),
|
||||
"Scale" => scale = str::parse(value).ok(),
|
||||
// "Context" => context = Some(value),
|
||||
"Type" => dtype = DirectoryType::from(value),
|
||||
"MaxSize" => max_size = str::parse(value).ok(),
|
||||
"MinSize" => min_size = str::parse(value).ok(),
|
||||
"Threshold" => threshold = str::parse(value).ok(),
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
||||
DirectorySection::Section(new_name) => {
|
||||
name = new_name;
|
||||
size = None;
|
||||
max_size = None;
|
||||
min_size = None;
|
||||
threshold = None;
|
||||
scale = None;
|
||||
dtype = DirectoryType::default();
|
||||
}
|
||||
|
||||
DirectorySection::EndSection => {
|
||||
if name.is_empty() || name == "Icon Theme" {
|
||||
continue;
|
||||
}
|
||||
|
||||
let size = size.take()?;
|
||||
|
||||
return Some(Directory {
|
||||
name,
|
||||
size,
|
||||
scale: scale.unwrap_or(1),
|
||||
// context,
|
||||
type_: dtype,
|
||||
maxsize: max_size.unwrap_or(size),
|
||||
minsize: min_size.unwrap_or(size),
|
||||
threshold: threshold.unwrap_or(2),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
})
|
||||
}
|
||||
|
||||
fn scaled_directories(&self) -> Vec<&str> {
|
||||
self.get_icon_theme_section()
|
||||
.and_then(|props| props.get("ScaledDirectories"))
|
||||
.map(|dirs| dirs.split(',').collect())
|
||||
.unwrap_or_default()
|
||||
}
|
||||
|
||||
fn get_icon_theme_section(&self) -> Option<&Properties> {
|
||||
self.index.section(Some("Icon Theme"))
|
||||
}
|
||||
|
||||
pub fn inherits(&self) -> Vec<&str> {
|
||||
self.get_icon_theme_section()
|
||||
.and_then(|props| props.get("Inherits"))
|
||||
.map(|parents| {
|
||||
pub fn inherits<'a>(&self, file: &'a str) -> Vec<&'a str> {
|
||||
icon_theme_section(file)
|
||||
.find(|&(key, _)| key == "Inherits")
|
||||
.map(|(_, parents)| {
|
||||
parents
|
||||
.split(',')
|
||||
// Filtering out 'hicolor' since we are going to fallback there anyway
|
||||
|
|
@ -37,47 +117,6 @@ impl Theme {
|
|||
})
|
||||
.unwrap_or_default()
|
||||
}
|
||||
|
||||
fn directories(&self) -> Vec<&str> {
|
||||
self.index
|
||||
.section(Some("Icon Theme"))
|
||||
.and_then(|props| props.get("Directories"))
|
||||
.map(|dirs| dirs.split(',').collect())
|
||||
.unwrap_or_default()
|
||||
}
|
||||
|
||||
fn get_directory<'a>(&'a self, name: &'a str) -> Option<Directory<'a>> {
|
||||
self.index.section(Some(name)).map(|props| {
|
||||
let size = props
|
||||
.get("Size")
|
||||
.and_then(|size| str::parse(size).ok())
|
||||
.expect("Size not found for icon");
|
||||
Directory {
|
||||
name,
|
||||
size,
|
||||
scale: props
|
||||
.get("Scale")
|
||||
.and_then(|scale| str::parse(scale).ok())
|
||||
.unwrap_or(1),
|
||||
type_: props
|
||||
.get("Type")
|
||||
.map(DirectoryType::from)
|
||||
.unwrap_or_default(),
|
||||
maxsize: props
|
||||
.get("MaxSize")
|
||||
.and_then(|max| str::parse(max).ok())
|
||||
.unwrap_or(size),
|
||||
minsize: props
|
||||
.get("MinSize")
|
||||
.and_then(|min| str::parse(min).ok())
|
||||
.unwrap_or(size),
|
||||
threshold: props
|
||||
.get("Threshold")
|
||||
.and_then(|thrsh| str::parse(thrsh).ok())
|
||||
.unwrap_or(2),
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
|
@ -88,7 +127,8 @@ mod test {
|
|||
#[test]
|
||||
fn should_get_theme_parents() {
|
||||
for theme in THEMES.get("Arc").unwrap() {
|
||||
let parents = theme.inherits();
|
||||
let file = crate::theme::read_ini_theme(&theme.index);
|
||||
let parents = theme.inherits(&file);
|
||||
|
||||
assert_that!(parents).does_not_contain("hicolor");
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue