From 3fe77c93e25d7702fc54dd0b71b268497cfd63c6 Mon Sep 17 00:00:00 2001 From: Chris Cochrun Date: Mon, 15 Sep 2025 11:19:27 -0500 Subject: [PATCH] perf, pedantic, nursery, and unwrap_used clippy fixes --- src/core/images.rs | 15 ++++---- src/core/kinds.rs | 2 +- src/core/model.rs | 4 +-- src/core/presentations.rs | 13 ++++--- src/core/service_items.rs | 75 +++++++++++++++++++-------------------- src/core/slide.rs | 46 ++++++++++++------------ src/core/songs.rs | 59 +++++++++++++++--------------- src/core/thumbnail.rs | 12 +++---- src/core/videos.rs | 16 ++++----- src/main.rs | 28 +++++++-------- src/ui/library.rs | 36 +++++++++---------- src/ui/presenter.rs | 21 ++++++----- src/ui/slide_editor.rs | 12 +++---- src/ui/song_editor.rs | 32 ++++++++--------- src/ui/text_svg.rs | 31 ++++++++-------- 15 files changed, 195 insertions(+), 207 deletions(-) diff --git a/src/core/images.rs b/src/core/images.rs index beba760..581ad6a 100644 --- a/src/core/images.rs +++ b/src/core/images.rs @@ -17,7 +17,7 @@ use std::path::PathBuf; use tracing::error; #[derive( - Clone, Debug, Default, PartialEq, Serialize, Deserialize, + Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize, )] pub struct Image { pub id: i32, @@ -52,8 +52,7 @@ impl Content for Image { if self.path.exists() { self.path .file_name() - .map(|f| f.to_string_lossy().to_string()) - .unwrap_or("Missing image".into()) + .map_or("Missing image".into(), |f| f.to_string_lossy().to_string()) } else { "Missing image".into() } @@ -85,7 +84,7 @@ impl From<&Value> for Image { let path = p.to_str().unwrap_or_default().to_string(); let title = - path.rsplit_once("/").unwrap_or_default().1; + path.rsplit_once('/').unwrap_or_default().1; title.to_string() }); Self { @@ -154,14 +153,14 @@ impl Model { .await; match result { Ok(v) => { - for image in v.into_iter() { + for image in v { let _ = self.add_item(image); } } Err(e) => { - error!("There was an error in converting images: {e}") + error!("There was an error in converting images: {e}"); } - }; + } } } @@ -172,7 +171,7 @@ pub async fn update_image_in_db( let path = image .path .to_str() - .map(|s| s.to_string()) + .map(std::string::ToString::to_string) .unwrap_or_default(); query!( r#"UPDATE images SET title = $2, file_path = $3 WHERE id = $1"#, diff --git a/src/core/kinds.rs b/src/core/kinds.rs index b366997..ebf4a3c 100644 --- a/src/core/kinds.rs +++ b/src/core/kinds.rs @@ -50,7 +50,7 @@ impl std::fmt::Display for ServiceItemKind { // } impl From for String { - fn from(val: ServiceItemKind) -> String { + fn from(val: ServiceItemKind) -> Self { match val { ServiceItemKind::Song(_) => "song".to_owned(), ServiceItemKind::Video(_) => "video".to_owned(), diff --git a/src/core/model.rs b/src/core/model.rs index a0afcd0..62d0c06 100644 --- a/src/core/model.rs +++ b/src/core/model.rs @@ -10,7 +10,7 @@ pub struct Model { pub kind: LibraryKind, } -#[derive(Debug, Clone, PartialEq, Copy)] +#[derive(Debug, Clone, PartialEq, Eq, Copy)] pub enum LibraryKind { Song, Video, @@ -46,7 +46,7 @@ impl Model { Ok(()) } - pub fn get_item(&self, index: i32) -> Option<&T> { + #[must_use] pub fn get_item(&self, index: i32) -> Option<&T> { self.items.get(index as usize) } diff --git a/src/core/presentations.rs b/src/core/presentations.rs index bf47b5b..c729563 100644 --- a/src/core/presentations.rs +++ b/src/core/presentations.rs @@ -75,8 +75,7 @@ impl Content for Presentation { if self.path.exists() { self.path .file_name() - .map(|f| f.to_string_lossy().to_string()) - .unwrap_or("Missing presentation".into()) + .map_or("Missing presentation".into(), |f| f.to_string_lossy().to_string()) } else { "Missing presentation".into() } @@ -190,14 +189,14 @@ impl ServiceTrait for Presentation { } impl Presentation { - pub fn new() -> Self { + #[must_use] pub fn new() -> Self { Self { - title: "".to_string(), + title: String::new(), ..Default::default() } } - pub fn get_kind(&self) -> &PresKind { + #[must_use] pub const fn get_kind(&self) -> &PresKind { &self.kind } } @@ -240,7 +239,7 @@ impl Model { .await; match result { Ok(v) => { - for presentation in v.into_iter() { + for presentation in v { let _ = self.add_item(Presentation { id: presentation.id, title: presentation.title, @@ -267,7 +266,7 @@ pub async fn update_presentation_in_db( let path = presentation .path .to_str() - .map(|s| s.to_string()) + .map(std::string::ToString::to_string) .unwrap_or_default(); let html = presentation.kind == PresKind::Html; query!( diff --git a/src/core/service_items.rs b/src/core/service_items.rs index a8a28a9..3f81a89 100644 --- a/src/core/service_items.rs +++ b/src/core/service_items.rs @@ -79,13 +79,13 @@ impl AsMimeTypes for ServiceItem { impl From<&ServiceItem> for Value { fn from(value: &ServiceItem) -> Self { match &value.kind { - ServiceItemKind::Song(song) => Value::from(song), - ServiceItemKind::Video(video) => Value::from(video), - ServiceItemKind::Image(image) => Value::from(image), + ServiceItemKind::Song(song) => Self::from(song), + ServiceItemKind::Video(video) => Self::from(video), + ServiceItemKind::Image(image) => Self::from(image), ServiceItemKind::Presentation(presentation) => { - Value::from(presentation) + Self::from(presentation) } - ServiceItemKind::Content(slide) => Value::from(slide), + ServiceItemKind::Content(slide) => Self::from(slide), } } } @@ -172,54 +172,51 @@ impl From<&Value> for ServiceItem { } else if let Some(background) = list.get(background_pos) { - match background { - Value::List(item) => match &item[0] { - Value::Symbol(Symbol(s)) - if s == "image" => - { - Self::from(&Image::from( - background, - )) - } - Value::Symbol(Symbol(s)) - if s == "video" => - { - Self::from(&Video::from( - background, - )) - } - Value::Symbol(Symbol(s)) - if s == "presentation" => - { - Self::from(&Presentation::from( - background, - )) - } - _ => todo!(), - }, - _ => { - error!( - "There is no background here: {:?}", - background - ); - ServiceItem::default() + if let Value::List(item) = background { match &item[0] { + Value::Symbol(Symbol(s)) + if s == "image" => + { + Self::from(&Image::from( + background, + )) } + Value::Symbol(Symbol(s)) + if s == "video" => + { + Self::from(&Video::from( + background, + )) + } + Value::Symbol(Symbol(s)) + if s == "presentation" => + { + Self::from(&Presentation::from( + background, + )) + } + _ => todo!(), + } } else { + error!( + "There is no background here: {:?}", + background + ); + Self::default() } } else { error!( "There is no background here: {:?}", background_pos ); - ServiceItem::default() + Self::default() } } Value::Symbol(Symbol(s)) if s == "song" => { let song = lisp_to_song(list.clone()); Self::from(&song) } - _ => ServiceItem::default(), + _ => Self::default(), }, - _ => ServiceItem::default(), + _ => Self::default(), } } } diff --git a/src/core/slide.rs b/src/core/slide.rs index b857afa..def56f7 100644 --- a/src/core/slide.rs +++ b/src/core/slide.rs @@ -107,9 +107,9 @@ impl TryFrom<&Background> for Video { fn try_from( value: &Background, ) -> std::result::Result { - Video::new( + Self::new( &url::Url::from_file_path(value.path.clone()) - .map_err(|_| ParseError::BackgroundNotVideo)?, + .map_err(|()| ParseError::BackgroundNotVideo)?, ) .map_err(|_| ParseError::BackgroundNotVideo) } @@ -121,9 +121,9 @@ impl TryFrom for Video { fn try_from( value: Background, ) -> std::result::Result { - Video::new( + Self::new( &url::Url::from_file_path(value.path) - .map_err(|_| ParseError::BackgroundNotVideo)?, + .map_err(|()| ParseError::BackgroundNotVideo)?, ) .map_err(|_| ParseError::BackgroundNotVideo) } @@ -132,7 +132,7 @@ impl TryFrom for Video { impl TryFrom for Background { type Error = ParseError; fn try_from(value: String) -> Result { - Background::try_from(value.as_str()) + Self::try_from(value.as_str()) } } @@ -147,7 +147,7 @@ impl TryFrom for Background { .to_str() .unwrap() .to_string(); - let path = path.replace("~", &home); + let path = path.replace('~', &home); PathBuf::from(path) } else { path @@ -192,10 +192,10 @@ impl TryFrom<&str> for Background { type Error = ParseError; fn try_from(value: &str) -> Result { let value = value.trim_start_matches("file://"); - if value.starts_with("~") { + if value.starts_with('~') { if let Some(home) = dirs::home_dir() { if let Some(home) = home.to_str() { - let value = value.replace("~", home); + let value = value.replace('~', home); Self::try_from(PathBuf::from(value)) } else { Self::try_from(PathBuf::from(value)) @@ -252,9 +252,9 @@ impl Display for ParseError { impl From for BackgroundKind { fn from(value: String) -> Self { if value == "image" { - BackgroundKind::Image + Self::Image } else { - BackgroundKind::Video + Self::Video } } } @@ -281,7 +281,7 @@ impl Slide { self } - pub fn set_font_size(mut self, font_size: i32) -> Self { + pub const fn set_font_size(mut self, font_size: i32) -> Self { self.font_size = font_size; self } @@ -291,12 +291,12 @@ impl Slide { self } - pub fn set_pdf_index(mut self, pdf_index: u32) -> Self { + pub const fn set_pdf_index(mut self, pdf_index: u32) -> Self { self.pdf_index = pdf_index; self } - pub fn background(&self) -> &Background { + pub const fn background(&self) -> &Background { &self.background } @@ -304,11 +304,11 @@ impl Slide { self.text.clone() } - pub fn text_alignment(&self) -> TextAlignment { + pub const fn text_alignment(&self) -> TextAlignment { self.text_alignment } - pub fn font_size(&self) -> i32 { + pub const fn font_size(&self) -> i32 { self.font_size } @@ -316,7 +316,7 @@ impl Slide { self.font.clone() } - pub fn video_loop(&self) -> bool { + pub const fn video_loop(&self) -> bool { self.video_loop } @@ -328,13 +328,13 @@ impl Slide { self.pdf_page.clone() } - pub fn pdf_index(&self) -> u32 { + pub const fn pdf_index(&self) -> u32 { self.pdf_index } pub fn song_slides(song: &Song) -> Result> { let lyrics = song.get_lyrics()?; - let slides: Vec = lyrics + let slides: Vec = lyrics .iter() .map(|l| { let song = song.clone(); @@ -358,7 +358,7 @@ impl Slide { Ok(slides) } - pub(crate) fn set_index(&mut self, index: i32) { + pub(crate) const fn set_index(&mut self, index: i32) { self.id = index; } @@ -381,7 +381,7 @@ impl From<&Value> for Slide { fn from(value: &Value) -> Self { match value { Value::List(list) => lisp_to_slide(list), - _ => Slide::default(), + _ => Self::default(), } } } @@ -404,7 +404,7 @@ fn lisp_to_slide(lisp: &Vec) -> Slide { slide = slide.background(lisp_to_background(background)); } else { slide = slide.background(Background::default()); - }; + } let text_position = lisp.iter().position(|v| match v { Value::List(vec) => { @@ -691,9 +691,7 @@ impl SlideBuilder { impl Image { fn new() -> Self { - Self { - ..Default::default() - } + Default::default() } } diff --git a/src/core/songs.rs b/src/core/songs.rs index 20dbebb..5ceffe1 100644 --- a/src/core/songs.rs +++ b/src/core/songs.rs @@ -128,7 +128,7 @@ impl FromRow<'_, SqliteRow> for Song { })), verse_order: Some({ let str: &str = row.try_get(0)?; - str.split(' ').map(|s| s.to_string()).collect() + str.split(' ').map(std::string::ToString::to_string).collect() }), background: { let string: String = row.try_get(7)?; @@ -251,8 +251,7 @@ pub fn lisp_to_song(list: Vec) -> Song { { let pos = key_pos + 1; list.get(pos) - .map(String::from) - .unwrap_or(String::from("song")) + .map_or(String::from("song"), String::from) } else { String::from("song") }; @@ -319,30 +318,30 @@ pub fn lisp_to_song(list: Vec) -> Song { let lyric = String::from(&lyric[1]); let verse_title = match lyric_verse.as_str() { - "i1" => r#"\n\nIntro 1\n"#, - "i2" => r#"\n\nIntro 1\n"#, - "v1" => r#"\n\nVerse 1\n"#, - "v2" => r#"\n\nVerse 2\n"#, - "v3" => r#"\n\nVerse 3\n"#, - "v4" => r#"\n\nVerse 4\n"#, - "v5" => r#"\n\nVerse 5\n"#, - "c1" => r#"\n\nChorus 1\n"#, - "c2" => r#"\n\nChorus 2\n"#, - "c3" => r#"\n\nChorus 3\n"#, - "c4" => r#"\n\nChorus 4\n"#, - "b1" => r#"\n\nBridge 1\n"#, - "b2" => r#"\n\nBridge 2\n"#, - "e1" => r#"\n\nEnding 1\n"#, - "e2" => r#"\n\nEnding 2\n"#, - "o1" => r#"\n\nOther 1\n"#, - "o2" => r#"\n\nOther 2\n"#, + "i1" => r"\n\nIntro 1\n", + "i2" => r"\n\nIntro 1\n", + "v1" => r"\n\nVerse 1\n", + "v2" => r"\n\nVerse 2\n", + "v3" => r"\n\nVerse 3\n", + "v4" => r"\n\nVerse 4\n", + "v5" => r"\n\nVerse 5\n", + "c1" => r"\n\nChorus 1\n", + "c2" => r"\n\nChorus 2\n", + "c3" => r"\n\nChorus 3\n", + "c4" => r"\n\nChorus 4\n", + "b1" => r"\n\nBridge 1\n", + "b2" => r"\n\nBridge 2\n", + "e1" => r"\n\nEnding 1\n", + "e2" => r"\n\nEnding 2\n", + "o1" => r"\n\nOther 1\n", + "o2" => r"\n\nOther 2\n", _ => "", }; let lyric = format!("{verse_title}{lyric}"); let lyric = lyric.replace( - "\\n", r#" -"#, + "\\n", r" +", ); lyrics.push(lyric); } @@ -392,15 +391,15 @@ impl Model { let result = query(r#"SELECT verse_order as "verse_order!", font_size as "font_size!: i32", background_type as "background_type!", horizontal_text_alignment as "horizontal_text_alignment!", vertical_text_alignment as "vertical_text_alignment!", title as "title!", font as "font!", background as "background!", lyrics as "lyrics!", ccli as "ccli!", author as "author!", audio as "audio!", id as "id: i32" from songs"#).fetch_all(db).await; match result { Ok(s) => { - for song in s.into_iter() { + for song in s { match Song::from_row(&song) { Ok(song) => { let _ = self.add_item(song); } Err(e) => { - error!("Could not convert song: {e}") + error!("Could not convert song: {e}"); } - }; + } } } Err(e) => { @@ -425,7 +424,7 @@ pub async fn update_song_in_db( }) .collect::() } else { - String::from("") + String::new() } }; @@ -488,13 +487,13 @@ impl Song { let verse_order = self.verse_order.clone(); let mut lyric_map = HashMap::new(); - let mut verse_title = String::from(""); - let mut lyric = String::from(""); + let mut verse_title = String::new(); + let mut lyric = String::new(); for (i, line) in raw_lyrics.split('\n').enumerate() { if VERSE_KEYWORDS.contains(&line) { if i != 0 { lyric_map.insert(verse_title, lyric); - lyric = String::from(""); + lyric = String::new(); verse_title = line.to_string(); } else { verse_title = line.to_string(); @@ -535,7 +534,7 @@ impl Song { lyric_list.push(lyric.to_string()); } else { // error!("NOT WORKING!"); - }; + } } // for lyric in lyric_list.iter() { // debug!(lyric = ?lyric) diff --git a/src/core/thumbnail.rs b/src/core/thumbnail.rs index dc100c5..2ff2f70 100644 --- a/src/core/thumbnail.rs +++ b/src/core/thumbnail.rs @@ -11,7 +11,9 @@ pub fn bg_from_video( video: &Path, screenshot: &Path, ) -> Result<(), Box> { - if !screenshot.exists() { + if screenshot.exists() { + debug!("Screenshot already exists"); + } else { let output_duration = Command::new("ffprobe") .args(["-i", &video.to_string_lossy()]) .output() @@ -26,9 +28,9 @@ pub fn bg_from_video( let mut duration = log.split_off(duration_index + 10); duration.truncate(11); // debug!("rust-duration-is: {duration}"); - let mut hours = String::from(""); - let mut minutes = String::from(""); - let mut seconds = String::from(""); + let mut hours = String::new(); + let mut minutes = String::new(); + let mut seconds = String::new(); for (i, c) in duration.chars().enumerate() { if i <= 1 { hours.push(c); @@ -63,8 +65,6 @@ pub fn bg_from_video( .expect("failed to execute ffmpeg"); // io::stdout().write_all(&output.stdout).unwrap(); // io::stderr().write_all(&output.stderr).unwrap(); - } else { - debug!("Screenshot already exists"); } Ok(()) } diff --git a/src/core/videos.rs b/src/core/videos.rs index c0c1dfb..11729f7 100644 --- a/src/core/videos.rs +++ b/src/core/videos.rs @@ -57,8 +57,7 @@ impl Content for Video { if self.path.exists() { self.path .file_name() - .map(|f| f.to_string_lossy().to_string()) - .unwrap_or("Missing video".into()) + .map_or("Missing video".into(), |f| f.to_string_lossy().to_string()) } else { "Missing video".into() } @@ -90,7 +89,7 @@ impl From<&Value> for Video { let path = p.to_str().unwrap_or_default().to_string(); let title = - path.rsplit_once("/").unwrap_or_default().1; + path.rsplit_once('/').unwrap_or_default().1; title.to_string() }); @@ -124,8 +123,7 @@ impl From<&Value> for Video { }) { let pos = loop_pos + 1; list.get(pos) - .map(|l| String::from(l) == *"true") - .unwrap_or_default() + .is_some_and(|l| String::from(l) == *"true") } else { false }; @@ -193,14 +191,14 @@ impl Model