Implement the rest of the v0.6 Optional design

This introduces a new OptionalProxied trait in order to support the needed trait methods.

PiperOrigin-RevId: 546938819
diff --git a/rust/optional.rs b/rust/optional.rs
index 1141dbb..1241f8a 100644
--- a/rust/optional.rs
+++ b/rust/optional.rs
@@ -33,12 +33,11 @@
 #![allow(unused)]
 
 use crate::__internal::Private;
-use crate::{Mut, MutProxy, Proxied, SettableValue, View, ViewProxy};
+use crate::{Mut, MutProxy, Proxied, ProxiedWithPresence, SettableValue, View, ViewProxy};
 use std::convert::{AsMut, AsRef};
 use std::fmt::{self, Debug};
-
-/// The type that will go here is not yet defined.
-pub type Todo<T = ()> = (std::marker::PhantomData<T>, std::convert::Infallible);
+use std::panic;
+use std::ptr;
 
 /// A protobuf value from a field that may not be set.
 ///
@@ -51,13 +50,15 @@
 /// Two `Optional`s are equal if they match both presence and the field values.
 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
 pub enum Optional<SetVal, UnsetVal = SetVal> {
-    /// The field is present. It can be accessed through this `T`.
+    /// The field is set; it is present in the serialized message.
     ///
     /// - For an `_opt()` accessor, this contains a `View<impl Proxied>`.
-    /// - For a `_mut()` accessor, this contains a [`PresentField`].
+    /// - For a `_mut()` accessor, this contains a [`PresentField`] that can be
+    ///   used to access the current value, convert to [`Mut`], clear presence,
+    ///   or set a new value.
     Set(SetVal),
 
-    /// The field is unset.
+    /// The field is unset; it is absent in the serialized message.
     ///
     /// - For an `_opt()` accessor, this contains a `View<impl Proxied>` with
     ///   the default value.
@@ -73,6 +74,11 @@
             Optional::Set(x) | Optional::Unset(x) => x,
         }
     }
+
+    /// Constructs an `Optional<T>` with a `T` value and presence bit.
+    pub fn new(val: T, is_set: bool) -> Self {
+        if is_set { Optional::Set(val) } else { Optional::Unset(val) }
+    }
 }
 
 impl<T, A> Optional<T, A> {
@@ -105,7 +111,7 @@
 /// Methods for `_mut()` accessors of optional types.
 ///
 /// The most common methods are [`set`] and [`or_default`].
-impl<'msg, T: Proxied + ?Sized + 'msg> FieldEntry<'msg, T> {
+impl<'msg, T: ProxiedWithPresence + ?Sized + 'msg> FieldEntry<'msg, T> {
     // is_set() is provided by `impl<T, A> Optional<T, A>`
 
     /// Gets a mutator for this field. Sets to the default value if not set.
@@ -118,30 +124,27 @@
 
     /// Sets the value of this field to `val`.
     ///
-    /// Equivalent to `self.or_default().set(val)`.
+    /// Equivalent to `self.or_default().set(val)`, but does not consume `self`.
     pub fn set(&mut self, val: impl SettableValue<T>) {
-        match self {
-            Optional::Set(x) => x.set(val),
-            Optional::Unset(x) => todo!(),
-        }
+        transform_mut(self, |mut self_| match self_ {
+            Optional::Set(ref mut present) => {
+                present.set(val);
+                self_
+            }
+            Optional::Unset(absent) => Optional::Set(absent.set(val)),
+        })
     }
 
     /// Clears the field; `is_set()` will return `false`.
     pub fn clear(&mut self) {
-        todo!("b/285308646: Requires a trait method")
-    }
-
-    /// Gets an immutable view of this field, using its default value if not
-    /// set.
-    ///
-    /// This has a shorter lifetime than the `field_name()` message accessor;
-    /// `into_view` provides that lifetime.
-    pub fn get(self) -> View<'msg, T> {
-        self.into_view()
+        transform_mut(self, |self_| match self_ {
+            Optional::Set(present) => Optional::Unset(present.clear()),
+            absent => absent,
+        })
     }
 }
 
