Just a nitpick. Rust's char is really a 21 bit unicode scalar value (a code point without surrogates) using a 32-bit representation and indeed there are a lot of invalid char values in a 32-bit space. Utf-8 is a different encoding format for code points using variable width (1-4 bytes per).
I agree in that the meaning of prove in that context is "put it to the test" but for me it doesn't go as far as finding the rule incorrect, because it's a general rule, not an absolute rule. A lot more exceptions would be necessary to make the rule incorrect for the general case.
The key difference is that this is a multidisciplinary conversational interface, and a tool in itself for interrelating structured meaning and reshaping it coherently enough so that it can be of great value both in the specific domain of the dialog, and in the potential to take it on any tangent in any way that can be expressed.
Of course it has limitations and you can't be sleep at the wheel, but that's true of any tool or task.
You can do a handy struct wrapper over a private Nonzero that xors the given value with the prohibited value (max in this case) at the new constructor. And like so for the get method. Xoring is very cheap. That's my favorite way of storing indices/links for nodes, since you can wrap them in Option for free.
I found that the stripping of the libc made impossible for me to manage signals that didn't exit the program. E.g. Sigint worked fine as long as the callback didnt return to the caller but e.g. trying to use Sigwinch or sigcontinue segfaulted and I never found a way to make that work from scratch in this type of binaries without linking to libc... I wonder if that's even possible.