WIP: Add Faux allocator API

This adds a alloc::faux module that implements an interpretation of @pnkfelix's proposed high-level allocator API (rust-lang/rfcs#244), optimized for the libstd usecases. This moves all of the tedious oom/zst/capacity-overflow logic into a central place, so that collections and other things don't need to think about it.

As part of this PR I have migrated RingBuf to this API as a proof of concept. Migrating Vec will likely be more tricky, because it does a lot more special tricks based on ZSTs, making the logic more tangled. It is possible that migrating to this API would cause a perf regression for duplicated checks/extra branching. However most of the checks are largely based on compile-time-constants, so I am optimistic about LLVM's ability to optimize these to death.

I guessed out the best semantics I could for some iffy things, like how the `alloc_array` API should handle `len = 0`.

I also am considering adding triple_alloc_array/triple_dealloc_array methods to handle the HashMap usecase (which BTree can also benefit from longterm).
> Is it reasonable to forbid new_len == old_len?

That's not going to work around the issue. There's a whole range of sizes corresponding to the same real size.

> Is it then possible to just check new_size != old_size unconditionally?

No, because the returned size is the *real* size.

> The docs seem unclear to me on how to evaluate if a shrink is successful, whatever that really means. Or is that just something we shouldn't care about? Like if a shrink fails "oh well"?

You can check for a shrink failure with the `usable_size` check. I don't think it's a common use case.