• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2023 Google LLC.  All rights reserved.
3 //
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
7 
8 // Rust Protobuf runtime using the C++ kernel.
9 
10 use crate::__internal::{Enum, Private};
11 use crate::{
12     IntoProxied, Map, MapIter, MapMut, MapView, Mut, ProtoBytes, ProtoStr, ProtoString, Proxied,
13     ProxiedInMapValue, ProxiedInRepeated, Repeated, RepeatedMut, RepeatedView, View,
14 };
15 use core::fmt::Debug;
16 use paste::paste;
17 use std::convert::identity;
18 use std::ffi::{c_int, c_void};
19 use std::fmt;
20 use std::marker::PhantomData;
21 use std::mem::{ManuallyDrop, MaybeUninit};
22 use std::ops::Deref;
23 use std::ptr::{self, NonNull};
24 use std::slice;
25 
26 /// Defines a set of opaque, unique, non-accessible pointees.
27 ///
28 /// The [Rustonomicon][nomicon] currently recommends a zero-sized struct,
29 /// though this should use [`extern type`] when that is stabilized.
30 /// [nomicon]: https://doc.rust-lang.org/nomicon/ffi.html#representing-opaque-structs
31 /// [`extern type`]: https://github.com/rust-lang/rust/issues/43467
32 #[doc(hidden)]
33 mod _opaque_pointees {
34     /// Opaque pointee for [`RawMessage`]
35     ///
36     /// This type is not meant to be dereferenced in Rust code.
37     /// It is only meant to provide type safety for raw pointers
38     /// which are manipulated behind FFI.
39     ///
40     /// [`RawMessage`]: super::RawMessage
41     #[repr(C)]
42     pub struct RawMessageData {
43         _data: [u8; 0],
44         _marker: std::marker::PhantomData<(*mut u8, ::std::marker::PhantomPinned)>,
45     }
46 
47     /// Opaque pointee for [`RawRepeatedField`]
48     ///
49     /// This type is not meant to be dereferenced in Rust code.
50     /// It is only meant to provide type safety for raw pointers
51     /// which are manipulated behind FFI.
52     #[repr(C)]
53     pub struct RawRepeatedFieldData {
54         _data: [u8; 0],
55         _marker: std::marker::PhantomData<(*mut u8, ::std::marker::PhantomPinned)>,
56     }
57 
58     /// Opaque pointee for [`RawMap`]
59     ///
60     /// This type is not meant to be dereferenced in Rust code.
61     /// It is only meant to provide type safety for raw pointers
62     /// which are manipulated behind FFI.
63     #[repr(C)]
64     pub struct RawMapData {
65         _data: [u8; 0],
66         _marker: std::marker::PhantomData<(*mut u8, ::std::marker::PhantomPinned)>,
67     }
68 
69     /// Opaque pointee for [`CppStdString`]
70     ///
71     /// This type is not meant to be dereferenced in Rust code.
72     /// It is only meant to provide type safety for raw pointers
73     /// which are manipulated behind FFI.
74     #[repr(C)]
75     pub struct CppStdStringData {
76         _data: [u8; 0],
77         _marker: std::marker::PhantomData<(*mut u8, ::std::marker::PhantomPinned)>,
78     }
79 }
80 
81 /// A raw pointer to the underlying message for this runtime.
82 #[doc(hidden)]
83 pub type RawMessage = NonNull<_opaque_pointees::RawMessageData>;
84 
85 /// A raw pointer to the underlying repeated field container for this runtime.
86 #[doc(hidden)]
87 pub type RawRepeatedField = NonNull<_opaque_pointees::RawRepeatedFieldData>;
88 
89 /// A raw pointer to the underlying arena for this runtime.
90 #[doc(hidden)]
91 pub type RawMap = NonNull<_opaque_pointees::RawMapData>;
92 
93 /// A raw pointer to a std::string.
94 #[doc(hidden)]
95 pub type CppStdString = NonNull<_opaque_pointees::CppStdStringData>;
96 
97 /// Kernel-specific owned `string` and `bytes` field type.
98 #[derive(Debug)]
99 #[doc(hidden)]
100 pub struct InnerProtoString {
101     owned_ptr: CppStdString,
102 }
103 
104 extern "C" {
proto2_rust_Message_delete(m: RawMessage)105     pub fn proto2_rust_Message_delete(m: RawMessage);
proto2_rust_Message_clear(m: RawMessage)106     pub fn proto2_rust_Message_clear(m: RawMessage);
proto2_rust_Message_parse(m: RawMessage, input: SerializedData) -> bool107     pub fn proto2_rust_Message_parse(m: RawMessage, input: SerializedData) -> bool;
proto2_rust_Message_serialize(m: RawMessage, output: &mut SerializedData) -> bool108     pub fn proto2_rust_Message_serialize(m: RawMessage, output: &mut SerializedData) -> bool;
proto2_rust_Message_copy_from(dst: RawMessage, src: RawMessage) -> bool109     pub fn proto2_rust_Message_copy_from(dst: RawMessage, src: RawMessage) -> bool;
proto2_rust_Message_merge_from(dst: RawMessage, src: RawMessage) -> bool110     pub fn proto2_rust_Message_merge_from(dst: RawMessage, src: RawMessage) -> bool;
111 }
112 
113 /// An opaque type matching MapNodeSizeInfoT from C++.
114 #[doc(hidden)]
115 #[repr(transparent)]
116 pub struct MapNodeSizeInfo(pub i32);
117 
118 impl Drop for InnerProtoString {
drop(&mut self)119     fn drop(&mut self) {
120         // SAFETY: `self.owned_ptr` points to a valid std::string object.
121         unsafe {
122             proto2_rust_cpp_delete_string(self.owned_ptr);
123         }
124     }
125 }
126 
127 impl InnerProtoString {
as_bytes(&self) -> &[u8]128     pub(crate) fn as_bytes(&self) -> &[u8] {
129         // SAFETY: `self.owned_ptr` points to a valid std::string object.
130         unsafe { proto2_rust_cpp_string_to_view(self.owned_ptr).as_ref() }
131     }
132 
into_raw(self) -> CppStdString133     pub fn into_raw(self) -> CppStdString {
134         let s = ManuallyDrop::new(self);
135         s.owned_ptr
136     }
137 
138     /// # Safety
139     ///  - `src` points to a valid CppStdString.
from_raw(src: CppStdString) -> InnerProtoString140     pub unsafe fn from_raw(src: CppStdString) -> InnerProtoString {
141         InnerProtoString { owned_ptr: src }
142     }
143 }
144 
145 impl From<&[u8]> for InnerProtoString {
from(val: &[u8]) -> Self146     fn from(val: &[u8]) -> Self {
147         // SAFETY: `val` is valid byte slice.
148         let owned_ptr: CppStdString = unsafe { proto2_rust_cpp_new_string(val.into()) };
149         InnerProtoString { owned_ptr }
150     }
151 }
152 
153 extern "C" {
proto2_rust_cpp_new_string(src: PtrAndLen) -> CppStdString154     fn proto2_rust_cpp_new_string(src: PtrAndLen) -> CppStdString;
proto2_rust_cpp_delete_string(src: CppStdString)155     fn proto2_rust_cpp_delete_string(src: CppStdString);
proto2_rust_cpp_string_to_view(src: CppStdString) -> PtrAndLen156     fn proto2_rust_cpp_string_to_view(src: CppStdString) -> PtrAndLen;
157 }
158 
159 /// Represents an ABI-stable version of `NonNull<[u8]>`/`string_view` (a
160 /// borrowed slice of bytes) for FFI use only.
161 ///
162 /// Has semantics similar to `std::string_view` in C++ and `&[u8]` in Rust,
163 /// but is not ABI-compatible with either.
164 ///
165 /// If `len` is 0, then `ptr` can be null or dangling. C++ considers a dangling
166 /// 0-len `std::string_view` to be invalid, and Rust considers a `&[u8]` with a
167 /// null data pointer to be invalid.
168 #[repr(C)]
169 #[derive(Copy, Clone)]
170 #[doc(hidden)]
171 pub struct PtrAndLen {
172     /// Pointer to the first byte.
173     /// Borrows the memory.
174     pub ptr: *const u8,
175 
176     /// Length of the `[u8]` pointed to by `ptr`.
177     pub len: usize,
178 }
179 
180 impl PtrAndLen {
181     /// Unsafely dereference this slice.
182     ///
183     /// # Safety
184     /// - `self.ptr` must be dereferencable and immutable for `self.len` bytes
185     ///   for the lifetime `'a`. It can be null or dangling if `self.len == 0`.
as_ref<'a>(self) -> &'a [u8]186     pub unsafe fn as_ref<'a>(self) -> &'a [u8] {
187         if self.ptr.is_null() {
188             assert_eq!(self.len, 0, "Non-empty slice with null data pointer");
189             &[]
190         } else {
191             // SAFETY:
192             // - `ptr` is non-null
193             // - `ptr` is valid for `len` bytes as promised by the caller.
194             unsafe { slice::from_raw_parts(self.ptr, self.len) }
195         }
196     }
197 }
198 
199 impl From<&[u8]> for PtrAndLen {
from(slice: &[u8]) -> Self200     fn from(slice: &[u8]) -> Self {
201         Self { ptr: slice.as_ptr(), len: slice.len() }
202     }
203 }
204 
205 impl From<&ProtoStr> for PtrAndLen {
from(s: &ProtoStr) -> Self206     fn from(s: &ProtoStr) -> Self {
207         let bytes = s.as_bytes();
208         Self { ptr: bytes.as_ptr(), len: bytes.len() }
209     }
210 }
211 
212 /// Serialized Protobuf wire format data. It's typically produced by
213 /// `<Message>.serialize()`.
214 ///
215 /// This struct is ABI-compatible with the equivalent struct on the C++ side. It
216 /// owns (and drops) its data.
217 #[repr(C)]
218 #[doc(hidden)]
219 pub struct SerializedData {
220     /// Owns the memory.
221     data: NonNull<u8>,
222     len: usize,
223 }
224 
225 impl SerializedData {
new() -> Self226     pub fn new() -> Self {
227         Self { data: NonNull::dangling(), len: 0 }
228     }
229 
230     /// Constructs owned serialized data from raw components.
231     ///
232     /// # Safety
233     /// - `data` must be readable for `len` bytes.
234     /// - `data` must be an owned pointer and valid until deallocated.
235     /// - `data` must have been allocated by the Rust global allocator with a
236     ///   size of `len` and align of 1.
from_raw_parts(data: NonNull<u8>, len: usize) -> Self237     pub unsafe fn from_raw_parts(data: NonNull<u8>, len: usize) -> Self {
238         Self { data, len }
239     }
240 
241     /// Gets a raw slice pointer.
as_ptr(&self) -> *const [u8]242     pub fn as_ptr(&self) -> *const [u8] {
243         ptr::slice_from_raw_parts(self.data.as_ptr(), self.len)
244     }
245 
246     /// Gets a mutable raw slice pointer.
as_mut_ptr(&mut self) -> *mut [u8]247     fn as_mut_ptr(&mut self) -> *mut [u8] {
248         ptr::slice_from_raw_parts_mut(self.data.as_ptr(), self.len)
249     }
250 
251     /// Converts into a Vec<u8>.
into_vec(self) -> Vec<u8>252     pub fn into_vec(self) -> Vec<u8> {
253         // We need to prevent self from being dropped, because we are going to transfer
254         // ownership of self.data to the Vec<u8>.
255         let s = ManuallyDrop::new(self);
256 
257         unsafe {
258             // SAFETY:
259             // - `data` was allocated by the Rust global allocator.
260             // - `data` was allocated with an alignment of 1 for u8.
261             // - The allocated size was `len`.
262             // - The length and capacity are equal.
263             // - All `len` bytes are initialized.
264             // - The capacity (`len` in this case) is the size the pointer was allocated
265             //   with.
266             // - The allocated size is no more than isize::MAX, because the protobuf
267             //   serializer will refuse to serialize a message if the output would exceed
268             //   2^31 - 1 bytes.
269             Vec::<u8>::from_raw_parts(s.data.as_ptr(), s.len, s.len)
270         }
271     }
272 }
273 
274 impl Deref for SerializedData {
275     type Target = [u8];
deref(&self) -> &Self::Target276     fn deref(&self) -> &Self::Target {
277         // SAFETY: `data` is valid for `len` bytes until deallocated as promised by
278         // `from_raw_parts`.
279         unsafe { &*self.as_ptr() }
280     }
281 }
282 
283 impl Drop for SerializedData {
drop(&mut self)284     fn drop(&mut self) {
285         // SAFETY: `data` was allocated by the Rust global allocator with a
286         // size of `len` and align of 1 as promised by `from_raw_parts`.
287         unsafe { drop(Box::from_raw(self.as_mut_ptr())) }
288     }
289 }
290 
291 impl fmt::Debug for SerializedData {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result292     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
293         fmt::Debug::fmt(self.deref(), f)
294     }
295 }
296 
297 /// A type to transfer an owned Rust string across the FFI boundary:
298 ///   * This struct is ABI-compatible with the equivalent C struct.
299 ///   * It owns its data but does not drop it. Immediately turn it into a
300 ///     `String` by calling `.into()` on it.
301 ///   * `.data` points to a valid UTF-8 string that has been allocated with the
302 ///     Rust allocator and is 1-byte aligned.
303 ///   * `.data` contains exactly `.len` bytes.
304 ///   * The empty string is represented as `.data.is_null() == true`.
305 #[repr(C)]
306 #[doc(hidden)]
307 pub struct RustStringRawParts {
308     data: *const u8,
309     len: usize,
310 }
311 
312 impl From<RustStringRawParts> for String {
from(value: RustStringRawParts) -> Self313     fn from(value: RustStringRawParts) -> Self {
314         if value.data.is_null() {
315             // Handle the case where the string is empty.
316             return String::new();
317         }
318         // SAFETY:
319         //  - `value.data` contains valid UTF-8 bytes as promised by
320         //    `RustStringRawParts`.
321         //  - `value.data` has been allocated with the Rust allocator and is 1-byte
322         //    aligned as promised by `RustStringRawParts`.
323         //  - `value.data` contains and is allocated for exactly `value.len` bytes.
324         unsafe { String::from_raw_parts(value.data as *mut u8, value.len, value.len) }
325     }
326 }
327 
328 extern "C" {
proto2_rust_utf8_debug_string(msg: RawMessage) -> RustStringRawParts329     fn proto2_rust_utf8_debug_string(msg: RawMessage) -> RustStringRawParts;
330 }
331 
debug_string(msg: RawMessage, f: &mut fmt::Formatter<'_>) -> fmt::Result332 pub fn debug_string(msg: RawMessage, f: &mut fmt::Formatter<'_>) -> fmt::Result {
333     // SAFETY:
334     // - `msg` is a valid protobuf message.
335     let dbg_str: String = unsafe { proto2_rust_utf8_debug_string(msg) }.into();
336     write!(f, "{dbg_str}")
337 }
338 
339 extern "C" {
340     /// # Safety
341     /// - `msg1` and `msg2` legally dereferencable MessageLite* pointers.
342     #[link_name = "proto2_rust_messagelite_equals"]
raw_message_equals(msg1: RawMessage, msg2: RawMessage) -> bool343     pub fn raw_message_equals(msg1: RawMessage, msg2: RawMessage) -> bool;
344 }
345 
346 pub type RawMapIter = UntypedMapIterator;
347 
348 /// The raw contents of every generated message.
349 #[derive(Debug)]
350 #[doc(hidden)]
351 pub struct MessageInner {
352     pub msg: RawMessage,
353 }
354 
355 /// Mutators that point to their original message use this to do so.
356 ///
357 /// Since C++ messages manage their own memory, this can just copy the
358 /// `RawMessage` instead of referencing an arena like UPB must.
359 ///
360 /// Note: even though this type is `Copy`, it should only be copied by
361 /// protobuf internals that can maintain mutation invariants:
362 ///
363 /// - No concurrent mutation for any two fields in a message: this means
364 ///   mutators cannot be `Send` but are `Sync`.
365 /// - If there are multiple accessible `Mut` to a single message at a time, they
366 ///   must be different fields, and not be in the same oneof. As such, a `Mut`
367 ///   cannot be `Clone` but *can* reborrow itself with `.as_mut()`, which
368 ///   converts `&'b mut Mut<'a, T>` to `Mut<'b, T>`.
369 #[derive(Clone, Copy, Debug)]
370 #[doc(hidden)]
371 pub struct MutatorMessageRef<'msg> {
372     msg: RawMessage,
373     _phantom: PhantomData<&'msg mut ()>,
374 }
375 impl<'msg> MutatorMessageRef<'msg> {
376     #[allow(clippy::needless_pass_by_ref_mut)] // Sound construction requires mutable access.
new(msg: &'msg mut MessageInner) -> Self377     pub fn new(msg: &'msg mut MessageInner) -> Self {
378         MutatorMessageRef { msg: msg.msg, _phantom: PhantomData }
379     }
380 
381     /// # Safety
382     /// - The underlying pointer must be sound and live for the lifetime 'msg.
wrap_raw(raw: RawMessage) -> Self383     pub unsafe fn wrap_raw(raw: RawMessage) -> Self {
384         MutatorMessageRef { msg: raw, _phantom: PhantomData }
385     }
386 
from_parent( _parent_msg: MutatorMessageRef<'msg>, message_field_ptr: RawMessage, ) -> Self387     pub fn from_parent(
388         _parent_msg: MutatorMessageRef<'msg>,
389         message_field_ptr: RawMessage,
390     ) -> Self {
391         Self { msg: message_field_ptr, _phantom: PhantomData }
392     }
393 
msg(&self) -> RawMessage394     pub fn msg(&self) -> RawMessage {
395         self.msg
396     }
397 
from_raw_msg(msg: &RawMessage) -> Self398     pub fn from_raw_msg(msg: &RawMessage) -> Self {
399         Self { msg: *msg, _phantom: PhantomData }
400     }
401 }
402 
403 /// The raw type-erased version of an owned `Repeated`.
404 #[derive(Debug)]
405 #[doc(hidden)]
406 pub struct InnerRepeated {
407     raw: RawRepeatedField,
408 }
409 
410 impl InnerRepeated {
as_mut(&mut self) -> InnerRepeatedMut<'_>411     pub fn as_mut(&mut self) -> InnerRepeatedMut<'_> {
412         InnerRepeatedMut::new(self.raw)
413     }
414 
raw(&self) -> RawRepeatedField415     pub fn raw(&self) -> RawRepeatedField {
416         self.raw
417     }
418 
419     /// # Safety
420     /// - `raw` must be a valid `proto2::RepeatedField*` or
421     ///   `proto2::RepeatedPtrField*`.
from_raw(raw: RawRepeatedField) -> Self422     pub unsafe fn from_raw(raw: RawRepeatedField) -> Self {
423         Self { raw }
424     }
425 }
426 
427 /// The raw type-erased pointer version of `RepeatedMut`.
428 ///
429 /// Contains a `proto2::RepeatedField*` or `proto2::RepeatedPtrField*`.
430 #[derive(Clone, Copy, Debug)]
431 #[doc(hidden)]
432 pub struct InnerRepeatedMut<'msg> {
433     pub(crate) raw: RawRepeatedField,
434     _phantom: PhantomData<&'msg ()>,
435 }
436 
437 impl<'msg> InnerRepeatedMut<'msg> {
438     #[doc(hidden)]
new(raw: RawRepeatedField) -> Self439     pub fn new(raw: RawRepeatedField) -> Self {
440         InnerRepeatedMut { raw, _phantom: PhantomData }
441     }
442 }
443 
444 trait CppTypeConversions: Proxied {
445     type InsertElemType;
446     type ElemType;
447 
elem_to_view<'msg>(v: Self::ElemType) -> View<'msg, Self>448     fn elem_to_view<'msg>(v: Self::ElemType) -> View<'msg, Self>;
into_insertelem(v: Self) -> Self::InsertElemType449     fn into_insertelem(v: Self) -> Self::InsertElemType;
450 }
451 
452 macro_rules! impl_cpp_type_conversions_for_scalars {
453     ($($t:ty),* $(,)?) => {
454         $(
455             impl CppTypeConversions for $t {
456                 type InsertElemType = Self;
457                 type ElemType = Self;
458 
459                 fn elem_to_view<'msg>(v: Self) -> View<'msg, Self> {
460                     v
461                 }
462 
463                 fn into_insertelem(v: Self) -> Self {
464                     v
465                 }
466             }
467         )*
468     }
469 }
470 
471 impl_cpp_type_conversions_for_scalars!(i32, u32, i64, u64, f32, f64, bool);
472 
473 impl CppTypeConversions for ProtoString {
474     type InsertElemType = CppStdString;
475     type ElemType = PtrAndLen;
476 
elem_to_view<'msg>(v: PtrAndLen) -> View<'msg, ProtoString>477     fn elem_to_view<'msg>(v: PtrAndLen) -> View<'msg, ProtoString> {
478         ptrlen_to_str(v)
479     }
480 
into_insertelem(v: Self) -> CppStdString481     fn into_insertelem(v: Self) -> CppStdString {
482         v.into_inner(Private).into_raw()
483     }
484 }
485 
486 impl CppTypeConversions for ProtoBytes {
487     type InsertElemType = CppStdString;
488     type ElemType = PtrAndLen;
489 
elem_to_view<'msg>(v: Self::ElemType) -> View<'msg, Self>490     fn elem_to_view<'msg>(v: Self::ElemType) -> View<'msg, Self> {
491         ptrlen_to_bytes(v)
492     }
493 
into_insertelem(v: Self) -> CppStdString494     fn into_insertelem(v: Self) -> CppStdString {
495         v.into_inner(Private).into_raw()
496     }
497 }
498 
499 macro_rules! impl_repeated_primitives {
500     (@impl $($t:ty => [
501         $new_thunk:ident,
502         $free_thunk:ident,
503         $add_thunk:ident,
504         $size_thunk:ident,
505         $get_thunk:ident,
506         $set_thunk:ident,
507         $clear_thunk:ident,
508         $copy_from_thunk:ident,
509         $reserve_thunk:ident $(,)?
510     ]),* $(,)?) => {
511         $(
512             extern "C" {
513                 fn $new_thunk() -> RawRepeatedField;
514                 fn $free_thunk(f: RawRepeatedField);
515                 fn $add_thunk(f: RawRepeatedField, v: <$t as CppTypeConversions>::InsertElemType);
516                 fn $size_thunk(f: RawRepeatedField) -> usize;
517                 fn $get_thunk(
518                     f: RawRepeatedField,
519                     i: usize) -> <$t as CppTypeConversions>::ElemType;
520                 fn $set_thunk(
521                     f: RawRepeatedField,
522                     i: usize,
523                     v: <$t as CppTypeConversions>::InsertElemType);
524                 fn $clear_thunk(f: RawRepeatedField);
525                 fn $copy_from_thunk(src: RawRepeatedField, dst: RawRepeatedField);
526                 fn $reserve_thunk(
527                     f: RawRepeatedField,
528                     additional: usize);
529             }
530 
531             unsafe impl ProxiedInRepeated for $t {
532                 #[allow(dead_code)]
533                 #[inline]
534                 fn repeated_new(_: Private) -> Repeated<$t> {
535                     Repeated::from_inner(Private, InnerRepeated {
536                         raw: unsafe { $new_thunk() }
537                     })
538                 }
539                 #[allow(dead_code)]
540                 #[inline]
541                 unsafe fn repeated_free(_: Private, f: &mut Repeated<$t>) {
542                     unsafe { $free_thunk(f.as_mut().as_raw(Private)) }
543                 }
544                 #[inline]
545                 fn repeated_len(f: View<Repeated<$t>>) -> usize {
546                     unsafe { $size_thunk(f.as_raw(Private)) }
547                 }
548                 #[inline]
549                 fn repeated_push(mut f: Mut<Repeated<$t>>, v: impl IntoProxied<$t>) {
550                     unsafe { $add_thunk(f.as_raw(Private), <$t as CppTypeConversions>::into_insertelem(v.into_proxied(Private))) }
551                 }
552                 #[inline]
553                 fn repeated_clear(mut f: Mut<Repeated<$t>>) {
554                     unsafe { $clear_thunk(f.as_raw(Private)) }
555                 }
556                 #[inline]
557                 unsafe fn repeated_get_unchecked(f: View<Repeated<$t>>, i: usize) -> View<$t> {
558                     <$t as CppTypeConversions>::elem_to_view(
559                         unsafe { $get_thunk(f.as_raw(Private), i) })
560                 }
561                 #[inline]
562                 unsafe fn repeated_set_unchecked(mut f: Mut<Repeated<$t>>, i: usize, v: impl IntoProxied<$t>) {
563                     unsafe { $set_thunk(f.as_raw(Private), i, <$t as CppTypeConversions>::into_insertelem(v.into_proxied(Private))) }
564                 }
565                 #[inline]
566                 fn repeated_copy_from(src: View<Repeated<$t>>, mut dest: Mut<Repeated<$t>>) {
567                     unsafe { $copy_from_thunk(src.as_raw(Private), dest.as_raw(Private)) }
568                 }
569                 #[inline]
570                 fn repeated_reserve(mut f: Mut<Repeated<$t>>, additional: usize) {
571                     unsafe { $reserve_thunk(f.as_raw(Private), additional) }
572                 }
573             }
574         )*
575     };
576     ($($t:ty),* $(,)?) => {
577         paste!{
578             impl_repeated_primitives!(@impl $(
579                 $t => [
580                     [< proto2_rust_RepeatedField_ $t _new >],
581                     [< proto2_rust_RepeatedField_ $t _free >],
582                     [< proto2_rust_RepeatedField_ $t _add >],
583                     [< proto2_rust_RepeatedField_ $t _size >],
584                     [< proto2_rust_RepeatedField_ $t _get >],
585                     [< proto2_rust_RepeatedField_ $t _set >],
586                     [< proto2_rust_RepeatedField_ $t _clear >],
587                     [< proto2_rust_RepeatedField_ $t _copy_from >],
588                     [< proto2_rust_RepeatedField_ $t _reserve >],
589                 ],
590             )*);
591         }
592     };
593 }
594 
595 impl_repeated_primitives!(i32, u32, i64, u64, f32, f64, bool, ProtoString, ProtoBytes);
596 
597 /// Cast a `RepeatedView<SomeEnum>` to `RepeatedView<c_int>`.
cast_enum_repeated_view<E: Enum + ProxiedInRepeated>( repeated: RepeatedView<E>, ) -> RepeatedView<c_int>598 pub fn cast_enum_repeated_view<E: Enum + ProxiedInRepeated>(
599     repeated: RepeatedView<E>,
600 ) -> RepeatedView<c_int> {
601     // SAFETY: the implementer of `Enum` has promised that this
602     // raw repeated is a type-erased `proto2::RepeatedField<int>*`.
603     unsafe { RepeatedView::from_raw(Private, repeated.as_raw(Private)) }
604 }
605 
606 /// Cast a `RepeatedMut<SomeEnum>` to `RepeatedMut<c_int>`.
607 ///
608 /// Writing an unknown value is sound because all enums
609 /// are representationally open.
cast_enum_repeated_mut<E: Enum + ProxiedInRepeated>( mut repeated: RepeatedMut<E>, ) -> RepeatedMut<c_int>610 pub fn cast_enum_repeated_mut<E: Enum + ProxiedInRepeated>(
611     mut repeated: RepeatedMut<E>,
612 ) -> RepeatedMut<c_int> {
613     // SAFETY: the implementer of `Enum` has promised that this
614     // raw repeated is a type-erased `proto2::RepeatedField<int>*`.
615     unsafe {
616         RepeatedMut::from_inner(
617             Private,
618             InnerRepeatedMut { raw: repeated.as_raw(Private), _phantom: PhantomData },
619         )
620     }
621 }
622 
623 /// Cast a `RepeatedMut<SomeEnum>` to `RepeatedMut<c_int>` and call
624 /// repeated_reserve.
reserve_enum_repeated_mut<E: Enum + ProxiedInRepeated>( repeated: RepeatedMut<E>, additional: usize, )625 pub fn reserve_enum_repeated_mut<E: Enum + ProxiedInRepeated>(
626     repeated: RepeatedMut<E>,
627     additional: usize,
628 ) {
629     let int_repeated = cast_enum_repeated_mut(repeated);
630     ProxiedInRepeated::repeated_reserve(int_repeated, additional);
631 }
632 
new_enum_repeated<E: Enum + ProxiedInRepeated>() -> Repeated<E>633 pub fn new_enum_repeated<E: Enum + ProxiedInRepeated>() -> Repeated<E> {
634     let int_repeated = Repeated::<c_int>::new();
635     let raw = int_repeated.inner.raw();
636     std::mem::forget(int_repeated);
637     unsafe { Repeated::from_inner(Private, InnerRepeated::from_raw(raw)) }
638 }
639 
640 /// Cast a `RepeatedMut<SomeEnum>` to `RepeatedMut<c_int>` and call
641 /// repeated_free.
642 /// # Safety
643 /// - The passed in `&mut Repeated<E>` must not be used after this function is
644 ///   called.
free_enum_repeated<E: Enum + ProxiedInRepeated>(repeated: &mut Repeated<E>)645 pub unsafe fn free_enum_repeated<E: Enum + ProxiedInRepeated>(repeated: &mut Repeated<E>) {
646     unsafe {
647         let mut int_r: Repeated<c_int> =
648             Repeated::from_inner(Private, InnerRepeated::from_raw(repeated.inner.raw()));
649         ProxiedInRepeated::repeated_free(Private, &mut int_r);
650         std::mem::forget(int_r);
651     }
652 }
653 
654 #[derive(Debug)]
655 #[doc(hidden)]
656 pub struct InnerMap {
657     pub(crate) raw: RawMap,
658 }
659 
660 impl InnerMap {
new(raw: RawMap) -> Self661     pub fn new(raw: RawMap) -> Self {
662         Self { raw }
663     }
664 
as_mut(&mut self) -> InnerMapMut<'_>665     pub fn as_mut(&mut self) -> InnerMapMut<'_> {
666         InnerMapMut { raw: self.raw, _phantom: PhantomData }
667     }
668 }
669 
670 #[derive(Clone, Copy, Debug)]
671 #[doc(hidden)]
672 pub struct InnerMapMut<'msg> {
673     pub(crate) raw: RawMap,
674     _phantom: PhantomData<&'msg ()>,
675 }
676 
677 #[doc(hidden)]
678 impl<'msg> InnerMapMut<'msg> {
new(raw: RawMap) -> Self679     pub fn new(raw: RawMap) -> Self {
680         InnerMapMut { raw, _phantom: PhantomData }
681     }
682 
as_raw(&self) -> RawMap683     pub fn as_raw(&self) -> RawMap {
684         self.raw
685     }
686 }
687 
688 /// An untyped iterator in a map, produced via `.cbegin()` on a typed map.
689 ///
690 /// This struct is ABI-compatible with `proto2::internal::UntypedMapIterator`.
691 /// It is trivially constructible and destructible.
692 #[repr(C)]
693 #[doc(hidden)]
694 pub struct UntypedMapIterator {
695     node: *mut c_void,
696     map: *const c_void,
697     bucket_index: u32,
698 }
699 
700 impl UntypedMapIterator {
701     /// Returns `true` if this iterator is at the end of the map.
at_end(&self) -> bool702     fn at_end(&self) -> bool {
703         // This behavior is verified via test `IteratorNodeFieldIsNullPtrAtEnd`.
704         self.node.is_null()
705     }
706 
707     /// Assumes that the map iterator is for the input types, gets the current
708     /// entry, and moves the iterator forward to the next entry.
709     ///
710     /// Conversion to and from FFI types is provided by the user.
711     /// This is a helper function for implementing
712     /// `ProxiedInMapValue::iter_next`.
713     ///
714     /// # Safety
715     /// - The backing map must be valid and not be mutated for `'a`.
716     /// - The thunk must be safe to call if the iterator is not at the end of
717     ///   the map.
718     /// - The thunk must always write to the `key` and `value` fields, but not
719     ///   read from them.
720     /// - The get thunk must not move the iterator forward or backward.
721     #[inline(always)]
next_unchecked<'a, K, V, FfiKey, FfiValue>( &mut self, iter_get_thunk: unsafe fn( iter: &mut UntypedMapIterator, key: *mut FfiKey, value: *mut FfiValue, ), from_ffi_key: impl FnOnce(FfiKey) -> View<'a, K>, from_ffi_value: impl FnOnce(FfiValue) -> View<'a, V>, ) -> Option<(View<'a, K>, View<'a, V>)> where K: Proxied + 'a, V: ProxiedInMapValue<K> + 'a,722     pub unsafe fn next_unchecked<'a, K, V, FfiKey, FfiValue>(
723         &mut self,
724 
725         iter_get_thunk: unsafe fn(
726             iter: &mut UntypedMapIterator,
727             key: *mut FfiKey,
728             value: *mut FfiValue,
729         ),
730         from_ffi_key: impl FnOnce(FfiKey) -> View<'a, K>,
731         from_ffi_value: impl FnOnce(FfiValue) -> View<'a, V>,
732     ) -> Option<(View<'a, K>, View<'a, V>)>
733     where
734         K: Proxied + 'a,
735         V: ProxiedInMapValue<K> + 'a,
736     {
737         if self.at_end() {
738             return None;
739         }
740         let mut ffi_key = MaybeUninit::uninit();
741         let mut ffi_value = MaybeUninit::uninit();
742         // SAFETY:
743         // - The backing map outlives `'a`.
744         // - The iterator is not at the end (node is non-null).
745         // - `ffi_key` and `ffi_value` are not read (as uninit) as promised by the
746         //   caller.
747         unsafe { (iter_get_thunk)(self, ffi_key.as_mut_ptr(), ffi_value.as_mut_ptr()) }
748 
749         // SAFETY:
750         // - The backing map is alive as promised by the caller.
751         // - `self.at_end()` is false and the `get` does not change that.
752         // - `UntypedMapIterator` has the same ABI as
753         //   `proto2::internal::UntypedMapIterator`. It is statically checked to be:
754         //   - Trivially copyable.
755         //   - Trivially destructible.
756         //   - Standard layout.
757         //   - The size and alignment of the Rust type above.
758         //   - With the `node_` field first.
759         unsafe { proto2_rust_thunk_UntypedMapIterator_increment(self) }
760 
761         // SAFETY:
762         // - The `get` function always writes valid values to `ffi_key` and `ffi_value`
763         //   as promised by the caller.
764         unsafe {
765             Some((from_ffi_key(ffi_key.assume_init()), from_ffi_value(ffi_value.assume_init())))
766         }
767     }
768 }
769 
770 #[doc(hidden)]
771 #[repr(transparent)]
772 pub struct MapNodeSizeInfoIndex(i32);
773 
774 #[doc(hidden)]
775 pub trait MapNodeSizeInfoIndexForType {
776     const SIZE_INFO_INDEX: MapNodeSizeInfoIndex;
777 }
778 
779 macro_rules! generate_map_node_size_info_mapping {
780     ( $($key:ty, $index:expr;)* ) => {
781         $(
782         impl MapNodeSizeInfoIndexForType for $key {
783             const SIZE_INFO_INDEX: MapNodeSizeInfoIndex = MapNodeSizeInfoIndex($index);
784         }
785         )*
786     }
787 }
788 
789 // LINT.IfChange(size_info_mapping)
790 generate_map_node_size_info_mapping!(
791     i32, 0;
792     u32, 0;
793     i64, 1;
794     u64, 1;
795     bool, 2;
796     ProtoString, 3;
797 );
798 // LINT.ThenChange(//depot/google3/third_party/protobuf/compiler/rust/message.
799 // cc:size_info_mapping)
800 
801 macro_rules! impl_map_primitives {
802     (@impl $(($rust_type:ty, $cpp_type:ty) => [
803         $insert_thunk:ident,
804         $get_thunk:ident,
805         $iter_get_thunk:ident,
806         $remove_thunk:ident,
807     ]),* $(,)?) => {
808         $(
809             extern "C" {
810                 pub fn $insert_thunk(
811                     m: RawMap,
812                     size_info: MapNodeSizeInfo,
813                     key: $cpp_type,
814                     value: RawMessage,
815                 ) -> bool;
816                 pub fn $get_thunk(
817                     m: RawMap,
818                     size_info: MapNodeSizeInfo,
819                     key: $cpp_type,
820                     value: *mut RawMessage,
821                 ) -> bool;
822                 pub fn $iter_get_thunk(
823                     iter: &mut UntypedMapIterator,
824                     size_info: MapNodeSizeInfo,
825                     key: *mut $cpp_type,
826                     value: *mut RawMessage,
827                 );
828                 pub fn $remove_thunk(m: RawMap, size_info: MapNodeSizeInfo, key: $cpp_type) -> bool;
829             }
830         )*
831     };
832     ($($rust_type:ty, $cpp_type:ty;)* $(,)?) => {
833         paste!{
834             impl_map_primitives!(@impl $(
835                     ($rust_type, $cpp_type) => [
836                     [< proto2_rust_map_insert_ $rust_type >],
837                     [< proto2_rust_map_get_ $rust_type >],
838                     [< proto2_rust_map_iter_get_ $rust_type >],
839                     [< proto2_rust_map_remove_ $rust_type >],
840                 ],
841             )*);
842         }
843     };
844 }
845 
846 impl_map_primitives!(
847     i32, i32;
848     u32, u32;
849     i64, i64;
850     u64, u64;
851     bool, bool;
852     ProtoString, PtrAndLen;
853 );
854 
855 extern "C" {
proto2_rust_thunk_UntypedMapIterator_increment(iter: &mut UntypedMapIterator)856     fn proto2_rust_thunk_UntypedMapIterator_increment(iter: &mut UntypedMapIterator);
857 
proto2_rust_map_new() -> RawMap858     pub fn proto2_rust_map_new() -> RawMap;
proto2_rust_map_free(m: RawMap, key_is_string: bool, size_info: MapNodeSizeInfo)859     pub fn proto2_rust_map_free(m: RawMap, key_is_string: bool, size_info: MapNodeSizeInfo);
proto2_rust_map_clear(m: RawMap, key_is_string: bool, size_info: MapNodeSizeInfo)860     pub fn proto2_rust_map_clear(m: RawMap, key_is_string: bool, size_info: MapNodeSizeInfo);
proto2_rust_map_size(m: RawMap) -> usize861     pub fn proto2_rust_map_size(m: RawMap) -> usize;
proto2_rust_map_iter(m: RawMap) -> UntypedMapIterator862     pub fn proto2_rust_map_iter(m: RawMap) -> UntypedMapIterator;
863 }
864 
865 macro_rules! impl_ProxiedInMapValue_for_non_generated_value_types {
866     ($key_t:ty, $ffi_key_t:ty, $to_ffi_key:expr, $from_ffi_key:expr, for $($t:ty, $ffi_view_t:ty, $ffi_value_t:ty, $to_ffi_value:expr, $from_ffi_value:expr;)*) => {
867         paste! { $(
868             extern "C" {
869                 pub fn [< proto2_rust_thunk_Map_ $key_t _ $t _new >]() -> RawMap;
870                 pub fn [< proto2_rust_thunk_Map_ $key_t _ $t _free >](m: RawMap);
871                 pub fn [< proto2_rust_thunk_Map_ $key_t _ $t _clear >](m: RawMap);
872                 pub fn [< proto2_rust_thunk_Map_ $key_t _ $t _size >](m: RawMap) -> usize;
873                 pub fn [< proto2_rust_thunk_Map_ $key_t _ $t _insert >](m: RawMap, key: $ffi_key_t, value: $ffi_value_t) -> bool;
874                 pub fn [< proto2_rust_thunk_Map_ $key_t _ $t _get >](m: RawMap, key: $ffi_key_t, value: *mut $ffi_view_t) -> bool;
875                 pub fn [< proto2_rust_thunk_Map_ $key_t _ $t _iter >](m: RawMap) -> UntypedMapIterator;
876                 pub fn [< proto2_rust_thunk_Map_ $key_t _ $t _iter_get >](iter: &mut UntypedMapIterator, key: *mut $ffi_key_t, value: *mut $ffi_view_t);
877                 pub fn [< proto2_rust_thunk_Map_ $key_t _ $t _remove >](m: RawMap, key: $ffi_key_t, value: *mut $ffi_view_t) -> bool;
878             }
879 
880             impl ProxiedInMapValue<$key_t> for $t {
881                 fn map_new(_private: Private) -> Map<$key_t, Self> {
882                     unsafe {
883                         Map::from_inner(
884                             Private,
885                             InnerMap {
886                                 raw: [< proto2_rust_thunk_Map_ $key_t _ $t _new >](),
887                             }
888                         )
889                     }
890                 }
891 
892                 unsafe fn map_free(_private: Private, map: &mut Map<$key_t, Self>) {
893                     // SAFETY:
894                     // - `map.inner.raw` is a live `RawMap`
895                     // - This function is only called once for `map` in `Drop`.
896                     unsafe { [< proto2_rust_thunk_Map_ $key_t _ $t _free >](map.as_mut().as_raw(Private)); }
897                 }
898 
899 
900                 fn map_clear(mut map: MapMut<$key_t, Self>) {
901                     unsafe { [< proto2_rust_thunk_Map_ $key_t _ $t _clear >](map.as_raw(Private)); }
902                 }
903 
904                 fn map_len(map: MapView<$key_t, Self>) -> usize {
905                     unsafe { [< proto2_rust_thunk_Map_ $key_t _ $t _size >](map.as_raw(Private)) }
906                 }
907 
908                 fn map_insert(mut map: MapMut<$key_t, Self>, key: View<'_, $key_t>, value: impl IntoProxied<Self>) -> bool {
909                     let ffi_key = $to_ffi_key(key);
910                     let ffi_value = $to_ffi_value(value.into_proxied(Private));
911                     unsafe { [< proto2_rust_thunk_Map_ $key_t _ $t _insert >](map.as_raw(Private), ffi_key, ffi_value) }
912                 }
913 
914                 fn map_get<'a>(map: MapView<'a, $key_t, Self>, key: View<'_, $key_t>) -> Option<View<'a, Self>> {
915                     let ffi_key = $to_ffi_key(key);
916                     let mut ffi_value = MaybeUninit::uninit();
917                     let found = unsafe { [< proto2_rust_thunk_Map_ $key_t _ $t _get >](map.as_raw(Private), ffi_key, ffi_value.as_mut_ptr()) };
918 
919                     if !found {
920                         return None;
921                     }
922                     // SAFETY: if `found` is true, then the `ffi_value` was written to by `get`.
923                     Some($from_ffi_value(unsafe { ffi_value.assume_init() }))
924                 }
925 
926                 fn map_remove(mut map: MapMut<$key_t, Self>, key: View<'_, $key_t>) -> bool {
927                     let ffi_key = $to_ffi_key(key);
928                     let mut ffi_value = MaybeUninit::uninit();
929                     unsafe { [< proto2_rust_thunk_Map_ $key_t _ $t _remove >](map.as_raw(Private), ffi_key, ffi_value.as_mut_ptr()) }
930                 }
931 
932                 fn map_iter(map: MapView<$key_t, Self>) -> MapIter<$key_t, Self> {
933                     // SAFETY:
934                     // - The backing map for `map.as_raw` is valid for at least '_.
935                     // - A View that is live for '_ guarantees the backing map is unmodified for '_.
936                     // - The `iter` function produces an iterator that is valid for the key
937                     //   and value types, and live for at least '_.
938                     unsafe {
939                         MapIter::from_raw(
940                             Private,
941                             [< proto2_rust_thunk_Map_ $key_t _ $t _iter >](map.as_raw(Private))
942                         )
943                     }
944                 }
945 
946                 fn map_iter_next<'a>(iter: &mut MapIter<'a, $key_t, Self>) -> Option<(View<'a, $key_t>, View<'a, Self>)> {
947                     // SAFETY:
948                     // - The `MapIter` API forbids the backing map from being mutated for 'a,
949                     //   and guarantees that it's the correct key and value types.
950                     // - The thunk is safe to call as long as the iterator isn't at the end.
951                     // - The thunk always writes to key and value fields and does not read.
952                     // - The thunk does not increment the iterator.
953                     unsafe {
954                         iter.as_raw_mut(Private).next_unchecked::<$key_t, Self, _, _>(
955                             |iter, key, value| { [< proto2_rust_thunk_Map_ $key_t _ $t _iter_get >](iter, key, value) },
956                             $from_ffi_key,
957                             $from_ffi_value,
958                         )
959                     }
960                 }
961             }
962          )* }
963     }
964 }
965 
str_to_ptrlen<'msg>(val: impl Into<&'msg ProtoStr>) -> PtrAndLen966 fn str_to_ptrlen<'msg>(val: impl Into<&'msg ProtoStr>) -> PtrAndLen {
967     val.into().as_bytes().into()
968 }
969 
970 // Warning: this function is unsound on its own! `val.as_ref()` must be safe to
971 // call.
ptrlen_to_str<'msg>(val: PtrAndLen) -> &'msg ProtoStr972 fn ptrlen_to_str<'msg>(val: PtrAndLen) -> &'msg ProtoStr {
973     unsafe { ProtoStr::from_utf8_unchecked(val.as_ref()) }
974 }
975 
protostr_into_cppstdstring(val: ProtoString) -> CppStdString976 fn protostr_into_cppstdstring(val: ProtoString) -> CppStdString {
977     val.into_inner(Private).into_raw()
978 }
979 
protobytes_into_cppstdstring(val: ProtoBytes) -> CppStdString980 fn protobytes_into_cppstdstring(val: ProtoBytes) -> CppStdString {
981     val.into_inner(Private).into_raw()
982 }
983 
984 // Warning: this function is unsound on its own! `val.as_ref()` must be safe to
985 // call.
ptrlen_to_bytes<'msg>(val: PtrAndLen) -> &'msg [u8]986 fn ptrlen_to_bytes<'msg>(val: PtrAndLen) -> &'msg [u8] {
987     unsafe { val.as_ref() }
988 }
989 
990 macro_rules! impl_ProxiedInMapValue_for_key_types {
991     ($($t:ty, $ffi_t:ty, $to_ffi_key:expr, $from_ffi_key:expr;)*) => {
992         paste! {
993             $(
994                 impl_ProxiedInMapValue_for_non_generated_value_types!(
995                     $t, $ffi_t, $to_ffi_key, $from_ffi_key, for
996                     f32, f32, f32, identity, identity;
997                     f64, f64, f64, identity, identity;
998                     i32, i32, i32, identity, identity;
999                     u32, u32, u32, identity, identity;
1000                     i64, i64, i64, identity, identity;
1001                     u64, u64, u64, identity, identity;
1002                     bool, bool, bool, identity, identity;
1003                     ProtoString, PtrAndLen, CppStdString, protostr_into_cppstdstring, ptrlen_to_str;
1004                     ProtoBytes, PtrAndLen, CppStdString, protobytes_into_cppstdstring, ptrlen_to_bytes;
1005                 );
1006             )*
1007         }
1008     }
1009 }
1010 
1011 impl_ProxiedInMapValue_for_key_types!(
1012     i32, i32, identity, identity;
1013     u32, u32, identity, identity;
1014     i64, i64, identity, identity;
1015     u64, u64, identity, identity;
1016     bool, bool, identity, identity;
1017     ProtoString, PtrAndLen, str_to_ptrlen, ptrlen_to_str;
1018 );
1019 
1020 #[cfg(test)]
1021 mod tests {
1022     use super::*;
1023     use googletest::prelude::*;
1024 
1025     // We need to allocate the byte array so SerializedData can own it and
1026     // deallocate it in its drop. This function makes it easier to do so for our
1027     // tests.
allocate_byte_array(content: &'static [u8]) -> (*mut u8, usize)1028     fn allocate_byte_array(content: &'static [u8]) -> (*mut u8, usize) {
1029         let content: &mut [u8] = Box::leak(content.into());
1030         (content.as_mut_ptr(), content.len())
1031     }
1032 
1033     #[gtest]
test_serialized_data_roundtrip()1034     fn test_serialized_data_roundtrip() {
1035         let (ptr, len) = allocate_byte_array(b"Hello world");
1036         let serialized_data = SerializedData { data: NonNull::new(ptr).unwrap(), len };
1037         assert_that!(&*serialized_data, eq(b"Hello world"));
1038     }
1039 
1040     #[gtest]
test_empty_string()1041     fn test_empty_string() {
1042         let empty_str: String = RustStringRawParts { data: std::ptr::null(), len: 0 }.into();
1043         assert_that!(empty_str, eq(""));
1044     }
1045 }
1046