mirror of
https://github.com/askama-rs/askama.git
synced 2025-10-02 15:25:19 +00:00
derive: MapChain does not need to be generic
This commit is contained in:
parent
07e6216e83
commit
466b92559a
@ -3,7 +3,7 @@ use std::collections::hash_map::{Entry, HashMap};
|
|||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::{cmp, hash, mem, str};
|
use std::{mem, str};
|
||||||
|
|
||||||
use parser::node::{
|
use parser::node::{
|
||||||
Call, Comment, Cond, CondTest, FilterBlock, If, Include, Let, Lit, Loop, Macro, Match,
|
Call, Comment, Cond, CondTest, FilterBlock, If, Include, Let, Lit, Loop, Macro, Match,
|
||||||
@ -65,7 +65,7 @@ struct Generator<'a> {
|
|||||||
// The heritage contains references to blocks and their ancestry
|
// The heritage contains references to blocks and their ancestry
|
||||||
heritage: Option<&'a Heritage<'a>>,
|
heritage: Option<&'a Heritage<'a>>,
|
||||||
// Variables accessible directly from the current scope (not redirected to context)
|
// Variables accessible directly from the current scope (not redirected to context)
|
||||||
locals: MapChain<'a, Cow<'a, str>, LocalMeta>,
|
locals: MapChain<'a>,
|
||||||
// Suffix whitespace from the previous literal. Will be flushed to the
|
// Suffix whitespace from the previous literal. Will be flushed to the
|
||||||
// output buffer unless suppressed by whitespace suppression on the next
|
// output buffer unless suppressed by whitespace suppression on the next
|
||||||
// non-literal.
|
// non-literal.
|
||||||
@ -86,7 +86,7 @@ impl<'a> Generator<'a> {
|
|||||||
input: &'n TemplateInput<'_>,
|
input: &'n TemplateInput<'_>,
|
||||||
contexts: &'n HashMap<&'n Arc<Path>, Context<'n>, FxBuildHasher>,
|
contexts: &'n HashMap<&'n Arc<Path>, Context<'n>, FxBuildHasher>,
|
||||||
heritage: Option<&'n Heritage<'_>>,
|
heritage: Option<&'n Heritage<'_>>,
|
||||||
locals: MapChain<'n, Cow<'n, str>, LocalMeta>,
|
locals: MapChain<'n>,
|
||||||
buf_writable_discard: bool,
|
buf_writable_discard: bool,
|
||||||
is_in_filter_block: usize,
|
is_in_filter_block: usize,
|
||||||
) -> Generator<'n> {
|
) -> Generator<'n> {
|
||||||
@ -304,8 +304,7 @@ impl<'a> Generator<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn is_var_defined(&self, var_name: &str) -> bool {
|
fn is_var_defined(&self, var_name: &str) -> bool {
|
||||||
self.locals.get(&var_name.into()).is_some()
|
self.locals.get(var_name).is_some() || self.input.fields.iter().any(|f| f == var_name)
|
||||||
|| self.input.fields.iter().any(|f| f == var_name)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn evaluate_condition(
|
fn evaluate_condition(
|
||||||
@ -991,7 +990,7 @@ impl<'a> Generator<'a> {
|
|||||||
match var {
|
match var {
|
||||||
Target::Name(name) => {
|
Target::Name(name) => {
|
||||||
let name = normalize_identifier(name);
|
let name = normalize_identifier(name);
|
||||||
match self.locals.get(&Cow::Borrowed(name)) {
|
match self.locals.get(name) {
|
||||||
// declares a new variable
|
// declares a new variable
|
||||||
None => Ok(false),
|
None => Ok(false),
|
||||||
// an initialized variable gets shadowed
|
// an initialized variable gets shadowed
|
||||||
@ -1062,7 +1061,7 @@ impl<'a> Generator<'a> {
|
|||||||
}
|
}
|
||||||
if shadowed
|
if shadowed
|
||||||
|| !matches!(l.var, Target::Name(_))
|
|| !matches!(l.var, Target::Name(_))
|
||||||
|| matches!(&l.var, Target::Name(name) if self.locals.get(&Cow::Borrowed(name)).is_none())
|
|| matches!(&l.var, Target::Name(name) if self.locals.get(name).is_none())
|
||||||
{
|
{
|
||||||
buf.write("let ");
|
buf.write("let ");
|
||||||
}
|
}
|
||||||
@ -1165,10 +1164,7 @@ impl<'a> Generator<'a> {
|
|||||||
// `<'b, 'b, ...>`. Except... it doesn't work because `self` still doesn't live long
|
// `<'b, 'b, ...>`. Except... it doesn't work because `self` still doesn't live long
|
||||||
// enough here for some reason...
|
// enough here for some reason...
|
||||||
MapChain::with_parent(unsafe {
|
MapChain::with_parent(unsafe {
|
||||||
mem::transmute::<
|
mem::transmute::<&MapChain<'_>, &MapChain<'_>>(&self.locals)
|
||||||
&MapChain<'_, Cow<'_, str>, LocalMeta>,
|
|
||||||
&MapChain<'_, Cow<'_, str>, LocalMeta>,
|
|
||||||
>(&self.locals)
|
|
||||||
}),
|
}),
|
||||||
self.buf_writable.discard,
|
self.buf_writable.discard,
|
||||||
self.is_in_filter_block,
|
self.is_in_filter_block,
|
||||||
@ -2766,20 +2762,13 @@ impl LocalMeta {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
struct MapChain<'a> {
|
||||||
struct MapChain<'a, K, V>
|
parent: Option<&'a MapChain<'a>>,
|
||||||
where
|
scopes: Vec<HashMap<Cow<'a, str>, LocalMeta, FxBuildHasher>>,
|
||||||
K: cmp::Eq + hash::Hash,
|
|
||||||
{
|
|
||||||
parent: Option<&'a MapChain<'a, K, V>>,
|
|
||||||
scopes: Vec<HashMap<K, V, FxBuildHasher>>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, K: 'a, V: 'a> MapChain<'a, K, V>
|
impl<'a> MapChain<'a> {
|
||||||
where
|
fn with_parent(parent: &'a MapChain<'_>) -> MapChain<'a> {
|
||||||
K: cmp::Eq + hash::Hash,
|
|
||||||
{
|
|
||||||
fn with_parent<'p>(parent: &'p MapChain<'_, K, V>) -> MapChain<'p, K, V> {
|
|
||||||
MapChain {
|
MapChain {
|
||||||
parent: Some(parent),
|
parent: Some(parent),
|
||||||
scopes: vec![HashMap::default()],
|
scopes: vec![HashMap::default()],
|
||||||
@ -2788,7 +2777,7 @@ where
|
|||||||
|
|
||||||
/// Iterates the scopes in reverse and returns `Some(LocalMeta)`
|
/// Iterates the scopes in reverse and returns `Some(LocalMeta)`
|
||||||
/// from the first scope where `key` exists.
|
/// from the first scope where `key` exists.
|
||||||
fn get(&self, key: &K) -> Option<&V> {
|
fn get<'b>(&'b self, key: &str) -> Option<&'b LocalMeta> {
|
||||||
let mut scopes = self.scopes.iter().rev();
|
let mut scopes = self.scopes.iter().rev();
|
||||||
scopes
|
scopes
|
||||||
.find_map(|set| set.get(key))
|
.find_map(|set| set.get(key))
|
||||||
@ -2799,7 +2788,7 @@ where
|
|||||||
self.scopes.last().unwrap().is_empty()
|
self.scopes.last().unwrap().is_empty()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn insert(&mut self, key: K, val: V) {
|
fn insert(&mut self, key: Cow<'a, str>, val: LocalMeta) {
|
||||||
self.scopes.last_mut().unwrap().insert(key, val);
|
self.scopes.last_mut().unwrap().insert(key, val);
|
||||||
|
|
||||||
// Note that if `insert` returns `Some` then it implies
|
// Note that if `insert` returns `Some` then it implies
|
||||||
@ -2809,15 +2798,10 @@ where
|
|||||||
// compile error "identifier `a` used more than once".
|
// compile error "identifier `a` used more than once".
|
||||||
}
|
}
|
||||||
|
|
||||||
fn insert_with_default(&mut self, key: K)
|
fn insert_with_default(&mut self, key: Cow<'a, str>) {
|
||||||
where
|
self.insert(key, LocalMeta::default());
|
||||||
V: Default,
|
|
||||||
{
|
|
||||||
self.insert(key, V::default());
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl MapChain<'_, Cow<'_, str>, LocalMeta> {
|
|
||||||
fn resolve(&self, name: &str) -> Option<String> {
|
fn resolve(&self, name: &str) -> Option<String> {
|
||||||
let name = normalize_identifier(name);
|
let name = normalize_identifier(name);
|
||||||
self.get(&Cow::Borrowed(name)).map(|meta| match &meta.refs {
|
self.get(&Cow::Borrowed(name)).map(|meta| match &meta.refs {
|
||||||
@ -2832,7 +2816,7 @@ impl MapChain<'_, Cow<'_, str>, LocalMeta> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, K: Eq + hash::Hash, V> Default for MapChain<'a, K, V> {
|
impl Default for MapChain<'_> {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
parent: None,
|
parent: None,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user