Description
Say type T has a field u of type U and field v of type V.
T and U are both ::protobuf::Message.
I have the following function:
fn foo(t: T) -> Result<U> {
// look into t.v and return Err based on same value
// return Ok(t.u)
}
Even though it seems like I have ownership over t, I can't deconstruct a Message and pass on ownership of the field u.
I recommend adding something similar to the following two extra functions per field
// same as existing
pub fn mut_field(&'a mut self) -> &'a mut T {
if self.status.is_none() {
self.field.set_default();
};
self.field.as_mut().unwrap()
}
// same as existing
pub fn get_field(&'a self) -> &'a T {
self.field.as_ref().unwrap_or_else(|| T::default_instance())
}
// new, the idea is to take the field away from the enclosing message
// ownership is transferred to the caller
pub fn take_field(&mut self) -> T {
// perhaps we should leave a tombstone behind
// the current impl of take refill the value with default
self.field.take().unwrap()
}
// the original message's life ends here,
// ownership of the field is passed on
pub fn unwrap_field(self) -> T {
self.field.unwrap()
}
With the new semantics I can now implement my method by:
fn foo(t: T) -> Result<U> {
let v = t.take_v();
if v.w { Err("Error...") }
else { Ok ( t.unwrap_u() ) }
}
I don't know if this is the correct way of solving the use case, but it makes it possible to implement.
Another option is...
A possible breaking change given that this needs to be implemented for each field is to have a single get_field
that returns Field<T>
and have that wrapper trait surface take()
, unwrap()
, as_ref()
, and as_mut()
(perhaps clone() if T : Clone). I know this is a subset of SingularField
and SingularPtrField
backing the internal Message
.
Honestly, I've seen all those functions being used throughout the std
and other crates, I'm not sure if it's worth bringing it up with the Rust devs but having 4 unique traits that represent each of those operations might clean up a lot of code and allow for certain generic macro sugaring. If I'm not mistaken, Deref and DerefMut cover the signatures for as_ref
and as_mut
as operator overloads which is what is currently available with get_field
and get_mut_field
. I'm not sure if the borrow module is more applicable.