blob: 2327e56b69986721e236aa076a792848e8264beb [file] [log] [blame]
Alyssa Haroldsen9a0bc392023-08-23 11:05:31 -07001// Protocol Buffers - Google's data interchange format
2// Copyright 2023 Google LLC. All rights reserved.
Alyssa Haroldsen9a0bc392023-08-23 11:05:31 -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
Alyssa Haroldsen9a0bc392023-08-23 11:05:31 -07007
8use crate::__internal::{Private, PtrAndLen, RawMessage};
9use crate::__runtime::{copy_bytes_in_arena_if_needed_by_runtime, MutatorMessageRef};
10use crate::{
11 AbsentField, FieldEntry, Mut, MutProxy, Optional, PresentField, Proxied, ProxiedWithPresence,
12 View, ViewProxy,
13};
14use 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.
21pub 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.
34pub 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)]
56pub 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>
62where
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.
90pub 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/
98impl<'msg, T: ProxiedWithRawVTable + ?Sized> Clone for RawVTableMutator<'msg, T> {
99 fn clone(&self) -> Self {
100 *self
101 }
102}
103impl<'msg, T: ProxiedWithRawVTable + ?Sized> Copy for RawVTableMutator<'msg, T> {}
104
105impl<'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
114impl<'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.
139pub struct RawVTableOptionalMutatorData<'msg, T: ProxiedWithRawOptionalVTable + ?Sized> {
140 msg_ref: MutatorMessageRef<'msg>,
141 vtable: &'static T::OptionalVTable,
142}
143
144unsafe 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/
152impl<'msg, T: ProxiedWithRawOptionalVTable + ?Sized> Clone
153 for RawVTableOptionalMutatorData<'msg, T>
154{
155 fn clone(&self) -> Self {
156 *self
157 }
158}
159impl<'msg, T: ProxiedWithRawOptionalVTable + ?Sized> Copy
160 for RawVTableOptionalMutatorData<'msg, T>
161{
162}
163
164impl<'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
175impl<'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
195impl<'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`.
216impl<'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
231impl 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
243impl 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łocha8c08df52023-09-06 02:48:39 -0700253/// A generic thunk vtable for mutating a present primitive field.
254#[doc(hidden)]
255#[derive(Debug)]
256pub 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łochac3031092023-10-18 08:34:52 -0700261#[doc(hidden)]
262#[derive(Debug)]
263/// A generic thunk vtable for mutating an `optional` primitive field.
264pub 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łocha8c08df52023-09-06 02:48:39 -0700270impl<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łochac3031092023-10-18 08:34:52 -0700281impl<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łocha8c08df52023-09-06 02:48:39 -0700294macro_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
318impl_raw_vtable_mutator_get_set!(bool, f32, f64, i32, i64, u32, u64);
319
Alyssa Haroldsen9a0bc392023-08-23 11:05:31 -0700320/// A generic thunk vtable for mutating a present `bytes` or `string` field.
321#[doc(hidden)]
322#[derive(Debug)]
323pub struct BytesMutVTable {
Protobuf Team Bot78d71ca2023-09-13 11:55:59 -0700324 pub(crate) setter: unsafe extern "C" fn(msg: RawMessage, val: PtrAndLen),
Alyssa Haroldsen9a0bc392023-08-23 11:05:31 -0700325 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)]
330pub 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
336impl BytesMutVTable {
337 #[doc(hidden)]
338 pub const fn new(
339 _private: Private,
340 getter: unsafe extern "C" fn(msg: RawMessage) -> PtrAndLen,
Protobuf Team Bot78d71ca2023-09-13 11:55:59 -0700341 setter: unsafe extern "C" fn(msg: RawMessage, val: PtrAndLen),
Alyssa Haroldsen9a0bc392023-08-23 11:05:31 -0700342 ) -> Self {
343 Self { getter, setter }
344 }
345}
346
347impl 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 Bot78d71ca2023-09-13 11:55:59 -0700355 setter: unsafe extern "C" fn(msg: RawMessage, val: PtrAndLen),
Alyssa Haroldsen9a0bc392023-08-23 11:05:31 -0700356 clearer: unsafe extern "C" fn(msg: RawMessage),
357 default: &'static [u8],
358 ) -> Self {
359 Self { base: BytesMutVTable { getter, setter }, clearer, default }
360 }
361}
362
363impl<'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 Bot78d71ca2023-09-13 11:55:59 -0700380 unsafe { (self.vtable.setter)(self.msg_ref.msg(), val.into()) }
Alyssa Haroldsen9a0bc392023-08-23 11:05:31 -0700381 }
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
395impl<'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 Bot78d71ca2023-09-13 11:55:59 -0700410 unsafe { (self.vtable.base.setter)(self.msg_ref.msg(), val.into()) }
Alyssa Haroldsen9a0bc392023-08-23 11:05:31 -0700411 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łochac3031092023-10-18 08:34:52 -0700423
424macro_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
455impl_raw_vtable_optional_mutator_data!(bool, f32, f64, i32, i64, u32, u64);