Rust v1.70: Replace once_cell with std::sync::OnceLock

This commit is contained in:
Uwe Klotz 2023-12-21 12:42:39 +01:00 committed by Alex
parent 80273a449c
commit 7ce77290e4
7 changed files with 70 additions and 53 deletions

View file

@ -10,6 +10,7 @@ keywords = ["tags", "audio", "metadata", "id3", "vorbis"]
categories = ["multimedia", "multimedia::audio", "parser-implementations"] categories = ["multimedia", "multimedia::audio", "parser-implementations"]
readme = "README.md" readme = "README.md"
include = ["src", "Cargo.toml", "LICENSE-APACHE", "LICENSE-MIT", "SUPPORTED_FORMATS.md"] include = ["src", "Cargo.toml", "LICENSE-APACHE", "LICENSE-MIT", "SUPPORTED_FORMATS.md"]
rust = "1.70.0"
[dependencies] [dependencies]
# Vorbis comments pictures # Vorbis comments pictures
@ -24,7 +25,6 @@ log = "0.4.20"
# OGG Vorbis/Opus # OGG Vorbis/Opus
ogg_pager = "0.5.0" ogg_pager = "0.5.0"
# Key maps # Key maps
once_cell = "1.18.0"
paste = "1.0.14" paste = "1.0.14"
[features] [features]

View file

