-
Hi there! I've developed a relatively simple example and I don't understand what is causing the behavior I'm seeing and how to get it to do what I'd like. In the example below, I've got a private type ( use minijinja::{Environment, context};
use serde::Serialize;
#[derive(Serialize)]
struct Private {
private_name: String,
}
#[derive(Serialize)]
struct Public<'a>(&'a Private);
impl<'a> Public<'a> {
fn new(private: &'a Private) -> Self {
Self(private)
}
fn public_name(&self) -> &str {
&self.0.private_name
}
}
fn main() {
let mut environment = Environment::new();
environment.add_template("base", "{{ data }}").unwrap();
let private = Private {
private_name: "private string".into(),
};
let public = Public::new(&private);
let template = environment.get_template("base").unwrap();
let rendered = template
.render(context! {
data => &public,
})
.unwrap();
println!("{rendered}");
} Running the above prints:
I would expect it to... not? Shouldn't it be a tuple? Separately, is there any way to access methods, like The above is all contrived, but what I'm really trying to do is pass some structs from another crate with my own wrapping that limits and transforms the fields a bit. Rather than initialize a bunch of fields based on the external struct, I figured it made more sense to wrap the functionality in methods, but that doesn't seem to be possible any way I've tried. |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 4 replies
-
With MiniJinja you have two options. One option is to go via serde in which case the object is effectively turned eagerly into a For instance this is what you might want: use std::sync::Arc;
use minijinja::value::{Enumerator, Object};
use minijinja::{Environment, Value, context};
#[derive(Debug)]
struct Private {
private_name: String,
}
#[derive(Debug)]
struct Public(Arc<Private>);
impl Public {
fn new(private: Arc<Private>) -> Self {
Self(private)
}
fn public_name(&self) -> &str {
&self.0.private_name
}
}
impl Object for Public {
fn get_value(self: &Arc<Self>, key: &Value) -> Option<Value> {
match key.as_str()? {
"public_name" => Some(Value::from(self.public_name())),
_ => None,
}
}
fn enumerate(self: &Arc<Self>) -> Enumerator {
Enumerator::Str(&["public_name"])
}
}
fn main() {
let mut environment = Environment::new();
environment.add_template("base", "{{ data }}").unwrap();
let private = Arc::new(Private {
private_name: "private string".into(),
});
let public = Public::new(private);
let template = environment.get_template("base").unwrap();
let rendered = template
.render(context! {
data => Value::from_object(public),
})
.unwrap();
println!("{rendered}");
} Note that in this case you need to use The docs for |
Beta Was this translation helpful? Give feedback.
You are doing that, but you then get the behavior that serde implements for newtypes. Which for newtypes is just serializing what's inside. You either need to implement a custom serializer on
Public
or you need to useObject
. To detect if you are serializing for minijinja uses within a serde serializer you can use this method to customize it: https://docs.rs/minijinja/latest/minijinja/value/fn.serializing_for_value.html