Since the conversation is claiming that you
can do everything in Rust that you can do in C, I want to provide some counter-nuance. :) I am guessing what people actually mean is that all the operations you want to do can be done via unsafe Rust somehow, and yes, you can do that. But also yes, it is not literally "just write 'unsafe'". You do need to use raw pointers.
For instance, if you want to overflow a buffer intentionally,
fn main() {
let mut a = [1, 2, 3, 4];
let b = [5, 6, 7, 8];
let ptr: *mut i32 = &mut a[0];
unsafe { ptr.add(5).write(999); }
println!("{:?}", b);
}
produces
[5, 999, 7, 8]
https://play.rust-lang.org/?version=stable&mode=debug&editio...(Note that this is not just extremely platform-specific and compiler-specific about whether a is in front of b or vice-versa, it is straight-up Undefined Behavior because you write past the end of an object... but the equivalent C code is also Undefined Behavior, and subject to the same LLVM optimizations. So if you were happy with the corresponding C code, this is the equivalent Rust.)
If you really, really want, you can write your own UnsafeSlice type that does the unsafe stuff internally and exposes the standard indexing operator, which would make foo[z] actually accept arbitrary indices just like in C. But you shouldn't. https://play.rust-lang.org/?version=stable&mode=debug&editio...
(Among other things, a code reviewer should be suspicious of your use of "unsafe" in the internals of a thing without stating why the higher-level abstraction is safe, and in fact the abstraction is wildly unsafe here, so it's bad style to write code that launders the unsafety, so to speak. In the Rust for Linux patches, there are "SAFETY" comments above each use of "unsafe" defending their logical safety.)