diff --git a/src/encoder.rs b/src/encoder.rs index 968a730..a41d340 100644 --- a/src/encoder.rs +++ b/src/encoder.rs @@ -16,20 +16,20 @@ pub trait Encoder { return Ok(src.into()); } let len = s.chars().count(); - let mut res = Vec::::with_capacity(len); + let mut res = Vec::with_capacity(len); - let res_ptr = res.as_mut_ptr(); + // extend uses iterator size hint to skip per-element capacity checks + res.extend( + (0..len) + .map(|_| self.encode_grapheme(&mut src).or(fallback)) + .flatten(), + ); - for i in 0..len { - let byte = self - .encode_grapheme(&mut src) - .or(fallback) - .ok_or(EncodeError {})?; - unsafe { *res_ptr.add(i) = byte }; + // If any encoding failed, we got fewer bytes than expected + if res.len() != len { + return Err(EncodeError {}); } - // Safety: len is calculated for graphemes, and `res` is now fully initialized. - unsafe { res.set_len(len) }; Ok(res.into()) } }