#![allow(dead_code)]
#![allow(unused)]
use crate::__internal::Private;
use crate::{Mut, MutProxy, Proxied, ProxiedWithPresence, SettableValue, View, ViewProxy};
use std::convert::{AsMut, AsRef};
use std::fmt::{self, Debug};
use std::panic;
use std::ptr;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Optional<SetVal, UnsetVal = SetVal> {
Set(SetVal),
Unset(UnsetVal),
}
impl<T> Optional<T> {
pub fn into_inner(self) -> T {
match self {
Optional::Set(x) | Optional::Unset(x) => x,
}
}
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> {
pub fn into_option(self) -> Option<T> {
if let Optional::Set(x) = self { Some(x) } else { None }
}
pub fn is_set(&self) -> bool {
matches!(self, Optional::Set(_))
}
pub fn is_unset(&self) -> bool {
matches!(self, Optional::Unset(_))
}
}
impl<T> From<Optional<T>> for Option<T> {
fn from(x: Optional<T>) -> Option<T> {
x.into_option()
}
}
pub type FieldEntry<'msg, T> = Optional<PresentField<'msg, T>, AbsentField<'msg, T>>;
impl<'msg, T: ProxiedWithPresence + ?Sized + 'msg> FieldEntry<'msg, T> {
pub fn or_default(self) -> Mut<'msg, T> {
match self {
Optional::Set(x) => x.into_mut(),
Optional::Unset(x) => x.set_default().into_mut(),
}
}
pub fn or_set(self, val: impl SettableValue<T>) -> Mut<'msg, T> {
self.or_set_with(move || val)
}
pub fn or_set_with<S>(self, val: impl FnOnce() -> S) -> Mut<'msg, T>
where
S: SettableValue<T>,
{
match self {
Optional::Set(x) => x.into_mut(),
Optional::Unset(x) => x.set(val()).into_mut(),
}
}
pub fn set(&mut self, val: impl SettableValue<T>) {
transform_mut(self, |mut self_| match self_ {
Optional::Set(ref mut present) => {
present.set(val);
self_
}
Optional::Unset(absent) => Optional::Set(absent.set(val)),
})
}
pub fn clear(&mut self) {
transform_mut(self, |self_| match self_ {
Optional::Set(present) => Optional::Unset(present.clear()),
absent => absent,
})
}
pub fn get(&self) -> View<'_, T> {
self.as_view()
}
pub fn into_optional_view(self) -> Optional<View<'msg, T>> {
let is_set = self.is_set();
Optional::new(self.into_view(), is_set)
}
pub fn try_into_mut(self) -> Option<Mut<'msg, T>> {
match self {
Optional::Set(x) => Some(x.into_mut()),
Optional::Unset(_) => None,
}
}
}
impl<'msg, T: ProxiedWithPresence + ?Sized + 'msg> ViewProxy<'msg> for FieldEntry<'msg, T> {
type Proxied = T;
fn as_view(&self) -> View<'_, T> {
match self {
Optional::Set(x) => x.as_view(),
Optional::Unset(x) => x.as_view(),
}
}
fn into_view<'shorter>(self) -> View<'shorter, T>
where
'msg: 'shorter,
{
match self {
Optional::Set(x) => x.into_view(),
Optional::Unset(x) => x.into_view(),
}
}
}
pub struct PresentField<'msg, T>
where
T: ProxiedWithPresence + ?Sized + 'msg,
{
pub(crate) inner: T::PresentMutData<'msg>,
}
impl<'msg, T: ProxiedWithPresence + ?Sized + 'msg> Debug for PresentField<'msg, T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.inner.fmt(f)
}
}
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 get(&self) -> View<'_, T> {
self.as_view()
}
pub fn set(&mut self, val: impl SettableValue<T>) {
val.set_on(Private, self.as_mut())
}
pub fn clear(mut self) -> AbsentField<'msg, T> {
AbsentField { inner: T::clear_present_field(self.inner) }
}
}
impl<'msg, T> ViewProxy<'msg> for PresentField<'msg, T>
where
T: ProxiedWithPresence + ?Sized + 'msg,
{
type Proxied = T;
fn as_view(&self) -> View<'_, T> {
self.inner.as_view()
}
fn into_view<'shorter>(self) -> View<'shorter, T>
where
'msg: 'shorter,
{
self.inner.into_view()
}
}
impl<'msg, T> MutProxy<'msg> for PresentField<'msg, T>
where
T: ProxiedWithPresence + ?Sized + 'msg,
{
fn as_mut(&mut self) -> Mut<'_, T> {
self.inner.as_mut()
}
fn into_mut<'shorter>(self) -> Mut<'shorter, T>
where
'msg: 'shorter,
{
self.inner.into_mut()
}
}
pub struct AbsentField<'msg, T>
where
T: ProxiedWithPresence + ?Sized + 'msg,
{
pub(crate) inner: T::AbsentMutData<'msg>,
}
impl<'msg, T: ProxiedWithPresence + ?Sized + 'msg> Debug for AbsentField<'msg, T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.inner.fmt(f)
}
}
impl<'msg, T: ProxiedWithPresence + ?Sized> AbsentField<'msg, T> {
#[doc(hidden)]
pub fn from_inner(_private: Private, inner: T::AbsentMutData<'msg>) -> Self {
Self { inner }
}
pub fn default_value(&self) -> View<'_, T> {
self.as_view()
}
pub fn set(self, val: impl SettableValue<T>) -> PresentField<'msg, T> {
PresentField { inner: val.set_on_absent(Private, self.inner) }
}
pub fn set_default(self) -> PresentField<'msg, T> {
PresentField { inner: T::set_absent_to_default(self.inner) }
}
}
impl<'msg, T> ViewProxy<'msg> for AbsentField<'msg, T>
where
T: ProxiedWithPresence + ?Sized + 'msg,
{
type Proxied = T;
fn as_view(&self) -> View<'_, T> {
self.inner.as_view()
}
fn into_view<'shorter>(self) -> View<'shorter, T>
where
'msg: 'shorter,
{
self.inner.into_view()
}
}
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()
}
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;
#[derive(Default, Debug)]
struct MyMessage {
a: i32,
b: i32,
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<'msg>(
msg: &'msg mut MyMessage,
vtable: &'msg ProxyVtable,
) -> FieldEntry<'msg, VtableProxied> {
if (vtable.has)(&*msg) {
Optional::Set(PresentField::from_inner(Private, VtableProxiedMut { msg, vtable }))
} else {
Optional::Unset(AbsentField::from_inner(Private, VtableProxiedMut { msg, vtable }))
}
}
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
}
#[derive(Debug)]
struct ProxyVtable {
get: fn(&MyMessage) -> i32,
set: fn(&mut MyMessage, val: i32),
clear: fn(&mut MyMessage),
has: fn(&MyMessage) -> bool,
}
struct VtableProxied;
impl Proxied for VtableProxied {
type View<'msg> = VtableProxiedView;
type Mut<'msg> = VtableProxiedMut<'msg>;
}
impl ProxiedWithPresence for VtableProxied {
type PresentMutData<'msg> = VtableProxiedMut<'msg>;
type AbsentMutData<'msg> = VtableProxiedMut<'msg>;
fn clear_present_field<'msg>(
present_mutator: Self::PresentMutData<'msg>,
) -> Self::AbsentMutData<'msg> {
(present_mutator.vtable.clear)(&mut *present_mutator.msg);
present_mutator
}
fn set_absent_to_default<'msg>(
absent_mutator: Self::AbsentMutData<'msg>,
) -> Self::PresentMutData<'msg> {
SettableValue::<VtableProxied>::set_on_absent(
absent_mutator.as_view().val(),
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<'msg> ViewProxy<'msg> for VtableProxiedView {
type Proxied = VtableProxied;
fn as_view(&self) -> View<'msg, VtableProxied> {
*self
}
fn into_view<'shorter>(self) -> View<'shorter, VtableProxied>
where
'msg: 'shorter,
{
self
}
}
#[derive(Debug)]
struct VtableProxiedMut<'msg> {
msg: &'msg mut MyMessage,
vtable: &'msg ProxyVtable,
}
impl<'msg> ViewProxy<'msg> for VtableProxiedMut<'msg> {
type Proxied = VtableProxied;
fn as_view(&self) -> View<'_, VtableProxied> {
VtableProxiedView::read(self.msg, self.vtable)
}
fn into_view<'shorter>(self) -> View<'shorter, VtableProxied>
where
'msg: 'shorter,
{
VtableProxiedView::read(self.msg, self.vtable)
}
}
impl<'msg> MutProxy<'msg> for VtableProxiedMut<'msg> {
fn as_mut(&mut self) -> Mut<'_, VtableProxied> {
VtableProxiedMut { msg: self.msg, vtable: self.vtable }
}
fn into_mut<'shorter>(self) -> Mut<'shorter, VtableProxied>
where
'msg: 'shorter,
{
self
}
}
impl SettableValue<VtableProxied> for View<'_, VtableProxied> {
fn set_on<'msg>(self, _private: Private, mutator: Mut<'msg, VtableProxied>)
where
VtableProxied: 'msg,
{
SettableValue::<VtableProxied>::set_on(self.val(), Private, mutator)
}
fn set_on_absent<'msg>(
self,
_private: Private,
absent_mutator: <VtableProxied as ProxiedWithPresence>::AbsentMutData<'msg>,
) -> <VtableProxied as ProxiedWithPresence>::PresentMutData<'msg> {
SettableValue::<VtableProxied>::set_on_absent(self.val(), Private, absent_mutator)
}
}
impl SettableValue<VtableProxied> for i32 {
fn set_on<'msg>(self, _private: Private, mutator: Mut<'msg, VtableProxied>)
where
VtableProxied: 'msg,
{
(mutator.vtable.set)(mutator.msg, self)
}
fn set_on_absent<'msg>(
self,
_private: Private,
absent_mutator: <VtableProxied as ProxiedWithPresence>::AbsentMutData<'msg>,
) -> <VtableProxied as ProxiedWithPresence>::PresentMutData<'msg> {
(absent_mutator.vtable.set)(absent_mutator.msg, self);
absent_mutator
}
}
#[test]
fn test_field_entry() {
use googletest::prelude::*;
let mut m1 = MyMessage::default();
let mut m2 = MyMessage::default();
let mut m1_a = m1.a_mut();
assert_that!(m1_a, matches_pattern!(Optional::Unset(_)));
assert_that!(m1_a.as_view().val(), eq(0));
assert_that!(m2.b().val(), eq(5));
let mut m2_b = m2.b_mut();
assert_that!(m2_b.is_unset(), eq(true));
assert_that!(m2_b.as_view().val(), eq(5));
m2_b.set(10);
assert_that!(m2_b.is_set(), eq(true));
assert_that!(m2_b, matches_pattern!(Optional::Set(_)));
assert_that!(m2_b.as_view().val(), eq(10));
assert_that!(m1_a.or_default().as_view().val(), eq(0));
assert_that!(m1.a_opt(), eq(Optional::Set(VtableProxiedView { val: 0 })));
m1.a_mut().clear();
assert_that!(m1.a().val(), eq(0));
assert_that!(m1.b().val(), eq(5));
assert_that!(m2.a().val(), eq(0));
assert_that!(m2.b().val(), eq(10));
}
#[test]
fn test_or_set() {
use googletest::prelude::*;
let mut m1 = MyMessage::default();
let mut m2 = MyMessage::default();
assert_that!(m1.a_mut().or_set(10).get().val(), eq(10));
assert_that!(m1.a_opt(), eq(Optional::Set(VtableProxiedView { val: 10 })));
assert_that!(m1.a_mut().or_set(20).get().val(), eq(10));
assert_that!(m1.a_opt(), eq(Optional::Set(VtableProxiedView { val: 10 })));
assert_that!(m2.a_mut().or_set_with(|| m1.a().val() + m1.b().val()).get().val(), eq(15));
assert_that!(m2.a_opt(), eq(Optional::Set(VtableProxiedView { val: 15 })));
assert_that!(m2.a_mut().or_set_with(|| None::<i32>.unwrap()).get().val(), eq(15));
assert_that!(m2.a_opt(), eq(Optional::Set(VtableProxiedView { val: 15 })));
}
#[test]
fn test_into_optional_view() {
use googletest::prelude::*;
let mut m1 = MyMessage::default();
assert_that!(
m1.a_mut().into_optional_view(),
eq(Optional::Unset(VtableProxiedView { val: 0 }))
);
m1.a_mut().set(10);
assert_that!(
m1.a_mut().into_optional_view(),
eq(Optional::Set(VtableProxiedView { val: 10 }))
);
assert_that!(
m1.b_mut().into_optional_view(),
eq(Optional::Unset(VtableProxiedView { val: 5 }))
);
}
#[test]
fn test_try_into_mut() {
use googletest::prelude::*;
let mut m1 = MyMessage::default();
assert_that!(m1.a_mut().try_into_mut().is_none(), eq(true));
m1.a_mut().set(10);
let mut a_mut = m1.a_mut().try_into_mut().expect("field to be set");
a_mut.set(20);
assert_that!(m1.a().val(), eq(20));
}
#[test]
fn test_present_field() {
use googletest::prelude::*;
let mut m = MyMessage::default();
m.a_mut().set(10);
match m.a_mut() {
Optional::Set(mut present) => {
assert_that!(present.as_view().val(), eq(10));
present.set(20);
assert_that!(present.as_view().val(), eq(20));
present.into_mut().set(30);
}
Optional::Unset(_) => unreachable!(),
}
assert_that!(m.a_opt(), eq(Optional::Set(VtableProxiedView { val: 30 })));
m.b_mut().set(20);
match m.b_mut() {
Optional::Set(present) => present.clear(),
Optional::Unset(_) => unreachable!(),
};
assert_that!(m.b_opt(), eq(Optional::Unset(VtableProxiedView { val: 5 })));
}
#[test]
fn test_absent_field() {
use googletest::prelude::*;
let mut m = MyMessage::default();
match m.a_mut() {
Optional::Set(_) => unreachable!(),
Optional::Unset(absent) => {
assert_that!(absent.as_view().val(), eq(0));
absent.set(20);
}
}
assert_that!(m.a_opt(), eq(Optional::Set(VtableProxiedView { val: 20 })));
match m.b_mut() {
Optional::Set(_) => unreachable!(),
Optional::Unset(absent) => {
assert_that!(absent.as_view().val(), eq(5));
absent.set_default();
}
}
assert_that!(m.b_opt(), eq(Optional::Set(VtableProxiedView { val: 5 })));
}
}