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
use crate::prelude::*; #[cfg(feature = "write")] impl<T: Writable> Writable for Option<T> { type WriterArray = NullableWriter<T::WriterArray>; fn write_root<O: EncodeOptions>(&self, stream: &mut WriterStream<'_, O>) -> 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> { profile!("Readable::read"); match sticks { DynRootBranch::Void => Ok(None), _ => Ok(Some(T::read(sticks, options)?)), } } } #[cfg(feature = "write")] #[derive(Default)] pub struct NullableWriter<V> { opt: <bool as Writable>::WriterArray, value: Option<V>, } #[cfg(feature = "write")] impl<T: Writable> WriterArray<Option<T>> for NullableWriter<T::WriterArray> { fn buffer<'a, 'b: 'a>(&'a mut self, value: &'b Option<T>) { self.opt.buffer(&value.is_some()); if let Some(value) = value { self.value.get_or_insert_with(T::WriterArray::default).buffer(value); } } fn flush<O: EncodeOptions>(self, stream: &mut WriterStream<'_, O>) -> ArrayTypeId { let Self { opt, value } = self; if let Some(value) = value { stream.write_with_id(|stream| opt.flush(stream)); 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>; type Error = T::Error; fn new(sticks: DynArrayBranch<'_>, options: &impl DecodeOptions) -> ReadResult<Self> { profile!("ReaderArray::new"); match sticks { DynArrayBranch::Nullable { opt, values } => { let (opts, values) = parallel(|| <bool as Readable>::ReaderArray::new(*opt, options), || T::new(*values, options), options); let opts = opts?; let values = values?; Ok(Some(NullableReader { opts, values })) } DynArrayBranch::Void => Ok(None), _ => Err(ReadError::SchemaMismatch), } } fn read_next(&mut self) -> Result<Self::Read, Self::Error> { Ok(if let Some(inner) = self { if inner.opts.read_next_infallible() { Some(inner.values.read_next()?) } else { None } } else { None }) } }