Skip to content

Commit

Permalink
derive: remove once_map dependency
Browse files Browse the repository at this point in the history
This change removes 14 (transitive) dependencies:

* ahash, getrandom, hashbrown, lock_api, once_map, parking_lot,
  parking_lot_core, redox_syscall, scopeguard, smallvec,
  stable_deref_trait, wasi, zerocopy, zerocopy_derive

The new implementation is less generic, but on the other hand it's only
30 non-empty lines of code.

The benchmarks are just about unchanged.
  • Loading branch information
Kijewski committed Oct 3, 2024
1 parent 55c0b6a commit 812a8dd
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 38 deletions.
44 changes: 19 additions & 25 deletions rinja_derive/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,13 @@ use std::path::{Path, PathBuf};
use std::sync::{Arc, OnceLock};
use std::{env, fs};

use once_map::sync::OnceMap;
use parser::node::Whitespace;
use parser::{ParseError, Parsed, Syntax, SyntaxBuilder};
use proc_macro2::Span;
use rustc_hash::FxBuildHasher;
#[cfg(feature = "config")]
use serde::Deserialize;

use crate::{CRATE, CompileError, FileInfo};
use crate::{CRATE, CompileError, FileInfo, OnceMap};

#[derive(Debug)]
pub(crate) struct Config {
Expand Down Expand Up @@ -77,23 +75,20 @@ impl Config {
template_whitespace: Option<&str>,
config_span: Option<Span>,
) -> Result<&'static Config, CompileError> {
static CACHE: ManuallyDrop<
OnceLock<OnceMap<OwnedConfigKey, &'static Config, FxBuildHasher>>,
> = ManuallyDrop::new(OnceLock::new());
CACHE.get_or_init(OnceMap::default).get_or_try_insert_ref(
static CACHE: ManuallyDrop<OnceLock<OnceMap<OwnedConfigKey, &'static Config>>> =
ManuallyDrop::new(OnceLock::new());
CACHE.get_or_init(OnceMap::default).get_or_try_insert(
&ConfigKey {
source: source.into(),
config_path: config_path.map(Cow::Borrowed),
template_whitespace: template_whitespace.map(Cow::Borrowed),
},
config_span,
ConfigKey::to_owned,
|config_span, key| {
let config = Config::new_uncached(*key, config_span)?;
|key| {
let config = Config::new_uncached(key.to_owned(), config_span)?;
let config = &*Box::leak(Box::new(config));
Ok((config, config))
Ok((config._key, config))
},
|_, _, config| config,
|config| *config,
)
}
}
Expand Down Expand Up @@ -234,7 +229,7 @@ impl Config {
#[derive(Debug, Default)]
pub(crate) struct SyntaxAndCache<'a> {
syntax: Syntax<'a>,
cache: OnceMap<OwnedSyntaxAndCacheKey, Arc<Parsed>, FxBuildHasher>,
cache: OnceMap<OwnedSyntaxAndCacheKey, Arc<Parsed>>,
}

impl<'a> Deref for SyntaxAndCache<'a> {
Expand Down Expand Up @@ -281,28 +276,27 @@ impl<'a> SyntaxAndCache<'a> {
source: Arc<str>,
source_path: Option<Arc<Path>>,
) -> Result<Arc<Parsed>, ParseError> {
self.cache.get_or_try_insert_ref(
self.cache.get_or_try_insert(
&SyntaxAndCacheKey {
source: Cow::Owned(source),
source_path: source_path.map(Cow::Owned),
},
&self.syntax,
|key| {
OwnedSyntaxAndCacheKey(SyntaxAndCacheKey {
let key = OwnedSyntaxAndCacheKey(SyntaxAndCacheKey {
source: Cow::Owned(Arc::clone(key.source.as_ref())),
source_path: key
.source_path
.as_deref()
.map(|v| Cow::Owned(Arc::clone(v))),
})
},
|syntax, key| {
let source = Arc::clone(key.source.as_ref());
let source_path = key.source_path.as_deref().map(Arc::clone);
let parsed = Arc::new(Parsed::new(source, source_path, syntax)?);
Ok((Arc::clone(&parsed), parsed))
});
let parsed = Parsed::new(
Arc::clone(key.source.as_ref()),
key.source_path.as_deref().map(Arc::clone),
&self.syntax,
)?;
Ok((key, Arc::new(parsed)))
},
|_, _, cached| Arc::clone(cached),
Arc::clone,
)
}
}
Expand Down
16 changes: 6 additions & 10 deletions rinja_derive/src/input.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,14 @@ use std::path::{Path, PathBuf};
use std::sync::{Arc, OnceLock};

use mime::Mime;
use once_map::OnceMap;
use parser::{Node, Parsed};
use proc_macro2::Span;
use rustc_hash::FxBuildHasher;
use syn::punctuated::Punctuated;
use syn::spanned::Spanned;

use crate::config::{Config, SyntaxAndCache};
use crate::{CompileError, FileInfo, MsgValidEscapers};
use crate::{CompileError, FileInfo, MsgValidEscapers, OnceMap};

pub(crate) struct TemplateInput<'a> {
pub(crate) ast: &'a syn::DeriveInput,
Expand Down Expand Up @@ -766,19 +765,16 @@ pub(crate) fn get_template_source(
tpl_path: &Arc<Path>,
import_from: Option<(&Arc<Path>, &str, &str)>,
) -> Result<Arc<str>, CompileError> {
static CACHE: OnceLock<OnceMap<Arc<Path>, Arc<str>, FxBuildHasher>> = OnceLock::new();
static CACHE: OnceLock<OnceMap<Arc<Path>, Arc<str>>> = OnceLock::new();

CACHE.get_or_init(OnceMap::default).get_or_try_insert_ref(
CACHE.get_or_init(OnceMap::default).get_or_try_insert(
tpl_path,
(),
Arc::clone,
|(), tpl_path| match read_to_string(tpl_path) {
|tpl_path| match read_to_string(tpl_path) {
Ok(mut source) => {
if source.ends_with('\n') {
let _ = source.pop();
}
let source = Arc::from(source);
Ok((Arc::clone(&source), source))
Ok((Arc::clone(tpl_path), Arc::from(source)))
}
Err(err) => Err(CompileError::new(
format_args!(
Expand All @@ -790,7 +786,7 @@ pub(crate) fn get_template_source(
}),
)),
},
|(), _, cached| Arc::clone(cached),
Arc::clone,
)
}

Expand Down
43 changes: 41 additions & 2 deletions rinja_derive/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,12 @@ mod input;
#[cfg(test)]
mod tests;

use std::borrow::Cow;
use std::collections::HashMap;
use std::borrow::{Borrow, Cow};
use std::collections::hash_map::{Entry, HashMap};
use std::fmt;
use std::hash::{BuildHasher, Hash};
use std::path::Path;
use std::sync::Mutex;

use config::{Config, read_config_file};
use generator::{Generator, MapChain};
Expand All @@ -25,6 +27,7 @@ use proc_macro::TokenStream as TokenStream12;
#[cfg(feature = "__standalone")]
use proc_macro2::TokenStream as TokenStream12;
use proc_macro2::{Span, TokenStream};
use rustc_hash::FxBuildHasher;
use syn::parse_quote_spanned;

/// The `Template` derive macro and its `template()` attribute.
Expand Down Expand Up @@ -379,6 +382,42 @@ impl fmt::Display for MsgValidEscapers<'_> {
}
}

#[derive(Debug)]
struct OnceMap<K, V>([Mutex<HashMap<K, V, FxBuildHasher>>; 8]);

impl<K, V> Default for OnceMap<K, V> {
fn default() -> Self {
Self(Default::default())
}
}

impl<K: Hash + Eq, V> OnceMap<K, V> {
// The API of this function was copied, and adapted from the `once_map` crate
// <https://crates.io/crates/once_map/0.4.18>.
fn get_or_try_insert<T, Q, E>(
&self,
key: &Q,
make_key_value: impl FnOnce(&Q) -> Result<(K, V), E>,
to_value: impl FnOnce(&V) -> T,
) -> Result<T, E>
where
K: Borrow<Q>,
Q: Hash + Eq,
{
let shard_idx = (FxBuildHasher.hash_one(key) % self.0.len() as u64) as usize;
let mut shard = self.0[shard_idx].lock().unwrap();
Ok(to_value(if let Some(v) = shard.get(key) {
v
} else {
let (k, v) = make_key_value(key)?;
match shard.entry(k) {
Entry::Vacant(entry) => entry.insert(v),
Entry::Occupied(_) => unreachable!("key in map when it should not have been"),
}
}))
}
}

// This is used by the code generator to decide whether a named filter is part of
// Rinja or should refer to a local `filters` module.
const BUILT_IN_FILTERS: &[&str] = &[
Expand Down
1 change: 0 additions & 1 deletion rinja_derive_standalone/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ serde = { version = "1.0", optional = true, features = ["derive"] }
memchr = "2"
mime = "0.3"
mime_guess = "2"
once_map = { version = "0.4.18", default-features = false, features = ["std"] }
proc-macro2 = "1"
quote = "1"
rustc-hash = "2.0.0"
Expand Down

0 comments on commit 812a8dd

Please sign in to comment.