How to format a string with a non-static formatting string? [duplicate]

I want to use the format! macro with a String as first argument, but because the macro expects a string literal, I am not able pass anything different to it.

I want to do this to dynamically add strings into the current string for use in a view engine. I'm open for suggestions if there might be a better way to do it.

let test = String::from("Test: {}");
let test2 = String::from("Not working!");
println!(test, test2);

What I actually want to achieve is the below example, where main.html contains {content}.

use std::io::prelude::*;
use std::fs::File;
use std::io;

fn main() {
    let mut buffer = String::new();
    read_from_file_using_try(&mut buffer);

    println!(&buffer, content="content");
}

fn read_from_file_using_try(buffer: &mut String) -> Result<(), io::Error> {
    let mut file = try!(File::open("main.html"));
    try!(file.read_to_string(buffer));
    Ok(())
}

So I want to print the contents of main.html after I formatted it.


Short answer: it cannot be done.


Long answer: the format! macro (and its derivatives) requires a string literal, that is a string known at compilation-time. In exchange for this requirement, if the arguments provided do not match the format, a compilation error is raised.


What you are looking for is known as a template engine. A non-exhaustive list of Rust template engines in no particular order:

  • Handlebars
  • Rustache
  • Maud
  • Horrorshow
  • fomat-macros
  • ...

Template engines have different characteristics, and notably differ by the degree of validation occurring at compile-time or run-time and their flexibility (I seem to recall that Maud was very HTML-centric, for example). It's up to you to find the one most fitting for your use case.


Check out the strfmt library, it is the closest I've found to do dynamic string formatting.