3 ms·
I have bad news for you, there are probably thousands of HTTP implementations out there, thousands of TCP implementations, thousands of SMTP implementations, et
by throwaway82652 5y ago
I have bad news for you, there are probably thousands of HTTP implementations out there, thousands of TCP implementations, thousands of SMTP implementations, etc. That's what happens when a protocol becomes an international standard.
But to address your comment directly, no it's not, not when you're actually building a different state machine with different constraints each time. I actually wish we could put this protocol code in one C library in a way that only handles the protocol logic and not the I/O part, and then we'd be done with it forever. But you know that wouldn't be good enough for some, those libraries exist and people still don't use them and instead they go and write their own in the new fancy language with their cool new concept for a state machine.
- anonymoushn 5y ago> I actually wish we could put this protocol code in one C library in a way that only handles the protocol logic and not the I/O part, and then we'd be done with it forever. Yes, this is a great approach. Unfortunately people in e.g. the Rust world tend to write crates that assume they can call malloc, recv, and send, rather than one crate just implementing the protocol logic and another that does all that other stuff. Zig's way of doing things causes the library people naively write and use to call malloc, recv, and send to also be a library that just implements the protocol logic, reads from and writes to static buffers, and doesn't call malloc. Edit to reply: Yes, Rust has no_std, but most libraries that implement a protocol are not divided into a no_std library that implements just the protocol logic and a separate std-using library that wraps it, nor are most libraries that implement a protocol asynchronously wrappers around a no_std library that is not async and only implements the protocol and makes 0 syscalls. A consequence of the fundamental non-composability of naively written Rust libraries is that users who want the wrong combination of asyncness and malloc-calling very frequently need to reimplement existing Rust libraries. A consequence of the fundamental composability of naively written Zig libraries is that they never need to do that.
- throwaway82652 5y agoI don't know what you mean, Rust actually has no_std for that exact purpose.
- mananaysiempre 5y ago> I actually wish we could put this protocol code in one C library in a way that only handles the protocol logic and not the I/O part, and then we'd be done with it forever. You can have one Python library at least[1], h11 and h2 in particular make a pretty convincing case as the ultimate in Python HTTP. (You will always have wrappers, though, because not all levels of detail are appropriate for all uses—similar to how imagemagick/libgd/etc. wrap libtiff which wraps libjpeg and wrap libpng which wraps zlib and so on.) The problem, as far as I can see, is that to avoid calling out to I/O you need inversion of control, and either you convert your code into CPS and state machines manually, which almost impossible, almost unreadable, and makes layering libraries a distant dream (not that people don’t do it anyway), or you use some sort of generic inversion-of-control mechanism like async/await or call/cc, which really wants dynamic memory allocation. It seems like being able to accurately track stack usage (per module, not per program) could solve this, but that means (we must abandon arbitrary recursion and) the compiler must be able to track arithmetic equations, which is liable to make Gödel and Turing rise from their graves just to shout NOPE! at you. There’s also ABI: what do you do when a new version of a protocol library requires a dozen more bytes on “the” stack, and you were putting these on your stack or in static storage? (As far as I can tell, Rust’s no_std answer to ABI of this kind is “no.”) [1] https://sans-io.readthedocs.io/ https://sans-io.readthedocs.io/
- throwaway82652 5y ago>or you use some sort of generic inversion-of-control mechanism like async/await or call/cc, which really wants dynamic memory allocation. To that end, Zig does have another kind of function coloring that's useful there: functions which take an allocator parameter. I like that about Zig, I wish C++ and Rust were better about doing it. Sadly you can still hide this by referencing a static allocator in Zig so it's not totally there yet on the language level.