Note: This site is currently "Under construction". I'm migrating to a new version of my site building software. Lots of things are in a state of disrepair as a result (for example, footnote links aren't working). It's all part of the process of building in public. Most things should still be readable though.

Use StructObject For Dynamic Variables In Rust's MiniJinja

Code

use crate::page::Page;
use minijinja::value::{StructObject, Value};
use serde::{Deserialize, Serialize};

#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
#[serde(content = "content", rename_all = "lowercase", tag = "type")]
pub struct Universe {
    pub pages: Vec<Page>,
}

impl Universe {
    pub fn home_page_links(&self) -> Vec<(String, String)> {
        vec![("a".to_string(), "b".to_string())]
    }
}

impl StructObject for Universe {
    fn get_field(&self, field: &str) -> Option<Value> {
        match field {
            "home_page_links" => Some(Value::from_serializable(&self.clone().home_page_links())),
            _ => None,
        }
    }
}

Code

use minijinja::value::{StructObject, Value};
use minijinja::{context, Environment};
use serde::{Deserialize, Serialize};

pub struct Widget;
pub struct Thing;

#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
#[serde(content = "content", rename_all = "lowercase", tag = "type")]
pub enum Payload {
    Tango { value: String },
}

impl Widget {
    fn alfa_signal(&self) -> String {
        "This is alfa in widget".to_string()
    }
}

impl StructObject for Widget {
    fn get_field(&self, field: &str) -> Option<Value> {
        match field {
            "alfa" => Some(Value::from(self.alfa_signal())),
            _ => None,
        }
    }
}

impl Thing {
    fn bravo_signal(&self) -> String {
        "This is bravo in thing".to_string()
    }
}

impl StructObject for Thing {
    fn get_field(&self, field: &str) -> Option<Value> {
        match field {
            "bravo" => Some(Value::from(self.bravo_signal())),
            _ => None,
        }
    }
}

fn main() {
    let widget = Widget;
    let thing = Thing;
    let p = Payload::Tango {
        value: "charlie".to_string(),
    };
    let env = Environment::new();
    let tmpl = env
        .template_from_str("{{ p.type}};{{ p.value }} -  {{ w.alfa }} - {{ t.bravo }}")
        .unwrap();
    let w = Value::from_struct_object(widget);
    let t = Value::from_struct_object(thing);
    let output = tmpl.render(context!(w => w, t => t, p=> p)).unwrap();
    dbg!(output);
}
  • Combine these two examples with .from and .from_seriliazble

  • Combine with 2vauitbb

  • Show regular object which allows method calls and is the way to go with neopoligin

References