 Awesome. Well, this is Rocket's logo. This is my name. That's my email address. You'll see it again at the end of the talk. And this is the second Rocket logo. So today, we're talking about, well, Rocket a bit. But mostly, I want to talk about code generation, which is obviously, well, if you know about Rocket, it's obviously what sort of makes Rocket rocket. And I think code generation is a somewhat underappreciated and sometimes way overappreciated feature of Rust. But I think if you use it well, you get really nice APIs that actually help you write better code or help you write better software. And I like to think Rocket is an instantiation of that. If we can use code generation well, then we can get good applications, good software. So the way I want to structure this talk is in three stages. First, I want to introduce you to Rocket. If you don't know about Rocket, it's what I think is a simple, fast, and type safe web framework for Rust. And I'll say a bit about what I mean by simple and type safe. Fast is self-descriptive. And it's powered by Rust code generation. Without Rust code generation, we wouldn't have Rocket. And the idea is that Rocket lets you write secure and robust web applications in a way that nothing else really lets you do. The closest that other web frameworks get are those in languages like Haskell using something like type Haskell or something like, or yeah. No, what's it called? Whatever. Templates, yes, template Haskell. Thank you. That's the right word, template Haskell. Great. And then I want to talk about code generation. So after you get to know a little bit about how Rocket looks, how Rocket code looks, and what Rocket does, I want to talk about code generation in Rocket and in Rust. So when Rocket was launched, there was this pervasive comment about how Rocket was so magical, how Rocket was like rails, and it's magic, and like avoid it like the plague, because it's too much magic. And I want to demystify that. I think code generation isn't magic. I think monkey patching and Ruby Mixins are magic, but not code generation. And in doing so, I want to show you very briefly what the code generation APIs look like. And when I say that, I mean the procedural macro APIs, which are very similar to what you can do now with derive if you've used that. And then I want to talk about a bit about the future. So what's coming in future versions of Rocket and how Rocket will continue to use code generation to give you a nice interface and really strong promises. So that's sort of the path we're taking for the talk today. Quick introduction on Rocket. Spend about 10, 15 minutes on that. If you already know Rocket, feel free to doze off for 15 minutes. Then we'll talk about code generation and Rocket. Let you know how Rocket uses code generation, what Rocket actually does, what code it generates, and how that works. And we'll talk a bit about the future of Rocket. OK, so let's start with an introduction to Rocket. So again, Rocket is a web framework for Rust that ideally makes it simple, i.e. like it's very easy to read, very easy to write, to write fast web applications, what you would expect from a program written in Rust, without sacrificing flexibility so you can do what you want to do, not what the framework wants you to do, or type safety. And I've underlined all of these things, but I really want to underline type safety. It's interesting that if you write a program in Rust, it doesn't mean your program actually takes advantage of type safety. You can dynamically cast in Rust if you're not aware. And that's like a really nice escape hatch if you're coming from the web, because the web is the string. You're trying to take the string and make sense of it in Rust. But if that's what we do, if we really do just dynamically cast things, then we're not really using the power of Rust, the power of the static, strict, strong type system that Rust gives us. And Rocket aims to exploit that type system. So that's what I mean by type safe there. So how did we get to Rocket? So this is the timeline. And every time I do a talk in Rocket, this timeline gets wider, which is nice. So Rocket launched about seven, eight months ago, eight months ago or so. And shortly thereafter, there was a version 0.2. I brought a bunch of nice stuff to Rocket. And about five months after that, there was a release of version 0.3, so it was just last month. And now we're at the end there. It's gained awesome traction. There are at least thousands of users and a couple dozen companies using it, which is pretty awesome. Something that's not in this timeline that totally surprised me was this blip here was how quickly someone told me, hey, I just launched something in production and my company's now using Rocket. It was like two weeks after Rocket launched, I got an IRC message saying, I rewrote this thing in Rocket. Thanks so much. I can throw away Node. I was like, all right, cool. That's great. Thanks for using version 0.1. I appreciate that. So that was quick. Now when I get those kinds of messages, I'm more excited than scared or nervous, I think. But it was surprising how quickly that happened. Just as a bit of fanfare here, when Rocket launched, it got really nice coverage. Hacker News loves Rust sometimes. But they generally liked Rocket so much so that Rocket was the top trending project when it launched, which I thought was awesome. So it got over 1,000 stars in the first day on GitHub. So that was fantastic. OK, so this is the timeline. Now, obviously, I'm missing a big component of this timeline, which is what happened before the launch. And well, obviously, I worked on it. That's what happened before the launch. So I had been working on Rocket for quite some time, about eight, nine months before Rocket actually launched. And mostly a full-time effort, kind of have to step back from Rust for a few months in the middle, mostly a full-time effort. And I just want to give a very tiny blurb about why Rocket exists. It wasn't just to create a new web framework, because there are so many of those in so many different languages. It's like, stop, no more web frameworks. I believe that. So why did I make Rocket? Well, yeah, I've worked in the web for a very long time. I've been writing web applications for a very long time. And I've been writing Rust for less time, obviously, because it hasn't existed that long, but almost five years now, like four years, so way before 1.0. And at some point, I wanted to marry the two ideas. I was like, yeah, let me write a web application in Rust. Let's see how this works. And I tried doing it, and it was not fun. When I programmed, I like to have fun. Otherwise, I'd just stop programming. And it was not fun, and it was not taking advantage of the type system. And for those two reasons, Rocket came into existence. It was really an idea of, how do we actually make this super easy, even though Rust's type system is not always the easiest thing to use? And at the same time, how do we take advantage of that type system, even though we're going to make it easy to do this? OK, so Rocket, web framework for Rust, makes it simple to write fast web applications without sacrificing flexibility or type safety. Great. So let's take a look at what a Rocket application looks like. This is Hello World. It's four lines. This is really all you write. Well, caveat, you need a main function. And yeah, so this is what you write. And first of all, I just think it's so cool that you can write this. And this is Rust. This is like a C successor, and you're writing this. I just think it's awesome. So what is this? What are you looking at? Well, the first thing up top here is an attribute. Obviously, you guys are familiar with Rust. So it's an attribute. And in Rocket, we call it the route attribute. And it's a description of matching conditions. It tells Rocket these things have to be true for a web request to be routed to this route. For Rocket to give a web request to this route, these conditions have to be true. So in this case, you need an HTTP request with the get method to the root path. The thing at the bottom is the route handler. It's just a function. It's not a special function. It's just a function. And it will be called if the route matches. And Rocket will call it. And it'll produce a response, which is an arbitrary type. Choose the type. As long as it implements a certain type class, you can return it. And that's it. That's really what makes up Rocket applications are these routes. And if you were to actually run this thing and you were to go to the root path, well, you'd see hello world, as you would expect. That's really all it takes to write a hello world application in Rocket. Now, like I said, you do need a main function. So this is not the 100% complete application. And the main function looks like this. So this is the main function. And there are a couple of things that are happening here. The first thing you see is this Rocket ignite. So obviously, you need to turn on the Rocket if you're going to launch this thing. So you ignite the Rocket. And then you need to put some stuff on the Rocket. In this case, we need to put routes on the Rocket because those belong in space, apparently. So you mount some stuff on the Rocket. And what mounting means is you just name space the route. So for instance, here, we're not really name spacing anything because we're just saying mount it to the root path. But if I were to change that to slash hello, for instance, then every route in sort of the list of routes would have to be prepended with slash hello in order for Rocket to route things to it. And then finally, you launch the Rocket. And that starts up the server. And it also prints a bunch of emojis, which is a contentious point. It was like the second GitHub issue after Rocket launched. Emojis, stop, please. I don't want that. But that looks like this. You get three emojis, not so bad. When you launch it, you get this thing. Rocket tries to be very, very helpful while you're developing an application. It tells you everything it knows about the environment, where it's actually serving this thing, the configuration of your application. It tells you what routes it knows about. And finally, it tells you where your application is actually being served. And emojis. No more emojis after this, just three emojis, but still a lot of backlash. So be careful if you choose to put emojis in your applications. You also can't get rid of them, which is great. You can try. They'll come back. All right. Mounting and launching. Great, so that's what our full application looks like. Pretty simple. This is really all you write. Obviously, they need to like extra and create Rocket and things of that nature. But this is really the entire application. All right. So this is fine, right? This is like, cool. We can write a hello world. But we can't really do anything particularly interesting yet from what I've shown you. We can change the path. So we can change get slash to, for instance, get slash world. And now we'd have to go to localhost 8,000 slash world. We change it to slash Sergio. And then we'd have to go to localhost 8,000 slash Sergio. But ideally, we can do more. And of course, you can do more. And so I want to talk to you about dynamic paths. So dynamic paths, as the name implies, allows you to have path segments that are dynamic. The user tells you what the value for that path segment is. And so here is our reworked hello world example. And you can see that we have parameters in brackets in the route attribute. So we have name in brackets, and that makes something dynamic. So whatever the user types into the path at that segment will be the value that the name parameter gets. And so again, these are in brackets. That's how you tell Rocket, hey, this is dynamic. I don't mean the literal slash name. I mean the dynamic name. And you can do more than these. You can do more than that. You can do slash names. That's age, for instance. And now you have two dynamic parameters. And the names of the parameters have to match the names of the function parameters. If not, you'll get a very nice compile time error that tells you, hey, these don't match. You know, look here, look here, not the same. Please figure it out. What's going on? And any type that implements any type that implements this trait called fromParam is allowed. So string implements fromParam, that Rocket implements fromParam in its library for you. U8 also implements fromParam, and so you can use these things. And the semantics of this are that Rocket will call fromParam for every parameter you list. And if the conversion succeeds, i.e. fromParam says, yep, this is a valid parameter of this type, then it'll call your handler. Otherwise, it can't call your handler. And so it doesn't. So the implication of this is, this thing is rather simple, but the implication of this is actually deeper. For instance, if we want to get a path from a user, i.e. we're gonna have a static file server. So we want a full path. You know, one very common attack when people try to write static file servers is to allow any file to be read, as opposed to just the files in one particular directory. And there's been like a bunch of people on Reddit slash Rust are like, look, I wrote a static file server in Hyper. And the first comment is like, oh, I can read your passwords, great. And so even here, even something as simple as parameters, we can, Rocket protects you here. So for instance, this is how you write a file server in Rocket, and it's totally safe. And so what happens here, what's happening here is, we've added these dot dots. I'm not gonna explain them, but all it says is that you're matching not only this segment, but every segment thereafter. And we're capturing that in a path parameter, which is a path buff. And the from parameter mutation for a path buff will actually verify the path and ensure that you cannot have a directory traversal attack. And so this is exactly what, this is in fact what we put in the guide about how you write a static file server in Rocket. And it's safe and you're protected. All right. So the last thing you wanna talk about before we talk about how this is actually working is what I believe the most exciting part about Rocket. And that's this concept of request guards. So for what we've seen so far, Rocket helps you with input validation, but there's more to it than just the path. There's arbitrary data in the request, and you wanna make sure that this request contains some information. For instance, I wanna check that it identifies an admin user. Well, there's nothing to match in the path for that. There's really nothing, it's just arbitrary how, what an admin user is. Maybe it means looking at a cookie. Maybe it means looking at a header. Who knows? So Rocket's mechanism to be able to describe these kinds of validations is, or are request guards. So any route, you can list any number of parameters in the handler that implement the trait from request. So here we have one, and it's admin user. So we have some type admin user. And what the admin user type does is it implements this from request trait, and the trait will verify that the request actually contains an admin user, and it'll convert whatever it needs to to give you a type that says, yep, there's an admin user here. And if it can't do that, well, it has one of two options. It can either fail, which says, no, do not call any handler that needs an admin user, or it can forward, which says, okay, look, this route, don't call it, it's not an admin user. Maybe someone else can validate the request. Maybe try a different kind of user, whatever. Just try something else, Rocket. And when you forward something, Rocket will try the next route that the nomenclature, whatever we say, is to collide. So for example, here we have two routes, and they are both requests, they're both match, the admin route, the admin path for get requests. So these collide, and if you were to actually run this, Rocket would say, hey, these collide. But we can fix that collision by ranking these routes. So we can add this rank equals two to our routes, and that means, hey, when there's a collision, try the thing with the lowest rank, and then try the thing with the next highest rank, and so on and so forth. And like I said, if you do this wrong, Rocket will give you, and ideally, a very helpful error. Here it is that says Rocket failed to launch because there are collisions. These two things collide, please fix them. Oh, by the way, did you know about ranking? That sometimes fixes this. Okay, so you have this. So what's gonna happen here? Well, if you were to go to get slash admin, then Rocket will try the lowest ranked route first. So that's the one with the admin user, which means you need an admin user to be validated, to be authenticated by the request. And then if that fails, Rocket will try the next ranked route, which is the one below that, which says you just need a regular user. And so what we've done here is actually implemented both authentication and authorization. So we've actually encoded our policy with routes request guards and forwarding mechanism. And we can go further and keep ranking things. So for instance, if you wanna have a route that has no requirements, maybe to tell the user, hey, log in so I can figure out if you're actually an admin user or regular user, then we can do that. So I think this is the most exciting part about Rocket is the ability to really encode arbitrary policies, whether it be authentication, authorization, or whatever. Request guards and forwarding allow you to do that. Okay, so that's really all I wanna say about Rocket. There is a lot more. It's a, I mean, you can do pretty much whatever you want. So there's a lot that I'm not going over. I'll link you to Rocket's website, which has a guide. It's pretty extensive. The documentation is fairly extensive. It talks about much, much more that I just don't have time to cover. Okay, so next up is code generation in Rocket and Rust. So let's go back to our hello world example. Here it is. We have our route, our high routes for the route path. And then we have our main function. Now I've restarted a bit because I need to fit code in the slide. So what does Rocket, what code does Rocket generate when you write this program? Well, it generates this code. Great, yay. What is this? Well, let's walk through it. So the first thing that happens is Rocket takes your route attribute and the signature of the function and generates this route info structure. And really you can sort of just map it directly. You can see exactly how the mapping works. It takes the name, makes it a string, takes the method, makes it an actual method type, takes the path, puts it in a string. This handler we'll talk about in a second and form it in rank or other aspects of Rocket that we don't have time to talk about. The next thing it does is it generates this function at the bottom here. So that's this high route. That's what that handler is. And what this is, it's a monomorphization of every route. So it is taking any possible signature that you can write and converting it into one signature because at the end of the day we are statically typed. We can't take a bunch of different signatures without doing dynamic dispatch. So we create one signature that effectively does dynamic dispatch at compile time. And all it does is it'll call that function to what you actually wrote. It'll get that response and it'll generate an outcome from that response. And the outcome is just what happens when you actually try to write that out on the network. And finally to tie things back together we have that routes bang macro in the mount, in the mount. And all we do here is we construct a route from the static information that we generated. So that routes bang becomes a vec and the vector contains all the routes that you wrote in the routes. And Rocket will do all the name matching necessary to actually make that happen. So that is the code that Rocket generates. Actually pretty straightforward. And the most interesting or the key here is this monomorphized function here. It's that we can take any signature and convert it into a function that has a static type, that has one type. Okay, so this is a pretty simple example but what about when we have guards and parameters? What code gets generated here? Well, the code for the route info is pretty much the same. We just kind of read everything, parse everything and invert that into a route info structure. And then Rocket has all this information to be able to convert it into something that we can use at runtime for routing. But the code for the guard and the parameters is more involved. And I could not fit the code that Rocket generates. So I took the code that Rocket generates and rewrote it into what you might actually write by hand but even that won't type check. So I've actually had to fuzz the types to fit this into one slide. But note that it is pure to what Rocket is actually generating. So what code does Rocket generate? We're gonna move this function up here so we have room for the code and this is what Rocket generates. Again, it's a function that goes from request to outcome just as before, it's always gonna be that. And what it does inside is sort of what you'd expect. So for every parameter, it generates a little bit of code. So for instance, for this user parameter, it generates the code that calls from request for a user. And it checks the outcome of that call and it does what you might expect. If it's successful, it gives you that value. If it's a forward, it just forwards the entire request. And if it's a failure, it fails with that status code. Well, what does it do for ID? Something very, very similar. It calls the from param implementation and if that succeeds, then you get a value and if that does not succeed, then you forward the request says, hey, try something else. And this really is the code that Rocket will generate, modular, making it very pretty to fit in the slide. All right, so in summary, this is all the code generation that Rocket does. It takes that route attribute and generates a route info structure, a static route information structure. It takes your route handler and it monomorphizes it into something that goes from request to outcome and then it takes your routes bang and converts it into a vector that containing routes that match your static route information. That's it. If you tell me this is magic, then I don't know what magic is. This is super simple. If you just sat and thought about it, this is probably what you'd do. This is not something super complicated. You can cargo expand before you compile. You can do rocket code gen debug equals one and it'll show you exactly the code that Rocket is emitting. And there's no magic. It's just doing things that you would do otherwise in your handler for you so you don't have to, so you don't get it wrong. So you do the right thing every single time. Okay. How does this work? How does Rocket make this code generation happen? So let's talk a bit about the internals. So the procedural macro API is actually pretty simple. Rust will call you and it'll give you the syntax that say the attribute was applied to or the syntax inside of a macro, of a macro call. And then your job is to take that syntax and emit other syntax that it should replace whatever syntax was called with, with. So you take some syntax, return some syntax, that's it. Pretty, really rather simple. The types of this syntax thing, and I've simplified it, but this is effectively what's going on. Syntax is really just a vector of these token tree things and a token tree contains a node. So like for instance, a semicolon or a plus or a string literal, something like that. And a span which says here is where in the code this token occurred. And the span is useful for error reporting and things of that nature. The span is not something that you can actually get with derive for instance, so if you were to derive the span information is just gone. You panic and you can't tell the user why you're panicking, just try to explain what's going on. But spans are extremely important and they will be in the PROC macro as 2.0 API. So this is sort of what it looks like now and what it will look like in the future, except much, much, much, much simpler. So this is the future, the present is muddy, the future is much nicer. All right, so that is code generation and Rocket and Rust. So what's next, what's coming up? Well we're gonna keep using code generation as you might imagine, and we're gonna do type URIs. The next thing, for the next release of Rocket I really wanna have typed URIs. And the idea is if you have a route like this that takes in a parameter of ID, that you can then create a URL to that route using the actual type that you'd expect. So for instance I can call URL bang for the retrieve route and specify that the ID is a paced ID of 100 or we'll actually call into for you automatically so you can just give anything that implements into for your type, in this case, assume U size or whatever, U32, implemented into for paced ID, then we could just write the thing at the bottom. And the nice thing of course is that if you get this wrong you'll get an error that says nope, those are not the right types. So you might imagine changing URLs and then everywhere you try to generate a URL for that new route, it'll fail compile time. Which is a really nice property to have. In this case we'll just get slash 100. So it's just replacing that ID with whatever you pass in and getting slash 100. Pretty straightforward. The next thing we're gonna do is database support. So to use databases with Rocket now, it's a bit cumbersome. This is what you write. If you were to do it, this is what you would have to write. You can do it, but it's not super elegant. It's gonna get much, much simpler. So what I want this to look like in version 0.4 is like this. So in your rocket.toml file, you're gonna specify, I have database named myDB and the adapter is diesels SQLite. And then in your actual rocket file and your code, you would just derive some trait and tell Rocket, oh the database that I wanna access with this type is myDB. And then you can just use that type as a request guard in your code. And so it really is taking something very big to something very small to make things really nice and easy to use. Again, we really wanna get rid of this boilerplate, but we still wanna keep type safety. So that's all I have to say about what's coming next. To this point, you've heard all about Rocket. You have some idea about how code generation works in Rocket. And I could end the talk here, but I thought I'd have some fun at the end of this and try to dispel some myths about Rocket. It's very interesting what happens when you release something and then you let other people tell you about the thing you just released. And I feel like the web is, like anything that has to do with the web is particularly sensitive to this topic. People have very strong opinions about the web and then we get JavaScript. So I don't know how this works. So the most, yeah, this is an opinion. It's not really a myth, but I think it's a myth. And that's that there's way too much magic in Rocket, you know, I don't know what's going on. Hopefully now you're convinced that that's just not true. What Rocket is doing with code generation is simple. It's what you would write, except it's writing it for you. So why do something the computer can do for you when you can do the same thing over and over and over again? So hopefully those of you who thought that there was too much magic, you're not convinced that there was in fact not too much magic, there's just code generation. The next sort of myth is that Rocket is somehow unstable. And if you've used Rocket, you might think, well, of course Rocket is unstable. It's using nightly. And if you look at the list of features that Rocket uses, there's a lot of them. Rocket uses a lot of nightly features. I'm here to tell you that that's true, but Rocket is not unstable. Rocket is stable in December sets. If you use Rocket 0.3, Rocket 0.3.1 will not break your application. Not sure where this, why people started saying this, but just because Rocket uses nightly doesn't mean that your Rocket application itself is unstable. It means that we have to keep track of nightly. We have to keep track of nightly, and we do keep track of nightly. There at most in the history of Rocket, there have been 24 hours between a new nightly breaking something in Rocket, and a new release of Rocket fixing itself for that nightly. So at worst, if you update your Rust installation every single day, you wait 24 hours and there's a brand new release of Rocket that works on the latest nightly. Or you can just stick on the latest nightly and it'll just keep working. So Rocket applications are not unstable. And finally, on the topic of nightly is that Rocket is forever on nightly. I should not try using Rocket because my company, yo, we use stable software. Every day, that's all we use in our company, stable software. We don't use MPM 5.0, we use MPM 4.0 because that's stable, I think. No, I know, but well, we can talk about that one later. All right. So if I wanna use Rocket that I'm committing to nightly, and nightly does make things like deploying more difficult and things of that nature, so is Rocket forever on nightly? Will Rocket ever work on stable? Well, yes, of course Rocket will eventually work on stable. Every single feature that Rocket uses is being worked on right now for stabilization. Every single one of them. Some of them are actually not needed. It's just because we're using unstable stuff, we actually need to use more unstable stuff, but everything that Rocket is using is being worked on right now. The procedural macros are being worked on right now. Everything that Rocket uses, specialization, everything that Rocket uses is being worked on right now. When is it gonna happen? I don't know, that depends on these guys over here. Some things are hard, like specialization is hard. It's not an easy problem. So it will happen, maybe this 2019 Rust thing. Maybe that'll get it. I'm hopeful it'll happen much, much sooner than that, like within a year. It seems like there's enough progress to get there, but we'll see where that goes. But it is not forever and nightly. It will work on stable, and I am committed to having it work on stable as soon as soon as possible, including writing code in Rust. To make Rocket happen, I had to write a bunch of code in the Rust compiler, and I'm committed to do that again to make it work on stable as soon as possible. So that's Rocket. That's all I have to say about Rocket and Code Generation. Take a look at Code Generation. If you're trying to do something the computer can do for you in a really nice way, take a look at Code Generation. The APIs will get much better. They're already better and nightly, and I think Code Generation can really improve the simplicity of APIs and the robustness applications using libraries that use Code Generation. Here's the website. There's a guide, there's a really long guide, there are tutorials, there's a bunch of Rust docs, there's news, and there's a link to the GitHub repository. I'm Sergio, here's my email, and thank you for your time.