diff --git a/CHANGELOG.md b/CHANGELOG.md index c97b27ee..9c9b9db2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,8 @@ All notable changes to MiniJinja are documented here. - Added custom formatters. - Restructured engine internals for greater clarity. - Added support for rendering to `io::Write`. (#111) +- Make it impossible to implement `Fitler`, `Test` + or `Function` from outside the crate (sealed the traits). # 0.20.0 diff --git a/minijinja/src/filters.rs b/minijinja/src/filters.rs index 1e1d13a0..f034a92b 100644 --- a/minijinja/src/filters.rs +++ b/minijinja/src/filters.rs @@ -60,6 +60,7 @@ use std::sync::Arc; use crate::defaults::escape_formatter; use crate::error::Error; use crate::output::Output; +use crate::utils::SealedMarker; use crate::value::{ArgType, FunctionArgs, FunctionResult, Value}; use crate::vm::State; use crate::AutoEscape; @@ -103,7 +104,7 @@ pub(crate) struct BoxedFilter(Arc); pub trait Filter: Send + Sync + 'static { /// Applies a filter to value with the given arguments. #[doc(hidden)] - fn apply_to(&self, state: &State, value: V, args: Args) -> Rv; + fn apply_to(&self, state: &State, value: V, args: Args, _: SealedMarker) -> Rv; } macro_rules! tuple_impls { @@ -115,7 +116,7 @@ macro_rules! tuple_impls { Rv: FunctionResult, $($name: for<'a> ArgType<'a>),* { - fn apply_to(&self, state: &State, value: V, args: ($($name,)*)) -> Rv { + fn apply_to(&self, state: &State, value: V, args: ($($name,)*), _: SealedMarker) -> Rv { #[allow(non_snake_case)] let ($($name,)*) = args; (self)(state, value, $($name,)*) @@ -145,6 +146,7 @@ impl BoxedFilter { state, ArgType::from_value(Some(value))?, FunctionArgs::from_values(args)?, + SealedMarker, ) .into_result() }, diff --git a/minijinja/src/functions.rs b/minijinja/src/functions.rs index 425b2c9c..bc9779f3 100644 --- a/minijinja/src/functions.rs +++ b/minijinja/src/functions.rs @@ -52,6 +52,7 @@ use std::fmt; use std::sync::Arc; use crate::error::Error; +use crate::utils::SealedMarker; use crate::value::{ArgType, FunctionArgs, FunctionResult, Object, Value}; use crate::vm::State; @@ -98,7 +99,7 @@ pub(crate) struct BoxedFunction(Arc, &'static str); pub trait Function: Send + Sync + 'static { /// Calls a function with the given arguments. #[doc(hidden)] - fn invoke(&self, env: &State, args: Args) -> Rv; + fn invoke(&self, env: &State, args: Args, _: SealedMarker) -> Rv; } macro_rules! tuple_impls { @@ -109,7 +110,7 @@ macro_rules! tuple_impls { Rv: FunctionResult, $($name: for<'a> ArgType<'a>),* { - fn invoke(&self, state: &State, args: ($($name,)*)) -> Rv { + fn invoke(&self, state: &State, args: ($($name,)*), _: SealedMarker) -> Rv { #[allow(non_snake_case)] let ($($name,)*) = args; (self)(state, $($name,)*) @@ -134,7 +135,7 @@ impl BoxedFunction { { BoxedFunction( Arc::new(move |env, args| -> Result { - f.invoke(env, FunctionArgs::from_values(args)?) + f.invoke(env, FunctionArgs::from_values(args)?, SealedMarker) .into_result() }), std::any::type_name::(), diff --git a/minijinja/src/tests.rs b/minijinja/src/tests.rs index 98738bcc..b91b9f6e 100644 --- a/minijinja/src/tests.rs +++ b/minijinja/src/tests.rs @@ -58,6 +58,7 @@ use std::sync::Arc; use crate::error::Error; +use crate::utils::SealedMarker; use crate::value::{ArgType, FunctionArgs, Value}; use crate::vm::State; @@ -126,7 +127,7 @@ impl TestResult for bool { pub trait Test: Send + Sync + 'static { /// Performs a test to value with the given arguments. #[doc(hidden)] - fn perform(&self, state: &State, value: V, args: Args) -> Rv; + fn perform(&self, state: &State, value: V, args: Args, _: SealedMarker) -> Rv; } macro_rules! tuple_impls { @@ -138,7 +139,7 @@ macro_rules! tuple_impls { Rv: TestResult, $($name: for<'a> ArgType<'a>),* { - fn perform(&self, state: &State, value: V, args: ($($name,)*)) -> Rv { + fn perform(&self, state: &State, value: V, args: ($($name,)*), _: SealedMarker) -> Rv { #[allow(non_snake_case)] let ($($name,)*) = args; (self)(state, value, $($name,)*) @@ -168,6 +169,7 @@ impl BoxedTest { state, ArgType::from_value(value)?, FunctionArgs::from_values(args)?, + SealedMarker, ) .into_result() })) diff --git a/minijinja/src/utils.rs b/minijinja/src/utils.rs index 20c38100..155add2d 100644 --- a/minijinja/src/utils.rs +++ b/minijinja/src/utils.rs @@ -9,6 +9,9 @@ use crate::error::{Error, ErrorKind}; #[cfg(test)] use similar_asserts::assert_eq; +/// internal marker to seal up some trait methods +pub struct SealedMarker; + pub fn memchr(haystack: &[u8], needle: u8) -> Option { haystack.iter().position(|&x| x == needle) }