1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90
#[cfg(feature = "read")] use crate::internal::encodings::packed_bool::decode_packed_bool; use crate::prelude::*; #[cfg(feature = "write")] impl<'a, T: Writable<'a>> Writable<'a> for Option<T> { type WriterArray = NullableWriter<'a, T::WriterArray>; fn write_root<'b: 'a>(value: &'b Self, bytes: &mut Vec<u8>, lens: &mut Vec<usize>) -> RootTypeId { if let Some(value) = value { T::write_root(value, bytes, lens) } else { RootTypeId::Void } } } #[cfg(feature = "read")] impl<T: Readable> Readable for Option<T> { type ReaderArray = Option<NullableReader<T::ReaderArray>>; fn read(sticks: DynRootBranch<'_>) -> ReadResult<Self> { match sticks { DynRootBranch::Void => Ok(None), _ => Ok(Some(T::read(sticks)?)), } } } #[cfg(feature = "write")] #[derive(Default)] pub struct NullableWriter<'a, V> { opt: <bool as Writable<'a>>::WriterArray, value: Option<V>, } #[cfg(feature = "write")] impl<'a, T: WriterArray<'a>> WriterArray<'a> for NullableWriter<'a, T> { type Write = Option<T::Write>; fn buffer<'b: 'a>(&mut self, value: &'b Self::Write) { self.opt.buffer(&value.is_some()); if let Some(value) = value { self.value.get_or_insert_with(T::default).buffer(value); } } fn flush(self, bytes: &mut Vec<u8>, lens: &mut Vec<usize>) -> ArrayTypeId { if let Some(value) = self.value { let opts_id = self.opt.flush(bytes, lens); debug_assert_eq!(opts_id, ArrayTypeId::Boolean); let type_index = bytes.len(); bytes.push(0); let type_id = value.flush(bytes, lens); bytes[type_index] = type_id.into(); ArrayTypeId::Nullable } else { ArrayTypeId::Void } } } #[cfg(feature = "read")] pub struct NullableReader<T> { opts: <bool as Readable>::ReaderArray, values: T, } #[cfg(feature = "read")] impl<T: ReaderArray> ReaderArray for Option<NullableReader<T>> { type Read = Option<T::Read>; fn new(sticks: DynArrayBranch<'_>) -> ReadResult<Self> { match sticks { DynArrayBranch::Nullable { opt, values } => { let opts = decode_packed_bool(opt).into_iter(); let values = T::new(*values)?; Ok(Some(NullableReader { opts, values })) } DynArrayBranch::Void => Ok(None), _ => Err(ReadError::SchemaMismatch), } } fn read_next(&mut self) -> ReadResult<Self::Read> { if let Some(inner) = self { if inner.opts.read_next()? { Ok(Some(inner.values.read_next()?)) } else { Ok(None) } } else { Ok(None) } } }