| 31 | } |
| 32 | |
| 33 | fn encode_vectored<'a>(&mut self, i: impl Iterator<Item = &'a Option<T>> + Clone) |
| 34 | where |
| 35 | Option<T>: 'a, |
| 36 | { |
| 37 | // Types with many vectorized encoders benefit from a &[&T] since encode_vectorized is still |
| 38 | // faster even with the extra indirection. TODO vectored encoder count >= 8 instead of size_of. |
| 39 | if std::mem::size_of::<T>() >= 64 { |
| 40 | let mut uninit = MaybeUninit::uninit(); |
| 41 | let mut refs = FastArrayVec::<_, MAX_VECTORED_CHUNK>::new(&mut uninit); |
| 42 | |
| 43 | for t in i { |
| 44 | self.variants.encode(&(t.is_some() as u8)); |
| 45 | if let Some(t) = t { |
| 46 | // Safety: encode_vectored guarantees less than `MAX_VECTORED_CHUNK` items. |
| 47 | unsafe { refs.push_unchecked(t) }; |
| 48 | } |
| 49 | } |
| 50 | |
| 51 | let refs = refs.as_slice(); |
| 52 | let Some(some_count) = NonZeroUsize::new(refs.len()) else { |
| 53 | return; |
| 54 | }; |
| 55 | self.some.reserve(some_count); |
| 56 | self.some.encode_vectored(refs.iter().copied()); |
| 57 | } else { |
| 58 | // Safety: encode_vectored guarantees `i.size_hint().1.unwrap() != 0`. |
| 59 | let size_hint = |
| 60 | unsafe { NonZeroUsize::new(i.size_hint().1.unwrap()).unwrap_unchecked() }; |
| 61 | // size_of::<T>() is small, so we can just assume all elements are Some. |
| 62 | // This will waste a maximum of `MAX_VECTORED_CHUNK * size_of::<T>()` bytes. |
| 63 | self.some.reserve(size_hint); |
| 64 | |
| 65 | for option in i { |
| 66 | self.variants.encode(&(option.is_some() as u8)); |
| 67 | if let Some(t) = option { |
| 68 | self.some.encode(t); |
| 69 | } |
| 70 | } |
| 71 | } |
| 72 | } |
| 73 | } |
| 74 | |
| 75 | impl<T: Encode> Buffer for OptionEncoder<T> { |