> preallocating an exactly correct size result buffer
Looks like it just uses the size of the original slice. If the average broken chunk is less than three bytes (maybe quite common?) then it'll have to grow the buffer, at least doubling it.
>> let bytestring = b"foobar\xcc";
>> bytestring.len()
7
>> let cleaned = String::from_utf8_lossy(bytestring).into_owned();
>> cleaned.len()
9
>> cleaned.capacity()
14