-impl<'msg, T: Proxied + ?Sized + 'msg> ViewProxy<'msg> for FieldEntry<'msg, T> {
+impl<'msg, T: ProxiedWithPresence + ?Sized + 'msg> ViewProxy<'msg> for FieldEntry<'msg, T> {
     type Proxied = T;
 
     fn as_view(&self) -> View<'_, T> {
@@ -169,20 +172,21 @@
 /// set field.
 pub struct PresentField<'msg, T>
 where
-    T: Proxied + ?Sized + 'msg,
+    T: ProxiedWithPresence + ?Sized + 'msg,
 {
-    inner: Todo<Mut<'msg, T>>,
+    inner: T::PresentMutData<'msg>,
 }
 
-impl<'msg, T: Proxied + ?Sized + 'msg> Debug for PresentField<'msg, T> {
+impl<'msg, T: ProxiedWithPresence + ?Sized + 'msg> Debug for PresentField<'msg, T> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        todo!()
+        self.inner.fmt(f)
     }
 }
 
-impl<'msg, T: Proxied + ?Sized + 'msg> PresentField<'msg, T> {
-    pub fn get(self) -> View<'msg, T> {
-        self.into_view()
+impl<'msg, T: ProxiedWithPresence + ?Sized + 'msg> PresentField<'msg, T> {
+    #[doc(hidden)]
+    pub fn from_inner(_private: Private, inner: T::PresentMutData<'msg>) -> Self {
+        Self { inner }
     }
 
     pub fn set(&mut self, val: impl SettableValue<T>) {
@@ -190,8 +194,8 @@
     }
 
     /// See [`FieldEntry::clear`].
-    pub fn clear(self) -> AbsentField<'msg, T> {
-        todo!("b/285308646: Requires a trait method")
+    pub fn clear(mut self) -> AbsentField<'msg, T> {
+        AbsentField { inner: T::clear_present_field(self.inner) }
     }
 
     // This cannot provide `reborrow` - `clear` consumes after setting the field
@@ -200,35 +204,35 @@
 
 impl<'msg, T> ViewProxy<'msg> for PresentField<'msg, T>
 where
-    T: Proxied + ?Sized + 'msg,
+    T: ProxiedWithPresence + ?Sized + 'msg,
 {
     type Proxied = T;
 
     fn as_view(&self) -> View<'_, T> {
-        todo!("b/285308646: Requires a trait method")
+        self.inner.as_view()
     }
 
     fn into_view<'shorter>(self) -> View<'shorter, T>
     where
         'msg: 'shorter,
     {
-        todo!("b/285308646: Requires a trait method")
+        self.inner.into_view()
     }
 }
 
 impl<'msg, T> MutProxy<'msg> for PresentField<'msg, T>
 where
-    T: Proxied + ?Sized + 'msg,
+    T: ProxiedWithPresence + ?Sized + 'msg,
 {
     fn as_mut(&mut self) -> Mut<'_, T> {
-        todo!("b/285308646: Requires a trait method")
+        self.inner.as_mut()
     }
 
     fn into_mut<'shorter>(self) -> Mut<'shorter, T>
     where
         'msg: 'shorter,
     {
-        todo!("b/285308646: Requires a trait method")
+        self.inner.into_mut()
     }
 }
 
@@ -236,18 +240,23 @@
 /// non-set field.
 pub struct AbsentField<'a, T>
 where
-    T: Proxied + ?Sized + 'a,
+    T: ProxiedWithPresence + ?Sized + 'a,
 {
-    inner: Todo<Option<Mut<'a, T>>>,
+    inner: T::AbsentMutData<'a>,
 }
 
-impl<'msg, T: Proxied + ?Sized + 'msg> Debug for AbsentField<'msg, T> {
+impl<'msg, T: ProxiedWithPresence + ?Sized + 'msg> Debug for AbsentField<'msg, T> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        todo!()
+        self.inner.fmt(f)
     }
 }
 
-impl<'msg, T: Proxied + ?Sized> AbsentField<'msg, T> {
+impl<'msg, T: ProxiedWithPresence + ?Sized> AbsentField<'msg, T> {
+    #[doc(hidden)]
+    pub fn from_inner(_private: Private, inner: T::AbsentMutData<'msg>) -> Self {
+        Self { inner }
+    }
+
     /// Gets the default value for this unset field.
     ///
     /// This is the same value that the primitive accessor would provide.
@@ -258,12 +267,12 @@
     /// See [`FieldEntry::set`]. Note that this consumes and returns a
     /// `PresentField`.
     pub fn set(self, val: impl SettableValue<T>) -> PresentField<'msg, T> {
-        todo!("b/285308646: Requires a trait method")
+        PresentField { inner: val.set_on_absent(Private, self.inner) }
     }
 
     /// Sets this absent field to its default value.
     pub fn set_default(self) -> PresentField<'msg, T> {
-        todo!("b/285308646: Requires a trait method")
+        PresentField { inner: T::set_absent_to_default(self.inner) }
     }
 
     // This cannot provide `reborrow` - `set` consumes after setting the field
