From 209d8e260be8e3b33fc78a7e7f956906b2d8dd22 Mon Sep 17 00:00:00 2001 From: Thomas Frans Date: Sat, 7 Oct 2023 17:33:48 +0200 Subject: [PATCH] refactor: remove `lazy_static` crate The `lazy_static` crate was superseded by the `once_cell` crate which has been included in Rust's standard library since version `1.70`. Remove the `lazy_static` dependency and refactor all use cases to use `std::sync::OnceLock` instead. Co-authored-by: Henrik Friedrichsen --- Cargo.lock | 1 - Cargo.toml | 1 - src/application.rs | 22 +++++++++++++--------- src/command.rs | 16 +++++++++------- src/config.rs | 6 ++---- src/main.rs | 2 -- src/mpris.rs | 2 +- src/spotify.rs | 6 ++++-- src/spotify_api.rs | 2 +- 9 files changed, 30 insertions(+), 28 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3acaed5..039cf6b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1968,7 +1968,6 @@ dependencies = [ "fern", "futures", "ioctl-rs", - "lazy_static", "libc", "librespot-core", "librespot-playback", diff --git a/Cargo.toml b/Cargo.toml index 5baa703..2f3d621 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -37,7 +37,6 @@ zbus = {version = "3.11.1", default-features = false, features = ["tokio"], opti fern = "0.6" futures = "0.3" ioctl-rs = {version = "0.2", optional = true} -lazy_static = "1.3.0" libc = "0.2.142" librespot-core = "0.4.2" librespot-playback = "0.4.2" diff --git a/src/application.rs b/src/application.rs index 82df8b1..86223a8 100644 --- a/src/application.rs +++ b/src/application.rs @@ -1,6 +1,6 @@ use std::path::Path; use std::rc::Rc; -use std::sync::Arc; +use std::sync::{Arc, OnceLock}; use cursive::traits::Nameable; use cursive::{Cursive, CursiveRunner}; @@ -55,13 +55,8 @@ pub struct UserDataInner { pub cmd: CommandManager, } -lazy_static!( - /// The global Tokio runtime for running asynchronous tasks. - pub static ref ASYNC_RUNTIME: tokio::runtime::Runtime = tokio::runtime::Builder::new_multi_thread() - .enable_all() - .build() - .unwrap(); -); +/// The global Tokio runtime for running asynchronous tasks. +pub static ASYNC_RUNTIME: OnceLock = OnceLock::new(); /// The representation of an ncspot application. pub struct Application { @@ -91,6 +86,15 @@ impl Application { // Things here may cause the process to abort; we must do them before creating curses // windows otherwise the error message will not be seen by a user + ASYNC_RUNTIME + .set( + tokio::runtime::Builder::new_multi_thread() + .enable_all() + .build() + .unwrap(), + ) + .unwrap(); + let configuration = Arc::new(Config::new(configuration_file_path)); let credentials = authentication::get_credentials(&configuration)?; let theme = configuration.build_theme(); @@ -134,7 +138,7 @@ impl Application { #[cfg(unix)] let ipc = ipc::IpcSocket::new( - ASYNC_RUNTIME.handle(), + ASYNC_RUNTIME.get().unwrap().handle(), crate::config::cache_path("ncspot.sock"), event_manager.clone(), ) diff --git a/src/command.rs b/src/command.rs index 77d0f5f..402d10e 100644 --- a/src/command.rs +++ b/src/command.rs @@ -2,6 +2,7 @@ use crate::queue::RepeatSetting; use crate::spotify_url::SpotifyUrl; use std::collections::HashMap; use std::fmt; +use std::sync::OnceLock; use strum_macros::Display; @@ -291,8 +292,12 @@ fn register_aliases(map: &mut HashMap<&str, &str>, cmd: &'static str, names: Vec } } -lazy_static! { - static ref ALIASES: HashMap<&'static str, &'static str> = { +fn handle_aliases(input: &str) -> &str { + // NOTE: There is probably a better way to write this than a static HashMap. The HashMap doesn't + // improve performance as there's far too few keys, and the use of static doesn't seem good. + static ALIASES: OnceLock> = OnceLock::new(); + + let aliases = ALIASES.get_or_init(|| { let mut m = HashMap::new(); register_aliases(&mut m, "quit", vec!["q", "x"]); @@ -302,13 +307,10 @@ lazy_static! { vec!["pause", "toggleplay", "toggleplayback"], ); register_aliases(&mut m, "repeat", vec!["loop"]); - m - }; -} + }); -fn handle_aliases(input: &str) -> &str { - if let Some(cmd) = ALIASES.get(input) { + if let Some(cmd) = aliases.get(input) { handle_aliases(cmd) } else { input diff --git a/src/config.rs b/src/config.rs index 07dd533..8e53335 100644 --- a/src/config.rs +++ b/src/config.rs @@ -175,10 +175,8 @@ impl Default for UserState { } } -lazy_static! { - /// Configuration files are read/written relative to this directory. - pub static ref BASE_PATH: RwLock> = RwLock::new(None); -} +/// Configuration files are read/written relative to this directory. +static BASE_PATH: RwLock> = RwLock::new(None); /// The complete configuration (state + user configuration) of ncspot. pub struct Config { diff --git a/src/main.rs b/src/main.rs index b114e51..2aad71a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,8 +3,6 @@ #[macro_use] extern crate cursive; #[macro_use] -extern crate lazy_static; -#[macro_use] extern crate serde; use std::path::PathBuf; diff --git a/src/mpris.rs b/src/mpris.rs index 68a0b83..bf1cb7f 100644 --- a/src/mpris.rs +++ b/src/mpris.rs @@ -484,7 +484,7 @@ impl MprisManager { let (tx, rx) = mpsc::unbounded_channel::<()>(); - ASYNC_RUNTIME.spawn(async { + ASYNC_RUNTIME.get().unwrap().spawn(async { let result = Self::serve(UnboundedReceiverStream::new(rx), root, player).await; if let Err(e) = result { log::error!("MPRIS error: {e}"); diff --git a/src/spotify.rs b/src/spotify.rs index c1edb5a..c8ce276 100644 --- a/src/spotify.rs +++ b/src/spotify.rs @@ -71,7 +71,7 @@ impl Spotify { let (user_tx, user_rx) = oneshot::channel(); spotify.start_worker(Some(user_tx)); - spotify.user = ASYNC_RUNTIME.block_on(user_rx).ok(); + spotify.user = ASYNC_RUNTIME.get().unwrap().block_on(user_rx).ok(); let volume = cfg.state().volume; spotify.set_volume(volume); @@ -95,7 +95,7 @@ impl Spotify { let events = self.events.clone(); let volume = self.volume(); let credentials = self.credentials.clone(); - ASYNC_RUNTIME.spawn(Self::worker( + ASYNC_RUNTIME.get().unwrap().spawn(Self::worker( worker_channel, events, rx, @@ -122,6 +122,8 @@ impl Spotify { pub fn test_credentials(credentials: Credentials) -> Result { let config = Self::session_config(); ASYNC_RUNTIME + .get() + .unwrap() .block_on(Session::connect(config, credentials, None, true)) .map(|r| r.0) } diff --git a/src/spotify_api.rs b/src/spotify_api.rs index 3d067ec..6d0042a 100644 --- a/src/spotify_api.rs +++ b/src/spotify_api.rs @@ -94,7 +94,7 @@ impl WebApi { .as_ref() { channel.send(cmd).expect("can't send message to worker"); - let token_option = ASYNC_RUNTIME.block_on(token_rx).unwrap(); + let token_option = ASYNC_RUNTIME.get().unwrap().block_on(token_rx).unwrap(); if let Some(token) = token_option { *self.api.token.lock().expect("can't writelock api token") = Some(Token { access_token: token.access_token,