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 91
#[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>(&'b self, stream: &mut impl WriterStream) -> RootTypeId { if let Some(value) = self { T::write_root(value, stream) } else { RootTypeId::Void } } } #[cfg(feature = "read")] impl<T: Readable> Readable for Option<T> { type ReaderArray = Option<NullableReader<T::ReaderArray>>; fn read(sticks: DynRootBranch<'_>, options: &impl DecodeOptions) -> ReadResult<Self> { match sticks { DynRootBranch::Void => Ok(None), _ => Ok(Some(T::read(sticks, options)?)), } } } #[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, stream: &mut impl WriterStream) -> ArrayTypeId { if let Some(value) = self.value { let opts_id = self.opt.flush(stream); debug_assert_eq!(opts_id, ArrayTypeId::Boolean); stream.write_with_id(|stream| value.flush(stream)); 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<'_>, options: &impl DecodeOptions) -> ReadResult<Self> { match sticks { DynArrayBranch::Nullable { opt, values } => { let (opts, values) = parallel( || decode_packed_bool(&opt).into_iter(), || T::new(*values, options), options ); let values = values?; Ok(Some(NullableReader { opts, values })) } DynArrayBranch::Void => Ok(None), _ => Err(ReadError::SchemaMismatch), } } fn read_next(&mut self) -> Self::Read { if let Some(inner) = self { if inner.opts.read_next() { Some(inner.values.read_next()) } else { None } } else { None } } }