@@ -273,18 +282,373 @@
 
 impl<'msg, T> ViewProxy<'msg> for AbsentField<'msg, T>
 where
-    T: Proxied + ?Sized + 'msg,
+    T: ProxiedWithPresence + ?Sized + 'msg,
 {
     type Proxied = T;
 
     fn as_view(&self) -> View<'_, T> {
-        todo!("b/285308646: Requires a trait method")
+        self.inner.as_view()
     }
 
     fn into_view<'shorter>(self) -> View<'shorter, T>
     where
         'msg: 'shorter,
     {
-        todo!("b/285308646: Requires a trait method")
+        self.inner.into_view()
+    }
+}
+
+/// Transforms a mutable reference in-place, treating it as if it were owned.
+///
+/// The program will abort if `transform` panics.
+///
+/// This is the same operation as provided by [`take_mut::take`].
+///
+/// [`take_mut::take`]: https://docs.rs/take_mut/latest/take_mut/fn.take.html
+fn transform_mut<T>(mut_ref: &mut T, transform: impl FnOnce(T) -> T) {
+    #[cold]
+    #[inline(never)]
+    fn panicked_in_transform_mut() -> ! {
+        use std::io::Write as _;
+        let backtrace = std::backtrace::Backtrace::force_capture();
+        let stderr = std::io::stderr();
+        let mut stderr = stderr.lock();
+        let _ = write!(&mut stderr, "BUG: A protobuf mutator panicked! Backtrace:\n{backtrace}\n");
+        let _ = stderr.flush();
+        std::process::abort()
+    }
+
+    // https://play.rust-lang.org/?edition=2021&gist=f3014e1f209013f0a38352e211f4a240
+    // provides a sample test to confirm this operation is sound in Miri.
+    // SAFETY:
+    // - `old_t` is not dropped without also replacing `*mut_ref`, preventing a
+    //   double-free.
+    // - If `transform` panics, the process aborts since `*mut_ref` has no possible
+    //   valid value.
+    // - After `ptr::write`, a valid `T` is located at `*mut_ref`
+    unsafe {
+        let p: *mut T = mut_ref;
+        let old_t = p.read();
+        let new_t = panic::catch_unwind(panic::AssertUnwindSafe(move || transform(old_t)))
+            .unwrap_or_else(|_| panicked_in_transform_mut());
+        p.write(new_t);
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+    use std::borrow::Cow;
+
+    /// A sample message with custom presence bits, meant to mirror a C++
+    /// message.
+    #[derive(Default, Debug)]
+    struct MyMessage {
+        /// has a default of `0`
+        a: i32,
+
+        /// has a default of `5`
+        b: i32,
+
+        /// Packed presence bitfield for `a` and `b`
+        presence: u8,
+    }
+
+    impl MyMessage {
+        fn a(&self) -> View<'_, VtableProxied> {
+            VtableProxiedView { val: get_a(self) }
+        }
+
+        fn a_opt(&self) -> Optional<View<'_, VtableProxied>> {
+            Optional::new(self.a(), has_a(self))
+        }
+
+        fn a_mut(&mut self) -> FieldEntry<'_, VtableProxied> {
+            static A_VTABLE: ProxyVtable =
+                ProxyVtable { get: get_a, set: set_a, clear: clear_a, has: has_a };
+            make_field_entry(self, &A_VTABLE)
+        }
+
+        fn b(&self) -> View<'_, VtableProxied> {
+            VtableProxiedView { val: get_b(self) }
+        }
+
+        fn b_opt(&self) -> Optional<View<'_, VtableProxied>> {
+            Optional::new(self.b(), has_b(self))
+        }
+
+        fn b_mut(&mut self) -> FieldEntry<'_, VtableProxied> {
+            static B_VTABLE: ProxyVtable =
+                ProxyVtable { get: get_b, set: set_b, clear: clear_b, has: has_b };
+            make_field_entry(self, &B_VTABLE)
+        }
+    }
+
+    fn make_field_entry<'a>(
+        msg: &'a mut MyMessage,
+        vtable: &'a ProxyVtable,
+    ) -> FieldEntry<'a, VtableProxied> {
+        if (vtable.has)(&*msg) {
+            Optional::Set(PresentField::from_inner(Private, VtableProxiedMut { msg, vtable }))
+        } else {
+            Optional::Unset(AbsentField::from_inner(Private, VtableProxiedMut { msg, vtable }))
+        }
+    }
+
+    // Thunks used for the vtable. For a C++ message these would be defined in C++
+    // and exported via a C API
+    const A_BIT: u8 = 0;
+    const B_BIT: u8 = 1;
+
+    fn get_a(msg: &MyMessage) -> i32 {
+        if has_a(msg) { msg.a } else { 0 }
+    }
+
+    fn get_b(msg: &MyMessage) -> i32 {
+        if has_b(msg) { msg.b } else { 5 }
+    }
+
+    fn set_a(msg: &mut MyMessage, val: i32) {
+        msg.presence |= (1 << A_BIT);
+        msg.a = val;
+    }
+
+    fn set_b(msg: &mut MyMessage, val: i32) {
+        msg.presence |= (1 << B_BIT);
+        msg.b = val;
+    }
+
+    fn clear_a(msg: &mut MyMessage) {
+        msg.presence &= !(1 << A_BIT);
+    }
+
+    fn clear_b(msg: &mut MyMessage) {
+        msg.presence &= !(1 << B_BIT);
+    }
+
+    fn has_a(msg: &MyMessage) -> bool {
+        msg.presence & (1 << A_BIT) != 0
+    }
+
+    fn has_b(msg: &MyMessage) -> bool {
+        msg.presence & (1 << B_BIT) != 0
+    }
+
+    struct ProxyVtable {
+        get: fn(&MyMessage) -> i32,
+        set: fn(&mut MyMessage, val: i32),
+        clear: fn(&mut MyMessage),
+        has: fn(&MyMessage) -> bool,
+    }
+
+    impl Debug for ProxyVtable {
+        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+            // Manual `Debug` impl to work around `fmt::Debug` not being implemented for
+            // functions pointers with higher-ranked lifetimes, which was fixed
+            // in Rust 1.70.
+            // TODO(hlopko): replace with `#[derive(Debug)]` when rustc is updated.
+            f.debug_struct("ProxyVtable")
+                .field("get", &(self.get as *const ()))
+                .field("set", &(self.set as *const ()))
+                .field("clear", &(self.clear as *const ()))
+                .field("has", &(self.has as *const ()))
+                .finish()
+        }
+    }
+
+    /// A proxy for a `i32` that is accessed through methods on a vtable.
+    struct VtableProxied;
+
+    impl Proxied for VtableProxied {
+        type View<'a> = VtableProxiedView;
+        type Mut<'a> = VtableProxiedMut<'a>;
+    }
+
+    impl ProxiedWithPresence for VtableProxied {
+        // In this case, the `PresentMutData` and `AbsentMutData` are identical to the
+        // `Mut` in layout. Other types/runtimes could require otherwise, e.g. `Mut`
+        // could be defined to only have get/set functions in its vtable, and not
+        // has/clear.
+        type PresentMutData<'a> = VtableProxiedMut<'a>;
+        type AbsentMutData<'a> = VtableProxiedMut<'a>;
+
+        fn clear_present_field<'a>(
+            present_mutator: Self::PresentMutData<'a>,
+        ) -> Self::AbsentMutData<'a> {
+            (present_mutator.vtable.clear)(&mut *present_mutator.msg);
+            present_mutator
+        }
+
+        fn set_absent_to_default<'a>(
+            absent_mutator: Self::AbsentMutData<'a>,
+        ) -> Self::PresentMutData<'a> {
+            absent_mutator.as_view().val().set_on_absent(Private, absent_mutator)
+        }
+    }
+
+    #[derive(Debug, Clone, Copy, PartialEq, Eq)]
+    struct VtableProxiedView {
+        val: i32,
+    }
+
+    impl VtableProxiedView {
+        fn val(&self) -> i32 {
+            self.val
+        }
+
+        fn read(msg: &MyMessage, vtable: &ProxyVtable) -> Self {
+            VtableProxiedView { val: (vtable.get)(msg) }
+        }
+    }
+
+    impl<'a> ViewProxy<'a> for VtableProxiedView {
+        type Proxied = VtableProxied;
+
+        fn as_view(&self) -> View<'a, VtableProxied> {
+            *self
+        }
+
+        fn into_view<'shorter>(self) -> View<'shorter, VtableProxied>
+        where
+            'a: 'shorter,
+        {
+            self
+        }
+    }
+
+    #[derive(Debug)]
+    struct VtableProxiedMut<'a> {
+        msg: &'a mut MyMessage,
+        vtable: &'a ProxyVtable,
+    }
+
+    impl<'a> ViewProxy<'a> for VtableProxiedMut<'a> {
+        type Proxied = VtableProxied;
+
+        fn as_view(&self) -> View<'_, VtableProxied> {
+            VtableProxiedView::read(self.msg, self.vtable)
+        }
+
+        fn into_view<'shorter>(self) -> View<'shorter, VtableProxied>
+        where
+            'a: 'shorter,
+        {
+            VtableProxiedView::read(self.msg, self.vtable)
+        }
+    }
+
+    impl<'a> MutProxy<'a> for VtableProxiedMut<'a> {
+        fn as_mut(&mut self) -> Mut<'_, VtableProxied> {
+            VtableProxiedMut { msg: self.msg, vtable: self.vtable }
+        }
+
+        fn into_mut<'shorter>(self) -> Mut<'shorter, VtableProxied>
+        where
+            'a: 'shorter,
+        {
+            self
+        }
+    }
+
+    impl SettableValue<VtableProxied> for View<'_, VtableProxied> {
+        fn set_on(self, _private: Private, mutator: Mut<VtableProxied>) {
+            self.val().set_on(Private, mutator)
+        }
+
+        fn set_on_absent<'a>(
+            self,
+            _private: Private,
+            absent_mutator: <VtableProxied as ProxiedWithPresence>::AbsentMutData<'a>,
+        ) -> <VtableProxied as ProxiedWithPresence>::PresentMutData<'a> {
+            self.val().set_on_absent(Private, absent_mutator)
+        }
+    }
+
+    impl SettableValue<VtableProxied> for i32 {
+        fn set_on(self, _private: Private, mutator: Mut<VtableProxied>) {
+            (mutator.vtable.set)(mutator.msg, self)
+        }
+
+        fn set_on_absent<'a>(
+            self,
+            _private: Private,
+            absent_mutator: <VtableProxied as ProxiedWithPresence>::AbsentMutData<'a>,
+        ) -> <VtableProxied as ProxiedWithPresence>::PresentMutData<'a> {
+            (absent_mutator.vtable.set)(absent_mutator.msg, self);
+            absent_mutator
+        }
+    }
+
+    #[test]
+    fn test_field_entry() {
+        let mut m1 = MyMessage::default();
+        let mut m2 = MyMessage::default();
+
+        let mut m1_a = m1.a_mut();
+        assert!(matches!(m1_a, Optional::Unset(_)));
+        assert_eq!(m1_a.as_view().val(), 0);
+
+        assert_eq!(m2.b().val(), 5);
+
+        let mut m2_b = m2.b_mut();
+        assert!(m2_b.is_unset());
+        assert_eq!(m2_b.as_view().val(), 5);
+
+        m2_b.set(10);
+        assert!(m2_b.is_set());
+        assert!(matches!(m2_b, Optional::Set(_)));
+        assert_eq!(m2_b.as_view().val(), 10);
+
+        assert_eq!(m1_a.or_default().as_view().val(), 0);
+        assert_eq!(m1.a_opt(), Optional::Set(VtableProxiedView { val: 0 }));
+        m1.a_mut().clear();
+
+        assert_eq!(m1.a().val(), 0);
+        assert_eq!(m1.b().val(), 5);
+        assert_eq!(m2.a().val(), 0);
+        assert_eq!(m2.b().val(), 10);
+    }
+
+    #[test]
+    fn test_present_field() {
+        let mut m = MyMessage::default();
+        m.a_mut().set(10);
+        match m.a_mut() {
+            Optional::Set(mut present) => {
+                assert_eq!(present.as_view().val(), 10);
+                present.set(20);
+                assert_eq!(present.as_view().val(), 20);
+                present.into_mut().set(30);
+            }
+            Optional::Unset(_) => unreachable!(),
+        }
+        assert_eq!(m.a_opt(), Optional::Set(VtableProxiedView { val: 30 }));
+        m.b_mut().set(20);
+        match m.b_mut() {
+            Optional::Set(present) => present.clear(),
+            Optional::Unset(_) => unreachable!(),
+        };
+        assert_eq!(m.b_opt(), Optional::Unset(VtableProxiedView { val: 5 }));
+    }
+
+    #[test]
+    fn test_absent_field() {
+        let mut m = MyMessage::default();
+        match m.a_mut() {
+            Optional::Set(_) => unreachable!(),
+            Optional::Unset(absent) => {
+                assert_eq!(absent.as_view().val(), 0);
+                absent.set(20);
+            }
+        }
+        assert_eq!(m.a_opt(), Optional::Set(VtableProxiedView { val: 20 }));
+        match m.b_mut() {
+            Optional::Set(_) => unreachable!(),
+            Optional::Unset(absent) => {
+                assert_eq!(absent.as_view().val(), 5);
+                absent.set_default();
+            }
+        }
+        assert_eq!(m.b_opt(), Optional::Set(VtableProxiedView { val: 5 }));
     }
 }