Template literals
If you’ve been paying attention on previous sections you might have seen odd
looking strings like `Hello ${name}`. These are called template
literals, and allow you to conveniently build strings using variables from the
environment.
Template literals are a concept borrowed from EcmaScript.
let age = 30;
dbg!(`I am ${age} years old!`);
$> cargo run -- run scripts/book/template_literals/basic_template.rn
"I am 30 years old!"
Template strings are accelerated by the Vm, each argument uses a display protocol and it can be very efficient to build complex strings out of it.
The DISPLAY_FMT protocol
The DISPLAY_FMT protocol is a function that can be implemented by any
external type which allows it to be used in a template string.
It expects a function with the signature fn(&self, buf: &mut String) -> fmt::Result.
use rune::{ContextError, Module};
use rune::runtime::{Protocol, Formatter};
use std::fmt::Write as _;
use std::fmt;
#[derive(Debug)]
pub struct StatusCode {
inner: u32,
}
impl StatusCode {
#[rune::function(protocol = DISPLAY_FMT)]
fn display_fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "{}", self.inner)
}
}
pub fn module() -> Result<Module, ContextError> {
let mut module = Module::new(["http"]);
module.function_meta(StatusCode::display_fmt)?;
Ok(module)
}
This is what allows status codes to be formatted into template strings, any types which do not implement this protocol will fail to run.
let vec = [1, 2, 3];
dbg!(`${vec}`);
$> cargo run -- run scripts/book/template_literals/not_a_template.rn
error: Missing protocol function `DISPLAY_FMT` for `::std::vec::Vec`
┌─ scripts/book/template_literals/not_a_template.rn:1:1
│
1 │ ╭ let vec = [1, 2, 3];
2 │ │ dbg!(`${vec}`);
│ ╰───────────^ Missing protocol function `DISPLAY_FMT` for `::std::vec::Vec`
Backtrace: