Perhaps it's the other way around and manual buffer management is actually the complex thing, since your application logic will have to involve a lot of code doing toil that isn't directly related to what you want to accomplish.
EDIT:
To expand a bit, I'm a huge proponent of simplicity; I think overabstraction is a massive problem with software nowadays. However, my thinking is that the problem isn't so much with the abstractions themselves, but that they aren't transparent. ORMs are a frequent offender here: a good abstraction wouldn't allow you to perform a thousand database queries by accident just by looping over a list. You could still model a list of database-backed persistent objects as a list, but any operation that hits the database should be an explicit fetch, not an implicit one.
Less accidentally quadratic algorithms, this way!
Maybe you need to iterate over two differently sized datastructures in lockstep, or over a complex nested structure, or accumulate and filter the values, or load the data into a temporary buffer that gets flushed and reused once it fills up, or maybe your data source is infinite, or all of the above.
These are cases where using iterators is significantly safer and notably, more composable.
LOL at "proper iterator abstractions" to replace loops. You will take loops from my cold, dead hands!
At the end of the day, all things are.
In the domain of programming languages, minimalistic low-level languages like assembly, C, and Forth, tend to be unsafe. They enable categories of serious bugs that never occur in safe languages. Modern garbage collectors, for example, are very complex and very valuable.
One of the reasons Safe Rust is so compelling is that it seems to succeed in offering safety, C-like performance, and good developer ergonomics. Prior to Safe Rust you had to pick two: C and C++ lack safety, Java/C# lack performance, and formal methods are hard to use (at least in the current state of the art).
Safe Rust is not a simple language. It's not possible to achieve what Safe Rust does without sophistication far beyond that of C.
But not all of that complexity is good. For example, things like branch-prediction vulnerabilities exist as a result of that complexity, which makes it extremely difficult to reason about the entire system and predict which interacting systems might lead to security issues.
And it looks as if some of the complexity of the x86_64 instruction set is a liability with respect to performance compared to "simpler" instruction sets like ARM.
Also with regard to Rust, the more that I write, the more that I wonder if some of that complexity is due to unsolved design problems in the core of the language. For instance, once you start introducing data structures with references inside, this starts to introduce all kinds of complexity, which baloons when these kinds of types start interacting with other systems like async.
I am not expert enough to know what the solution would be, or to know if these types of problems really could be avoided, but Rust sometimes feels like a language which is missing that one key piece which would keep all of this complexity under control.
I don't think any of the issues with Intel's x86-64 chips are due to the instruction-set, they're due to the chips' internal architectures. ARM CPUs are by no means 'safe by nature'.
> the more that I write, the more that I wonder if some of that complexity is due to unsolved design problems in the core of the language
> Rust sometimes feels like a language which is missing that one key piece which would keep all of this complexity under control.
I'm reminded of a quote [0] from Bjarne Stroustrup, creator of C++:
> Within C++, there is a much smaller and cleaner language struggling to get out.