diff --git a/Cargo.lock b/Cargo.lock index 483a161b5..b530d6cd0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -76,7 +76,6 @@ dependencies = [ "getopts", "hprof", "log 0.4.20", - "once_cell", "regex", "rustdoc-stripper", "toml", diff --git a/Cargo.toml b/Cargo.toml index 892de53a9..6787abc46 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,7 +17,6 @@ getter_rules = { package = "fix-getters-rules", version = "0.3.0", default-featu xml-rs = "0.8" toml = { version = "0.8" , features = ["preserve_order"] } env_logger = { version = "0.11", default-features = false } -once_cell = "1.19" log = "0.4" regex = "1.10" hprof = "0.1" diff --git a/src/codegen/doc/format.rs b/src/codegen/doc/format.rs index 2916314f7..833003124 100644 --- a/src/codegen/doc/format.rs +++ b/src/codegen/doc/format.rs @@ -1,8 +1,7 @@ #![allow(clippy::manual_map)] -use std::fmt::Write; +use std::{fmt::Write, sync::OnceLock}; use log::{info, warn}; -use once_cell::sync::Lazy; use regex::{Captures, Regex}; use super::{gi_docgen, LocationInObject}; @@ -141,7 +140,7 @@ fn replace_symbols( ) -> String { if env.config.use_gi_docgen { let out = gi_docgen::replace_c_types(input, env, in_type); - let out = GI_DOCGEN_SYMBOL.replace_all(&out, |caps: &Captures<'_>| match &caps[2] { + let out = gi_docgen_symbol().replace_all(&out, |caps: &Captures<'_>| match &caps[2] { "TRUE" => "[`true`]".to_string(), "FALSE" => "[`false`]".to_string(), "NULL" => "[`None`]".to_string(), @@ -151,7 +150,7 @@ fn replace_symbols( s => panic!("Unknown symbol prefix `{s}`"), }, }); - let out = GDK_GTK.replace_all(&out, |caps: &Captures<'_>| { + let out = gdk_gtk().replace_all(&out, |caps: &Captures<'_>| { find_type(&caps[2], env).unwrap_or_else(|| format!("`{}`", &caps[2])) }); @@ -161,28 +160,49 @@ fn replace_symbols( } } -static SYMBOL: Lazy = Lazy::new(|| Regex::new(r"([@#%])(\w+\b)([:.]+[\w-]+\b)?").unwrap()); -static GI_DOCGEN_SYMBOL: Lazy = - Lazy::new(|| Regex::new(r"([%])(\w+\b)([:.]+[\w-]+\b)?").unwrap()); -static FUNCTION: Lazy = - Lazy::new(|| Regex::new(r"([@#%])?(\w+\b[:.]+)?(\b[a-z0-9_]+)\(\)").unwrap()); -// **note** -// The optional . at the end is to make the regex more relaxed for some weird -// broken cases on gtk3's docs it doesn't hurt other docs so please don't drop -// it -static GDK_GTK: Lazy = Lazy::new(|| { - Regex::new(r"`([^\(:])?((G[dts]k|Pango|cairo_|graphene_|Adw|Hdy|GtkSource)\w+\b)(\.)?`") - .unwrap() -}); -static TAGS: Lazy = Lazy::new(|| Regex::new(r"<[\w/-]+>").unwrap()); -static SPACES: Lazy = Lazy::new(|| Regex::new(r"[ ]{2,}").unwrap()); +fn symbol() -> &'static Regex { + static REGEX: OnceLock = OnceLock::new(); + REGEX.get_or_init(|| Regex::new(r"([@#%])(\w+\b)([:.]+[\w-]+\b)?").unwrap()) +} + +fn gi_docgen_symbol() -> &'static Regex { + static REGEX: OnceLock = OnceLock::new(); + REGEX.get_or_init(|| Regex::new(r"([%])(\w+\b)([:.]+[\w-]+\b)?").unwrap()) +} + +fn function() -> &'static Regex { + static REGEX: OnceLock = OnceLock::new(); + REGEX.get_or_init(|| Regex::new(r"([@#%])?(\w+\b[:.]+)?(\b[a-z0-9_]+)\(\)").unwrap()) +} + +fn gdk_gtk() -> &'static Regex { + // **note** + // The optional . at the end is to make the regex more relaxed for some weird + // broken cases on gtk3's docs it doesn't hurt other docs so please don't drop + // it + static REGEX: OnceLock = OnceLock::new(); + REGEX.get_or_init(|| { + Regex::new(r"`([^\(:])?((G[dts]k|Pango|cairo_|graphene_|Adw|Hdy|GtkSource)\w+\b)(\.)?`") + .unwrap() + }) +} + +fn tags() -> &'static Regex { + static REGEX: OnceLock = OnceLock::new(); + REGEX.get_or_init(|| Regex::new(r"<[\w/-]+>").unwrap()) +} + +fn spaces() -> &'static Regex { + static REGEX: OnceLock = OnceLock::new(); + REGEX.get_or_init(|| Regex::new(r"[ ]{2,}").unwrap()) +} fn replace_c_types( entry: &str, env: &Env, in_type: Option<(&TypeId, Option)>, ) -> String { - let out = FUNCTION.replace_all(entry, |caps: &Captures<'_>| { + let out = function().replace_all(entry, |caps: &Captures<'_>| { let name = &caps[3]; find_method_or_function_by_ctype(None, name, env, in_type).unwrap_or_else(|| { if !IGNORE_C_WARNING_FUNCS.contains(&name) { @@ -192,7 +212,7 @@ fn replace_c_types( }) }); - let out = SYMBOL.replace_all(&out, |caps: &Captures<'_>| match &caps[2] { + let out = symbol().replace_all(&out, |caps: &Captures<'_>| match &caps[2] { "TRUE" => "[`true`]".to_string(), "FALSE" => "[`false`]".to_string(), "NULL" => "[`None`]".to_string(), @@ -245,11 +265,11 @@ fn replace_c_types( s => panic!("Unknown symbol prefix `{s}`"), }, }); - let out = GDK_GTK.replace_all(&out, |caps: &Captures<'_>| { + let out = gdk_gtk().replace_all(&out, |caps: &Captures<'_>| { find_type(&caps[2], env).unwrap_or_else(|| format!("`{}`", &caps[2])) }); - let out = TAGS.replace_all(&out, "`$0`"); - SPACES.replace_all(&out, " ").into_owned() + let out = tags().replace_all(&out, "`$0`"); + spaces().replace_all(&out, " ").into_owned() } /// Wrapper around [`find_constant_or_variant`] that fallbacks to returning diff --git a/src/codegen/doc/gi_docgen.rs b/src/codegen/doc/gi_docgen.rs index 234bbc8da..1d60cc565 100644 --- a/src/codegen/doc/gi_docgen.rs +++ b/src/codegen/doc/gi_docgen.rs @@ -1,9 +1,9 @@ use std::{ fmt::{self, Display, Formatter}, str::FromStr, + sync::OnceLock, }; -use once_cell::sync::Lazy; use regex::{Captures, Regex}; use super::format::find_method_or_function; @@ -92,16 +92,19 @@ fn namespace_type_method_from_details( } } -static GI_DOCGEN_SYMBOLS: Lazy = Lazy::new(|| { - Regex::new(r"\[(callback|id|alias|class|const|ctor|enum|error|flags|func|iface|method|property|signal|struct|vfunc)[@](\w+\b)([:.]+[\w-]+\b)?([:.]+[\w-]+\b)?\]?").unwrap() -}); +fn gi_docgen_symbols() -> &'static Regex { + static REGEX: OnceLock = OnceLock::new(); + REGEX.get_or_init(|| { + Regex::new(r"\[(callback|id|alias|class|const|ctor|enum|error|flags|func|iface|method|property|signal|struct|vfunc)[@](\w+\b)([:.]+[\w-]+\b)?([:.]+[\w-]+\b)?\]?").unwrap() + }) +} pub(crate) fn replace_c_types( entry: &str, env: &Env, in_type: Option<(&TypeId, Option)>, ) -> String { - GI_DOCGEN_SYMBOLS + gi_docgen_symbols() .replace_all(entry, |caps: &Captures<'_>| { if let Ok(gi_type) = GiDocgen::from_str(&caps[0]) { gi_type.rust_link(env, in_type) diff --git a/src/codegen/doc/mod.rs b/src/codegen/doc/mod.rs index 71a03e01b..71ce26919 100644 --- a/src/codegen/doc/mod.rs +++ b/src/codegen/doc/mod.rs @@ -2,10 +2,10 @@ use std::{ borrow::Cow, collections::{BTreeSet, HashSet}, io::{Result, Write}, + sync::OnceLock, }; use log::{error, info}; -use once_cell::sync::Lazy; use regex::{Captures, Regex}; use stripper_lib::{write_file_name, write_item_doc, Type as SType, TypeStruct}; @@ -819,10 +819,13 @@ fn create_bitfield_doc( Ok(()) } -static PARAM_NAME: Lazy = Lazy::new(|| Regex::new(r"@(\w+)\b").unwrap()); +fn param_name() -> &'static Regex { + static REGEX: OnceLock = OnceLock::new(); + REGEX.get_or_init(|| Regex::new(r"@(\w+)\b").unwrap()) +} fn fix_param_names<'a>(doc: &'a str, self_name: &Option) -> Cow<'a, str> { - PARAM_NAME.replace_all(doc, |caps: &Captures<'_>| { + param_name().replace_all(doc, |caps: &Captures<'_>| { if let Some(self_name) = self_name { if &caps[1] == self_name { return "@self".into(); diff --git a/src/codegen/enums.rs b/src/codegen/enums.rs index ac2f2cc75..511ba1f0a 100644 --- a/src/codegen/enums.rs +++ b/src/codegen/enums.rs @@ -364,10 +364,11 @@ impl FromGlib<{sys_crate_name}::{ffi_name}> for {name} {{ ErrorDomain::Quark(quark) => { writeln!( w, - " static QUARK: once_cell::sync::Lazy<{0}ffi::GQuark> = once_cell::sync::Lazy::new(|| unsafe {{ + " static QUARK: ::std::sync::OnceLock<{0}ffi::GQuark> = ::std::sync::OnceLock::new(); + let quark = *QUARK.get_or_init(|| unsafe {{ {0}ffi::g_quark_from_static_string(b\"{1}\\0\".as_ptr() as *const _) }}); - unsafe {{ from_glib(*QUARK) }}", + unsafe {{ from_glib(quark) }}", use_glib_if_needed(env, ""), quark, )?; diff --git a/src/codegen/sys/functions.rs b/src/codegen/sys/functions.rs index 0383b35a5..bf663cf16 100644 --- a/src/codegen/sys/functions.rs +++ b/src/codegen/sys/functions.rs @@ -1,6 +1,7 @@ -use std::io::{Result, Write}; - -use once_cell::sync::Lazy; +use std::{ + io::{Result, Write}, + sync::OnceLock, +}; use super::ffi_type::*; use crate::{ @@ -14,7 +15,10 @@ use crate::{ // used as glib:get-type in GLib-2.0.gir const INTERN: &str = "intern"; -static DEFAULT_OBJ: Lazy = Lazy::new(Default::default); +fn default_obj() -> &'static GObject { + static OBJ: OnceLock = OnceLock::new(); + OBJ.get_or_init(Default::default) +} pub fn generate_records_funcs( w: &mut dyn Write, @@ -24,7 +28,7 @@ pub fn generate_records_funcs( let intern_str = INTERN.to_string(); for record in records { let name = format!("{}.{}", env.config.library_name, record.name); - let obj = env.config.objects.get(&name).unwrap_or(&DEFAULT_OBJ); + let obj = env.config.objects.get(&name).unwrap_or(default_obj()); let version = obj.version.or(record.version); let glib_get_type = record.glib_get_type.as_ref().unwrap_or(&intern_str); generate_object_funcs( @@ -48,7 +52,7 @@ pub fn generate_classes_funcs( ) -> Result<()> { for klass in classes { let name = format!("{}.{}", env.config.library_name, klass.name); - let obj = env.config.objects.get(&name).unwrap_or(&DEFAULT_OBJ); + let obj = env.config.objects.get(&name).unwrap_or(default_obj()); let version = obj.version.or(klass.version); generate_object_funcs( w, @@ -72,7 +76,7 @@ pub fn generate_bitfields_funcs( let intern_str = INTERN.to_string(); for bitfield in bitfields { let name = format!("{}.{}", env.config.library_name, bitfield.name); - let obj = env.config.objects.get(&name).unwrap_or(&DEFAULT_OBJ); + let obj = env.config.objects.get(&name).unwrap_or(default_obj()); let version = obj.version.or(bitfield.version); let glib_get_type = bitfield.glib_get_type.as_ref().unwrap_or(&intern_str); generate_object_funcs( @@ -97,7 +101,7 @@ pub fn generate_enums_funcs( let intern_str = INTERN.to_string(); for en in enums { let name = format!("{}.{}", env.config.library_name, en.name); - let obj = env.config.objects.get(&name).unwrap_or(&DEFAULT_OBJ); + let obj = env.config.objects.get(&name).unwrap_or(default_obj()); let version = obj.version.or(en.version); let glib_get_type = en.glib_get_type.as_ref().unwrap_or(&intern_str); generate_object_funcs( @@ -125,7 +129,7 @@ pub fn generate_unions_funcs( return Ok(()); }; let name = format!("{}.{}", env.config.library_name, union.name); - let obj = env.config.objects.get(&name).unwrap_or(&DEFAULT_OBJ); + let obj = env.config.objects.get(&name).unwrap_or(default_obj()); let glib_get_type = union.glib_get_type.as_ref().unwrap_or(&intern_str); generate_object_funcs( w, @@ -148,7 +152,7 @@ pub fn generate_interfaces_funcs( ) -> Result<()> { for interface in interfaces { let name = format!("{}.{}", env.config.library_name, interface.name); - let obj = env.config.objects.get(&name).unwrap_or(&DEFAULT_OBJ); + let obj = env.config.objects.get(&name).unwrap_or(default_obj()); let version = obj.version.or(interface.version); generate_object_funcs( w, @@ -170,7 +174,7 @@ pub fn generate_other_funcs( functions: &[library::Function], ) -> Result<()> { let name = format!("{}.*", env.config.library_name); - let obj = env.config.objects.get(&name).unwrap_or(&DEFAULT_OBJ); + let obj = env.config.objects.get(&name).unwrap_or(default_obj()); generate_object_funcs(w, env, obj, None, "Other functions", INTERN, functions) } diff --git a/src/nameutil.rs b/src/nameutil.rs index 35da3a5dd..9a5f6076d 100644 --- a/src/nameutil.rs +++ b/src/nameutil.rs @@ -1,6 +1,4 @@ -use std::{borrow::Cow, collections::HashMap, path::*}; - -use once_cell::sync::Lazy; +use std::{borrow::Cow, collections::HashMap, path::*, sync::OnceLock}; use crate::case::*; @@ -93,32 +91,35 @@ pub fn bitfield_member_name(name: &str) -> String { } pub fn needs_mangling(name: &str) -> bool { - KEYWORDS.contains_key(name) + keywords().contains_key(name) } // If the mangling happened, guaranteed to return Owned. pub fn mangle_keywords<'a, S: Into>>(name: S) -> Cow<'a, str> { let name = name.into(); - if let Some(s) = KEYWORDS.get(&*name) { + if let Some(s) = keywords().get(&*name) { s.clone().into() } else { name } } -static KEYWORDS: Lazy> = Lazy::new(|| { - [ - "abstract", "alignof", "as", "async", "await", "become", "box", "break", "const", - "continue", "crate", "do", "dyn", "else", "enum", "extern", "false", "final", "fn", "for", - "if", "impl", "in", "let", "loop", "macro", "match", "mod", "move", "mut", "offsetof", - "override", "priv", "proc", "pub", "pure", "ref", "return", "Self", "self", "sizeof", - "static", "struct", "super", "trait", "true", "try", "type", "typeof", "unsafe", "unsized", - "use", "virtual", "where", "while", "yield", - ] - .iter() - .map(|k| (*k, format!("{k}_"))) - .collect() -}); +fn keywords() -> &'static HashMap<&'static str, String> { + static KEYWORDS: OnceLock> = OnceLock::new(); + KEYWORDS.get_or_init(|| { + [ + "abstract", "alignof", "as", "async", "await", "become", "box", "break", "const", + "continue", "crate", "do", "dyn", "else", "enum", "extern", "false", "final", "fn", + "for", "if", "impl", "in", "let", "loop", "macro", "match", "mod", "move", "mut", + "offsetof", "override", "priv", "proc", "pub", "pure", "ref", "return", "Self", "self", + "sizeof", "static", "struct", "super", "trait", "true", "try", "type", "typeof", + "unsafe", "unsized", "use", "virtual", "where", "while", "yield", + ] + .iter() + .map(|k| (*k, format!("{k}_"))) + .collect() + }) +} pub fn signal_to_snake(signal: &str) -> String { signal.replace("::", "_").replace('-', "_")