blob: ba9955b62c8045c0d4b30fb933297cce68a82c38 [file] [log] [blame]
Protobuf Team Bot263248e2023-06-22 09:14:12 -07001// Protocol Buffers - Google's data interchange format
Hong Shin4f20efb2023-07-10 07:35:36 -07002// Copyright 2023 Google LLC. All rights reserved.
Protobuf Team Bot263248e2023-06-22 09:14:12 -07003//
Joshua Haberman4a513032023-09-08 17:12:50 -07004// Use of this source code is governed by a BSD-style
5// license that can be found in the LICENSE file or at
6// https://developers.google.com/open-source/licenses/bsd
Protobuf Team Bot263248e2023-06-22 09:14:12 -07007
8//! Items specific to `optional` fields.
9#![allow(dead_code)]
10#![allow(unused)]
11
Protobuf Team Bot29a26152023-06-22 09:51:38 -070012use crate::__internal::Private;
Protobuf Team Bot0d7a3962023-07-10 11:51:22 -070013use crate::{Mut, MutProxy, Proxied, ProxiedWithPresence, SettableValue, View, ViewProxy};
Protobuf Team Bot263248e2023-06-22 09:14:12 -070014use std::convert::{AsMut, AsRef};
15use std::fmt::{self, Debug};
Protobuf Team Bot0d7a3962023-07-10 11:51:22 -070016use std::panic;
17use std::ptr;
Protobuf Team Bot263248e2023-06-22 09:14:12 -070018
19/// A protobuf value from a field that may not be set.
20///
21/// This can be pattern matched with `match` or `if let` to determine if the
22/// field is set and access the field data.
23///
24/// [`FieldEntry`], a specific type alias for `Optional`, provides much of the
25/// functionality for this type.
26///
27/// Two `Optional`s are equal if they match both presence and the field values.
28#[derive(Debug, Clone, Copy, PartialEq, Eq)]
29pub enum Optional<SetVal, UnsetVal = SetVal> {
Protobuf Team Bot0d7a3962023-07-10 11:51:22 -070030 /// The field is set; it is present in the serialized message.
Protobuf Team Bot263248e2023-06-22 09:14:12 -070031 ///
32 /// - For an `_opt()` accessor, this contains a `View<impl Proxied>`.
Protobuf Team Bot0d7a3962023-07-10 11:51:22 -070033 /// - For a `_mut()` accessor, this contains a [`PresentField`] that can be
34 /// used to access the current value, convert to [`Mut`], clear presence,
35 /// or set a new value.
Protobuf Team Bot263248e2023-06-22 09:14:12 -070036 Set(SetVal),
37
Protobuf Team Bot0d7a3962023-07-10 11:51:22 -070038 /// The field is unset; it is absent in the serialized message.
Protobuf Team Bot263248e2023-06-22 09:14:12 -070039 ///
40 /// - For an `_opt()` accessor, this contains a `View<impl Proxied>` with
41 /// the default value.
42 /// - For a `_mut()` accessor, this contains an [`AbsentField`] that can be
43 /// used to access the default or set a new value.
44 Unset(UnsetVal),
45}
46
47impl<T> Optional<T> {
48 /// Gets the field value, ignoring whether it was set or not.
49 pub fn into_inner(self) -> T {
50 match self {
51 Optional::Set(x) | Optional::Unset(x) => x,
52 }
53 }
Protobuf Team Bot0d7a3962023-07-10 11:51:22 -070054
55 /// Constructs an `Optional<T>` with a `T` value and presence bit.
56 pub fn new(val: T, is_set: bool) -> Self {
57 if is_set { Optional::Set(val) } else { Optional::Unset(val) }
58 }
Protobuf Team Bot263248e2023-06-22 09:14:12 -070059}
60
61impl<T, A> Optional<T, A> {
62 /// Converts into an `Option` of the set value, ignoring any unset value.
63 pub fn into_option(self) -> Option<T> {
64 if let Optional::Set(x) = self { Some(x) } else { None }
65 }
66
67 /// Returns if the field is set.
68 pub fn is_set(&self) -> bool {
69 matches!(self, Optional::Set(_))
70 }
71
72 /// Returns if the field is unset.
73 pub fn is_unset(&self) -> bool {
74 matches!(self, Optional::Unset(_))
75 }
76}
77
78impl<T> From<Optional<T>> for Option<T> {
79 fn from(x: Optional<T>) -> Option<T> {
80 x.into_option()
81 }
82}
83
84/// A mutable view into the value of an optional field, which may be set or
85/// unset.
86pub type FieldEntry<'a, T> = Optional<PresentField<'a, T>, AbsentField<'a, T>>;
87
88/// Methods for `_mut()` accessors of optional types.
89///
90/// The most common methods are [`set`] and [`or_default`].
Protobuf Team Bot0d7a3962023-07-10 11:51:22 -070091impl<'msg, T: ProxiedWithPresence + ?Sized + 'msg> FieldEntry<'msg, T> {
Protobuf Team Bot263248e2023-06-22 09:14:12 -070092 // is_set() is provided by `impl<T, A> Optional<T, A>`
93
94 /// Gets a mutator for this field. Sets to the default value if not set.
95 pub fn or_default(self) -> Mut<'msg, T> {
96 match self {
97 Optional::Set(x) => x.into_mut(),
98 Optional::Unset(x) => x.set_default().into_mut(),
99 }
100 }
101
Protobuf Team Botd42b2372023-07-10 18:24:33 -0700102 /// Gets a mutator for this field. Sets to the given `val` if not set.
103 ///
104 /// If the field is already set, `val` is ignored.
105 pub fn or_set(self, val: impl SettableValue<T>) -> Mut<'msg, T> {
106 self.or_set_with(move || val)
107 }
108
109 /// Gets a mutator for this field. Sets using the given `val` function if
110 /// not set.
111 ///
112 /// If the field is already set, `val` is not invoked.
113 pub fn or_set_with<S>(self, val: impl FnOnce() -> S) -> Mut<'msg, T>
114 where
115 S: SettableValue<T>,
116 {
117 match self {
118 Optional::Set(x) => x.into_mut(),
119 Optional::Unset(x) => x.set(val()).into_mut(),
120 }
121 }
122
Protobuf Team Bot263248e2023-06-22 09:14:12 -0700123 /// Sets the value of this field to `val`.
124 ///
Protobuf Team Bot0d7a3962023-07-10 11:51:22 -0700125 /// Equivalent to `self.or_default().set(val)`, but does not consume `self`.
Protobuf Team Botd42b2372023-07-10 18:24:33 -0700126 ///
127 /// `set` has the same parameters as in [`MutProxy`], so making a field
128 /// `optional` will switch to using this method. This makes transitioning
129 /// from implicit to explicit presence easier.
Protobuf Team Bot29a26152023-06-22 09:51:38 -0700130 pub fn set(&mut self, val: impl SettableValue<T>) {
Protobuf Team Bot0d7a3962023-07-10 11:51:22 -0700131 transform_mut(self, |mut self_| match self_ {
132 Optional::Set(ref mut present) => {
133 present.set(val);
134 self_
135 }
136 Optional::Unset(absent) => Optional::Set(absent.set(val)),
137 })
Protobuf Team Bot263248e2023-06-22 09:14:12 -0700138 }
139
140 /// Clears the field; `is_set()` will return `false`.
141 pub fn clear(&mut self) {
Protobuf Team Bot0d7a3962023-07-10 11:51:22 -0700142 transform_mut(self, |self_| match self_ {
143 Optional::Set(present) => Optional::Unset(present.clear()),
144 absent => absent,
145 })
Protobuf Team Bot263248e2023-06-22 09:14:12 -0700146 }
Protobuf Team Botd42b2372023-07-10 18:24:33 -0700147
148 /// Gets an immutable view of this field, using its default value if not
149 /// set. This is shorthand for `as_view`.
150 ///
151 /// This provides a shorter lifetime than `into_view` but can also be called
152 /// multiple times - if the result of `get` is not living long enough
153 /// for your use, use that instead.
154 ///
155 /// `get` has the same parameters as in [`MutProxy`], so making a field
156 /// `optional` will switch to using this method. This makes transitioning
157 /// from implicit to explicit presence easier.
158 pub fn get(&self) -> View<'_, T> {
159 self.as_view()
160 }
161
162 /// Converts to an immutable view of this optional field, preserving the
163 /// field's presence.
164 pub fn into_optional_view(self) -> Optional<View<'msg, T>> {
165 let is_set = self.is_set();
166 Optional::new(self.into_view(), is_set)
167 }
168
169 /// Returns a field mutator if the field is set.
170 ///
171 /// Returns `None` if the field is not set. This does not affect `is_set()`.
172 ///
173 /// This returns `Option` and _not_ `Optional` since returning a defaulted
174 /// `Mut` would require mutating the presence of the field - for that
175 /// behavior, use `or_default()`.
176 pub fn try_into_mut(self) -> Option<Mut<'msg, T>> {
177 match self {
178 Optional::Set(x) => Some(x.into_mut()),
179 Optional::Unset(_) => None,
180 }
181 }
Protobuf Team Bot263248e2023-06-22 09:14:12 -0700182}
183
Protobuf Team Bot0d7a3962023-07-10 11:51:22 -0700184impl<'msg, T: ProxiedWithPresence + ?Sized + 'msg> ViewProxy<'msg> for FieldEntry<'msg, T> {
Protobuf Team Bot263248e2023-06-22 09:14:12 -0700185 type Proxied = T;
186
187 fn as_view(&self) -> View<'_, T> {
188 match self {
189 Optional::Set(x) => x.as_view(),
190 Optional::Unset(x) => x.as_view(),
191 }
192 }
193
194 fn into_view<'shorter>(self) -> View<'shorter, T>
195 where
196 'msg: 'shorter,
197 {
198 match self {
199 Optional::Set(x) => x.into_view(),
200 Optional::Unset(x) => x.into_view(),
201 }
202 }
203}
204
205// `MutProxy` not implemented for `FieldEntry` since the field may not be set,
206// and `as_mut`/`into_mut` should not insert.
207
208/// A field mutator capable of clearing that is statically known to point to a
209/// set field.
210pub struct PresentField<'msg, T>
211where
Protobuf Team Bot0d7a3962023-07-10 11:51:22 -0700212 T: ProxiedWithPresence + ?Sized + 'msg,
Protobuf Team Bot263248e2023-06-22 09:14:12 -0700213{
Alyssa Haroldsen614e29f2023-08-30 12:51:55 -0700214 pub(crate) inner: T::PresentMutData<'msg>,
Protobuf Team Bot263248e2023-06-22 09:14:12 -0700215}
216
Protobuf Team Bot0d7a3962023-07-10 11:51:22 -0700217impl<'msg, T: ProxiedWithPresence + ?Sized + 'msg> Debug for PresentField<'msg, T> {
Protobuf Team Bot263248e2023-06-22 09:14:12 -0700218 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
Protobuf Team Bot0d7a3962023-07-10 11:51:22 -0700219 self.inner.fmt(f)
Protobuf Team Bot263248e2023-06-22 09:14:12 -0700220 }
221}
222
Protobuf Team Bot0d7a3962023-07-10 11:51:22 -0700223impl<'msg, T: ProxiedWithPresence + ?Sized + 'msg> PresentField<'msg, T> {
224 #[doc(hidden)]
225 pub fn from_inner(_private: Private, inner: T::PresentMutData<'msg>) -> Self {
226 Self { inner }
Protobuf Team Bot263248e2023-06-22 09:14:12 -0700227 }
228
Protobuf Team Botd42b2372023-07-10 18:24:33 -0700229 /// Gets an immutable view of this present field. This is shorthand for
230 /// `as_view`.
231 ///
232 /// This provides a shorter lifetime than `into_view` but can also be called
233 /// multiple times - if the result of `get` is not living long enough
234 /// for your use, use that instead.
235 pub fn get(&self) -> View<'_, T> {
236 self.as_view()
237 }
238
Protobuf Team Bot29a26152023-06-22 09:51:38 -0700239 pub fn set(&mut self, val: impl SettableValue<T>) {
240 val.set_on(Private, self.as_mut())
Protobuf Team Bot263248e2023-06-22 09:14:12 -0700241 }
242
243 /// See [`FieldEntry::clear`].
Protobuf Team Bot0d7a3962023-07-10 11:51:22 -0700244 pub fn clear(mut self) -> AbsentField<'msg, T> {
245 AbsentField { inner: T::clear_present_field(self.inner) }
Protobuf Team Bot263248e2023-06-22 09:14:12 -0700246 }
247
248 // This cannot provide `reborrow` - `clear` consumes after setting the field
249 // because it would violate a condition of `PresentField` - the field being set.
250}
251
252impl<'msg, T> ViewProxy<'msg> for PresentField<'msg, T>
253where
Protobuf Team Bot0d7a3962023-07-10 11:51:22 -0700254 T: ProxiedWithPresence + ?Sized + 'msg,
Protobuf Team Bot263248e2023-06-22 09:14:12 -0700255{
256 type Proxied = T;
257
258 fn as_view(&self) -> View<'_, T> {
Protobuf Team Bot0d7a3962023-07-10 11:51:22 -0700259 self.inner.as_view()
Protobuf Team Bot263248e2023-06-22 09:14:12 -0700260 }
261
262 fn into_view<'shorter>(self) -> View<'shorter, T>
263 where
264 'msg: 'shorter,
265 {
Protobuf Team Bot0d7a3962023-07-10 11:51:22 -0700266 self.inner.into_view()
Protobuf Team Bot263248e2023-06-22 09:14:12 -0700267 }
268}
269
270impl<'msg, T> MutProxy<'msg> for PresentField<'msg, T>
271where
Protobuf Team Bot0d7a3962023-07-10 11:51:22 -0700272 T: ProxiedWithPresence + ?Sized + 'msg,
Protobuf Team Bot263248e2023-06-22 09:14:12 -0700273{
274 fn as_mut(&mut self) -> Mut<'_, T> {
Protobuf Team Bot0d7a3962023-07-10 11:51:22 -0700275 self.inner.as_mut()
Protobuf Team Bot263248e2023-06-22 09:14:12 -0700276 }
277
278 fn into_mut<'shorter>(self) -> Mut<'shorter, T>
279 where
280 'msg: 'shorter,
281 {
Protobuf Team Bot0d7a3962023-07-10 11:51:22 -0700282 self.inner.into_mut()
Protobuf Team Bot263248e2023-06-22 09:14:12 -0700283 }
284}
285
286/// A field mutator capable of setting that is statically known to point to a
287/// non-set field.
288pub struct AbsentField<'a, T>
289where
Protobuf Team Bot0d7a3962023-07-10 11:51:22 -0700290 T: ProxiedWithPresence + ?Sized + 'a,
Protobuf Team Bot263248e2023-06-22 09:14:12 -0700291{
Alyssa Haroldsen614e29f2023-08-30 12:51:55 -0700292 pub(crate) inner: T::AbsentMutData<'a>,
Protobuf Team Bot263248e2023-06-22 09:14:12 -0700293}
294
Protobuf Team Bot0d7a3962023-07-10 11:51:22 -0700295impl<'msg, T: ProxiedWithPresence + ?Sized + 'msg> Debug for AbsentField<'msg, T> {
Protobuf Team Bot263248e2023-06-22 09:14:12 -0700296 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
Protobuf Team Bot0d7a3962023-07-10 11:51:22 -0700297 self.inner.fmt(f)
Protobuf Team Bot263248e2023-06-22 09:14:12 -0700298 }
299}
300
Protobuf Team Bot0d7a3962023-07-10 11:51:22 -0700301impl<'msg, T: ProxiedWithPresence + ?Sized> AbsentField<'msg, T> {
302 #[doc(hidden)]
303 pub fn from_inner(_private: Private, inner: T::AbsentMutData<'msg>) -> Self {
304 Self { inner }
305 }
306
Protobuf Team Bot263248e2023-06-22 09:14:12 -0700307 /// Gets the default value for this unset field.
308 ///
Protobuf Team Botd42b2372023-07-10 18:24:33 -0700309 /// This is the same value that the primitive accessor would provide, though
310 /// with the shorter lifetime of `as_view`.
311 pub fn default_value(&self) -> View<'_, T> {
312 self.as_view()
Protobuf Team Bot263248e2023-06-22 09:14:12 -0700313 }
314
315 /// See [`FieldEntry::set`]. Note that this consumes and returns a
316 /// `PresentField`.
Protobuf Team Bot29a26152023-06-22 09:51:38 -0700317 pub fn set(self, val: impl SettableValue<T>) -> PresentField<'msg, T> {
Protobuf Team Bot0d7a3962023-07-10 11:51:22 -0700318 PresentField { inner: val.set_on_absent(Private, self.inner) }
Protobuf Team Bot263248e2023-06-22 09:14:12 -0700319 }
320
321 /// Sets this absent field to its default value.
322 pub fn set_default(self) -> PresentField<'msg, T> {
Protobuf Team Bot0d7a3962023-07-10 11:51:22 -0700323 PresentField { inner: T::set_absent_to_default(self.inner) }
Protobuf Team Bot263248e2023-06-22 09:14:12 -0700324 }
325
326 // This cannot provide `reborrow` - `set` consumes after setting the field
327 // because it would violate a condition of `AbsentField` - the field being
328 // unset.
329}
330
331impl<'msg, T> ViewProxy<'msg> for AbsentField<'msg, T>
332where
Protobuf Team Bot0d7a3962023-07-10 11:51:22 -0700333 T: ProxiedWithPresence + ?Sized + 'msg,
Protobuf Team Bot263248e2023-06-22 09:14:12 -0700334{
335 type Proxied = T;
336
337 fn as_view(&self) -> View<'_, T> {
Protobuf Team Bot0d7a3962023-07-10 11:51:22 -0700338 self.inner.as_view()
Protobuf Team Bot263248e2023-06-22 09:14:12 -0700339 }
340
341 fn into_view<'shorter>(self) -> View<'shorter, T>
342 where
343 'msg: 'shorter,
344 {
Protobuf Team Bot0d7a3962023-07-10 11:51:22 -0700345 self.inner.into_view()
346 }
347}
348
349/// Transforms a mutable reference in-place, treating it as if it were owned.
350///
351/// The program will abort if `transform` panics.
352///
353/// This is the same operation as provided by [`take_mut::take`].
354///
355/// [`take_mut::take`]: https://docs.rs/take_mut/latest/take_mut/fn.take.html
356fn transform_mut<T>(mut_ref: &mut T, transform: impl FnOnce(T) -> T) {
357 #[cold]
358 #[inline(never)]
359 fn panicked_in_transform_mut() -> ! {
360 use std::io::Write as _;
361 let backtrace = std::backtrace::Backtrace::force_capture();
362 let stderr = std::io::stderr();
363 let mut stderr = stderr.lock();
364 let _ = write!(&mut stderr, "BUG: A protobuf mutator panicked! Backtrace:\n{backtrace}\n");
365 let _ = stderr.flush();
366 std::process::abort()
367 }
368
369 // https://play.rust-lang.org/?edition=2021&gist=f3014e1f209013f0a38352e211f4a240
370 // provides a sample test to confirm this operation is sound in Miri.
371 // SAFETY:
372 // - `old_t` is not dropped without also replacing `*mut_ref`, preventing a
373 // double-free.
374 // - If `transform` panics, the process aborts since `*mut_ref` has no possible
375 // valid value.
376 // - After `ptr::write`, a valid `T` is located at `*mut_ref`
377 unsafe {
378 let p: *mut T = mut_ref;
379 let old_t = p.read();
380 let new_t = panic::catch_unwind(panic::AssertUnwindSafe(move || transform(old_t)))
381 .unwrap_or_else(|_| panicked_in_transform_mut());
382 p.write(new_t);
383 }
384}
385
386#[cfg(test)]
387mod tests {
388 use super::*;
389 use std::borrow::Cow;
390
391 /// A sample message with custom presence bits, meant to mirror a C++
392 /// message.
393 #[derive(Default, Debug)]
394 struct MyMessage {
395 /// has a default of `0`
396 a: i32,
397
398 /// has a default of `5`
399 b: i32,
400
401 /// Packed presence bitfield for `a` and `b`
402 presence: u8,
403 }
404
405 impl MyMessage {
406 fn a(&self) -> View<'_, VtableProxied> {
407 VtableProxiedView { val: get_a(self) }
408 }
409
410 fn a_opt(&self) -> Optional<View<'_, VtableProxied>> {
411 Optional::new(self.a(), has_a(self))
412 }
413
414 fn a_mut(&mut self) -> FieldEntry<'_, VtableProxied> {
415 static A_VTABLE: ProxyVtable =
416 ProxyVtable { get: get_a, set: set_a, clear: clear_a, has: has_a };
417 make_field_entry(self, &A_VTABLE)
418 }
419
420 fn b(&self) -> View<'_, VtableProxied> {
421 VtableProxiedView { val: get_b(self) }
422 }
423
424 fn b_opt(&self) -> Optional<View<'_, VtableProxied>> {
425 Optional::new(self.b(), has_b(self))
426 }
427
428 fn b_mut(&mut self) -> FieldEntry<'_, VtableProxied> {
429 static B_VTABLE: ProxyVtable =
430 ProxyVtable { get: get_b, set: set_b, clear: clear_b, has: has_b };
431 make_field_entry(self, &B_VTABLE)
432 }
433 }
434
435 fn make_field_entry<'a>(
436 msg: &'a mut MyMessage,
437 vtable: &'a ProxyVtable,
438 ) -> FieldEntry<'a, VtableProxied> {
439 if (vtable.has)(&*msg) {
440 Optional::Set(PresentField::from_inner(Private, VtableProxiedMut { msg, vtable }))
441 } else {
442 Optional::Unset(AbsentField::from_inner(Private, VtableProxiedMut { msg, vtable }))
443 }
444 }
445
446 // Thunks used for the vtable. For a C++ message these would be defined in C++
447 // and exported via a C API
448 const A_BIT: u8 = 0;
449 const B_BIT: u8 = 1;
450
451 fn get_a(msg: &MyMessage) -> i32 {
452 if has_a(msg) { msg.a } else { 0 }
453 }
454
455 fn get_b(msg: &MyMessage) -> i32 {
456 if has_b(msg) { msg.b } else { 5 }
457 }
458
459 fn set_a(msg: &mut MyMessage, val: i32) {
460 msg.presence |= (1 << A_BIT);
461 msg.a = val;
462 }
463
464 fn set_b(msg: &mut MyMessage, val: i32) {
465 msg.presence |= (1 << B_BIT);
466 msg.b = val;
467 }
468
469 fn clear_a(msg: &mut MyMessage) {
470 msg.presence &= !(1 << A_BIT);
471 }
472
473 fn clear_b(msg: &mut MyMessage) {
474 msg.presence &= !(1 << B_BIT);
475 }
476
477 fn has_a(msg: &MyMessage) -> bool {
478 msg.presence & (1 << A_BIT) != 0
479 }
480
481 fn has_b(msg: &MyMessage) -> bool {
482 msg.presence & (1 << B_BIT) != 0
483 }
484
Marcel Hlopko8e210a82023-07-18 10:14:31 -0700485 #[derive(Debug)]
Protobuf Team Bot0d7a3962023-07-10 11:51:22 -0700486 struct ProxyVtable {
487 get: fn(&MyMessage) -> i32,
488 set: fn(&mut MyMessage, val: i32),
489 clear: fn(&mut MyMessage),
490 has: fn(&MyMessage) -> bool,
491 }
492
Protobuf Team Bot0d7a3962023-07-10 11:51:22 -0700493 /// A proxy for a `i32` that is accessed through methods on a vtable.
494 struct VtableProxied;
495
496 impl Proxied for VtableProxied {
497 type View<'a> = VtableProxiedView;
498 type Mut<'a> = VtableProxiedMut<'a>;
499 }
500
501 impl ProxiedWithPresence for VtableProxied {
502 // In this case, the `PresentMutData` and `AbsentMutData` are identical to the
503 // `Mut` in layout. Other types/runtimes could require otherwise, e.g. `Mut`
504 // could be defined to only have get/set functions in its vtable, and not
505 // has/clear.
506 type PresentMutData<'a> = VtableProxiedMut<'a>;
507 type AbsentMutData<'a> = VtableProxiedMut<'a>;
508
509 fn clear_present_field<'a>(
510 present_mutator: Self::PresentMutData<'a>,
511 ) -> Self::AbsentMutData<'a> {
512 (present_mutator.vtable.clear)(&mut *present_mutator.msg);
513 present_mutator
514 }
515
516 fn set_absent_to_default<'a>(
517 absent_mutator: Self::AbsentMutData<'a>,
518 ) -> Self::PresentMutData<'a> {
Adrian Sadłocha8c08df52023-09-06 02:48:39 -0700519 SettableValue::<VtableProxied>::set_on_absent(
520 absent_mutator.as_view().val(),
521 Private,
522 absent_mutator,
523 )
Protobuf Team Bot0d7a3962023-07-10 11:51:22 -0700524 }
525 }
526
527 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
528 struct VtableProxiedView {
529 val: i32,
530 }
531
532 impl VtableProxiedView {
533 fn val(&self) -> i32 {
534 self.val
535 }
536
537 fn read(msg: &MyMessage, vtable: &ProxyVtable) -> Self {
538 VtableProxiedView { val: (vtable.get)(msg) }
539 }
540 }
541
542 impl<'a> ViewProxy<'a> for VtableProxiedView {
543 type Proxied = VtableProxied;
544
545 fn as_view(&self) -> View<'a, VtableProxied> {
546 *self
547 }
548
549 fn into_view<'shorter>(self) -> View<'shorter, VtableProxied>
550 where
551 'a: 'shorter,
552 {
553 self
554 }
555 }
556
557 #[derive(Debug)]
558 struct VtableProxiedMut<'a> {
559 msg: &'a mut MyMessage,
560 vtable: &'a ProxyVtable,
561 }
562
563 impl<'a> ViewProxy<'a> for VtableProxiedMut<'a> {
564 type Proxied = VtableProxied;
565
566 fn as_view(&self) -> View<'_, VtableProxied> {
567 VtableProxiedView::read(self.msg, self.vtable)
568 }
569
570 fn into_view<'shorter>(self) -> View<'shorter, VtableProxied>
571 where
572 'a: 'shorter,
573 {
574 VtableProxiedView::read(self.msg, self.vtable)
575 }
576 }
577
578 impl<'a> MutProxy<'a> for VtableProxiedMut<'a> {
579 fn as_mut(&mut self) -> Mut<'_, VtableProxied> {
580 VtableProxiedMut { msg: self.msg, vtable: self.vtable }
581 }
582
583 fn into_mut<'shorter>(self) -> Mut<'shorter, VtableProxied>
584 where
585 'a: 'shorter,
586 {
587 self
588 }
589 }
590
591 impl SettableValue<VtableProxied> for View<'_, VtableProxied> {
Jakob Buchgraberab11a0d2023-11-27 08:14:21 -0800592 fn set_on<'a>(self, _private: Private, mutator: Mut<'a, VtableProxied>)
593 where
594 VtableProxied: 'a,
595 {
Adrian Sadłocha8c08df52023-09-06 02:48:39 -0700596 SettableValue::<VtableProxied>::set_on(self.val(), Private, mutator)
Protobuf Team Bot0d7a3962023-07-10 11:51:22 -0700597 }
598
599 fn set_on_absent<'a>(
600 self,
601 _private: Private,
602 absent_mutator: <VtableProxied as ProxiedWithPresence>::AbsentMutData<'a>,
603 ) -> <VtableProxied as ProxiedWithPresence>::PresentMutData<'a> {
Adrian Sadłocha8c08df52023-09-06 02:48:39 -0700604 SettableValue::<VtableProxied>::set_on_absent(self.val(), Private, absent_mutator)
Protobuf Team Bot0d7a3962023-07-10 11:51:22 -0700605 }
606 }
607
608 impl SettableValue<VtableProxied> for i32 {
Jakob Buchgraberab11a0d2023-11-27 08:14:21 -0800609 fn set_on<'a>(self, _private: Private, mutator: Mut<'a, VtableProxied>)
610 where
611 VtableProxied: 'a,
612 {
Protobuf Team Bot0d7a3962023-07-10 11:51:22 -0700613 (mutator.vtable.set)(mutator.msg, self)
614 }
615
616 fn set_on_absent<'a>(
617 self,
618 _private: Private,
619 absent_mutator: <VtableProxied as ProxiedWithPresence>::AbsentMutData<'a>,
620 ) -> <VtableProxied as ProxiedWithPresence>::PresentMutData<'a> {
621 (absent_mutator.vtable.set)(absent_mutator.msg, self);
622 absent_mutator
623 }
624 }
625
626 #[test]
627 fn test_field_entry() {
Hong Shin1a5cdb92023-11-16 09:35:13 -0800628 use googletest::prelude::*;
Protobuf Team Bot0d7a3962023-07-10 11:51:22 -0700629 let mut m1 = MyMessage::default();
630 let mut m2 = MyMessage::default();
631
632 let mut m1_a = m1.a_mut();
Hong Shin1a5cdb92023-11-16 09:35:13 -0800633 assert_that!(m1_a, matches_pattern!(Optional::Unset(_)));
Protobuf Team Bot0d7a3962023-07-10 11:51:22 -0700634
Hong Shin1a5cdb92023-11-16 09:35:13 -0800635 assert_that!(m1_a.as_view().val(), eq(0));
636
637 assert_that!(m2.b().val(), eq(5));
Protobuf Team Bot0d7a3962023-07-10 11:51:22 -0700638
639 let mut m2_b = m2.b_mut();
Hong Shin1a5cdb92023-11-16 09:35:13 -0800640 assert_that!(m2_b.is_unset(), eq(true));
641 assert_that!(m2_b.as_view().val(), eq(5));
Protobuf Team Bot0d7a3962023-07-10 11:51:22 -0700642
643 m2_b.set(10);
Hong Shin1a5cdb92023-11-16 09:35:13 -0800644 assert_that!(m2_b.is_set(), eq(true));
645 assert_that!(m2_b, matches_pattern!(Optional::Set(_)));
646 assert_that!(m2_b.as_view().val(), eq(10));
Protobuf Team Bot0d7a3962023-07-10 11:51:22 -0700647
Hong Shin1a5cdb92023-11-16 09:35:13 -0800648 assert_that!(m1_a.or_default().as_view().val(), eq(0));
649 assert_that!(m1.a_opt(), eq(Optional::Set(VtableProxiedView { val: 0 })));
Protobuf Team Bot0d7a3962023-07-10 11:51:22 -0700650 m1.a_mut().clear();
651
Hong Shin1a5cdb92023-11-16 09:35:13 -0800652 assert_that!(m1.a().val(), eq(0));
653 assert_that!(m1.b().val(), eq(5));
654 assert_that!(m2.a().val(), eq(0));
655 assert_that!(m2.b().val(), eq(10));
Protobuf Team Bot0d7a3962023-07-10 11:51:22 -0700656 }
657
658 #[test]
Protobuf Team Botd42b2372023-07-10 18:24:33 -0700659 fn test_or_set() {
Hong Shin1a5cdb92023-11-16 09:35:13 -0800660 use googletest::prelude::*;
Protobuf Team Botd42b2372023-07-10 18:24:33 -0700661 let mut m1 = MyMessage::default();
662 let mut m2 = MyMessage::default();
663
Hong Shin1a5cdb92023-11-16 09:35:13 -0800664 assert_that!(m1.a_mut().or_set(10).get().val(), eq(10));
665 assert_that!(m1.a_opt(), eq(Optional::Set(VtableProxiedView { val: 10 })));
666 assert_that!(m1.a_mut().or_set(20).get().val(), eq(10));
667 assert_that!(m1.a_opt(), eq(Optional::Set(VtableProxiedView { val: 10 })));
Protobuf Team Botd42b2372023-07-10 18:24:33 -0700668
Hong Shin1a5cdb92023-11-16 09:35:13 -0800669 assert_that!(m2.a_mut().or_set_with(|| m1.a().val() + m1.b().val()).get().val(), eq(15));
670 assert_that!(m2.a_opt(), eq(Optional::Set(VtableProxiedView { val: 15 })));
671 assert_that!(m2.a_mut().or_set_with(|| None::<i32>.unwrap()).get().val(), eq(15));
672 assert_that!(m2.a_opt(), eq(Optional::Set(VtableProxiedView { val: 15 })));
Protobuf Team Botd42b2372023-07-10 18:24:33 -0700673 }
674
675 #[test]
676 fn test_into_optional_view() {
Hong Shin1a5cdb92023-11-16 09:35:13 -0800677 use googletest::prelude::*;
Protobuf Team Botd42b2372023-07-10 18:24:33 -0700678 let mut m1 = MyMessage::default();
Hong Shin1a5cdb92023-11-16 09:35:13 -0800679 assert_that!(
680 m1.a_mut().into_optional_view(),
681 eq(Optional::Unset(VtableProxiedView { val: 0 }))
682 );
Protobuf Team Botd42b2372023-07-10 18:24:33 -0700683 m1.a_mut().set(10);
Hong Shin1a5cdb92023-11-16 09:35:13 -0800684 assert_that!(
685 m1.a_mut().into_optional_view(),
686 eq(Optional::Set(VtableProxiedView { val: 10 }))
687 );
688 assert_that!(
689 m1.b_mut().into_optional_view(),
690 eq(Optional::Unset(VtableProxiedView { val: 5 }))
691 );
Protobuf Team Botd42b2372023-07-10 18:24:33 -0700692 }
693
694 #[test]
695 fn test_try_into_mut() {
Hong Shin1a5cdb92023-11-16 09:35:13 -0800696 use googletest::prelude::*;
Protobuf Team Botd42b2372023-07-10 18:24:33 -0700697 let mut m1 = MyMessage::default();
Hong Shin1a5cdb92023-11-16 09:35:13 -0800698 assert_that!(m1.a_mut().try_into_mut().is_none(), eq(true));
Protobuf Team Botd42b2372023-07-10 18:24:33 -0700699 m1.a_mut().set(10);
700 let mut a_mut = m1.a_mut().try_into_mut().expect("field to be set");
701 a_mut.set(20);
Hong Shin1a5cdb92023-11-16 09:35:13 -0800702 assert_that!(m1.a().val(), eq(20));
Protobuf Team Botd42b2372023-07-10 18:24:33 -0700703 }
704
705 #[test]
Protobuf Team Bot0d7a3962023-07-10 11:51:22 -0700706 fn test_present_field() {
Hong Shin1a5cdb92023-11-16 09:35:13 -0800707 use googletest::prelude::*;
Protobuf Team Bot0d7a3962023-07-10 11:51:22 -0700708 let mut m = MyMessage::default();
709 m.a_mut().set(10);
710 match m.a_mut() {
711 Optional::Set(mut present) => {
Hong Shin1a5cdb92023-11-16 09:35:13 -0800712 assert_that!(present.as_view().val(), eq(10));
Protobuf Team Bot0d7a3962023-07-10 11:51:22 -0700713 present.set(20);
Hong Shin1a5cdb92023-11-16 09:35:13 -0800714 assert_that!(present.as_view().val(), eq(20));
Protobuf Team Bot0d7a3962023-07-10 11:51:22 -0700715 present.into_mut().set(30);
716 }
717 Optional::Unset(_) => unreachable!(),
718 }
Hong Shin1a5cdb92023-11-16 09:35:13 -0800719 assert_that!(m.a_opt(), eq(Optional::Set(VtableProxiedView { val: 30 })));
Protobuf Team Bot0d7a3962023-07-10 11:51:22 -0700720 m.b_mut().set(20);
721 match m.b_mut() {
722 Optional::Set(present) => present.clear(),
723 Optional::Unset(_) => unreachable!(),
724 };
Hong Shin1a5cdb92023-11-16 09:35:13 -0800725 assert_that!(m.b_opt(), eq(Optional::Unset(VtableProxiedView { val: 5 })));
Protobuf Team Bot0d7a3962023-07-10 11:51:22 -0700726 }
727
728 #[test]
729 fn test_absent_field() {
Hong Shin1a5cdb92023-11-16 09:35:13 -0800730 use googletest::prelude::*;
Protobuf Team Bot0d7a3962023-07-10 11:51:22 -0700731 let mut m = MyMessage::default();
732 match m.a_mut() {
733 Optional::Set(_) => unreachable!(),
734 Optional::Unset(absent) => {
Hong Shin1a5cdb92023-11-16 09:35:13 -0800735 assert_that!(absent.as_view().val(), eq(0));
Protobuf Team Bot0d7a3962023-07-10 11:51:22 -0700736 absent.set(20);
737 }
738 }
Hong Shin1a5cdb92023-11-16 09:35:13 -0800739 assert_that!(m.a_opt(), eq(Optional::Set(VtableProxiedView { val: 20 })));
Protobuf Team Bot0d7a3962023-07-10 11:51:22 -0700740 match m.b_mut() {
741 Optional::Set(_) => unreachable!(),
742 Optional::Unset(absent) => {
Hong Shin1a5cdb92023-11-16 09:35:13 -0800743 assert_that!(absent.as_view().val(), eq(5));
Protobuf Team Bot0d7a3962023-07-10 11:51:22 -0700744 absent.set_default();
745 }
746 }
Hong Shin1a5cdb92023-11-16 09:35:13 -0800747 assert_that!(m.b_opt(), eq(Optional::Set(VtableProxiedView { val: 5 })));
Protobuf Team Bot263248e2023-06-22 09:14:12 -0700748 }
749}