@ -1,7 +1,7 @@
use crate::error::Result; use crate::error::Result;
use crate::probe::ParseOptions; use crate::probe::ParseOptions;
use crate::properties::FileProperties; use crate::properties::FileProperties;
use crate::resolve::CUSTOM_RESOLVERS; use crate::resolve::custom_resolvers;
use crate::tag::{Tag, TagType}; use crate::tag::{Tag, TagType};
use crate::traits::TagExt; use crate::traits::TagExt;
@ -831,7 +831,7 @@ impl FileType {
"mpc" | "mp+" | "mpp" => Some(Self::Mpc), "mpc" | "mp+" | "mpp" => Some(Self::Mpc),
"spx" => Some(Self::Speex), "spx" => Some(Self::Speex),
e => { e => {
if let Some((ty, _)) = CUSTOM_RESOLVERS if let Some((ty, _)) = custom_resolvers()
.lock() .lock()
.ok()? .ok()?
.iter() .iter()

View file

@ -15,7 +15,7 @@ use std::collections::HashMap;
/// assert_eq!(new_title, Some("TIT2")); /// assert_eq!(new_title, Some("TIT2"));
/// ``` /// ```
pub fn upgrade_v2(key: &str) -> Option<&'static str> { pub fn upgrade_v2(key: &str) -> Option<&'static str> {
V2KEYS.get(key).copied() v2keys().get(key).copied()
} }
/// Upgrade an ID3v2.3 key to an ID3v2.4 key /// Upgrade an ID3v2.3 key to an ID3v2.4 key
@ -31,33 +31,41 @@ pub fn upgrade_v2(key: &str) -> Option<&'static str> {
/// assert_eq!(new_involved_people_list, Some("TIPL")); /// assert_eq!(new_involved_people_list, Some("TIPL"));
/// ``` /// ```
pub fn upgrade_v3(key: &str) -> Option<&'static str> { pub fn upgrade_v3(key: &str) -> Option<&'static str> {
V3KEYS.get(key).copied() v3keys().get(key).copied()
} }
macro_rules! gen_upgrades { macro_rules! gen_upgrades {
(V2 => [$($($v2_key:literal)|* => $id3v24_from_v2:literal),+]; V3 => [$($($v3_key:literal)|* => $id3v24_from_v3:literal),+]) => { (V2 => [$($($v2_key:literal)|* => $id3v24_from_v2:literal),+]; V3 => [$($($v3_key:literal)|* => $id3v24_from_v3:literal),+]) => {
use once_cell::sync::Lazy; use std::sync::OnceLock;
static V2KEYS: Lazy<HashMap<&'static str, &'static str>> = Lazy::new(|| { static V2KEYS: OnceLock<HashMap<&'static str, &'static str>> = OnceLock::new();
let mut map = HashMap::new();
$(
$(
map.insert($v2_key, $id3v24_from_v2);
)+
)+
map
});
static V3KEYS: Lazy<HashMap<&'static str, &'static str>> = Lazy::new(|| { fn v2keys() -> &'static HashMap<&'static str, &'static str> {
let mut map = HashMap::new(); V2KEYS.get_or_init(|| {
$( let mut map = HashMap::new();
$( $(
map.insert($v3_key, $id3v24_from_v3); $(
map.insert($v2_key, $id3v24_from_v2);
)+
)+ )+
)+ map
map })
}); }
}
static V3KEYS: OnceLock<HashMap<&'static str, &'static str>> = OnceLock::new();
fn v3keys() -> &'static HashMap<&'static str, &'static str> {
V3KEYS.get_or_init(|| {
let mut map = HashMap::new();
$(
$(
map.insert($v3_key, $id3v24_from_v3);
)+
)+
map
})
}
};
} }
gen_upgrades!( gen_upgrades!(

View file

@ -15,22 +15,27 @@ use crate::probe::Probe;
use std::fs::File; use std::fs::File;
use std::io::{Cursor, Read, Seek, SeekFrom, Write}; use std::io::{Cursor, Read, Seek, SeekFrom, Write};
use std::ops::Not; use std::ops::Not;
use std::sync::OnceLock;
use byteorder::{BigEndian, LittleEndian, WriteBytesExt}; use byteorder::{BigEndian, LittleEndian, WriteBytesExt};
static CRC_32_TABLE: OnceLock<[u32; 256]> = OnceLock::new();
// In the very rare chance someone wants to write a CRC in their extended header // In the very rare chance someone wants to write a CRC in their extended header
static CRC_32_TABLE: once_cell::sync::Lazy<[u32; 256]> = once_cell::sync::Lazy::new(|| { fn crc_32_table() -> &'static [u32; 256] {
let mut crc32_table = [0; 256]; CRC_32_TABLE.get_or_init(|| {
let mut crc32_table = [0; 256];
for n in 0..256 { for n in 0..256 {
crc32_table[n as usize] = (0..8).fold(n as u32, |acc, _| match acc & 1 { crc32_table[n as usize] = (0..8).fold(n as u32, |acc, _| match acc & 1 {
1 => 0xEDB8_8320 ^ (acc >> 1), 1 => 0xEDB8_8320 ^ (acc >> 1),
_ => acc >> 1, _ => acc >> 1,
}); });
} }
crc32_table crc32_table
}); })
}
#[allow(clippy::shadow_unrelated)] #[allow(clippy::shadow_unrelated)]
pub(crate) fn write_id3v2<'a, I: Iterator<Item = FrameRef<'a>> + Clone + 'a>( pub(crate) fn write_id3v2<'a, I: Iterator<Item = FrameRef<'a>> + Clone + 'a>(
@ -232,7 +237,7 @@ fn calculate_crc(content: &[u8]) -> [u8; 5] {
let crc: u32 = content let crc: u32 = content
.iter() .iter()
.fold(!0, |crc, octet| { .fold(!0, |crc, octet| {
(crc >> 8) ^ CRC_32_TABLE[(((crc & 0xFF) ^ u32::from(*octet)) & 0xFF) as usize] (crc >> 8) ^ crc_32_table()[(((crc & 0xFF) ^ u32::from(*octet)) & 0xFF) as usize]
}) })
.not(); .not();

View file

@ -13,7 +13,7 @@ use crate::musepack::MpcFile;
use crate::ogg::opus::OpusFile; use crate::ogg::opus::OpusFile;
use crate::ogg::speex::SpeexFile; use crate::ogg::speex::SpeexFile;
use crate::ogg::vorbis::VorbisFile; use crate::ogg::vorbis::VorbisFile;
use crate::resolve::CUSTOM_RESOLVERS; use crate::resolve::custom_resolvers;
use crate::wavpack::WavPackFile; use crate::wavpack::WavPackFile;
use std::fs::File; use std::fs::File;
@ -568,7 +568,7 @@ impl<R: Read + Seek> Probe<R> {
ret ret
}, },
_ => { _ => {
if let Ok(lock) = CUSTOM_RESOLVERS.lock() { if let Ok(lock) = custom_resolvers().lock() {
#[allow(clippy::significant_drop_in_scrutinee)] #[allow(clippy::significant_drop_in_scrutinee)]
for (_, resolve) in lock.iter() { for (_, resolve) in lock.iter() {
if let ret @ Some(_) = resolve.guess(&buf[..buf_len]) { if let ret @ Some(_) = resolve.guess(&buf[..buf_len]) {

View file

@ -9,9 +9,7 @@ use crate::tag::TagType;
use std::collections::HashMap; use std::collections::HashMap;
use std::io::{Read, Seek}; use std::io::{Read, Seek};
use std::marker::PhantomData; use std::marker::PhantomData;
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex, OnceLock};
use once_cell::sync::Lazy;
/// A custom file resolver /// A custom file resolver
/// ///
@ -37,11 +35,14 @@ pub trait FileResolver: Send + Sync + AudioFile {
// Just broken out to its own type to make `CUSTOM_RESOLVER`'s type shorter :) // Just broken out to its own type to make `CUSTOM_RESOLVER`'s type shorter :)
type ResolverMap = HashMap<&'static str, &'static dyn ObjectSafeFileResolver>; type ResolverMap = HashMap<&'static str, &'static dyn ObjectSafeFileResolver>;
pub(crate) static CUSTOM_RESOLVERS: Lazy<Arc<Mutex<ResolverMap>>> = static CUSTOM_RESOLVERS: OnceLock<Arc<Mutex<ResolverMap>>> = OnceLock::new();
Lazy::new(|| Arc::new(Mutex::new(HashMap::new())));
pub(crate) fn custom_resolvers() -> &'static Arc<Mutex<ResolverMap>> {
CUSTOM_RESOLVERS.get_or_init(Default::default)
}
pub(crate) fn lookup_resolver(name: &'static str) -> &'static dyn ObjectSafeFileResolver { pub(crate) fn lookup_resolver(name: &'static str) -> &'static dyn ObjectSafeFileResolver {
let res = CUSTOM_RESOLVERS.lock().unwrap(); let res = custom_resolvers().lock().unwrap();
if let Some(resolver) = res.get(name).copied() { if let Some(resolver) = res.get(name).copied() {
return resolver; return resolver;
@ -114,7 +115,10 @@ impl<T: FileResolver> ObjectSafeFileResolver for GhostlyResolver<T> {
/// * Attempting to register an existing name or type /// * Attempting to register an existing name or type
/// * See [`Mutex::lock`] /// * See [`Mutex::lock`]
pub fn register_custom_resolver<T: FileResolver + 'static>(name: &'static str) { pub fn register_custom_resolver<T: FileResolver + 'static>(name: &'static str) {
let mut res = CUSTOM_RESOLVERS.lock().unwrap(); let mut res = CUSTOM_RESOLVERS
.get_or_init(Default::default)
.lock()
.unwrap();
assert!( assert!(
res.iter().all(|(n, _)| *n != name), res.iter().all(|(n, _)| *n != name),
"Resolver `{}` already exists!", "Resolver `{}` already exists!",

View file

@ -29,15 +29,7 @@ macro_rules! gen_map {
($(#[$meta:meta])? $NAME:ident; $($($key:literal)|+ => $variant:ident),+) => { ($(#[$meta:meta])? $NAME:ident; $($($key:literal)|+ => $variant:ident),+) => {
paste::paste! { paste::paste! {
$(#[$meta])? $(#[$meta])?
static [<$NAME _INNER>]: once_cell::sync::Lazy<HashMap<&'static str, ItemKey>> = once_cell::sync::Lazy::new(|| { static [<$NAME _INNER>]: std::sync::OnceLock<HashMap<&'static str, ItemKey>> = std::sync::OnceLock::new();
let mut map = HashMap::new();
$(
$(
map.insert($key, ItemKey::$variant);
)+
)+
map
});
$(#[$meta])? $(#[$meta])?
#[allow(non_camel_case_types)] #[allow(non_camel_case_types)]
@ -46,7 +38,15 @@ macro_rules! gen_map {
$(#[$meta])? $(#[$meta])?
impl $NAME { impl $NAME {
pub(crate) fn get_item_key(&self, key: &str) -> Option<ItemKey> { pub(crate) fn get_item_key(&self, key: &str) -> Option<ItemKey> {
[<$NAME _INNER>].iter().find(|(k, _)| k.eq_ignore_ascii_case(key)).map(|(_, v)| v.clone()) [<$NAME _INNER>].get_or_init(|| {
let mut map = HashMap::new();
$(
$(
map.insert($key, ItemKey::$variant);
)+
)+
map
}).iter().find(|(k, _)| k.eq_ignore_ascii_case(key)).map(|(_, v)| v.clone())
} }
pub(crate) fn get_key(&self, item_key: &ItemKey) -> Option<&str> { pub(crate) fn get_key(&self, item_key: &ItemKey) -> Option<&str> {