Coming from Go I'm wondering if there is a native way to generate code (or files) in Rust

Coming from Go I'm wondering if there is an easy way to natively generate code (or files) like I do in Go using only text/template.

It's very easy to generate code with Go like this.

Is there a similar way in Rust or I should search for 3rd party template engine?

In rust we would use generics and/or macros.

2 Likes

Generally codegen is Rust is done via frequent calls to std::fmt.

Im not using templating for Go code only. I'm using it to generate other files too. So in Rust there is nothing like that right?

And are there 3rd party template engines?

What are you generating then ? You could use the build.rs file to do that.

1 Like

Can you better explain?

https://doc.rust-lang.org/cargo/reference/build-scripts.html

There are lots of 3rd party template engines, but nothing in the std lib besides std::fmt as noted previously, most of the generated code i've run across doesn't use a template library.

I used minijinja once, for generating rust code, but that was providing a rust based alternative to existing python tools, while also using existing templates generating c-code, adding templates generating rust-code...

This wasn't in a cargo based build, but that would be easy via build.rs as noted above. But overall it was successful, in that I can now run the code generation on either python with jinja, or rust with minijinja, so we can do a nice orderly transition (perhaps).

Anyhow, to answer your question: yes, there are 3rd party templating engines (many of them), but i've rarely seen then used for codegen except in this case where there was an existing template based codegen mechanism...

And that's probably because macros and generics are powerful enough for most "codegen" type tasks.

5 Likes

But I'm not referring to Rust code only. I'm referring to things like scaffolding an entire project, with typescript, yaml, svg files and other things too.

I think using std::fmt for this is very difficult.

To answer your question directly, I've had great experiences using handlebars and tera. That said, you can get surprisingly far by just using std::io::Write and the write!() macro.

To understand why there is no text/template module in std, it might help to understand the differences in philosophy and background between Go and Rust.

Go prefers to come with batteries included, giving you everything you need to implement a web server without any 3rd party libraries. However, for Rust the standard library is intended to have the bare essentials for writing a program (typically a CLI program or library) that is cross-platform by default. These are things like...

  • Data structures which almost all Rust programs will need (Vec, HashMap, RefCell, Box, Arc, etc.)
  • Core abstractions that are required to implement the language (slices, Deref, Iterator, Send, Sync, std::fmt and its associated macros, etc.)
  • Cross-platform abstractions over the OS (File, Mutex, TcpListener, etc.)
  • etc.

All of these tend to have 1 obvious implementation and you wouldn't be able to write a Rust program without them (imagine the chaos if std::io::Write, Iterator, or Vec had to come from 3rd party libraries :grimacing:).

For a counter example, on crates.io alone there are 179 crates in the "Templating Engine" category that all have different designs and trade-offs. Given our previously stated philosophy, for a Rustacean it wouldn't make sense to have a text/template module in the standard library.

I'm not saying that one philosophy is better than the other, but sometimes knowing more about the history can help you understand why certain decisions were made and avoid getting frustrated when a language does things differently to what you are used to.

7 Likes