aboutsummaryrefslogtreecommitdiff
path: root/src/reflect/optional/mod.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/reflect/optional/mod.rs')
-rw-r--r--src/reflect/optional/mod.rs74
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()),
+ }
+ }
+}