Rust-the-language doesn't do any dynamic allocation, so it doesn't exhaust memory at all. The Rust stdlib currently guarantees an abort on OOM, but in the future this will be changed to a panic (which you can always configure to be an abort if you want). Both of these behaviors are memory-safe (it's unclear what "memory exhaustion safety" is referring to).
Also to clarify: there are platforms (like linux) which de facto have nonfailable allocation, if you run out of memory the system will oom kill your process, and neither zig nor rust will save you from that.
I believe In practice the most common place where failable OOM is a big deal is in embedded systems programming
No language can save you from OOMs, but because Zig pervasively uses explicit memory allocation, it makes it easy to greatly mitigate OOM risks by front-loading all the fallibility:
1. Calculate and allocate all your required memory immediately upon process startup (including memory from OS resources like sockets)
2. Call mlockall to prevent the pages from being swapped out
3. Write "-1000" to /proc/self/oom_score_adj to avoid the OOM killer
4. Use your preallocated memory as a pool for all further allocations
With the above approach, the application has full control over how to handle application-level OOMs (e.g. applying backpressure to connecting clients, or shrinking non-critical caches) once it is past the start-up stage.