It's not that hard. It can be done. Also, I am not here to start a new language flame. I'm not a troll, or at least not too much. So, be gentle, please. Do not start a language flame.
Also, I'm not criticizing LLHTTP or Feather at all, because Feather is a very good person, and LLHTTP was an amazing and performant parser that I loved. Its architecture is the inspiration and the basis of Milo, obviously. I still have a state machine, but much simpler, I have much less states. We dropped from 80 to 32, and I chose to use a declarative way to write states, using no code restriction in Rust.
Now, it's not black magic. Nothing is black magic in IT, right? I just leverage the macros. The Rust macro system is one of the most powerful, if not the most powerful, I have ever seen. Basically, the idea that you can think of is that before getting to completion of your code, if you use a macro, I'm not talking about procedural macros, you can basically run another Rust part that generates Rust code that is eventually compiled. So, basically, the macro in Rust will produce Rust code, but you don't have any code limitation, you can do whatever you want. For instance, I load the list of methods, states, and so forth, from YAML files that are not present or embedded at runtime, because they're passed at compile time, I generate Rust code, and I create a Rust executable.
Also, there is a tool which is made specifically to debug the procedural macro in Rust, because in Rust, you usually use the scene and quote crates, and with cargo span, you can see what these crates are actually doing with your code, so you can have an additional step before the compile time. Examples are usually more than a thousand words. Let's take a look. So, even if you're not a Rust programmer, you can easily resemble the similarity between the left hand side and right hand side. Now, on the left hand side, you have an actual state in Milo, which is the state after receiving a chunk and going back to the next chunk length, eventually, if you receive a slash r slash n. Otherwise, if you receive other two characters that you're not expecting, you fail the parsing. Or, if you don't have at least two characters to make the comparison, so you just usually have one, you suspend execution, so you stop parsing for now, and you return to the caller. On the right hand side, after transpiling the macros, which for the record are the ones that end in the exclamation mark, you have the compiled code. Basically, state becomes a function with a specific signature that you don't have to remember because it's implicit in the macro. CR LF becomes slash r slash n, but with expanded syntax that Rust is expecting. Same goes with MOV2 that becomes MOV2 parser, a state, and a size. Finally, you can also return a constant. But you don't have to remember all these details because the macros will do that for you. Now, what is the memory? We know that Milo is performance, right? But what about the memory footprint? Milo has a very small memory footprint.
Comments