Skip to content

Commit

Permalink
Allow clearing field via reflection
Browse files Browse the repository at this point in the history
  • Loading branch information
appaquet authored and stepancheg committed Jun 22, 2022
1 parent a9ca7ed commit d4aa230
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 2 deletions.
39 changes: 37 additions & 2 deletions protobuf/src/reflect/acc/v2/singular/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ pub(crate) trait SingularFieldAccessor: Send + Sync + 'static {
fn get_field<'a>(&self, m: &'a dyn MessageDyn) -> ReflectOptionalRef<'a>;
fn mut_field_or_default<'a>(&self, m: &'a mut dyn MessageDyn) -> ReflectValueMut<'a>;
fn set_field(&self, m: &mut dyn MessageDyn, value: ReflectValueBox);
fn clear_field(&self, m: &mut dyn MessageDyn);
}

pub(crate) struct SingularFieldAccessorHolder {
Expand All @@ -34,23 +35,26 @@ impl SingularFieldAccessorHolder {
get_field: impl for<'a> Fn(&'a M) -> ReflectOptionalRef<'a> + Send + Sync + 'static,
mut_field_or_default: impl for<'a> Fn(&'a mut M) -> ReflectValueMut<'a> + Send + Sync + 'static,
set_field: impl Fn(&mut M, ReflectValueBox) + Send + Sync + 'static,
clear_field: impl Fn(&mut M) + Send + Sync + 'static,
) -> SingularFieldAccessorHolder
where
M: MessageFull,
{
struct Impl<M, G, H, S> {
struct Impl<M, G, H, S, C> {
get_field: G,
mut_field_or_default: H,
set_field: S,
clear_field: C,
_marker: marker::PhantomData<M>,
}

impl<M, G, H, S> SingularFieldAccessor for Impl<M, G, H, S>
impl<M, G, H, S, C> SingularFieldAccessor for Impl<M, G, H, S, C>
where
M: MessageFull,
G: for<'a> Fn(&'a M) -> ReflectOptionalRef<'a> + Send + Sync + 'static,
H: for<'a> Fn(&'a mut M) -> ReflectValueMut<'a> + Send + Sync + 'static,
S: Fn(&mut M, ReflectValueBox) + Send + Sync + 'static,
C: Fn(&mut M) + Send + Sync + 'static,
{
fn get_field<'a>(&self, m: &'a dyn MessageDyn) -> ReflectOptionalRef<'a> {
(self.get_field)(m.downcast_ref::<M>().unwrap())
Expand All @@ -63,13 +67,18 @@ impl SingularFieldAccessorHolder {
fn set_field(&self, m: &mut dyn MessageDyn, value: ReflectValueBox) {
(self.set_field)(m.downcast_mut::<M>().unwrap(), value);
}

fn clear_field(&self, m: &mut dyn MessageDyn) {
(self.clear_field)(m.downcast_mut::<M>().unwrap());
}
}

SingularFieldAccessorHolder {
accessor: Box::new(Impl {
get_field,
mut_field_or_default,
set_field,
clear_field,
_marker: marker::PhantomData,
}),
}
Expand All @@ -90,6 +99,10 @@ impl SingularFieldAccessorHolder {
},
move |m| V::RuntimeType::as_mut((mut_field)(m)),
move |m, value| V::RuntimeType::set_from_value_box((mut_field)(m), value),
move |m| {
let default_value = V::RuntimeType::default_value_ref().to_box();
V::RuntimeType::set_from_value_box((mut_field)(m), default_value);
},
)
}

Expand All @@ -107,6 +120,7 @@ impl SingularFieldAccessorHolder {
move |m, value| {
*(mut_field)(m) = Some(V::RuntimeType::from_value_box(value).expect("wrong type"))
},
move |m| *(mut_field)(m) = None,
)
}

Expand All @@ -131,6 +145,9 @@ impl SingularFieldAccessorHolder {
*(mut_field)(m) =
MessageField::some(V::RuntimeType::from_value_box(value).expect("wrong type"))
},
move |m| {
*(mut_field)(m) = MessageField::none();
},
)
}

Expand Down Expand Up @@ -161,6 +178,9 @@ impl SingularFieldAccessorHolder {
}
_ => panic!("expecting enum value"),
},
move |m| {
(set)(m, EnumOrUnknown::from_i32(0));
},
)
}

Expand All @@ -183,6 +203,11 @@ impl SingularFieldAccessorHolder {
},
|_m| unimplemented!(),
move |m, value| (set)(m, value.downcast::<V>().expect("wrong type")),
move |m| {
if (has)(m) {
(set)(m, V::default());
}
},
)
}

Expand All @@ -208,6 +233,11 @@ impl SingularFieldAccessorHolder {
},
|_m| unimplemented!(),
move |m, value| (set)(m, value.downcast::<V>().expect("message")),
move |m| {
if (has)(m) {
(set)(m, V::default());
}
},
)
}

Expand All @@ -231,6 +261,11 @@ impl SingularFieldAccessorHolder {
},
move |m| F::RuntimeType::as_mut((mut_field)(m)),
move |m, value| (set_field)(m, value.downcast::<F>().expect("message")),
move |m| {
if (has_field)(m) {
(set_field)(m, F::default());
}
},
)
}
}
Expand Down
4 changes: 4 additions & 0 deletions protobuf/src/reflect/field/dynamic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,8 @@ impl<'a> DynamicFieldDescriptorRef<'a> {
pub(crate) fn set_field(&self, message: &mut dyn MessageDyn, value: ReflectValueBox) {
DynamicMessage::downcast_mut(message).set_field(&self.field, value)
}

pub(crate) fn clear_field(&self, message: &mut dyn MessageDyn) {
DynamicMessage::downcast_mut(message).clear_field(&self.field)
}
}
14 changes: 14 additions & 0 deletions protobuf/src/reflect/field/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -438,6 +438,20 @@ impl FieldDescriptor {
}
}

/// Clear a field.
pub fn clear_field(&self, m: &mut dyn MessageDyn) {
if self.is_singular() {
match self.singular() {
SingularFieldAccessorRef::Generated(g) => g.accessor.clear_field(m),
SingularFieldAccessorRef::Dynamic(d) => d.clear_field(m),
}
} else if self.is_repeated() {
self.mut_repeated(m).clear();
} else if self.is_map() {
self.mut_map(m).clear();
}
}

/// Dynamic representation of field type with wire type.
pub(crate) fn protobuf_field_type(&self) -> ProtobufFieldType {
self.index().field_type.resolve(self.file_descriptor())
Expand Down

0 comments on commit d4aa230

Please sign in to comment.