Alyssa Haroldsen | 9a0bc39 | 2023-08-23 11:05:31 -0700 | [diff] [blame] | 1 | // Protocol Buffers - Google's data interchange format |
| 2 | // Copyright 2023 Google LLC. All rights reserved. |
Alyssa Haroldsen | 9a0bc39 | 2023-08-23 11:05:31 -0700 | [diff] [blame] | 3 | // |
Joshua Haberman | 4a51303 | 2023-09-08 17:12:50 -0700 | [diff] [blame] | 4 | // 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 |
Alyssa Haroldsen | 9a0bc39 | 2023-08-23 11:05:31 -0700 | [diff] [blame] | 7 | |
| 8 | use crate::__internal::{Private, PtrAndLen, RawMessage}; |
| 9 | use crate::__runtime::{copy_bytes_in_arena_if_needed_by_runtime, MutatorMessageRef}; |
| 10 | use crate::{ |
| 11 | AbsentField, FieldEntry, Mut, MutProxy, Optional, PresentField, Proxied, ProxiedWithPresence, |
| 12 | View, ViewProxy, |
| 13 | }; |
| 14 | use std::fmt::{self, Debug}; |
| 15 | |
| 16 | /// A proxied type that can use a vtable to provide get/set access for a |
| 17 | /// present field. |
| 18 | /// |
| 19 | /// This vtable should consist of `unsafe fn`s that call thunks that operate on |
| 20 | /// `RawMessage`. The structure of this vtable is different per proxied type. |
| 21 | pub trait ProxiedWithRawVTable: Proxied { |
| 22 | /// The vtable for get/set access, stored in static memory. |
| 23 | type VTable: Debug + 'static; |
| 24 | |
| 25 | fn make_view(_private: Private, mut_inner: RawVTableMutator<'_, Self>) -> View<'_, Self>; |
| 26 | fn make_mut(_private: Private, inner: RawVTableMutator<'_, Self>) -> Mut<'_, Self>; |
| 27 | } |
| 28 | |
| 29 | /// A proxied type that can use a vtable to provide get/set/clear access for |
| 30 | /// an optional field. |
| 31 | /// |
| 32 | /// This vtable should consist of `unsafe fn`s that call thunks that operate on |
| 33 | /// `RawMessage`. The structure of this vtable is different per-proxied type. |
| 34 | pub trait ProxiedWithRawOptionalVTable: ProxiedWithRawVTable + ProxiedWithPresence { |
| 35 | /// The vtable for get/set/clear, must contain `Self::VTable`. |
| 36 | type OptionalVTable: Debug + 'static; |
| 37 | |
| 38 | /// Cast from a static reference of `OptionalVTable` to `VTable`. |
| 39 | /// This should mean `OptionalVTable` contains a `VTable`. |
| 40 | fn upcast_vtable( |
| 41 | _private: Private, |
| 42 | optional_vtable: &'static Self::OptionalVTable, |
| 43 | ) -> &'static Self::VTable; |
| 44 | } |
| 45 | |
| 46 | /// Constructs a new field entry from a raw message, a vtable for manipulation, |
| 47 | /// and an eager check for whether the value is present or not. |
| 48 | /// |
| 49 | /// # Safety |
| 50 | /// - `msg_ref` must be valid to provide as an argument for `vtable`'s methods |
| 51 | /// for `'msg`. |
| 52 | /// - If given `msg_ref` as an argument, any values returned by `vtable` methods |
| 53 | /// must be valid for `'msg`. |
| 54 | /// - Operations on the vtable must be thread-compatible. |
| 55 | #[doc(hidden)] |
| 56 | pub unsafe fn new_vtable_field_entry<'msg, T: ProxiedWithRawOptionalVTable + ?Sized>( |
| 57 | _private: Private, |
| 58 | msg_ref: MutatorMessageRef<'msg>, |
| 59 | optional_vtable: &'static T::OptionalVTable, |
| 60 | is_set: bool, |
| 61 | ) -> FieldEntry<'msg, T> |
| 62 | where |
| 63 | T: ProxiedWithPresence< |
| 64 | PresentMutData<'msg> = RawVTableOptionalMutatorData<'msg, T>, |
| 65 | AbsentMutData<'msg> = RawVTableOptionalMutatorData<'msg, T>, |
| 66 | >, |
| 67 | { |
| 68 | let data = RawVTableOptionalMutatorData { msg_ref, vtable: optional_vtable }; |
| 69 | if is_set { |
| 70 | Optional::Set(PresentField::from_inner(Private, data)) |
| 71 | } else { |
| 72 | Optional::Unset(AbsentField::from_inner(Private, data)) |
| 73 | } |
| 74 | } |
| 75 | |
| 76 | /// The internal implementation type for a vtable-based `protobuf::Mut<T>`. |
| 77 | /// |
| 78 | /// This stores the two components necessary to mutate the field: |
| 79 | /// borrowed message data and a vtable reference. |
| 80 | /// |
| 81 | /// The borrowed message data varies per runtime: C++ needs a message pointer, |
| 82 | /// while UPB needs a message pointer and an `&Arena`. |
| 83 | /// |
| 84 | /// Implementations of `ProxiedWithRawVTable` implement get/set |
| 85 | /// on top of `RawVTableMutator<T>`, and the top-level mutator (e.g. |
| 86 | /// `BytesMut`) calls these methods. |
| 87 | /// |
| 88 | /// [`RawVTableOptionalMutatorData`] is similar, but also includes the |
| 89 | /// capability to has/clear. |
| 90 | pub struct RawVTableMutator<'msg, T: ProxiedWithRawVTable + ?Sized> { |
| 91 | msg_ref: MutatorMessageRef<'msg>, |
| 92 | vtable: &'static T::VTable, |
| 93 | } |
| 94 | |
| 95 | // These use manual impls instead of derives to avoid unnecessary bounds on `T`. |
| 96 | // This problem is referred to as "perfect derive". |
| 97 | // https://smallcultfollowing.com/babysteps/blog/2022/04/12/implied-bounds-and-perfect-derive/ |
| 98 | impl<'msg, T: ProxiedWithRawVTable + ?Sized> Clone for RawVTableMutator<'msg, T> { |
| 99 | fn clone(&self) -> Self { |
| 100 | *self |
| 101 | } |
| 102 | } |
| 103 | impl<'msg, T: ProxiedWithRawVTable + ?Sized> Copy for RawVTableMutator<'msg, T> {} |
| 104 | |
| 105 | impl<'msg, T: ProxiedWithRawVTable + ?Sized> Debug for RawVTableMutator<'msg, T> { |
| 106 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
| 107 | f.debug_struct("RawVTableMutator") |
| 108 | .field("msg_ref", &self.msg_ref) |
| 109 | .field("vtable", &self.vtable) |
| 110 | .finish() |
| 111 | } |
| 112 | } |
| 113 | |
| 114 | impl<'msg, T: ProxiedWithRawVTable + ?Sized> RawVTableMutator<'msg, T> { |
| 115 | /// # Safety |
| 116 | /// - `msg_ref` must be valid to provide as an argument for `vtable`'s |
| 117 | /// methods for `'msg`. |
| 118 | /// - If given `msg_ref` as an argument, any values returned by `vtable` |
| 119 | /// methods must be valid for `'msg`. |
| 120 | #[doc(hidden)] |
| 121 | pub unsafe fn new( |
| 122 | _private: Private, |
| 123 | msg_ref: MutatorMessageRef<'msg>, |
| 124 | vtable: &'static T::VTable, |
| 125 | ) -> Self { |
| 126 | RawVTableMutator { msg_ref, vtable } |
| 127 | } |
| 128 | } |
| 129 | |
| 130 | /// [`RawVTableMutator`], but also includes has/clear. |
| 131 | /// |
| 132 | /// This is used as the `PresentData` and `AbsentData` for `impl |
| 133 | /// ProxiedWithPresence for T`. In that implementation, `clear_present_field` |
| 134 | /// and `set_absent_to_default` will use methods implemented on |
| 135 | /// `RawVTableOptionalMutatorData<T>` to do the setting and clearing. |
| 136 | /// |
| 137 | /// This has the same representation for "present" and "absent" data; |
| 138 | /// differences like default values are obviated by the vtable. |
| 139 | pub struct RawVTableOptionalMutatorData<'msg, T: ProxiedWithRawOptionalVTable + ?Sized> { |
| 140 | msg_ref: MutatorMessageRef<'msg>, |
| 141 | vtable: &'static T::OptionalVTable, |
| 142 | } |
| 143 | |
| 144 | unsafe impl<'msg, T: ProxiedWithRawOptionalVTable + ?Sized> Sync |
| 145 | for RawVTableOptionalMutatorData<'msg, T> |
| 146 | { |
| 147 | } |
| 148 | |
| 149 | // These use manual impls instead of derives to avoid unnecessary bounds on `T`. |
| 150 | // This problem is referred to as "perfect derive". |
| 151 | // https://smallcultfollowing.com/babysteps/blog/2022/04/12/implied-bounds-and-perfect-derive/ |
| 152 | impl<'msg, T: ProxiedWithRawOptionalVTable + ?Sized> Clone |
| 153 | for RawVTableOptionalMutatorData<'msg, T> |
| 154 | { |
| 155 | fn clone(&self) -> Self { |
| 156 | *self |
| 157 | } |
| 158 | } |
| 159 | impl<'msg, T: ProxiedWithRawOptionalVTable + ?Sized> Copy |
| 160 | for RawVTableOptionalMutatorData<'msg, T> |
| 161 | { |
| 162 | } |
| 163 | |
| 164 | impl<'msg, T: ProxiedWithRawOptionalVTable + ?Sized> Debug |
| 165 | for RawVTableOptionalMutatorData<'msg, T> |
| 166 | { |
| 167 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
| 168 | f.debug_struct("RawVTableOptionalMutatorData") |
| 169 | .field("msg_ref", &self.msg_ref) |
| 170 | .field("vtable", &self.vtable) |
| 171 | .finish() |
| 172 | } |
| 173 | } |
| 174 | |
| 175 | impl<'msg, T: ProxiedWithRawOptionalVTable + ?Sized> RawVTableOptionalMutatorData<'msg, T> { |
| 176 | /// # Safety |
| 177 | /// - `msg_ref` must be valid to provide as an argument for `vtable`'s |
| 178 | /// methods for `'msg`. |
| 179 | /// - If given `msg_ref` as an argument, any values returned by `vtable` |
| 180 | /// methods must be valid for `'msg`. |
| 181 | #[doc(hidden)] |
| 182 | pub unsafe fn new( |
| 183 | _private: Private, |
| 184 | msg_ref: MutatorMessageRef<'msg>, |
| 185 | vtable: &'static T::OptionalVTable, |
| 186 | ) -> Self { |
| 187 | Self { msg_ref, vtable } |
| 188 | } |
| 189 | |
| 190 | fn into_raw_mut(self) -> RawVTableMutator<'msg, T> { |
| 191 | RawVTableMutator { msg_ref: self.msg_ref, vtable: T::upcast_vtable(Private, self.vtable) } |
| 192 | } |
| 193 | } |
| 194 | |
| 195 | impl<'msg, T: ProxiedWithRawOptionalVTable + ?Sized + 'msg> ViewProxy<'msg> |
| 196 | for RawVTableOptionalMutatorData<'msg, T> |
| 197 | { |
| 198 | type Proxied = T; |
| 199 | |
| 200 | fn as_view(&self) -> View<'_, T> { |
| 201 | T::make_view(Private, self.into_raw_mut()) |
| 202 | } |
| 203 | |
| 204 | fn into_view<'shorter>(self) -> View<'shorter, T> |
| 205 | where |
| 206 | 'msg: 'shorter, |
| 207 | { |
| 208 | T::make_view(Private, self.into_raw_mut()) |
| 209 | } |
| 210 | } |
| 211 | |
| 212 | // Note: though this raw value implements `MutProxy`, the `as_mut` is only valid |
| 213 | // when the field is known to be present. `FieldEntry` enforces this in its |
| 214 | // design: `AbsentField { inner: RawVTableOptionalMutatorData<T> }` does not |
| 215 | // implement `MutProxy`. |
| 216 | impl<'msg, T: ProxiedWithRawOptionalVTable + ?Sized + 'msg> MutProxy<'msg> |
| 217 | for RawVTableOptionalMutatorData<'msg, T> |
| 218 | { |
| 219 | fn as_mut(&mut self) -> Mut<'_, T> { |
| 220 | T::make_mut(Private, self.into_raw_mut()) |
| 221 | } |
| 222 | |
| 223 | fn into_mut<'shorter>(self) -> Mut<'shorter, T> |
| 224 | where |
| 225 | 'msg: 'shorter, |
| 226 | { |
| 227 | T::make_mut(Private, self.into_raw_mut()) |
| 228 | } |
| 229 | } |
| 230 | |
| 231 | impl ProxiedWithRawVTable for [u8] { |
| 232 | type VTable = BytesMutVTable; |
| 233 | |
| 234 | fn make_view(_private: Private, mut_inner: RawVTableMutator<'_, Self>) -> View<'_, Self> { |
| 235 | mut_inner.get() |
| 236 | } |
| 237 | |
| 238 | fn make_mut(_private: Private, inner: RawVTableMutator<'_, Self>) -> Mut<'_, Self> { |
| 239 | crate::string::BytesMut::from_inner(Private, inner) |
| 240 | } |
| 241 | } |
| 242 | |
| 243 | impl ProxiedWithRawOptionalVTable for [u8] { |
| 244 | type OptionalVTable = BytesOptionalMutVTable; |
| 245 | fn upcast_vtable( |
| 246 | _private: Private, |
| 247 | optional_vtable: &'static Self::OptionalVTable, |
| 248 | ) -> &'static Self::VTable { |
| 249 | &optional_vtable.base |
| 250 | } |
| 251 | } |
| 252 | |
Adrian Sadłocha | 8c08df5 | 2023-09-06 02:48:39 -0700 | [diff] [blame] | 253 | /// A generic thunk vtable for mutating a present primitive field. |
| 254 | #[doc(hidden)] |
| 255 | #[derive(Debug)] |
| 256 | pub struct PrimitiveVTable<T> { |
| 257 | pub(crate) setter: unsafe extern "C" fn(msg: RawMessage, val: T), |
| 258 | pub(crate) getter: unsafe extern "C" fn(msg: RawMessage) -> T, |
| 259 | } |
| 260 | |
Adrian Sadłocha | c303109 | 2023-10-18 08:34:52 -0700 | [diff] [blame] | 261 | #[doc(hidden)] |
| 262 | #[derive(Debug)] |
| 263 | /// A generic thunk vtable for mutating an `optional` primitive field. |
| 264 | pub struct PrimitiveOptionalMutVTable<T> { |
| 265 | pub(crate) base: PrimitiveVTable<T>, |
| 266 | pub(crate) clearer: unsafe extern "C" fn(msg: RawMessage), |
| 267 | pub(crate) default: T, |
| 268 | } |
| 269 | |
Adrian Sadłocha | 8c08df5 | 2023-09-06 02:48:39 -0700 | [diff] [blame] | 270 | impl<T> PrimitiveVTable<T> { |
| 271 | #[doc(hidden)] |
| 272 | pub const fn new( |
| 273 | _private: Private, |
| 274 | getter: unsafe extern "C" fn(msg: RawMessage) -> T, |
| 275 | setter: unsafe extern "C" fn(msg: RawMessage, val: T), |
| 276 | ) -> Self { |
| 277 | Self { getter, setter } |
| 278 | } |
| 279 | } |
| 280 | |
Adrian Sadłocha | c303109 | 2023-10-18 08:34:52 -0700 | [diff] [blame] | 281 | impl<T> PrimitiveOptionalMutVTable<T> { |
| 282 | #[doc(hidden)] |
| 283 | pub const fn new( |
| 284 | _private: Private, |
| 285 | getter: unsafe extern "C" fn(msg: RawMessage) -> T, |
| 286 | setter: unsafe extern "C" fn(msg: RawMessage, val: T), |
| 287 | clearer: unsafe extern "C" fn(msg: RawMessage), |
| 288 | default: T, |
| 289 | ) -> Self { |
| 290 | Self { base: PrimitiveVTable { getter, setter }, clearer, default } |
| 291 | } |
| 292 | } |
| 293 | |
Adrian Sadłocha | 8c08df5 | 2023-09-06 02:48:39 -0700 | [diff] [blame] | 294 | macro_rules! impl_raw_vtable_mutator_get_set { |
| 295 | ($($t:ty),*) => { |
| 296 | $( |
| 297 | impl RawVTableMutator<'_, $t> { |
| 298 | pub(crate) fn get(self) -> $t { |
| 299 | // SAFETY: |
| 300 | // - `msg_ref` is valid for the lifetime of `RawVTableMutator` as promised by the |
| 301 | // caller of `new`. |
| 302 | unsafe { (self.vtable.getter)(self.msg_ref.msg()) } |
| 303 | } |
| 304 | |
| 305 | /// # Safety |
| 306 | /// - `msg_ref` must be valid for the lifetime of `RawVTableMutator`. |
| 307 | pub(crate) unsafe fn set(self, val: $t) { |
| 308 | // SAFETY: |
| 309 | // - `msg_ref` is valid for the lifetime of `RawVTableMutator` as promised by the |
| 310 | // caller of `new`. |
| 311 | unsafe { (self.vtable.setter)(self.msg_ref.msg(), val) } |
| 312 | } |
| 313 | } |
| 314 | )* |
| 315 | } |
| 316 | } |
| 317 | |
| 318 | impl_raw_vtable_mutator_get_set!(bool, f32, f64, i32, i64, u32, u64); |
| 319 | |
Alyssa Haroldsen | 9a0bc39 | 2023-08-23 11:05:31 -0700 | [diff] [blame] | 320 | /// A generic thunk vtable for mutating a present `bytes` or `string` field. |
| 321 | #[doc(hidden)] |
| 322 | #[derive(Debug)] |
| 323 | pub struct BytesMutVTable { |
Protobuf Team Bot | 78d71ca | 2023-09-13 11:55:59 -0700 | [diff] [blame] | 324 | pub(crate) setter: unsafe extern "C" fn(msg: RawMessage, val: PtrAndLen), |
Alyssa Haroldsen | 9a0bc39 | 2023-08-23 11:05:31 -0700 | [diff] [blame] | 325 | pub(crate) getter: unsafe extern "C" fn(msg: RawMessage) -> PtrAndLen, |
| 326 | } |
| 327 | |
| 328 | /// A generic thunk vtable for mutating an `optional` `bytes` or `string` field. |
| 329 | #[derive(Debug)] |
| 330 | pub struct BytesOptionalMutVTable { |
| 331 | pub(crate) base: BytesMutVTable, |
| 332 | pub(crate) clearer: unsafe extern "C" fn(msg: RawMessage), |
| 333 | pub(crate) default: &'static [u8], |
| 334 | } |
| 335 | |
| 336 | impl BytesMutVTable { |
| 337 | #[doc(hidden)] |
| 338 | pub const fn new( |
| 339 | _private: Private, |
| 340 | getter: unsafe extern "C" fn(msg: RawMessage) -> PtrAndLen, |
Protobuf Team Bot | 78d71ca | 2023-09-13 11:55:59 -0700 | [diff] [blame] | 341 | setter: unsafe extern "C" fn(msg: RawMessage, val: PtrAndLen), |
Alyssa Haroldsen | 9a0bc39 | 2023-08-23 11:05:31 -0700 | [diff] [blame] | 342 | ) -> Self { |
| 343 | Self { getter, setter } |
| 344 | } |
| 345 | } |
| 346 | |
| 347 | impl BytesOptionalMutVTable { |
| 348 | /// # Safety |
| 349 | /// The `default` value must be UTF-8 if required by |
| 350 | /// the runtime and this is for a `string` field. |
| 351 | #[doc(hidden)] |
| 352 | pub const unsafe fn new( |
| 353 | _private: Private, |
| 354 | getter: unsafe extern "C" fn(msg: RawMessage) -> PtrAndLen, |
Protobuf Team Bot | 78d71ca | 2023-09-13 11:55:59 -0700 | [diff] [blame] | 355 | setter: unsafe extern "C" fn(msg: RawMessage, val: PtrAndLen), |
Alyssa Haroldsen | 9a0bc39 | 2023-08-23 11:05:31 -0700 | [diff] [blame] | 356 | clearer: unsafe extern "C" fn(msg: RawMessage), |
| 357 | default: &'static [u8], |
| 358 | ) -> Self { |
| 359 | Self { base: BytesMutVTable { getter, setter }, clearer, default } |
| 360 | } |
| 361 | } |
| 362 | |
| 363 | impl<'msg> RawVTableMutator<'msg, [u8]> { |
| 364 | pub(crate) fn get(self) -> &'msg [u8] { |
| 365 | // SAFETY: |
| 366 | // - `msg_ref` is valid for `'msg` as promised by the caller of `new`. |
| 367 | // - The caller of `BytesMutVTable` promised that the returned `PtrAndLen` is |
| 368 | // valid for `'msg`. |
| 369 | unsafe { (self.vtable.getter)(self.msg_ref.msg()).as_ref() } |
| 370 | } |
| 371 | |
| 372 | /// # Safety |
| 373 | /// - `msg_ref` must be valid for `'msg` |
| 374 | /// - If this is for a `string` field, `val` must be valid UTF-8 if the |
| 375 | /// runtime requires it. |
| 376 | pub(crate) unsafe fn set(self, val: &[u8]) { |
| 377 | let val = copy_bytes_in_arena_if_needed_by_runtime(self.msg_ref, val); |
| 378 | // SAFETY: |
| 379 | // - `msg_ref` is valid for `'msg` as promised by the caller of `new`. |
Protobuf Team Bot | 78d71ca | 2023-09-13 11:55:59 -0700 | [diff] [blame] | 380 | unsafe { (self.vtable.setter)(self.msg_ref.msg(), val.into()) } |
Alyssa Haroldsen | 9a0bc39 | 2023-08-23 11:05:31 -0700 | [diff] [blame] | 381 | } |
| 382 | |
| 383 | pub(crate) fn truncate(&self, len: usize) { |
| 384 | if len == 0 { |
| 385 | // SAFETY: The empty string is valid UTF-8. |
| 386 | unsafe { |
| 387 | self.set(b""); |
| 388 | } |
| 389 | return; |
| 390 | } |
| 391 | todo!("b/294252563") |
| 392 | } |
| 393 | } |
| 394 | |
| 395 | impl<'msg> RawVTableOptionalMutatorData<'msg, [u8]> { |
| 396 | /// Sets an absent `bytes`/`string` field to its default value. |
| 397 | pub(crate) fn set_absent_to_default(self) -> Self { |
| 398 | // SAFETY: The default value is UTF-8 if required by the |
| 399 | // runtime as promised by the caller of `BytesOptionalMutVTable::new`. |
| 400 | unsafe { self.set(self.vtable.default) } |
| 401 | } |
| 402 | |
| 403 | /// # Safety |
| 404 | /// - If this is a `string` field, `val` must be valid UTF-8 if required by |
| 405 | /// the runtime. |
| 406 | pub(crate) unsafe fn set(self, val: &[u8]) -> Self { |
| 407 | let val = copy_bytes_in_arena_if_needed_by_runtime(self.msg_ref, val); |
| 408 | // SAFETY: |
| 409 | // - `msg_ref` is valid for `'msg` as promised by the caller. |
Protobuf Team Bot | 78d71ca | 2023-09-13 11:55:59 -0700 | [diff] [blame] | 410 | unsafe { (self.vtable.base.setter)(self.msg_ref.msg(), val.into()) } |
Alyssa Haroldsen | 9a0bc39 | 2023-08-23 11:05:31 -0700 | [diff] [blame] | 411 | self |
| 412 | } |
| 413 | |
| 414 | pub(crate) fn clear(self) -> Self { |
| 415 | // SAFETY: |
| 416 | // - `msg_ref` is valid for `'msg` as promised by the caller. |
| 417 | // - The caller of `new` promised that the returned `PtrAndLen` is valid for |
| 418 | // `'msg`. |
| 419 | unsafe { (self.vtable.clearer)(self.msg_ref.msg()) } |
| 420 | self |
| 421 | } |
| 422 | } |
Adrian Sadłocha | c303109 | 2023-10-18 08:34:52 -0700 | [diff] [blame] | 423 | |
| 424 | macro_rules! impl_raw_vtable_optional_mutator_data { |
| 425 | ($($t:ty),*) => { |
| 426 | $( |
| 427 | impl<'msg> RawVTableOptionalMutatorData<'msg, $t> { |
| 428 | pub(crate) fn set_absent_to_default(self) -> Self { |
| 429 | // SAFETY: |
| 430 | // - `msg_ref` is valid for the lifetime of `RawVTableOptionalMutatorData` as |
| 431 | // promised by the caller of `new`. |
| 432 | self.set(self.vtable.default) |
| 433 | } |
| 434 | |
| 435 | pub(crate) fn set(self, val: $t) -> Self { |
| 436 | // SAFETY: |
| 437 | // - `msg_ref` is valid for the lifetime of `RawVTableOptionalMutatorData` as |
| 438 | // promised by the caller of `new`. |
| 439 | unsafe { (self.vtable.base.setter)(self.msg_ref.msg(), val.into()) } |
| 440 | self |
| 441 | } |
| 442 | |
| 443 | pub(crate) fn clear(self) -> Self { |
| 444 | // SAFETY: |
| 445 | // - `msg_ref` is valid for the lifetime of `RawVTableOptionalMutatorData` as |
| 446 | // promised by the caller of `new`. |
| 447 | unsafe { (self.vtable.clearer)(self.msg_ref.msg()) } |
| 448 | self |
| 449 | } |
| 450 | } |
| 451 | )* |
| 452 | } |
| 453 | } |
| 454 | |
| 455 | impl_raw_vtable_optional_mutator_data!(bool, f32, f64, i32, i64, u32, u64); |