Protobuf Team Bot | 5a48187 | 2023-06-14 10:29:31 -0700 | [diff] [blame] | 1 | // Protocol Buffers - Google's data interchange format |
Hong Shin | 4f20efb | 2023-07-10 07:35:36 -0700 | [diff] [blame] | 2 | // Copyright 2023 Google LLC. All rights reserved. |
Protobuf Team Bot | 5a48187 | 2023-06-14 10:29: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 |
Protobuf Team Bot | 5a48187 | 2023-06-14 10:29:31 -0700 | [diff] [blame] | 7 | |
| 8 | //! Kernel-agnostic logic for the Rust Protobuf runtime that should not be |
| 9 | //! exposed to through the `protobuf` path but must be public for use by |
| 10 | //! generated code. |
| 11 | |
Alyssa Haroldsen | 9a0bc39 | 2023-08-23 11:05:31 -0700 | [diff] [blame] | 12 | pub use crate::vtable::{ |
Adrian Sadłocha | c303109 | 2023-10-18 08:34:52 -0700 | [diff] [blame] | 13 | new_vtable_field_entry, BytesMutVTable, BytesOptionalMutVTable, PrimitiveOptionalMutVTable, |
| 14 | PrimitiveVTable, RawVTableMutator, |
Alyssa Haroldsen | 9a0bc39 | 2023-08-23 11:05:31 -0700 | [diff] [blame] | 15 | }; |
Hong Shin | 5c33ed0 | 2023-08-24 16:34:08 -0700 | [diff] [blame] | 16 | use std::ptr::NonNull; |
Protobuf Team Bot | 5a48187 | 2023-06-14 10:29:31 -0700 | [diff] [blame] | 17 | use std::slice; |
| 18 | |
Protobuf Team Bot | 29a2615 | 2023-06-22 09:51:38 -0700 | [diff] [blame] | 19 | /// Used to protect internal-only items from being used accidentally. |
| 20 | pub struct Private; |
| 21 | |
Hong Shin | 5c33ed0 | 2023-08-24 16:34:08 -0700 | [diff] [blame] | 22 | /// Defines a set of opaque, unique, non-accessible pointees. |
| 23 | /// |
| 24 | /// The [Rustonomicon][nomicon] currently recommends a zero-sized struct, |
| 25 | /// though this should use [`extern type`] when that is stabilized. |
| 26 | /// [nomicon]: https://doc.rust-lang.org/nomicon/ffi.html#representing-opaque-structs |
| 27 | /// [`extern type`]: https://github.com/rust-lang/rust/issues/43467 |
| 28 | mod _opaque_pointees { |
| 29 | /// Opaque pointee for [`RawMessage`] |
| 30 | /// |
| 31 | /// This type is not meant to be dereferenced in Rust code. |
| 32 | /// It is only meant to provide type safety for raw pointers |
| 33 | /// which are manipulated behind FFI. |
| 34 | /// |
| 35 | /// [`RawMessage`]: super::RawMessage |
| 36 | #[repr(C)] |
| 37 | pub struct RawMessageData { |
| 38 | _data: [u8; 0], |
| 39 | _marker: std::marker::PhantomData<(*mut u8, ::std::marker::PhantomPinned)>, |
| 40 | } |
Protobuf Team Bot | 1525300 | 2023-08-01 16:20:23 -0700 | [diff] [blame] | 41 | |
Hong Shin | 5c33ed0 | 2023-08-24 16:34:08 -0700 | [diff] [blame] | 42 | /// Opaque pointee for [`RawArena`] |
| 43 | /// |
| 44 | /// This type is not meant to be dereferenced in Rust code. |
| 45 | /// It is only meant to provide type safety for raw pointers |
| 46 | /// which are manipulated behind FFI. |
| 47 | /// |
| 48 | /// [`RawArena`]: super::RawArena |
| 49 | #[repr(C)] |
| 50 | pub struct RawArenaData { |
| 51 | _data: [u8; 0], |
| 52 | _marker: std::marker::PhantomData<(*mut u8, ::std::marker::PhantomPinned)>, |
| 53 | } |
Protobuf Team Bot | e1bb7d6 | 2023-10-17 14:15:37 -0700 | [diff] [blame] | 54 | |
| 55 | /// Opaque pointee for [`RawRepeatedField`] |
| 56 | /// |
| 57 | /// This type is not meant to be dereferenced in Rust code. |
| 58 | /// It is only meant to provide type safety for raw pointers |
| 59 | /// which are manipulated behind FFI. |
| 60 | #[repr(C)] |
| 61 | pub struct RawRepeatedFieldData { |
| 62 | _data: [u8; 0], |
| 63 | _marker: std::marker::PhantomData<(*mut u8, ::std::marker::PhantomPinned)>, |
| 64 | } |
Jakob Buchgraber | ac3f553 | 2023-11-08 02:13:42 -0800 | [diff] [blame] | 65 | |
| 66 | /// Opaque pointee for [`RawMap`] |
| 67 | /// |
| 68 | /// This type is not meant to be dereferenced in Rust code. |
| 69 | /// It is only meant to provide type safety for raw pointers |
| 70 | /// which are manipulated behind FFI. |
| 71 | #[repr(C)] |
| 72 | pub struct RawMapData { |
| 73 | _data: [u8; 0], |
| 74 | _marker: std::marker::PhantomData<(*mut u8, ::std::marker::PhantomPinned)>, |
| 75 | } |
Hong Shin | 5c33ed0 | 2023-08-24 16:34:08 -0700 | [diff] [blame] | 76 | } |
| 77 | |
| 78 | /// A raw pointer to the underlying message for this runtime. |
| 79 | pub type RawMessage = NonNull<_opaque_pointees::RawMessageData>; |
| 80 | |
| 81 | /// A raw pointer to the underlying arena for this runtime. |
| 82 | pub type RawArena = NonNull<_opaque_pointees::RawArenaData>; |
Protobuf Team Bot | 1525300 | 2023-08-01 16:20:23 -0700 | [diff] [blame] | 83 | |
Protobuf Team Bot | e1bb7d6 | 2023-10-17 14:15:37 -0700 | [diff] [blame] | 84 | /// A raw pointer to the underlying repeated field container for this runtime. |
| 85 | pub type RawRepeatedField = NonNull<_opaque_pointees::RawRepeatedFieldData>; |
| 86 | |
Jakob Buchgraber | ac3f553 | 2023-11-08 02:13:42 -0800 | [diff] [blame] | 87 | /// A raw pointer to the underlying arena for this runtime. |
| 88 | pub type RawMap = NonNull<_opaque_pointees::RawMapData>; |
| 89 | |
Protobuf Team Bot | 5a48187 | 2023-06-14 10:29:31 -0700 | [diff] [blame] | 90 | /// Represents an ABI-stable version of `NonNull<[u8]>`/`string_view` (a |
| 91 | /// borrowed slice of bytes) for FFI use only. |
| 92 | /// |
| 93 | /// Has semantics similar to `std::string_view` in C++ and `&[u8]` in Rust, |
| 94 | /// but is not ABI-compatible with either. |
| 95 | /// |
| 96 | /// If `len` is 0, then `ptr` can be null or dangling. C++ considers a dangling |
| 97 | /// 0-len `std::string_view` to be invalid, and Rust considers a `&[u8]` with a |
| 98 | /// null data pointer to be invalid. |
| 99 | #[repr(C)] |
| 100 | #[derive(Copy, Clone)] |
| 101 | pub struct PtrAndLen { |
| 102 | /// Pointer to the first byte. |
| 103 | /// Borrows the memory. |
| 104 | pub ptr: *const u8, |
| 105 | |
| 106 | /// Length of the `[u8]` pointed to by `ptr`. |
| 107 | pub len: usize, |
| 108 | } |
| 109 | |
| 110 | impl PtrAndLen { |
| 111 | /// Unsafely dereference this slice. |
| 112 | /// |
| 113 | /// # Safety |
Protobuf Team Bot | 49d3bca | 2023-07-18 11:46:53 -0700 | [diff] [blame] | 114 | /// - `self.ptr` must be dereferencable and immutable for `self.len` bytes |
| 115 | /// for the lifetime `'a`. It can be null or dangling if `self.len == 0`. |
Protobuf Team Bot | 5a48187 | 2023-06-14 10:29:31 -0700 | [diff] [blame] | 116 | pub unsafe fn as_ref<'a>(self) -> &'a [u8] { |
| 117 | if self.ptr.is_null() { |
| 118 | assert_eq!(self.len, 0, "Non-empty slice with null data pointer"); |
| 119 | &[] |
| 120 | } else { |
Protobuf Team Bot | 49d3bca | 2023-07-18 11:46:53 -0700 | [diff] [blame] | 121 | // SAFETY: |
| 122 | // - `ptr` is non-null |
| 123 | // - `ptr` is valid for `len` bytes as promised by the caller. |
| 124 | unsafe { slice::from_raw_parts(self.ptr, self.len) } |
Protobuf Team Bot | 5a48187 | 2023-06-14 10:29:31 -0700 | [diff] [blame] | 125 | } |
| 126 | } |
| 127 | } |
Protobuf Team Bot | 78d71ca | 2023-09-13 11:55:59 -0700 | [diff] [blame] | 128 | |
| 129 | impl From<&[u8]> for PtrAndLen { |
| 130 | fn from(slice: &[u8]) -> Self { |
| 131 | Self { ptr: slice.as_ptr(), len: slice.len() } |
| 132 | } |
| 133 | } |