diff options
Diffstat (limited to 'src/reflect/optional/mod.rs')
-rw-r--r-- | src/reflect/optional/mod.rs | 74 |
1 files changed, 74 insertions, 0 deletions
diff --git a/src/reflect/optional/mod.rs b/src/reflect/optional/mod.rs new file mode 100644 index 0000000..9d34a30 --- /dev/null +++ b/src/reflect/optional/mod.rs @@ -0,0 +1,74 @@ +use crate::reflect::runtime_types::RuntimeTypeTrait; +use crate::reflect::ProtobufValue; +use crate::reflect::ReflectEq; +use crate::reflect::ReflectEqMode; +use crate::reflect::ReflectValueRef; +use crate::reflect::RuntimeType; + +enum Impl<'a> { + None(RuntimeType), + Some(ReflectValueRef<'a>), +} + +/// Singular field field and value type. +pub struct ReflectOptionalRef<'a>(Impl<'a>); + +impl<'a> PartialEq for ReflectOptionalRef<'a> { + fn eq(&self, other: &Self) -> bool { + self.reflect_eq(other, &ReflectEqMode::default()) + } +} + +impl<'a> ReflectEq for ReflectOptionalRef<'a> { + fn reflect_eq(&self, that: &Self, mode: &ReflectEqMode) -> bool { + match (&self.0, &that.0) { + (Impl::None(at), Impl::None(bt)) => at == bt, + (Impl::Some(a), Impl::Some(b)) => a.reflect_eq(b, mode), + (Impl::None(_), Impl::Some(_)) | (Impl::Some(_), Impl::None(_)) => false, + } + } +} + +impl<'a> ReflectOptionalRef<'a> { + /// No value. + pub fn none(elem: RuntimeType) -> ReflectOptionalRef<'a> { + ReflectOptionalRef(Impl::None(elem)) + } + + /// Has value. + pub fn some(value: ReflectValueRef<'a>) -> ReflectOptionalRef<'a> { + ReflectOptionalRef(Impl::Some(value)) + } + + pub(crate) fn none_from<V: ProtobufValue>() -> ReflectOptionalRef<'a> { + ReflectOptionalRef::none(V::RuntimeType::runtime_type_box()) + } + + pub(crate) fn some_from<V: ProtobufValue>(value: &'a V) -> ReflectOptionalRef<'a> { + ReflectOptionalRef::some(V::RuntimeType::as_ref(value)) + } + + pub(crate) fn new_filter_non_zero<V: ProtobufValue>(v: &'a V) -> ReflectOptionalRef<'a> { + if V::RuntimeType::is_non_zero(v) { + ReflectOptionalRef::some_from(v) + } else { + ReflectOptionalRef::none_from::<V>() + } + } + + pub(crate) fn new_from_option<V: ProtobufValue>(v: Option<&'a V>) -> ReflectOptionalRef<'a> { + if let Some(v) = v { + ReflectOptionalRef::some_from(v) + } else { + ReflectOptionalRef::none_from::<V>() + } + } + + /// Obtain the value, drop the type. + pub fn value(&self) -> Option<ReflectValueRef<'a>> { + match &self.0 { + Impl::None(_) => None, + Impl::Some(v) => Some(v.clone()), + } + } +} |