Marcel Hlopko | ab9f1ab | 2023-03-16 04:57:32 -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. |
Marcel Hlopko | ab9f1ab | 2023-03-16 04:57:32 -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 |
Marcel Hlopko | ab9f1ab | 2023-03-16 04:57:32 -0700 | [diff] [blame] | 7 | |
Miguel Young de la Sota | 8e53046 | 2023-04-20 09:54:41 -0700 | [diff] [blame] | 8 | //! UPB FFI wrapper code for use by Rust Protobuf. |
Marcel Hlopko | ab9f1ab | 2023-03-16 04:57:32 -0700 | [diff] [blame] | 9 | |
Protobuf Team Bot | c7d4697 | 2024-07-30 05:39:53 -0700 | [diff] [blame] | 10 | use crate::__internal::{Enum, Private, SealedInternal}; |
Jakob Buchgraber | b539fa9 | 2023-12-20 02:41:41 -0800 | [diff] [blame] | 11 | use crate::{ |
Adam Cozzette | 1142838 | 2024-09-12 11:22:07 -0700 | [diff] [blame] | 12 | IntoProxied, Map, MapIter, MapMut, MapView, Mut, ProtoBytes, ProtoStr, ProtoString, Proxied, |
| 13 | ProxiedInMapValue, ProxiedInRepeated, Repeated, RepeatedMut, RepeatedView, View, |
Jakob Buchgraber | b539fa9 | 2023-12-20 02:41:41 -0800 | [diff] [blame] | 14 | }; |
Jakob Buchgraber | 95073f8 | 2023-11-21 04:27:56 -0800 | [diff] [blame] | 15 | use core::fmt::Debug; |
Protobuf Team Bot | e26ef86 | 2024-08-26 05:14:52 -0700 | [diff] [blame] | 16 | use std::mem::{size_of, ManuallyDrop, MaybeUninit}; |
Adam Cozzette | c3df359 | 2024-09-05 11:09:02 -0700 | [diff] [blame] | 17 | use std::ptr::{self, NonNull}; |
| 18 | use std::slice; |
| 19 | use std::sync::OnceLock; |
Marcel Hlopko | 5814f6c | 2023-04-11 12:57:07 -0700 | [diff] [blame] | 20 | |
Derek Benson | 6f58085 | 2024-07-26 08:09:33 -0700 | [diff] [blame] | 21 | #[cfg(bzl)] |
Protobuf Team Bot | 2678e10 | 2024-04-12 13:50:28 -0700 | [diff] [blame] | 22 | extern crate upb; |
Derek Benson | 6f58085 | 2024-07-26 08:09:33 -0700 | [diff] [blame] | 23 | #[cfg(not(bzl))] |
| 24 | use crate::upb; |
Protobuf Team Bot | 2678e10 | 2024-04-12 13:50:28 -0700 | [diff] [blame] | 25 | |
| 26 | // Temporarily 'pub' since a lot of gencode is directly calling any of the ffi |
| 27 | // fns. |
| 28 | pub use upb::*; |
| 29 | |
| 30 | pub type RawArena = upb::RawArena; |
| 31 | pub type RawMessage = upb::RawMessage; |
| 32 | pub type RawRepeatedField = upb::RawArray; |
| 33 | pub type RawMap = upb::RawMap; |
| 34 | pub type PtrAndLen = upb::StringView; |
| 35 | |
| 36 | impl From<&ProtoStr> for PtrAndLen { |
| 37 | fn from(s: &ProtoStr) -> Self { |
| 38 | let bytes = s.as_bytes(); |
| 39 | Self { ptr: bytes.as_ptr(), len: bytes.len() } |
| 40 | } |
| 41 | } |
| 42 | |
Alyssa Haroldsen | 4395d97 | 2024-02-23 00:15:08 -0800 | [diff] [blame] | 43 | /// The scratch size of 64 KiB matches the maximum supported size that a |
| 44 | /// upb_Message can possibly be. |
Protobuf Team Bot | 9473beb | 2024-02-12 11:57:19 -0800 | [diff] [blame] | 45 | const UPB_SCRATCH_SPACE_BYTES: usize = 65_536; |
Hong Shin | 6d4ea61 | 2023-10-16 09:45:35 -0700 | [diff] [blame] | 46 | |
| 47 | /// Holds a zero-initialized block of memory for use by upb. |
Alyssa Haroldsen | 4395d97 | 2024-02-23 00:15:08 -0800 | [diff] [blame] | 48 | /// |
Hong Shin | 6d4ea61 | 2023-10-16 09:45:35 -0700 | [diff] [blame] | 49 | /// By default, if a message is not set in cpp, a default message is created. |
| 50 | /// upb departs from this and returns a null ptr. However, since contiguous |
| 51 | /// chunks of memory filled with zeroes are legit messages from upb's point of |
| 52 | /// view, we can allocate a large block and refer to that when dealing |
| 53 | /// with readonly access. |
Alyssa Haroldsen | 4395d97 | 2024-02-23 00:15:08 -0800 | [diff] [blame] | 54 | #[repr(C, align(8))] // align to UPB_MALLOC_ALIGN = 8 |
Protobuf Team Bot | e26ef86 | 2024-08-26 05:14:52 -0700 | [diff] [blame] | 55 | #[doc(hidden)] |
Alyssa Haroldsen | 4395d97 | 2024-02-23 00:15:08 -0800 | [diff] [blame] | 56 | pub struct ScratchSpace([u8; UPB_SCRATCH_SPACE_BYTES]); |
Hong Shin | 6d4ea61 | 2023-10-16 09:45:35 -0700 | [diff] [blame] | 57 | impl ScratchSpace { |
Protobuf Team Bot | e26ef86 | 2024-08-26 05:14:52 -0700 | [diff] [blame] | 58 | pub fn zeroed_block() -> RawMessage { |
Alyssa Haroldsen | 4395d97 | 2024-02-23 00:15:08 -0800 | [diff] [blame] | 59 | static ZEROED_BLOCK: ScratchSpace = ScratchSpace([0; UPB_SCRATCH_SPACE_BYTES]); |
| 60 | NonNull::from(&ZEROED_BLOCK).cast() |
Hong Shin | 6d4ea61 | 2023-10-16 09:45:35 -0700 | [diff] [blame] | 61 | } |
| 62 | } |
| 63 | |
Protobuf Team Bot | 9d2dafe | 2024-07-22 11:30:36 -0700 | [diff] [blame] | 64 | #[doc(hidden)] |
Protobuf Team Bot | 734729a | 2024-04-24 12:25:37 -0700 | [diff] [blame] | 65 | pub type SerializedData = upb::OwnedArenaBox<[u8]>; |
Protobuf Team Bot | c288343 | 2023-12-20 06:52:48 -0800 | [diff] [blame] | 66 | |
Protobuf Team Bot | c7d4697 | 2024-07-30 05:39:53 -0700 | [diff] [blame] | 67 | impl SealedInternal for SerializedData {} |
| 68 | |
Marcel Hlopko | 6b7e814 | 2024-06-20 05:54:09 -0700 | [diff] [blame] | 69 | impl IntoProxied<ProtoBytes> for SerializedData { |
| 70 | fn into_proxied(self, _private: Private) -> ProtoBytes { |
| 71 | ProtoBytes { inner: InnerProtoString(self) } |
| 72 | } |
| 73 | } |
| 74 | |
Alyssa Haroldsen | 9a0bc39 | 2023-08-23 11:05:31 -0700 | [diff] [blame] | 75 | /// The raw contents of every generated message. |
| 76 | #[derive(Debug)] |
Protobuf Team Bot | e26ef86 | 2024-08-26 05:14:52 -0700 | [diff] [blame] | 77 | #[doc(hidden)] |
Alyssa Haroldsen | 9a0bc39 | 2023-08-23 11:05:31 -0700 | [diff] [blame] | 78 | pub struct MessageInner { |
| 79 | pub msg: RawMessage, |
| 80 | pub arena: Arena, |
| 81 | } |
| 82 | |
| 83 | /// Mutators that point to their original message use this to do so. |
| 84 | /// |
| 85 | /// Since UPB expects runtimes to manage their own arenas, this needs to have |
| 86 | /// access to an `Arena`. |
| 87 | /// |
| 88 | /// This has two possible designs: |
| 89 | /// - Store two pointers here, `RawMessage` and `&'msg Arena`. This doesn't |
| 90 | /// place any restriction on the layout of generated messages and their |
| 91 | /// mutators. This makes a vtable-based mutator three pointers, which can no |
| 92 | /// longer be returned in registers on most platforms. |
| 93 | /// - Store one pointer here, `&'msg MessageInner`, where `MessageInner` stores |
| 94 | /// a `RawMessage` and an `Arena`. This would require all generated messages |
| 95 | /// to store `MessageInner`, and since their mutators need to be able to |
| 96 | /// generate `BytesMut`, would also require `BytesMut` to store a `&'msg |
| 97 | /// MessageInner` since they can't store an owned `Arena`. |
| 98 | /// |
| 99 | /// Note: even though this type is `Copy`, it should only be copied by |
Alyssa Haroldsen | 9fe3ac6 | 2023-08-28 03:23:39 -0700 | [diff] [blame] | 100 | /// protobuf internals that can maintain mutation invariants: |
| 101 | /// |
| 102 | /// - No concurrent mutation for any two fields in a message: this means |
| 103 | /// mutators cannot be `Send` but are `Sync`. |
| 104 | /// - If there are multiple accessible `Mut` to a single message at a time, they |
| 105 | /// must be different fields, and not be in the same oneof. As such, a `Mut` |
| 106 | /// cannot be `Clone` but *can* reborrow itself with `.as_mut()`, which |
| 107 | /// converts `&'b mut Mut<'a, T>` to `Mut<'b, T>`. |
Alyssa Haroldsen | 9a0bc39 | 2023-08-23 11:05:31 -0700 | [diff] [blame] | 108 | #[derive(Clone, Copy, Debug)] |
Protobuf Team Bot | e26ef86 | 2024-08-26 05:14:52 -0700 | [diff] [blame] | 109 | #[doc(hidden)] |
Alyssa Haroldsen | 9a0bc39 | 2023-08-23 11:05:31 -0700 | [diff] [blame] | 110 | pub struct MutatorMessageRef<'msg> { |
| 111 | msg: RawMessage, |
| 112 | arena: &'msg Arena, |
| 113 | } |
| 114 | |
| 115 | impl<'msg> MutatorMessageRef<'msg> { |
| 116 | #[doc(hidden)] |
| 117 | #[allow(clippy::needless_pass_by_ref_mut)] // Sound construction requires mutable access. |
Protobuf Team Bot | e26ef86 | 2024-08-26 05:14:52 -0700 | [diff] [blame] | 118 | pub fn new(msg: &'msg mut MessageInner) -> Self { |
Alyssa Haroldsen | 9a0bc39 | 2023-08-23 11:05:31 -0700 | [diff] [blame] | 119 | MutatorMessageRef { msg: msg.msg, arena: &msg.arena } |
| 120 | } |
| 121 | |
Protobuf Team Bot | e26ef86 | 2024-08-26 05:14:52 -0700 | [diff] [blame] | 122 | pub fn from_parent(parent_msg: MutatorMessageRef<'msg>, message_field_ptr: RawMessage) -> Self { |
Protobuf Team Bot | d716c2e | 2024-01-16 11:20:45 -0800 | [diff] [blame] | 123 | MutatorMessageRef { msg: message_field_ptr, arena: parent_msg.arena } |
Hong Shin | b3cfff3 | 2023-11-13 09:08:02 -0800 | [diff] [blame] | 124 | } |
| 125 | |
Alyssa Haroldsen | 9a0bc39 | 2023-08-23 11:05:31 -0700 | [diff] [blame] | 126 | pub fn msg(&self) -> RawMessage { |
| 127 | self.msg |
| 128 | } |
Kevin King | 8876b10 | 2024-01-02 11:19:58 -0800 | [diff] [blame] | 129 | |
Protobuf Team Bot | e26ef86 | 2024-08-26 05:14:52 -0700 | [diff] [blame] | 130 | pub fn arena(&self) -> &Arena { |
Protobuf Team Bot | deb2dff | 2024-01-16 09:43:44 -0800 | [diff] [blame] | 131 | self.arena |
Kevin King | 8876b10 | 2024-01-02 11:19:58 -0800 | [diff] [blame] | 132 | } |
Alyssa Haroldsen | 9a0bc39 | 2023-08-23 11:05:31 -0700 | [diff] [blame] | 133 | } |
| 134 | |
Marcel Hlopko | 6b7e814 | 2024-06-20 05:54:09 -0700 | [diff] [blame] | 135 | /// Kernel-specific owned `string` and `bytes` field type. |
Protobuf Team Bot | e26ef86 | 2024-08-26 05:14:52 -0700 | [diff] [blame] | 136 | #[doc(hidden)] |
Marcel Hlopko | 6b7e814 | 2024-06-20 05:54:09 -0700 | [diff] [blame] | 137 | pub struct InnerProtoString(OwnedArenaBox<[u8]>); |
| 138 | |
| 139 | impl InnerProtoString { |
| 140 | pub(crate) fn as_bytes(&self) -> &[u8] { |
| 141 | &self.0 |
| 142 | } |
Jakob Buchgraber | 08da921 | 2024-07-09 06:59:28 -0700 | [diff] [blame] | 143 | |
| 144 | #[doc(hidden)] |
Protobuf Team Bot | e26ef86 | 2024-08-26 05:14:52 -0700 | [diff] [blame] | 145 | pub fn into_raw_parts(self) -> (PtrAndLen, Arena) { |
Jakob Buchgraber | 08da921 | 2024-07-09 06:59:28 -0700 | [diff] [blame] | 146 | let (data_ptr, arena) = self.0.into_parts(); |
| 147 | (unsafe { data_ptr.as_ref().into() }, arena) |
| 148 | } |
Marcel Hlopko | 6b7e814 | 2024-06-20 05:54:09 -0700 | [diff] [blame] | 149 | } |
| 150 | |
| 151 | impl From<&[u8]> for InnerProtoString { |
| 152 | fn from(val: &[u8]) -> InnerProtoString { |
| 153 | let arena = Arena::new(); |
Protobuf Team Bot | b35d4ba | 2024-09-06 13:04:52 -0700 | [diff] [blame] | 154 | let in_arena_copy = arena.copy_slice_in(val).unwrap(); |
Marcel Hlopko | 6b7e814 | 2024-06-20 05:54:09 -0700 | [diff] [blame] | 155 | // SAFETY: |
| 156 | // - `in_arena_copy` is valid slice that will live for `arena`'s lifetime and |
| 157 | // this is the only reference in the program to it. |
| 158 | // - `in_arena_copy` is a pointer into an allocation on `arena` |
| 159 | InnerProtoString(unsafe { OwnedArenaBox::new(Into::into(in_arena_copy), arena) }) |
| 160 | } |
| 161 | } |
| 162 | |
Protobuf Team Bot | 9ff062c | 2024-03-12 04:48:15 -0700 | [diff] [blame] | 163 | /// The raw type-erased version of an owned `Repeated`. |
| 164 | #[derive(Debug)] |
Protobuf Team Bot | e26ef86 | 2024-08-26 05:14:52 -0700 | [diff] [blame] | 165 | #[doc(hidden)] |
Protobuf Team Bot | 9ff062c | 2024-03-12 04:48:15 -0700 | [diff] [blame] | 166 | pub struct InnerRepeated { |
| 167 | raw: RawRepeatedField, |
| 168 | arena: Arena, |
| 169 | } |
| 170 | |
| 171 | impl InnerRepeated { |
| 172 | pub fn as_mut(&mut self) -> InnerRepeatedMut<'_> { |
Protobuf Team Bot | e26ef86 | 2024-08-26 05:14:52 -0700 | [diff] [blame] | 173 | InnerRepeatedMut::new(self.raw, &self.arena) |
Protobuf Team Bot | 9ff062c | 2024-03-12 04:48:15 -0700 | [diff] [blame] | 174 | } |
Jakob Buchgraber | b6e0a48 | 2024-05-06 05:16:05 -0700 | [diff] [blame] | 175 | |
| 176 | pub fn raw(&self) -> RawRepeatedField { |
| 177 | self.raw |
| 178 | } |
| 179 | |
| 180 | pub fn arena(&self) -> &Arena { |
| 181 | &self.arena |
| 182 | } |
Derek Benson | 9c99424 | 2024-07-15 12:36:48 -0700 | [diff] [blame] | 183 | |
| 184 | /// # Safety |
| 185 | /// - `raw` must be a valid `RawRepeatedField` |
Protobuf Team Bot | e26ef86 | 2024-08-26 05:14:52 -0700 | [diff] [blame] | 186 | pub unsafe fn from_raw_parts(raw: RawRepeatedField, arena: Arena) -> Self { |
Derek Benson | 9c99424 | 2024-07-15 12:36:48 -0700 | [diff] [blame] | 187 | Self { raw, arena } |
| 188 | } |
Protobuf Team Bot | 9ff062c | 2024-03-12 04:48:15 -0700 | [diff] [blame] | 189 | } |
| 190 | |
Alyssa Haroldsen | 6ae76fd | 2023-12-14 11:44:00 -0800 | [diff] [blame] | 191 | /// The raw type-erased pointer version of `RepeatedMut`. |
Protobuf Team Bot | e1bb7d6 | 2023-10-17 14:15:37 -0700 | [diff] [blame] | 192 | #[derive(Clone, Copy, Debug)] |
Protobuf Team Bot | e26ef86 | 2024-08-26 05:14:52 -0700 | [diff] [blame] | 193 | #[doc(hidden)] |
Alyssa Haroldsen | 6ae76fd | 2023-12-14 11:44:00 -0800 | [diff] [blame] | 194 | pub struct InnerRepeatedMut<'msg> { |
| 195 | pub(crate) raw: RawRepeatedField, |
Protobuf Team Bot | 9ff062c | 2024-03-12 04:48:15 -0700 | [diff] [blame] | 196 | arena: &'msg Arena, |
Protobuf Team Bot | e1bb7d6 | 2023-10-17 14:15:37 -0700 | [diff] [blame] | 197 | } |
| 198 | |
Alyssa Haroldsen | 6ae76fd | 2023-12-14 11:44:00 -0800 | [diff] [blame] | 199 | impl<'msg> InnerRepeatedMut<'msg> { |
| 200 | #[doc(hidden)] |
Protobuf Team Bot | e26ef86 | 2024-08-26 05:14:52 -0700 | [diff] [blame] | 201 | pub fn new(raw: RawRepeatedField, arena: &'msg Arena) -> Self { |
Protobuf Team Bot | 9ff062c | 2024-03-12 04:48:15 -0700 | [diff] [blame] | 202 | InnerRepeatedMut { raw, arena } |
Protobuf Team Bot | e1bb7d6 | 2023-10-17 14:15:37 -0700 | [diff] [blame] | 203 | } |
| 204 | } |
| 205 | |
Alyssa Haroldsen | 3ccccdb | 2024-02-06 10:22:46 -0800 | [diff] [blame] | 206 | macro_rules! impl_repeated_base { |
| 207 | ($t:ty, $elem_t:ty, $ufield:ident, $upb_tag:expr) => { |
| 208 | #[allow(dead_code)] |
Derek Benson | 904266d | 2024-05-13 07:16:57 -0700 | [diff] [blame] | 209 | #[inline] |
Alyssa Haroldsen | 3ccccdb | 2024-02-06 10:22:46 -0800 | [diff] [blame] | 210 | fn repeated_new(_: Private) -> Repeated<$t> { |
Protobuf Team Bot | 9ff062c | 2024-03-12 04:48:15 -0700 | [diff] [blame] | 211 | let arena = Arena::new(); |
Derek Benson | 9c99424 | 2024-07-15 12:36:48 -0700 | [diff] [blame] | 212 | Repeated::from_inner( |
| 213 | Private, |
| 214 | InnerRepeated { raw: unsafe { upb_Array_New(arena.raw(), $upb_tag) }, arena }, |
| 215 | ) |
Alyssa Haroldsen | 3ccccdb | 2024-02-06 10:22:46 -0800 | [diff] [blame] | 216 | } |
| 217 | #[allow(dead_code)] |
Protobuf Team Bot | 9ff062c | 2024-03-12 04:48:15 -0700 | [diff] [blame] | 218 | unsafe fn repeated_free(_: Private, _f: &mut Repeated<$t>) { |
| 219 | // No-op: the memory will be dropped by the arena. |
Alyssa Haroldsen | 3ccccdb | 2024-02-06 10:22:46 -0800 | [diff] [blame] | 220 | } |
Derek Benson | 904266d | 2024-05-13 07:16:57 -0700 | [diff] [blame] | 221 | #[inline] |
Alyssa Haroldsen | 3ccccdb | 2024-02-06 10:22:46 -0800 | [diff] [blame] | 222 | fn repeated_len(f: View<Repeated<$t>>) -> usize { |
| 223 | unsafe { upb_Array_Size(f.as_raw(Private)) } |
| 224 | } |
Derek Benson | 904266d | 2024-05-13 07:16:57 -0700 | [diff] [blame] | 225 | #[inline] |
Jakob Buchgraber | 0d6e979 | 2024-07-09 04:44:21 -0700 | [diff] [blame] | 226 | fn repeated_push(mut f: Mut<Repeated<$t>>, v: impl IntoProxied<$t>) { |
Alyssa Haroldsen | 3ccccdb | 2024-02-06 10:22:46 -0800 | [diff] [blame] | 227 | let arena = f.raw_arena(Private); |
| 228 | unsafe { |
Protobuf Team Bot | 2678e10 | 2024-04-12 13:50:28 -0700 | [diff] [blame] | 229 | assert!(upb_Array_Append( |
Alyssa Haroldsen | 3ccccdb | 2024-02-06 10:22:46 -0800 | [diff] [blame] | 230 | f.as_raw(Private), |
Jakob Buchgraber | 0d6e979 | 2024-07-09 04:44:21 -0700 | [diff] [blame] | 231 | <$t as UpbTypeConversions>::into_message_value_fuse_if_required( |
| 232 | arena, |
| 233 | v.into_proxied(Private) |
| 234 | ), |
Alyssa Haroldsen | 3ccccdb | 2024-02-06 10:22:46 -0800 | [diff] [blame] | 235 | arena, |
Protobuf Team Bot | 2678e10 | 2024-04-12 13:50:28 -0700 | [diff] [blame] | 236 | )); |
Alyssa Haroldsen | 3ccccdb | 2024-02-06 10:22:46 -0800 | [diff] [blame] | 237 | } |
| 238 | } |
Derek Benson | 904266d | 2024-05-13 07:16:57 -0700 | [diff] [blame] | 239 | #[inline] |
Alyssa Haroldsen | 3ccccdb | 2024-02-06 10:22:46 -0800 | [diff] [blame] | 240 | fn repeated_clear(mut f: Mut<Repeated<$t>>) { |
| 241 | unsafe { |
| 242 | upb_Array_Resize(f.as_raw(Private), 0, f.raw_arena(Private)); |
| 243 | } |
| 244 | } |
Derek Benson | 904266d | 2024-05-13 07:16:57 -0700 | [diff] [blame] | 245 | #[inline] |
Alyssa Haroldsen | 3ccccdb | 2024-02-06 10:22:46 -0800 | [diff] [blame] | 246 | unsafe fn repeated_get_unchecked(f: View<Repeated<$t>>, i: usize) -> View<$t> { |
| 247 | unsafe { |
| 248 | <$t as UpbTypeConversions>::from_message_value(upb_Array_Get(f.as_raw(Private), i)) |
| 249 | } |
| 250 | } |
Derek Benson | 904266d | 2024-05-13 07:16:57 -0700 | [diff] [blame] | 251 | #[inline] |
Jakob Buchgraber | 0d6e979 | 2024-07-09 04:44:21 -0700 | [diff] [blame] | 252 | unsafe fn repeated_set_unchecked( |
| 253 | mut f: Mut<Repeated<$t>>, |
| 254 | i: usize, |
| 255 | v: impl IntoProxied<$t>, |
| 256 | ) { |
Alyssa Haroldsen | 3ccccdb | 2024-02-06 10:22:46 -0800 | [diff] [blame] | 257 | let arena = f.raw_arena(Private); |
| 258 | unsafe { |
| 259 | upb_Array_Set( |
| 260 | f.as_raw(Private), |
| 261 | i, |
Jakob Buchgraber | 0d6e979 | 2024-07-09 04:44:21 -0700 | [diff] [blame] | 262 | <$t as UpbTypeConversions>::into_message_value_fuse_if_required( |
| 263 | arena, |
| 264 | v.into_proxied(Private), |
| 265 | ), |
Alyssa Haroldsen | 3ccccdb | 2024-02-06 10:22:46 -0800 | [diff] [blame] | 266 | ) |
| 267 | } |
| 268 | } |
Derek Benson | 904266d | 2024-05-13 07:16:57 -0700 | [diff] [blame] | 269 | #[inline] |
Derek Benson | f2d8c2b | 2024-05-13 05:48:10 -0700 | [diff] [blame] | 270 | fn repeated_reserve(mut f: Mut<Repeated<$t>>, additional: usize) { |
| 271 | // SAFETY: |
| 272 | // - `upb_Array_Reserve` is unsafe but assumed to be sound when called on a |
| 273 | // valid array. |
| 274 | unsafe { |
| 275 | let arena = f.raw_arena(Private); |
| 276 | let size = upb_Array_Size(f.as_raw(Private)); |
| 277 | assert!(upb_Array_Reserve(f.as_raw(Private), size + additional, arena)); |
| 278 | } |
| 279 | } |
Alyssa Haroldsen | 3ccccdb | 2024-02-06 10:22:46 -0800 | [diff] [blame] | 280 | }; |
| 281 | } |
| 282 | |
Protobuf Team Bot | e1bb7d6 | 2023-10-17 14:15:37 -0700 | [diff] [blame] | 283 | macro_rules! impl_repeated_primitives { |
Marcel Hlopko | 39e8ca7 | 2024-01-19 07:00:32 -0800 | [diff] [blame] | 284 | ($(($t:ty, $elem_t:ty, $ufield:ident, $upb_tag:expr)),* $(,)?) => { |
Protobuf Team Bot | e1bb7d6 | 2023-10-17 14:15:37 -0700 | [diff] [blame] | 285 | $( |
Alyssa Haroldsen | 6ae76fd | 2023-12-14 11:44:00 -0800 | [diff] [blame] | 286 | unsafe impl ProxiedInRepeated for $t { |
Alyssa Haroldsen | 3ccccdb | 2024-02-06 10:22:46 -0800 | [diff] [blame] | 287 | impl_repeated_base!($t, $elem_t, $ufield, $upb_tag); |
| 288 | |
Alyssa Haroldsen | 6ae76fd | 2023-12-14 11:44:00 -0800 | [diff] [blame] | 289 | fn repeated_copy_from(src: View<Repeated<$t>>, mut dest: Mut<Repeated<$t>>) { |
Alyssa Haroldsen | 3ccccdb | 2024-02-06 10:22:46 -0800 | [diff] [blame] | 290 | let arena = dest.raw_arena(Private); |
Protobuf Team Bot | 0a13fde | 2023-11-15 17:04:27 -0800 | [diff] [blame] | 291 | // SAFETY: |
| 292 | // - `upb_Array_Resize` is unsafe but assumed to be always sound to call. |
| 293 | // - `copy_nonoverlapping` is unsafe but here we guarantee that both pointers |
| 294 | // are valid, the pointers are `#[repr(u8)]`, and the size is correct. |
| 295 | unsafe { |
Alyssa Haroldsen | 3ccccdb | 2024-02-06 10:22:46 -0800 | [diff] [blame] | 296 | if (!upb_Array_Resize(dest.as_raw(Private), src.len(), arena)) { |
Protobuf Team Bot | 0a13fde | 2023-11-15 17:04:27 -0800 | [diff] [blame] | 297 | panic!("upb_Array_Resize failed."); |
| 298 | } |
| 299 | ptr::copy_nonoverlapping( |
Alyssa Haroldsen | 6ae76fd | 2023-12-14 11:44:00 -0800 | [diff] [blame] | 300 | upb_Array_DataPtr(src.as_raw(Private)).cast::<u8>(), |
| 301 | upb_Array_MutableDataPtr(dest.as_raw(Private)).cast::<u8>(), |
Marcel Hlopko | 39e8ca7 | 2024-01-19 07:00:32 -0800 | [diff] [blame] | 302 | size_of::<$elem_t>() * src.len()); |
Kevin King | 65cdac4 | 2023-10-23 14:50:42 -0700 | [diff] [blame] | 303 | } |
| 304 | } |
Protobuf Team Bot | e1bb7d6 | 2023-10-17 14:15:37 -0700 | [diff] [blame] | 305 | } |
| 306 | )* |
| 307 | } |
| 308 | } |
| 309 | |
Alyssa Haroldsen | 3ccccdb | 2024-02-06 10:22:46 -0800 | [diff] [blame] | 310 | macro_rules! impl_repeated_bytes { |
| 311 | ($(($t:ty, $upb_tag:expr)),* $(,)?) => { |
| 312 | $( |
| 313 | unsafe impl ProxiedInRepeated for $t { |
| 314 | impl_repeated_base!($t, PtrAndLen, str_val, $upb_tag); |
| 315 | |
Derek Benson | 904266d | 2024-05-13 07:16:57 -0700 | [diff] [blame] | 316 | #[inline] |
Alyssa Haroldsen | 3ccccdb | 2024-02-06 10:22:46 -0800 | [diff] [blame] | 317 | fn repeated_copy_from(src: View<Repeated<$t>>, mut dest: Mut<Repeated<$t>>) { |
| 318 | let len = src.len(); |
| 319 | // SAFETY: |
| 320 | // - `upb_Array_Resize` is unsafe but assumed to be always sound to call. |
| 321 | // - `upb_Array` ensures its elements are never uninitialized memory. |
| 322 | // - The `DataPtr` and `MutableDataPtr` functions return pointers to spans |
| 323 | // of memory that are valid for at least `len` elements of PtrAndLen. |
| 324 | // - `copy_nonoverlapping` is unsafe but here we guarantee that both pointers |
| 325 | // are valid, the pointers are `#[repr(u8)]`, and the size is correct. |
| 326 | // - The bytes held within a valid array are valid. |
| 327 | unsafe { |
| 328 | let arena = ManuallyDrop::new(Arena::from_raw(dest.raw_arena(Private))); |
| 329 | if (!upb_Array_Resize(dest.as_raw(Private), src.len(), arena.raw())) { |
| 330 | panic!("upb_Array_Resize failed."); |
| 331 | } |
| 332 | let src_ptrs: &[PtrAndLen] = slice::from_raw_parts( |
| 333 | upb_Array_DataPtr(src.as_raw(Private)).cast(), |
| 334 | len |
| 335 | ); |
| 336 | let dest_ptrs: &mut [PtrAndLen] = slice::from_raw_parts_mut( |
| 337 | upb_Array_MutableDataPtr(dest.as_raw(Private)).cast(), |
| 338 | len |
| 339 | ); |
| 340 | for (src_ptr, dest_ptr) in src_ptrs.iter().zip(dest_ptrs) { |
Protobuf Team Bot | b35d4ba | 2024-09-06 13:04:52 -0700 | [diff] [blame] | 341 | *dest_ptr = arena.copy_slice_in(src_ptr.as_ref()).unwrap().into(); |
Alyssa Haroldsen | 3ccccdb | 2024-02-06 10:22:46 -0800 | [diff] [blame] | 342 | } |
| 343 | } |
| 344 | } |
| 345 | } |
| 346 | )* |
| 347 | } |
| 348 | } |
| 349 | |
Jakob Buchgraber | 0d6e979 | 2024-07-09 04:44:21 -0700 | [diff] [blame] | 350 | impl<'msg, T> RepeatedMut<'msg, T> { |
Alyssa Haroldsen | 6ae76fd | 2023-12-14 11:44:00 -0800 | [diff] [blame] | 351 | // Returns a `RawArena` which is live for at least `'msg` |
| 352 | #[doc(hidden)] |
Alyssa Haroldsen | 3657e05 | 2024-02-05 12:51:41 -0800 | [diff] [blame] | 353 | pub fn raw_arena(&mut self, _private: Private) -> RawArena { |
Protobuf Team Bot | 9ff062c | 2024-03-12 04:48:15 -0700 | [diff] [blame] | 354 | self.inner.arena.raw() |
Alyssa Haroldsen | 6ae76fd | 2023-12-14 11:44:00 -0800 | [diff] [blame] | 355 | } |
| 356 | } |
| 357 | |
Protobuf Team Bot | e1bb7d6 | 2023-10-17 14:15:37 -0700 | [diff] [blame] | 358 | impl_repeated_primitives!( |
Protobuf Team Bot | 2678e10 | 2024-04-12 13:50:28 -0700 | [diff] [blame] | 359 | // proxied type, element type, upb_MessageValue field name, upb::CType variant |
| 360 | (bool, bool, bool_val, upb::CType::Bool), |
| 361 | (f32, f32, float_val, upb::CType::Float), |
| 362 | (f64, f64, double_val, upb::CType::Double), |
| 363 | (i32, i32, int32_val, upb::CType::Int32), |
| 364 | (u32, u32, uint32_val, upb::CType::UInt32), |
| 365 | (i64, i64, int64_val, upb::CType::Int64), |
| 366 | (u64, u64, uint64_val, upb::CType::UInt64), |
Protobuf Team Bot | e1bb7d6 | 2023-10-17 14:15:37 -0700 | [diff] [blame] | 367 | ); |
| 368 | |
Marcel Hlopko | 6b7e814 | 2024-06-20 05:54:09 -0700 | [diff] [blame] | 369 | impl_repeated_bytes!((ProtoString, upb::CType::String), (ProtoBytes, upb::CType::Bytes),); |
Alyssa Haroldsen | 3ccccdb | 2024-02-06 10:22:46 -0800 | [diff] [blame] | 370 | |
Kevin King | df376c8 | 2024-01-17 11:41:53 -0800 | [diff] [blame] | 371 | /// Copy the contents of `src` into `dest`. |
| 372 | /// |
| 373 | /// # Safety |
| 374 | /// - `minitable` must be a pointer to the minitable for message `T`. |
| 375 | pub unsafe fn repeated_message_copy_from<T: ProxiedInRepeated>( |
| 376 | src: View<Repeated<T>>, |
| 377 | mut dest: Mut<Repeated<T>>, |
Protobuf Team Bot | 2678e10 | 2024-04-12 13:50:28 -0700 | [diff] [blame] | 378 | minitable: *const upb_MiniTable, |
Kevin King | df376c8 | 2024-01-17 11:41:53 -0800 | [diff] [blame] | 379 | ) { |
| 380 | // SAFETY: |
| 381 | // - `src.as_raw()` is a valid `const upb_Array*`. |
| 382 | // - `dest.as_raw()` is a valid `upb_Array*`. |
| 383 | // - Elements of `src` and have message minitable `$minitable$`. |
| 384 | unsafe { |
| 385 | let size = upb_Array_Size(src.as_raw(Private)); |
| 386 | if !upb_Array_Resize(dest.as_raw(Private), size, dest.raw_arena(Private)) { |
| 387 | panic!("upb_Array_Resize failed."); |
| 388 | } |
| 389 | for i in 0..size { |
| 390 | let src_msg = upb_Array_Get(src.as_raw(Private), i) |
| 391 | .msg_val |
| 392 | .expect("upb_Array* element should not be NULL"); |
| 393 | // Avoid the use of `upb_Array_DeepClone` as it creates an |
| 394 | // entirely new `upb_Array*` at a new memory address. |
| 395 | let cloned_msg = upb_Message_DeepClone(src_msg, minitable, dest.raw_arena(Private)) |
| 396 | .expect("upb_Message_DeepClone failed."); |
| 397 | upb_Array_Set(dest.as_raw(Private), i, upb_MessageValue { msg_val: Some(cloned_msg) }); |
| 398 | } |
| 399 | } |
| 400 | } |
| 401 | |
Alyssa Haroldsen | 0ce51da | 2023-12-20 10:08:11 -0800 | [diff] [blame] | 402 | /// Cast a `RepeatedView<SomeEnum>` to `RepeatedView<i32>`. |
| 403 | pub fn cast_enum_repeated_view<E: Enum + ProxiedInRepeated>( |
Alyssa Haroldsen | 0ce51da | 2023-12-20 10:08:11 -0800 | [diff] [blame] | 404 | repeated: RepeatedView<E>, |
| 405 | ) -> RepeatedView<i32> { |
| 406 | // SAFETY: Reading an enum array as an i32 array is sound. |
Protobuf Team Bot | e26ef86 | 2024-08-26 05:14:52 -0700 | [diff] [blame] | 407 | unsafe { RepeatedView::from_raw(Private, repeated.as_raw(Private)) } |
Alyssa Haroldsen | 0ce51da | 2023-12-20 10:08:11 -0800 | [diff] [blame] | 408 | } |
| 409 | |
| 410 | /// Cast a `RepeatedMut<SomeEnum>` to `RepeatedMut<i32>`. |
| 411 | /// |
| 412 | /// Writing an unknown value is sound because all enums |
| 413 | /// are representationally open. |
| 414 | pub fn cast_enum_repeated_mut<E: Enum + ProxiedInRepeated>( |
Alyssa Haroldsen | 0ce51da | 2023-12-20 10:08:11 -0800 | [diff] [blame] | 415 | repeated: RepeatedMut<E>, |
| 416 | ) -> RepeatedMut<i32> { |
| 417 | // SAFETY: |
| 418 | // - Reading an enum array as an i32 array is sound. |
| 419 | // - No shared mutation is possible through the output. |
| 420 | unsafe { |
Alyssa Haroldsen | 3657e05 | 2024-02-05 12:51:41 -0800 | [diff] [blame] | 421 | let InnerRepeatedMut { arena, raw, .. } = repeated.inner; |
Protobuf Team Bot | e26ef86 | 2024-08-26 05:14:52 -0700 | [diff] [blame] | 422 | RepeatedMut::from_inner(Private, InnerRepeatedMut { arena, raw }) |
Alyssa Haroldsen | 0ce51da | 2023-12-20 10:08:11 -0800 | [diff] [blame] | 423 | } |
| 424 | } |
| 425 | |
Derek Benson | f2d8c2b | 2024-05-13 05:48:10 -0700 | [diff] [blame] | 426 | /// Cast a `RepeatedMut<SomeEnum>` to `RepeatedMut<i32>` and call |
| 427 | /// repeated_reserve. |
| 428 | pub fn reserve_enum_repeated_mut<E: Enum + ProxiedInRepeated>( |
Derek Benson | f2d8c2b | 2024-05-13 05:48:10 -0700 | [diff] [blame] | 429 | repeated: RepeatedMut<E>, |
| 430 | additional: usize, |
| 431 | ) { |
Protobuf Team Bot | e26ef86 | 2024-08-26 05:14:52 -0700 | [diff] [blame] | 432 | let int_repeated = cast_enum_repeated_mut(repeated); |
Derek Benson | f2d8c2b | 2024-05-13 05:48:10 -0700 | [diff] [blame] | 433 | ProxiedInRepeated::repeated_reserve(int_repeated, additional); |
| 434 | } |
| 435 | |
Protobuf Team Bot | e26ef86 | 2024-08-26 05:14:52 -0700 | [diff] [blame] | 436 | pub fn new_enum_repeated<E: Enum + ProxiedInRepeated>() -> Repeated<E> { |
Derek Benson | 9c99424 | 2024-07-15 12:36:48 -0700 | [diff] [blame] | 437 | let arena = Arena::new(); |
| 438 | // SAFETY: |
| 439 | // - `upb_Array_New` is unsafe but assumed to be sound when called on a valid |
| 440 | // arena. |
| 441 | unsafe { |
| 442 | let raw = upb_Array_New(arena.raw(), upb::CType::Int32); |
Protobuf Team Bot | e26ef86 | 2024-08-26 05:14:52 -0700 | [diff] [blame] | 443 | Repeated::from_inner(Private, InnerRepeated::from_raw_parts(raw, arena)) |
Derek Benson | 9c99424 | 2024-07-15 12:36:48 -0700 | [diff] [blame] | 444 | } |
| 445 | } |
| 446 | |
Protobuf Team Bot | e26ef86 | 2024-08-26 05:14:52 -0700 | [diff] [blame] | 447 | pub fn free_enum_repeated<E: Enum + ProxiedInRepeated>(_repeated: &mut Repeated<E>) { |
Derek Benson | 9c99424 | 2024-07-15 12:36:48 -0700 | [diff] [blame] | 448 | // No-op: the memory will be dropped by the arena. |
| 449 | } |
| 450 | |
Alyssa Haroldsen | 6ae76fd | 2023-12-14 11:44:00 -0800 | [diff] [blame] | 451 | /// Returns a static empty RepeatedView. |
Protobuf Team Bot | a1c53e4 | 2024-07-22 11:35:04 -0700 | [diff] [blame] | 452 | pub fn empty_array<T: ProxiedInRepeated>() -> RepeatedView<'static, T> { |
Alyssa Haroldsen | 6ae76fd | 2023-12-14 11:44:00 -0800 | [diff] [blame] | 453 | // TODO: Consider creating a static empty array in C. |
Protobuf Team Bot | e1bb7d6 | 2023-10-17 14:15:37 -0700 | [diff] [blame] | 454 | |
Alyssa Haroldsen | 406fa60 | 2024-01-11 11:32:53 -0800 | [diff] [blame] | 455 | // Use `i32` for a shared empty repeated for all repeated types in the program. |
Adam Cozzette | f712ca5 | 2024-07-16 12:57:33 -0700 | [diff] [blame] | 456 | static EMPTY_REPEATED_VIEW: OnceLock<Repeated<i32>> = OnceLock::new(); |
Alyssa Haroldsen | 6ae76fd | 2023-12-14 11:44:00 -0800 | [diff] [blame] | 457 | |
| 458 | // SAFETY: |
| 459 | // - Because the repeated is never mutated, the repeated type is unused and |
| 460 | // therefore valid for `T`. |
Alyssa Haroldsen | 6ae76fd | 2023-12-14 11:44:00 -0800 | [diff] [blame] | 461 | unsafe { |
| 462 | RepeatedView::from_raw( |
| 463 | Private, |
Adam Cozzette | f712ca5 | 2024-07-16 12:57:33 -0700 | [diff] [blame] | 464 | EMPTY_REPEATED_VIEW.get_or_init(Repeated::new).as_view().as_raw(Private), |
Alyssa Haroldsen | 6ae76fd | 2023-12-14 11:44:00 -0800 | [diff] [blame] | 465 | ) |
| 466 | } |
Protobuf Team Bot | e1bb7d6 | 2023-10-17 14:15:37 -0700 | [diff] [blame] | 467 | } |
| 468 | |
Jakob Buchgraber | 8d9e3e9 | 2024-01-12 00:39:31 -0800 | [diff] [blame] | 469 | /// Returns a static empty MapView. |
| 470 | pub fn empty_map<K, V>() -> MapView<'static, K, V> |
Jakob Buchgraber | 991a2f4 | 2024-01-08 05:25:58 -0800 | [diff] [blame] | 471 | where |
Protobuf Team Bot | a1c53e4 | 2024-07-22 11:35:04 -0700 | [diff] [blame] | 472 | K: Proxied, |
| 473 | V: ProxiedInMapValue<K>, |
Jakob Buchgraber | 991a2f4 | 2024-01-08 05:25:58 -0800 | [diff] [blame] | 474 | { |
Jakob Buchgraber | 8d9e3e9 | 2024-01-12 00:39:31 -0800 | [diff] [blame] | 475 | // TODO: Consider creating a static empty map in C. |
| 476 | |
Marcel Hlopko | 73769a0 | 2024-02-12 00:46:04 -0800 | [diff] [blame] | 477 | // Use `<bool, bool>` for a shared empty map for all map types. |
| 478 | // |
| 479 | // This relies on an implicit contract with UPB that it is OK to use an empty |
| 480 | // Map<bool, bool> as an empty map of all other types. The only const |
| 481 | // function on `upb_Map` that will care about the size of key or value is |
| 482 | // `get()` where it will hash the appropriate number of bytes of the |
| 483 | // provided `upb_MessageValue`, and that bool being the smallest type in the |
| 484 | // union means it will happen to work for all possible key types. |
| 485 | // |
| 486 | // If we used a larger key, then UPB would hash more bytes of the key than Rust |
| 487 | // initialized. |
Adam Cozzette | f712ca5 | 2024-07-16 12:57:33 -0700 | [diff] [blame] | 488 | static EMPTY_MAP_VIEW: OnceLock<Map<bool, bool>> = OnceLock::new(); |
Jakob Buchgraber | 8d9e3e9 | 2024-01-12 00:39:31 -0800 | [diff] [blame] | 489 | |
| 490 | // SAFETY: |
Marcel Hlopko | 73769a0 | 2024-02-12 00:46:04 -0800 | [diff] [blame] | 491 | // - The map is empty and never mutated. |
| 492 | // - The value type is never used. |
| 493 | // - The size of the key type is used when `get()` computes the hash of the key. |
| 494 | // The map is empty, therefore it doesn't matter what hash is computed, but we |
| 495 | // have to use `bool` type as the smallest key possible (otherwise UPB would |
| 496 | // read more bytes than Rust allocated). |
Jakob Buchgraber | 8d9e3e9 | 2024-01-12 00:39:31 -0800 | [diff] [blame] | 497 | unsafe { |
Adam Cozzette | f712ca5 | 2024-07-16 12:57:33 -0700 | [diff] [blame] | 498 | MapView::from_raw(Private, EMPTY_MAP_VIEW.get_or_init(Map::new).as_view().as_raw(Private)) |
Jakob Buchgraber | 991a2f4 | 2024-01-08 05:25:58 -0800 | [diff] [blame] | 499 | } |
Jakob Buchgraber | 991a2f4 | 2024-01-08 05:25:58 -0800 | [diff] [blame] | 500 | } |
Jakob Buchgraber | 001be3c | 2023-11-16 01:36:28 -0800 | [diff] [blame] | 501 | |
Alyssa Haroldsen | 3657e05 | 2024-02-05 12:51:41 -0800 | [diff] [blame] | 502 | impl<'msg, K: ?Sized, V: ?Sized> MapMut<'msg, K, V> { |
| 503 | // Returns a `RawArena` which is live for at least `'msg` |
| 504 | #[doc(hidden)] |
| 505 | pub fn raw_arena(&mut self, _private: Private) -> RawArena { |
Protobuf Team Bot | 9ff062c | 2024-03-12 04:48:15 -0700 | [diff] [blame] | 506 | self.inner.arena.raw() |
| 507 | } |
| 508 | } |
| 509 | |
| 510 | #[derive(Debug)] |
Protobuf Team Bot | e26ef86 | 2024-08-26 05:14:52 -0700 | [diff] [blame] | 511 | #[doc(hidden)] |
Protobuf Team Bot | 9ff062c | 2024-03-12 04:48:15 -0700 | [diff] [blame] | 512 | pub struct InnerMap { |
| 513 | pub(crate) raw: RawMap, |
| 514 | arena: Arena, |
| 515 | } |
| 516 | |
| 517 | impl InnerMap { |
Protobuf Team Bot | e26ef86 | 2024-08-26 05:14:52 -0700 | [diff] [blame] | 518 | pub fn new(raw: RawMap, arena: Arena) -> Self { |
Protobuf Team Bot | 9ff062c | 2024-03-12 04:48:15 -0700 | [diff] [blame] | 519 | Self { raw, arena } |
| 520 | } |
| 521 | |
| 522 | pub fn as_mut(&mut self) -> InnerMapMut<'_> { |
| 523 | InnerMapMut { raw: self.raw, arena: &self.arena } |
Alyssa Haroldsen | 3657e05 | 2024-02-05 12:51:41 -0800 | [diff] [blame] | 524 | } |
| 525 | } |
| 526 | |
Jakob Buchgraber | 8d9e3e9 | 2024-01-12 00:39:31 -0800 | [diff] [blame] | 527 | #[derive(Clone, Copy, Debug)] |
Protobuf Team Bot | e26ef86 | 2024-08-26 05:14:52 -0700 | [diff] [blame] | 528 | #[doc(hidden)] |
Jakob Buchgraber | 8d9e3e9 | 2024-01-12 00:39:31 -0800 | [diff] [blame] | 529 | pub struct InnerMapMut<'msg> { |
| 530 | pub(crate) raw: RawMap, |
Protobuf Team Bot | 9ff062c | 2024-03-12 04:48:15 -0700 | [diff] [blame] | 531 | arena: &'msg Arena, |
Jakob Buchgraber | 8d9e3e9 | 2024-01-12 00:39:31 -0800 | [diff] [blame] | 532 | } |
Jakob Buchgraber | 991a2f4 | 2024-01-08 05:25:58 -0800 | [diff] [blame] | 533 | |
Marcel Hlopko | 5842cc9 | 2024-02-09 03:25:00 -0800 | [diff] [blame] | 534 | #[doc(hidden)] |
Jakob Buchgraber | 8d9e3e9 | 2024-01-12 00:39:31 -0800 | [diff] [blame] | 535 | impl<'msg> InnerMapMut<'msg> { |
Protobuf Team Bot | e26ef86 | 2024-08-26 05:14:52 -0700 | [diff] [blame] | 536 | pub fn new(raw: RawMap, arena: &'msg Arena) -> Self { |
Protobuf Team Bot | 9ff062c | 2024-03-12 04:48:15 -0700 | [diff] [blame] | 537 | InnerMapMut { raw, arena } |
Jakob Buchgraber | 991a2f4 | 2024-01-08 05:25:58 -0800 | [diff] [blame] | 538 | } |
Marcel Hlopko | 5842cc9 | 2024-02-09 03:25:00 -0800 | [diff] [blame] | 539 | |
| 540 | #[doc(hidden)] |
Protobuf Team Bot | e26ef86 | 2024-08-26 05:14:52 -0700 | [diff] [blame] | 541 | pub fn as_raw(&self) -> RawMap { |
Marcel Hlopko | 5842cc9 | 2024-02-09 03:25:00 -0800 | [diff] [blame] | 542 | self.raw |
| 543 | } |
| 544 | |
Adam Cozzette | 7d619e8 | 2024-10-18 09:44:13 -0700 | [diff] [blame] | 545 | pub fn arena(&mut self) -> &Arena { |
| 546 | self.arena |
| 547 | } |
| 548 | |
Marcel Hlopko | 5842cc9 | 2024-02-09 03:25:00 -0800 | [diff] [blame] | 549 | #[doc(hidden)] |
Adam Cozzette | 7d619e8 | 2024-10-18 09:44:13 -0700 | [diff] [blame] | 550 | pub fn raw_arena(&mut self) -> RawArena { |
Protobuf Team Bot | 9ff062c | 2024-03-12 04:48:15 -0700 | [diff] [blame] | 551 | self.arena.raw() |
Marcel Hlopko | 5842cc9 | 2024-02-09 03:25:00 -0800 | [diff] [blame] | 552 | } |
Jakob Buchgraber | 001be3c | 2023-11-16 01:36:28 -0800 | [diff] [blame] | 553 | } |
| 554 | |
Marcel Hlopko | 5842cc9 | 2024-02-09 03:25:00 -0800 | [diff] [blame] | 555 | pub trait UpbTypeConversions: Proxied { |
Protobuf Team Bot | 2678e10 | 2024-04-12 13:50:28 -0700 | [diff] [blame] | 556 | fn upb_type() -> upb::CType; |
Jakob Buchgraber | 0d6e979 | 2024-07-09 04:44:21 -0700 | [diff] [blame] | 557 | |
Jakob Buchgraber | 85972e5 | 2024-01-17 03:32:53 -0800 | [diff] [blame] | 558 | fn to_message_value(val: View<'_, Self>) -> upb_MessageValue; |
Jakob Buchgraber | 85972e5 | 2024-01-17 03:32:53 -0800 | [diff] [blame] | 559 | |
| 560 | /// # Safety |
| 561 | /// - `raw_arena` must point to a valid upb arena. |
Jakob Buchgraber | 0d6e979 | 2024-07-09 04:44:21 -0700 | [diff] [blame] | 562 | unsafe fn into_message_value_fuse_if_required( |
Jakob Buchgraber | 85972e5 | 2024-01-17 03:32:53 -0800 | [diff] [blame] | 563 | raw_arena: RawArena, |
Jakob Buchgraber | 0d6e979 | 2024-07-09 04:44:21 -0700 | [diff] [blame] | 564 | val: Self, |
Jakob Buchgraber | 85972e5 | 2024-01-17 03:32:53 -0800 | [diff] [blame] | 565 | ) -> upb_MessageValue; |
| 566 | |
| 567 | /// # Safety |
| 568 | /// - `msg` must be the correct variant for `Self`. |
| 569 | /// - `msg` pointers must point to memory valid for `'msg` lifetime. |
| 570 | unsafe fn from_message_value<'msg>(msg: upb_MessageValue) -> View<'msg, Self>; |
| 571 | } |
| 572 | |
| 573 | macro_rules! impl_upb_type_conversions_for_scalars { |
| 574 | ($($t:ty, $ufield:ident, $upb_tag:expr, $zero_val:literal;)*) => { |
| 575 | $( |
| 576 | impl UpbTypeConversions for $t { |
Alyssa Haroldsen | 3ccccdb | 2024-02-06 10:22:46 -0800 | [diff] [blame] | 577 | #[inline(always)] |
Protobuf Team Bot | 2678e10 | 2024-04-12 13:50:28 -0700 | [diff] [blame] | 578 | fn upb_type() -> upb::CType { |
Jakob Buchgraber | 85972e5 | 2024-01-17 03:32:53 -0800 | [diff] [blame] | 579 | $upb_tag |
| 580 | } |
| 581 | |
Alyssa Haroldsen | 3ccccdb | 2024-02-06 10:22:46 -0800 | [diff] [blame] | 582 | #[inline(always)] |
Jakob Buchgraber | 85972e5 | 2024-01-17 03:32:53 -0800 | [diff] [blame] | 583 | fn to_message_value(val: View<'_, $t>) -> upb_MessageValue { |
| 584 | upb_MessageValue { $ufield: val } |
| 585 | } |
| 586 | |
Alyssa Haroldsen | 3ccccdb | 2024-02-06 10:22:46 -0800 | [diff] [blame] | 587 | #[inline(always)] |
Jakob Buchgraber | 0d6e979 | 2024-07-09 04:44:21 -0700 | [diff] [blame] | 588 | unsafe fn into_message_value_fuse_if_required(_: RawArena, val: $t) -> upb_MessageValue { |
Jakob Buchgraber | 85972e5 | 2024-01-17 03:32:53 -0800 | [diff] [blame] | 589 | Self::to_message_value(val) |
| 590 | } |
| 591 | |
Alyssa Haroldsen | 3ccccdb | 2024-02-06 10:22:46 -0800 | [diff] [blame] | 592 | #[inline(always)] |
Jakob Buchgraber | 85972e5 | 2024-01-17 03:32:53 -0800 | [diff] [blame] | 593 | unsafe fn from_message_value<'msg>(msg: upb_MessageValue) -> View<'msg, $t> { |
| 594 | unsafe { msg.$ufield } |
| 595 | } |
| 596 | } |
| 597 | )* |
| 598 | }; |
| 599 | } |
| 600 | |
| 601 | impl_upb_type_conversions_for_scalars!( |
Protobuf Team Bot | 2678e10 | 2024-04-12 13:50:28 -0700 | [diff] [blame] | 602 | f32, float_val, upb::CType::Float, 0f32; |
| 603 | f64, double_val, upb::CType::Double, 0f64; |
| 604 | i32, int32_val, upb::CType::Int32, 0i32; |
| 605 | u32, uint32_val, upb::CType::UInt32, 0u32; |
| 606 | i64, int64_val, upb::CType::Int64, 0i64; |
| 607 | u64, uint64_val, upb::CType::UInt64, 0u64; |
| 608 | bool, bool_val, upb::CType::Bool, false; |
Jakob Buchgraber | 85972e5 | 2024-01-17 03:32:53 -0800 | [diff] [blame] | 609 | ); |
| 610 | |
Marcel Hlopko | 6b7e814 | 2024-06-20 05:54:09 -0700 | [diff] [blame] | 611 | impl UpbTypeConversions for ProtoBytes { |
Protobuf Team Bot | 2678e10 | 2024-04-12 13:50:28 -0700 | [diff] [blame] | 612 | fn upb_type() -> upb::CType { |
| 613 | upb::CType::Bytes |
Jakob Buchgraber | 85972e5 | 2024-01-17 03:32:53 -0800 | [diff] [blame] | 614 | } |
| 615 | |
Marcel Hlopko | 6b7e814 | 2024-06-20 05:54:09 -0700 | [diff] [blame] | 616 | fn to_message_value(val: View<'_, ProtoBytes>) -> upb_MessageValue { |
Jakob Buchgraber | 85972e5 | 2024-01-17 03:32:53 -0800 | [diff] [blame] | 617 | upb_MessageValue { str_val: val.into() } |
| 618 | } |
| 619 | |
Jakob Buchgraber | 0d6e979 | 2024-07-09 04:44:21 -0700 | [diff] [blame] | 620 | unsafe fn into_message_value_fuse_if_required( |
| 621 | raw_parent_arena: RawArena, |
| 622 | val: ProtoBytes, |
Jakob Buchgraber | 85972e5 | 2024-01-17 03:32:53 -0800 | [diff] [blame] | 623 | ) -> upb_MessageValue { |
Alyssa Haroldsen | 3ccccdb | 2024-02-06 10:22:46 -0800 | [diff] [blame] | 624 | // SAFETY: The arena memory is not freed due to `ManuallyDrop`. |
Jakob Buchgraber | 0d6e979 | 2024-07-09 04:44:21 -0700 | [diff] [blame] | 625 | let parent_arena = ManuallyDrop::new(unsafe { Arena::from_raw(raw_parent_arena) }); |
Jakob Buchgraber | 0d6e979 | 2024-07-09 04:44:21 -0700 | [diff] [blame] | 626 | |
Protobuf Team Bot | e26ef86 | 2024-08-26 05:14:52 -0700 | [diff] [blame] | 627 | let (view, arena) = val.inner.into_raw_parts(); |
Jakob Buchgraber | 0d6e979 | 2024-07-09 04:44:21 -0700 | [diff] [blame] | 628 | parent_arena.fuse(&arena); |
| 629 | |
Jakob Buchgraber | 08da921 | 2024-07-09 06:59:28 -0700 | [diff] [blame] | 630 | upb_MessageValue { str_val: view } |
Jakob Buchgraber | 85972e5 | 2024-01-17 03:32:53 -0800 | [diff] [blame] | 631 | } |
| 632 | |
Marcel Hlopko | 6b7e814 | 2024-06-20 05:54:09 -0700 | [diff] [blame] | 633 | unsafe fn from_message_value<'msg>(msg: upb_MessageValue) -> View<'msg, ProtoBytes> { |
Jakob Buchgraber | 85972e5 | 2024-01-17 03:32:53 -0800 | [diff] [blame] | 634 | unsafe { msg.str_val.as_ref() } |
| 635 | } |
| 636 | } |
| 637 | |
Marcel Hlopko | 6b7e814 | 2024-06-20 05:54:09 -0700 | [diff] [blame] | 638 | impl UpbTypeConversions for ProtoString { |
Protobuf Team Bot | 2678e10 | 2024-04-12 13:50:28 -0700 | [diff] [blame] | 639 | fn upb_type() -> upb::CType { |
| 640 | upb::CType::String |
Jakob Buchgraber | 85972e5 | 2024-01-17 03:32:53 -0800 | [diff] [blame] | 641 | } |
| 642 | |
Marcel Hlopko | 6b7e814 | 2024-06-20 05:54:09 -0700 | [diff] [blame] | 643 | fn to_message_value(val: View<'_, ProtoString>) -> upb_MessageValue { |
Jakob Buchgraber | 85972e5 | 2024-01-17 03:32:53 -0800 | [diff] [blame] | 644 | upb_MessageValue { str_val: val.as_bytes().into() } |
| 645 | } |
| 646 | |
Jakob Buchgraber | 0d6e979 | 2024-07-09 04:44:21 -0700 | [diff] [blame] | 647 | unsafe fn into_message_value_fuse_if_required( |
Jakob Buchgraber | 85972e5 | 2024-01-17 03:32:53 -0800 | [diff] [blame] | 648 | raw_arena: RawArena, |
Jakob Buchgraber | 0d6e979 | 2024-07-09 04:44:21 -0700 | [diff] [blame] | 649 | val: ProtoString, |
Jakob Buchgraber | 85972e5 | 2024-01-17 03:32:53 -0800 | [diff] [blame] | 650 | ) -> upb_MessageValue { |
Alyssa Haroldsen | 3ccccdb | 2024-02-06 10:22:46 -0800 | [diff] [blame] | 651 | // SAFETY: `raw_arena` is valid as promised by the caller |
| 652 | unsafe { |
Jakob Buchgraber | 0d6e979 | 2024-07-09 04:44:21 -0700 | [diff] [blame] | 653 | <ProtoBytes as UpbTypeConversions>::into_message_value_fuse_if_required( |
Alyssa Haroldsen | 3ccccdb | 2024-02-06 10:22:46 -0800 | [diff] [blame] | 654 | raw_arena, |
Jakob Buchgraber | 0d6e979 | 2024-07-09 04:44:21 -0700 | [diff] [blame] | 655 | val.into(), |
Alyssa Haroldsen | 3ccccdb | 2024-02-06 10:22:46 -0800 | [diff] [blame] | 656 | ) |
| 657 | } |
Jakob Buchgraber | 85972e5 | 2024-01-17 03:32:53 -0800 | [diff] [blame] | 658 | } |
| 659 | |
Marcel Hlopko | 6b7e814 | 2024-06-20 05:54:09 -0700 | [diff] [blame] | 660 | unsafe fn from_message_value<'msg>(msg: upb_MessageValue) -> View<'msg, ProtoString> { |
Jakob Buchgraber | 85972e5 | 2024-01-17 03:32:53 -0800 | [diff] [blame] | 661 | unsafe { ProtoStr::from_utf8_unchecked(msg.str_val.as_ref()) } |
| 662 | } |
| 663 | } |
| 664 | |
Protobuf Team Bot | e26ef86 | 2024-08-26 05:14:52 -0700 | [diff] [blame] | 665 | #[doc(hidden)] |
Alyssa Haroldsen | 035d6ec | 2024-02-05 15:17:56 -0800 | [diff] [blame] | 666 | pub struct RawMapIter { |
| 667 | // TODO: Replace this `RawMap` with the const type. |
| 668 | map: RawMap, |
| 669 | iter: usize, |
| 670 | } |
| 671 | |
| 672 | impl RawMapIter { |
Protobuf Team Bot | e26ef86 | 2024-08-26 05:14:52 -0700 | [diff] [blame] | 673 | pub fn new(map: RawMap) -> Self { |
Derek Benson | 1e1bf0d | 2024-07-26 11:07:22 -0700 | [diff] [blame] | 674 | RawMapIter { map, iter: UPB_MAP_BEGIN } |
Alyssa Haroldsen | 035d6ec | 2024-02-05 15:17:56 -0800 | [diff] [blame] | 675 | } |
| 676 | |
| 677 | /// # Safety |
| 678 | /// - `self.map` must be valid, and remain valid while the return value is |
| 679 | /// in use. |
Protobuf Team Bot | e26ef86 | 2024-08-26 05:14:52 -0700 | [diff] [blame] | 680 | pub unsafe fn next_unchecked(&mut self) -> Option<(upb_MessageValue, upb_MessageValue)> { |
Alyssa Haroldsen | 035d6ec | 2024-02-05 15:17:56 -0800 | [diff] [blame] | 681 | let mut key = MaybeUninit::uninit(); |
| 682 | let mut value = MaybeUninit::uninit(); |
| 683 | // SAFETY: the `map` is valid as promised by the caller |
| 684 | unsafe { upb_Map_Next(self.map, key.as_mut_ptr(), value.as_mut_ptr(), &mut self.iter) } |
| 685 | // SAFETY: if upb_Map_Next returns true, then key and value have been populated. |
| 686 | .then(|| unsafe { (key.assume_init(), value.assume_init()) }) |
| 687 | } |
| 688 | } |
| 689 | |
Adam Cozzette | c3df359 | 2024-09-05 11:09:02 -0700 | [diff] [blame] | 690 | impl<Key, MessageType> ProxiedInMapValue<Key> for MessageType |
| 691 | where |
| 692 | Key: Proxied + UpbTypeConversions, |
Adam Cozzette | 1142838 | 2024-09-12 11:22:07 -0700 | [diff] [blame] | 693 | MessageType: Proxied + UpbTypeConversions, |
Adam Cozzette | c3df359 | 2024-09-05 11:09:02 -0700 | [diff] [blame] | 694 | { |
| 695 | fn map_new(_private: Private) -> Map<Key, Self> { |
| 696 | let arena = Arena::new(); |
| 697 | let raw = unsafe { |
| 698 | upb_Map_New( |
| 699 | arena.raw(), |
| 700 | <Key as UpbTypeConversions>::upb_type(), |
| 701 | <Self as UpbTypeConversions>::upb_type(), |
| 702 | ) |
| 703 | }; |
| 704 | |
| 705 | Map::from_inner(Private, InnerMap::new(raw, arena)) |
| 706 | } |
| 707 | |
| 708 | unsafe fn map_free(_private: Private, _map: &mut Map<Key, Self>) { |
| 709 | // No-op: the memory will be dropped by the arena. |
| 710 | } |
| 711 | |
| 712 | fn map_clear(mut map: MapMut<Key, Self>) { |
| 713 | unsafe { |
| 714 | upb_Map_Clear(map.as_raw(Private)); |
| 715 | } |
| 716 | } |
| 717 | |
| 718 | fn map_len(map: MapView<Key, Self>) -> usize { |
| 719 | unsafe { upb_Map_Size(map.as_raw(Private)) } |
| 720 | } |
| 721 | |
| 722 | fn map_insert( |
| 723 | mut map: MapMut<Key, Self>, |
| 724 | key: View<'_, Key>, |
| 725 | value: impl IntoProxied<Self>, |
| 726 | ) -> bool { |
| 727 | let arena = map.inner(Private).raw_arena(); |
| 728 | unsafe { |
| 729 | upb_Map_InsertAndReturnIfInserted( |
| 730 | map.as_raw(Private), |
| 731 | <Key as UpbTypeConversions>::to_message_value(key), |
| 732 | <Self as UpbTypeConversions>::into_message_value_fuse_if_required( |
| 733 | arena, |
| 734 | value.into_proxied(Private), |
| 735 | ), |
| 736 | arena, |
| 737 | ) |
| 738 | } |
| 739 | } |
| 740 | |
| 741 | fn map_get<'a>(map: MapView<'a, Key, Self>, key: View<'_, Key>) -> Option<View<'a, Self>> { |
| 742 | let mut val = MaybeUninit::uninit(); |
| 743 | let found = unsafe { |
| 744 | upb_Map_Get( |
| 745 | map.as_raw(Private), |
| 746 | <Key as UpbTypeConversions>::to_message_value(key), |
| 747 | val.as_mut_ptr(), |
| 748 | ) |
| 749 | }; |
| 750 | if !found { |
| 751 | return None; |
| 752 | } |
| 753 | Some(unsafe { <Self as UpbTypeConversions>::from_message_value(val.assume_init()) }) |
| 754 | } |
| 755 | |
| 756 | fn map_remove(mut map: MapMut<Key, Self>, key: View<'_, Key>) -> bool { |
| 757 | unsafe { |
| 758 | upb_Map_Delete( |
| 759 | map.as_raw(Private), |
| 760 | <Key as UpbTypeConversions>::to_message_value(key), |
| 761 | ptr::null_mut(), |
| 762 | ) |
| 763 | } |
| 764 | } |
| 765 | fn map_iter(map: MapView<Key, Self>) -> MapIter<Key, Self> { |
| 766 | // SAFETY: MapView<'_,..>> guarantees its RawMap outlives '_. |
| 767 | unsafe { MapIter::from_raw(Private, RawMapIter::new(map.as_raw(Private))) } |
| 768 | } |
| 769 | |
| 770 | fn map_iter_next<'a>( |
| 771 | iter: &mut MapIter<'a, Key, Self>, |
| 772 | ) -> Option<(View<'a, Key>, View<'a, Self>)> { |
| 773 | // SAFETY: MapIter<'a, ..> guarantees its RawMapIter outlives 'a. |
| 774 | unsafe { iter.as_raw_mut(Private).next_unchecked() } |
| 775 | // SAFETY: MapIter<K, V> returns key and values message values |
| 776 | // with the variants for K and V active. |
| 777 | .map(|(k, v)| unsafe { |
| 778 | ( |
| 779 | <Key as UpbTypeConversions>::from_message_value(k), |
| 780 | <Self as UpbTypeConversions>::from_message_value(v), |
| 781 | ) |
| 782 | }) |
| 783 | } |
| 784 | } |
| 785 | |
Alyssa Haroldsen | a48090e | 2024-02-01 14:21:41 -0800 | [diff] [blame] | 786 | /// `upb_Map_Insert`, but returns a `bool` for whether insert occurred. |
| 787 | /// |
| 788 | /// Returns `true` if the entry was newly inserted. |
| 789 | /// |
| 790 | /// # Panics |
| 791 | /// Panics if the arena is out of memory. |
| 792 | /// |
| 793 | /// # Safety |
| 794 | /// The same as `upb_Map_Insert`: |
| 795 | /// - `map` must be a valid map. |
| 796 | /// - The `arena` must be valid and outlive the map. |
| 797 | /// - The inserted value must outlive the map. |
| 798 | #[allow(non_snake_case)] |
| 799 | pub unsafe fn upb_Map_InsertAndReturnIfInserted( |
| 800 | map: RawMap, |
| 801 | key: upb_MessageValue, |
| 802 | value: upb_MessageValue, |
| 803 | arena: RawArena, |
| 804 | ) -> bool { |
| 805 | match unsafe { upb_Map_Insert(map, key, value, arena) } { |
Protobuf Team Bot | 2678e10 | 2024-04-12 13:50:28 -0700 | [diff] [blame] | 806 | upb::MapInsertStatus::Inserted => true, |
| 807 | upb::MapInsertStatus::Replaced => false, |
| 808 | upb::MapInsertStatus::OutOfMemory => panic!("map arena is out of memory"), |
Alyssa Haroldsen | a48090e | 2024-02-01 14:21:41 -0800 | [diff] [blame] | 809 | } |
| 810 | } |