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 #include "google/protobuf/compiler/rust/message.h"
9
10 #include <string>
11
12 #include "absl/log/absl_check.h"
13 #include "absl/log/absl_log.h"
14 #include "absl/strings/str_cat.h"
15 #include "absl/strings/string_view.h"
16 #include "google/protobuf/compiler/cpp/helpers.h"
17 #include "google/protobuf/compiler/cpp/names.h"
18 #include "google/protobuf/compiler/rust/accessors/accessor_case.h"
19 #include "google/protobuf/compiler/rust/accessors/accessors.h"
20 #include "google/protobuf/compiler/rust/context.h"
21 #include "google/protobuf/compiler/rust/enum.h"
22 #include "google/protobuf/compiler/rust/naming.h"
23 #include "google/protobuf/compiler/rust/oneof.h"
24 #include "google/protobuf/compiler/rust/upb_helpers.h"
25 #include "google/protobuf/descriptor.h"
26
27 namespace google {
28 namespace protobuf {
29 namespace compiler {
30 namespace rust {
31 namespace {
32
MessageNew(Context & ctx,const Descriptor & msg)33 void MessageNew(Context& ctx, const Descriptor& msg) {
34 switch (ctx.opts().kernel) {
35 case Kernel::kCpp:
36 ctx.Emit({{"new_thunk", ThunkName(ctx, msg, "new")}}, R"rs(
37 Self { inner: $pbr$::MessageInner { msg: unsafe { $new_thunk$() } } }
38 )rs");
39 return;
40
41 case Kernel::kUpb:
42 ctx.Emit(R"rs(
43 let arena = $pbr$::Arena::new();
44 let raw_msg = unsafe {
45 $pbr$::upb_Message_New(
46 <Self as $pbr$::AssociatedMiniTable>::mini_table(),
47 arena.raw()).unwrap()
48 };
49 Self {
50 inner: $pbr$::MessageInner {
51 msg: raw_msg,
52 arena,
53 }
54 }
55 )rs");
56 return;
57 }
58
59 ABSL_LOG(FATAL) << "unreachable";
60 }
61
MessageSerialize(Context & ctx,const Descriptor & msg)62 void MessageSerialize(Context& ctx, const Descriptor& msg) {
63 switch (ctx.opts().kernel) {
64 case Kernel::kCpp:
65 ctx.Emit({}, R"rs(
66 let mut serialized_data = $pbr$::SerializedData::new();
67 let success = unsafe {
68 $pbr$::proto2_rust_Message_serialize(self.raw_msg(), &mut serialized_data)
69 };
70 if success {
71 Ok(serialized_data.into_vec())
72 } else {
73 Err($pb$::SerializeError)
74 }
75 )rs");
76 return;
77
78 case Kernel::kUpb:
79 ctx.Emit({{"minitable", UpbMiniTableName(msg)}},
80 R"rs(
81 // SAFETY: `MINI_TABLE` is the one associated with `self.raw_msg()`.
82 let encoded = unsafe {
83 $pbr$::wire::encode(self.raw_msg(),
84 <Self as $pbr$::AssociatedMiniTable>::mini_table())
85 };
86 //~ TODO: This discards the info we have about the reason
87 //~ of the failure, we should try to keep it instead.
88 encoded.map_err(|_| $pb$::SerializeError)
89 )rs");
90 return;
91 }
92
93 ABSL_LOG(FATAL) << "unreachable";
94 }
95
MessageMutClear(Context & ctx,const Descriptor & msg)96 void MessageMutClear(Context& ctx, const Descriptor& msg) {
97 switch (ctx.opts().kernel) {
98 case Kernel::kCpp:
99 ctx.Emit({},
100 R"rs(
101 unsafe { $pbr$::proto2_rust_Message_clear(self.raw_msg()) }
102 )rs");
103 return;
104 case Kernel::kUpb:
105 ctx.Emit(
106 R"rs(
107 unsafe {
108 $pbr$::upb_Message_Clear(
109 self.raw_msg(),
110 <Self as $pbr$::AssociatedMiniTable>::mini_table())
111 }
112 )rs");
113 return;
114 }
115 }
116
MessageClearAndParse(Context & ctx,const Descriptor & msg)117 void MessageClearAndParse(Context& ctx, const Descriptor& msg) {
118 switch (ctx.opts().kernel) {
119 case Kernel::kCpp:
120 ctx.Emit({},
121 R"rs(
122 let success = unsafe {
123 // SAFETY: `data.as_ptr()` is valid to read for `data.len()`.
124 let data = $pbr$::SerializedData::from_raw_parts(
125 $NonNull$::new(data.as_ptr() as *mut _).unwrap(),
126 data.len(),
127 );
128
129 $pbr$::proto2_rust_Message_parse(self.raw_msg(), data)
130 };
131 success.then_some(()).ok_or($pb$::ParseError)
132 )rs");
133 return;
134
135 case Kernel::kUpb:
136 ctx.Emit(
137 R"rs(
138 let mut msg = Self::new();
139
140 // SAFETY:
141 // - `data.as_ptr()` is valid to read for `data.len()`
142 // - `mini_table` is the one used to construct `msg.raw_msg()`
143 // - `msg.arena().raw()` is held for the same lifetime as `msg`.
144 let status = unsafe {
145 $pbr$::wire::decode(
146 data,
147 msg.raw_msg(),
148 <Self as $pbr$::AssociatedMiniTable>::mini_table(),
149 msg.arena())
150 };
151 match status {
152 Ok(_) => {
153 //~ This swap causes the old self.inner.arena to be moved into `msg`
154 //~ which we immediately drop, which will release any previous
155 //~ message that was held here.
156 $std$::mem::swap(self, &mut msg);
157 Ok(())
158 }
159 Err(_) => Err($pb$::ParseError)
160 }
161 )rs");
162 return;
163 }
164
165 ABSL_LOG(FATAL) << "unreachable";
166 }
167
MessageDebug(Context & ctx,const Descriptor & msg)168 void MessageDebug(Context& ctx, const Descriptor& msg) {
169 switch (ctx.opts().kernel) {
170 case Kernel::kCpp:
171 ctx.Emit({},
172 R"rs(
173 $pbr$::debug_string(self.raw_msg(), f)
174 )rs");
175 return;
176
177 case Kernel::kUpb:
178 ctx.Emit(
179 R"rs(
180 let string = unsafe {
181 $pbr$::debug_string(
182 self.raw_msg(),
183 <Self as $pbr$::AssociatedMiniTable>::mini_table()
184 )
185 };
186 write!(f, "{}", string)
187 )rs");
188 return;
189 }
190
191 ABSL_LOG(FATAL) << "unreachable";
192 }
193
CppMessageExterns(Context & ctx,const Descriptor & msg)194 void CppMessageExterns(Context& ctx, const Descriptor& msg) {
195 ABSL_CHECK(ctx.is_cpp());
196 ctx.Emit(
197 {{"new_thunk", ThunkName(ctx, msg, "new")},
198 {"default_instance_thunk", ThunkName(ctx, msg, "default_instance")},
199 {"repeated_new_thunk", ThunkName(ctx, msg, "repeated_new")},
200 {"repeated_free_thunk", ThunkName(ctx, msg, "repeated_free")},
201 {"repeated_len_thunk", ThunkName(ctx, msg, "repeated_len")},
202 {"repeated_get_thunk", ThunkName(ctx, msg, "repeated_get")},
203 {"repeated_get_mut_thunk", ThunkName(ctx, msg, "repeated_get_mut")},
204 {"repeated_add_thunk", ThunkName(ctx, msg, "repeated_add")},
205 {"repeated_clear_thunk", ThunkName(ctx, msg, "repeated_clear")},
206 {"repeated_copy_from_thunk", ThunkName(ctx, msg, "repeated_copy_from")},
207 {"repeated_reserve_thunk", ThunkName(ctx, msg, "repeated_reserve")},
208 {"map_size_info_thunk", ThunkName(ctx, msg, "size_info")}},
209 R"rs(
210 fn $new_thunk$() -> $pbr$::RawMessage;
211 fn $default_instance_thunk$() -> $pbr$::RawMessage;
212 fn $repeated_new_thunk$() -> $pbr$::RawRepeatedField;
213 fn $repeated_free_thunk$(raw: $pbr$::RawRepeatedField);
214 fn $repeated_len_thunk$(raw: $pbr$::RawRepeatedField) -> usize;
215 fn $repeated_add_thunk$(raw: $pbr$::RawRepeatedField) -> $pbr$::RawMessage;
216 fn $repeated_get_thunk$(raw: $pbr$::RawRepeatedField, index: usize) -> $pbr$::RawMessage;
217 fn $repeated_get_mut_thunk$(raw: $pbr$::RawRepeatedField, index: usize) -> $pbr$::RawMessage;
218 fn $repeated_clear_thunk$(raw: $pbr$::RawRepeatedField);
219 fn $repeated_copy_from_thunk$(dst: $pbr$::RawRepeatedField, src: $pbr$::RawRepeatedField);
220 fn $repeated_reserve_thunk$(raw: $pbr$::RawRepeatedField, additional: usize);
221 fn $map_size_info_thunk$(i: $pbr$::MapNodeSizeInfoIndex) -> $pbr$::MapNodeSizeInfo;
222 )rs");
223 }
224
MessageDrop(Context & ctx,const Descriptor & msg)225 void MessageDrop(Context& ctx, const Descriptor& msg) {
226 if (ctx.is_upb()) {
227 // Nothing to do here; drop glue (which will run drop(self.arena)
228 // automatically) is sufficient.
229 return;
230 }
231
232 ctx.Emit(R"rs(
233 unsafe { $pbr$::proto2_rust_Message_delete(self.raw_msg()); }
234 )rs");
235 }
236
IntoProxiedForMessage(Context & ctx,const Descriptor & msg)237 void IntoProxiedForMessage(Context& ctx, const Descriptor& msg) {
238 switch (ctx.opts().kernel) {
239 case Kernel::kCpp:
240 ctx.Emit(R"rs(
241 impl<'msg> $pb$::IntoProxied<$Msg$> for $Msg$View<'msg> {
242 fn into_proxied(self, _private: $pbi$::Private) -> $Msg$ {
243 let dst = $Msg$::new();
244 unsafe { $pbr$::proto2_rust_Message_copy_from(dst.inner.msg, self.msg) };
245 dst
246 }
247 }
248
249 impl<'msg> $pb$::IntoProxied<$Msg$> for $Msg$Mut<'msg> {
250 fn into_proxied(self, _private: $pbi$::Private) -> $Msg$ {
251 $pb$::IntoProxied::into_proxied($pb$::IntoView::into_view(self), _private)
252 }
253 }
254 )rs");
255 return;
256
257 case Kernel::kUpb:
258 ctx.Emit(R"rs(
259 impl<'msg> $pb$::IntoProxied<$Msg$> for $Msg$View<'msg> {
260 fn into_proxied(self, _private: $pbi$::Private) -> $Msg$ {
261 let dst = $Msg$::new();
262 unsafe { $pbr$::upb_Message_DeepCopy(
263 dst.inner.msg,
264 self.msg,
265 <Self as $pbr$::AssociatedMiniTable>::mini_table(),
266 dst.inner.arena.raw(),
267 ) };
268 dst
269 }
270 }
271
272 impl<'msg> $pb$::IntoProxied<$Msg$> for $Msg$Mut<'msg> {
273 fn into_proxied(self, _private: $pbi$::Private) -> $Msg$ {
274 $pb$::IntoProxied::into_proxied($pb$::IntoView::into_view(self), _private)
275 }
276 }
277 )rs");
278 return;
279 }
280
281 ABSL_LOG(FATAL) << "unreachable";
282 }
283
UpbGeneratedMessageTraitImpls(Context & ctx,const Descriptor & msg)284 void UpbGeneratedMessageTraitImpls(Context& ctx, const Descriptor& msg) {
285 if (ctx.opts().kernel == Kernel::kUpb) {
286 ctx.Emit({{"minitable", UpbMiniTableName(msg)}}, R"rs(
287 unsafe impl $pbr$::AssociatedMiniTable for $Msg$ {
288 #[inline(always)]
289 fn mini_table() -> *const $pbr$::upb_MiniTable {
290 // This is unsafe only for Rust 1.80 and below and thus can be dropped
291 // once our MSRV is 1.81+
292 #[allow(unused_unsafe)]
293 unsafe {
294 $std$::ptr::addr_of!($minitable$)
295 }
296 }
297 }
298
299 unsafe impl $pbr$::AssociatedMiniTable for $Msg$View<'_> {
300 #[inline(always)]
301 fn mini_table() -> *const $pbr$::upb_MiniTable {
302 // This is unsafe only for Rust 1.80 and below and thus can be dropped
303 // once our MSRV is 1.81+
304 #[allow(unused_unsafe)]
305 unsafe {
306 $std$::ptr::addr_of!($minitable$)
307 }
308 }
309 }
310
311 unsafe impl $pbr$::AssociatedMiniTable for $Msg$Mut<'_> {
312 #[inline(always)]
313 fn mini_table() -> *const $pbr$::upb_MiniTable {
314 // This is unsafe only for Rust 1.80 and below and thus can be dropped
315 // once our MSRV is 1.81+
316 #[allow(unused_unsafe)]
317 unsafe {
318 $std$::ptr::addr_of!($minitable$)
319 }
320 }
321 }
322 )rs");
323 }
324 }
325
MessageMutMergeFrom(Context & ctx,const Descriptor & msg)326 void MessageMutMergeFrom(Context& ctx, const Descriptor& msg) {
327 switch (ctx.opts().kernel) {
328 case Kernel::kCpp:
329 ctx.Emit({},
330 R"rs(
331 impl $pb$::MergeFrom for $Msg$Mut<'_> {
332 fn merge_from(&mut self, src: impl $pb$::AsView<Proxied = $Msg$>) {
333 // SAFETY: self and src are both valid `$Msg$`s.
334 unsafe {
335 $pbr$::proto2_rust_Message_merge_from(self.raw_msg(), src.as_view().raw_msg());
336 }
337 }
338 }
339 )rs");
340 return;
341 case Kernel::kUpb:
342 ctx.Emit(
343 R"rs(
344 impl $pb$::MergeFrom for $Msg$Mut<'_> {
345 fn merge_from(&mut self, src: impl $pb$::AsView<Proxied = $Msg$>) {
346 // SAFETY: self and src are both valid `$Msg$`s.
347 unsafe {
348 assert!(
349 $pbr$::upb_Message_MergeFrom(self.raw_msg(),
350 src.as_view().raw_msg(),
351 <Self as $pbr$::AssociatedMiniTable>::mini_table(),
352 // Use a nullptr for the ExtensionRegistry.
353 $std$::ptr::null(),
354 self.arena().raw())
355 );
356 }
357 }
358 }
359 )rs");
360 return;
361 }
362 }
363
MessageProxiedInRepeated(Context & ctx,const Descriptor & msg)364 void MessageProxiedInRepeated(Context& ctx, const Descriptor& msg) {
365 switch (ctx.opts().kernel) {
366 case Kernel::kCpp:
367 ctx.Emit(
368 {
369 {"Msg", RsSafeName(msg.name())},
370 {"repeated_len_thunk", ThunkName(ctx, msg, "repeated_len")},
371 {"repeated_get_thunk", ThunkName(ctx, msg, "repeated_get")},
372 {"repeated_get_mut_thunk",
373 ThunkName(ctx, msg, "repeated_get_mut")},
374 {"repeated_add_thunk", ThunkName(ctx, msg, "repeated_add")},
375 {"repeated_new_thunk", ThunkName(ctx, msg, "repeated_new")},
376 {"repeated_free_thunk", ThunkName(ctx, msg, "repeated_free")},
377 {"repeated_clear_thunk", ThunkName(ctx, msg, "repeated_clear")},
378 {"repeated_copy_from_thunk",
379 ThunkName(ctx, msg, "repeated_copy_from")},
380 {"repeated_reserve_thunk",
381 ThunkName(ctx, msg, "repeated_reserve")},
382 },
383 R"rs(
384 unsafe impl $pb$::ProxiedInRepeated for $Msg$ {
385 fn repeated_new(_private: $pbi$::Private) -> $pb$::Repeated<Self> {
386 // SAFETY:
387 // - The thunk returns an unaliased and valid `RepeatedPtrField*`
388 unsafe {
389 $pb$::Repeated::from_inner($pbi$::Private,
390 $pbr$::InnerRepeated::from_raw($repeated_new_thunk$()
391 )
392 )
393 }
394 }
395
396 unsafe fn repeated_free(_private: $pbi$::Private, f: &mut $pb$::Repeated<Self>) {
397 // SAFETY
398 // - `f.raw()` is a valid `RepeatedPtrField*`.
399 unsafe { $repeated_free_thunk$(f.as_view().as_raw($pbi$::Private)) }
400 }
401
402 fn repeated_len(f: $pb$::View<$pb$::Repeated<Self>>) -> usize {
403 // SAFETY: `f.as_raw()` is a valid `RepeatedPtrField*`.
404 unsafe { $repeated_len_thunk$(f.as_raw($pbi$::Private)) }
405 }
406
407 unsafe fn repeated_set_unchecked(
408 mut f: $pb$::Mut<$pb$::Repeated<Self>>,
409 i: usize,
410 v: impl $pb$::IntoProxied<Self>,
411 ) {
412 // SAFETY:
413 // - `f.as_raw()` is a valid `RepeatedPtrField*`.
414 // - `i < len(f)` is promised by caller.
415 // - `v.raw_msg()` is a valid `const Message&`.
416 unsafe {
417 $pbr$::proto2_rust_Message_copy_from(
418 $repeated_get_mut_thunk$(f.as_raw($pbi$::Private), i),
419 v.into_proxied($pbi$::Private).raw_msg(),
420 );
421 }
422 }
423
424 unsafe fn repeated_get_unchecked(
425 f: $pb$::View<$pb$::Repeated<Self>>,
426 i: usize,
427 ) -> $pb$::View<Self> {
428 // SAFETY:
429 // - `f.as_raw()` is a valid `const RepeatedPtrField&`.
430 // - `i < len(f)` is promised by caller.
431 let msg = unsafe { $repeated_get_thunk$(f.as_raw($pbi$::Private), i) };
432 $pb$::View::<Self>::new($pbi$::Private, msg)
433 }
434 fn repeated_clear(mut f: $pb$::Mut<$pb$::Repeated<Self>>) {
435 // SAFETY:
436 // - `f.as_raw()` is a valid `RepeatedPtrField*`.
437 unsafe { $repeated_clear_thunk$(f.as_raw($pbi$::Private)) };
438 }
439
440 fn repeated_push(mut f: $pb$::Mut<$pb$::Repeated<Self>>, v: impl $pb$::IntoProxied<Self>) {
441 // SAFETY:
442 // - `f.as_raw()` is a valid `RepeatedPtrField*`.
443 // - `v.raw_msg()` is a valid `const Message&`.
444 unsafe {
445 let new_elem = $repeated_add_thunk$(f.as_raw($pbi$::Private));
446 $pbr$::proto2_rust_Message_copy_from(new_elem, v.into_proxied($pbi$::Private).raw_msg());
447 }
448 }
449
450 fn repeated_copy_from(
451 src: $pb$::View<$pb$::Repeated<Self>>,
452 mut dest: $pb$::Mut<$pb$::Repeated<Self>>,
453 ) {
454 // SAFETY:
455 // - `dest.as_raw()` is a valid `RepeatedPtrField*`.
456 // - `src.as_raw()` is a valid `const RepeatedPtrField&`.
457 unsafe {
458 $repeated_copy_from_thunk$(dest.as_raw($pbi$::Private), src.as_raw($pbi$::Private));
459 }
460 }
461
462 fn repeated_reserve(
463 mut f: $pb$::Mut<$pb$::Repeated<Self>>,
464 additional: usize,
465 ) {
466 // SAFETY:
467 // - `f.as_raw()` is a valid `RepeatedPtrField*`.
468 unsafe { $repeated_reserve_thunk$(f.as_raw($pbi$::Private), additional) }
469 }
470 }
471 )rs");
472 return;
473 case Kernel::kUpb:
474 ctx.Emit(
475 {
476 {"new_thunk", ThunkName(ctx, msg, "new")},
477 },
478 R"rs(
479 unsafe impl $pb$::ProxiedInRepeated for $Msg$ {
480 fn repeated_new(_private: $pbi$::Private) -> $pb$::Repeated<Self> {
481 let arena = $pbr$::Arena::new();
482 unsafe {
483 $pb$::Repeated::from_inner(
484 $pbi$::Private,
485 $pbr$::InnerRepeated::from_raw_parts(
486 $pbr$::upb_Array_New(arena.raw(), $pbr$::CType::Message),
487 arena,
488 ))
489 }
490 }
491
492 unsafe fn repeated_free(_private: $pbi$::Private, _f: &mut $pb$::Repeated<Self>) {
493 // No-op: the memory will be dropped by the arena.
494 }
495
496 fn repeated_len(f: $pb$::View<$pb$::Repeated<Self>>) -> usize {
497 // SAFETY: `f.as_raw()` is a valid `upb_Array*`.
498 unsafe { $pbr$::upb_Array_Size(f.as_raw($pbi$::Private)) }
499 }
500 unsafe fn repeated_set_unchecked(
501 mut f: $pb$::Mut<$pb$::Repeated<Self>>,
502 i: usize,
503 v: impl $pb$::IntoProxied<Self>,
504 ) {
505 unsafe {
506 $pbr$::upb_Array_Set(
507 f.as_raw($pbi$::Private),
508 i,
509 <Self as $pbr$::UpbTypeConversions>::into_message_value_fuse_if_required(
510 f.raw_arena($pbi$::Private),
511 v.into_proxied($pbi$::Private),
512 ),
513 )
514 }
515 }
516
517 unsafe fn repeated_get_unchecked(
518 f: $pb$::View<$pb$::Repeated<Self>>,
519 i: usize,
520 ) -> $pb$::View<Self> {
521 // SAFETY:
522 // - `f.as_raw()` is a valid `const upb_Array*`.
523 // - `i < len(f)` is promised by the caller.
524 let msg_ptr = unsafe { $pbr$::upb_Array_Get(f.as_raw($pbi$::Private), i).msg_val }
525 .expect("upb_Array* element should not be NULL.");
526 $pb$::View::<Self>::new($pbi$::Private, msg_ptr)
527 }
528
529 fn repeated_clear(mut f: $pb$::Mut<$pb$::Repeated<Self>>) {
530 // SAFETY:
531 // - `f.as_raw()` is a valid `upb_Array*`.
532 unsafe {
533 $pbr$::upb_Array_Resize(f.as_raw($pbi$::Private), 0, f.raw_arena($pbi$::Private))
534 };
535 }
536 fn repeated_push(mut f: $pb$::Mut<$pb$::Repeated<Self>>, v: impl $pb$::IntoProxied<Self>) {
537 // SAFETY:
538 // - `f.as_raw()` is a valid `upb_Array*`.
539 // - `msg_ptr` is a valid `upb_Message*`.
540 unsafe {
541 $pbr$::upb_Array_Append(
542 f.as_raw($pbi$::Private),
543 <Self as $pbr$::UpbTypeConversions>::into_message_value_fuse_if_required(f.raw_arena($pbi$::Private), v.into_proxied($pbi$::Private)),
544 f.raw_arena($pbi$::Private)
545 );
546 };
547 }
548
549 fn repeated_copy_from(
550 src: $pb$::View<$pb$::Repeated<Self>>,
551 dest: $pb$::Mut<$pb$::Repeated<Self>>,
552 ) {
553 // SAFETY:
554 // - Elements of `src` and `dest` have message minitable `MINI_TABLE`.
555 unsafe {
556 $pbr$::repeated_message_copy_from(src, dest, <Self as $pbr$::AssociatedMiniTable>::mini_table());
557 }
558 }
559
560 fn repeated_reserve(
561 mut f: $pb$::Mut<$pb$::Repeated<Self>>,
562 additional: usize,
563 ) {
564 // SAFETY:
565 // - `f.as_raw()` is a valid `upb_Array*`.
566 unsafe {
567 let size = $pbr$::upb_Array_Size(f.as_raw($pbi$::Private));
568 $pbr$::upb_Array_Reserve(f.as_raw($pbi$::Private), size + additional, f.raw_arena($pbi$::Private));
569 }
570 }
571 }
572 )rs");
573 return;
574 }
575 ABSL_LOG(FATAL) << "unreachable";
576 }
577
MessageProxiedInMapValue(Context & ctx,const Descriptor & msg)578 void MessageProxiedInMapValue(Context& ctx, const Descriptor& msg) {
579 switch (ctx.opts().kernel) {
580 case Kernel::kCpp:
581 for (const auto& t : kMapKeyTypes) {
582 ctx.Emit(
583 {{"map_size_info_thunk", ThunkName(ctx, msg, "size_info")},
584 {"map_insert",
585 absl::StrCat("proto2_rust_map_insert_", t.thunk_ident)},
586 {"map_remove",
587 absl::StrCat("proto2_rust_map_remove_", t.thunk_ident)},
588 {"map_get", absl::StrCat("proto2_rust_map_get_", t.thunk_ident)},
589 {"map_iter_get",
590 absl::StrCat("proto2_rust_map_iter_get_", t.thunk_ident)},
591 {"key_expr", t.rs_to_ffi_key_expr},
592 {"key_is_string",
593 t.thunk_ident == "ProtoString" ? "true" : "false"},
594 io::Printer::Sub("ffi_key_t", [&] { ctx.Emit(t.rs_ffi_key_t); })
595 .WithSuffix(""),
596 io::Printer::Sub("key_t", [&] { ctx.Emit(t.rs_key_t); })
597 .WithSuffix(""),
598 io::Printer::Sub("from_ffi_key_expr",
599 [&] { ctx.Emit(t.rs_from_ffi_key_expr); })
600 .WithSuffix("")},
601 R"rs(
602 impl $pb$::ProxiedInMapValue<$key_t$> for $Msg$ {
603 fn map_new(_private: $pbi$::Private) -> $pb$::Map<$key_t$, Self> {
604 unsafe {
605 $pb$::Map::from_inner(
606 $pbi$::Private,
607 $pbr$::InnerMap::new($pbr$::proto2_rust_map_new())
608 )
609 }
610 }
611
612 unsafe fn map_free(_private: $pbi$::Private, map: &mut $pb$::Map<$key_t$, Self>) {
613 use $pbr$::MapNodeSizeInfoIndexForType;
614 unsafe { $pbr$::proto2_rust_map_free(map.as_raw($pbi$::Private), $key_is_string$, $map_size_info_thunk$($key_t$::SIZE_INFO_INDEX)); }
615 }
616
617 fn map_clear(mut map: $pb$::MapMut<$key_t$, Self>) {
618 use $pbr$::MapNodeSizeInfoIndexForType;
619 unsafe { $pbr$::proto2_rust_map_clear(map.as_raw($pbi$::Private), $key_is_string$, $map_size_info_thunk$($key_t$::SIZE_INFO_INDEX)); }
620 }
621
622 fn map_len(map: $pb$::MapView<$key_t$, Self>) -> usize {
623 unsafe { $pbr$::proto2_rust_map_size(map.as_raw($pbi$::Private)) }
624 }
625
626 fn map_insert(mut map: $pb$::MapMut<$key_t$, Self>, key: $pb$::View<'_, $key_t$>, value: impl $pb$::IntoProxied<Self>) -> bool {
627 use $pbr$::MapNodeSizeInfoIndexForType;
628 unsafe {
629 $pbr$::$map_insert$(
630 map.as_raw($pbi$::Private),
631 $map_size_info_thunk$($key_t$::SIZE_INFO_INDEX),
632 $key_expr$,
633 value.into_proxied($pbi$::Private).raw_msg())
634 }
635 }
636
637 fn map_get<'a>(map: $pb$::MapView<'a, $key_t$, Self>, key: $pb$::View<'_, $key_t$>) -> $Option$<$pb$::View<'a, Self>> {
638 use $pbr$::MapNodeSizeInfoIndexForType;
639 let key = $key_expr$;
640 let mut value = $std$::mem::MaybeUninit::uninit();
641 let found = unsafe {
642 $pbr$::$map_get$(
643 map.as_raw($pbi$::Private),
644 $map_size_info_thunk$($key_t$::SIZE_INFO_INDEX),
645 key,
646 value.as_mut_ptr())
647 };
648 if !found {
649 return None;
650 }
651 Some($Msg$View::new($pbi$::Private, unsafe { value.assume_init() }))
652 }
653
654 fn map_remove(mut map: $pb$::MapMut<$key_t$, Self>, key: $pb$::View<'_, $key_t$>) -> bool {
655 use $pbr$::MapNodeSizeInfoIndexForType;
656 unsafe {
657 $pbr$::$map_remove$(
658 map.as_raw($pbi$::Private),
659 $map_size_info_thunk$($key_t$::SIZE_INFO_INDEX),
660 $key_expr$)
661 }
662 }
663
664 fn map_iter(map: $pb$::MapView<$key_t$, Self>) -> $pb$::MapIter<$key_t$, Self> {
665 // SAFETY:
666 // - The backing map for `map.as_raw` is valid for at least '_.
667 // - A View that is live for '_ guarantees the backing map is unmodified for '_.
668 // - The `iter` function produces an iterator that is valid for the key
669 // and value types, and live for at least '_.
670 unsafe {
671 $pb$::MapIter::from_raw(
672 $pbi$::Private,
673 $pbr$::proto2_rust_map_iter(map.as_raw($pbi$::Private))
674 )
675 }
676 }
677
678 fn map_iter_next<'a>(iter: &mut $pb$::MapIter<'a, $key_t$, Self>) -> $Option$<($pb$::View<'a, $key_t$>, $pb$::View<'a, Self>)> {
679 use $pbr$::MapNodeSizeInfoIndexForType;
680 // SAFETY:
681 // - The `MapIter` API forbids the backing map from being mutated for 'a,
682 // and guarantees that it's the correct key and value types.
683 // - The thunk is safe to call as long as the iterator isn't at the end.
684 // - The thunk always writes to key and value fields and does not read.
685 // - The thunk does not increment the iterator.
686 unsafe {
687 iter.as_raw_mut($pbi$::Private).next_unchecked::<$key_t$, Self, _, _>(
688 |iter, key, value| { $pbr$::$map_iter_get$(
689 iter, $map_size_info_thunk$($key_t$::SIZE_INFO_INDEX), key, value) },
690 |ffi_key| $from_ffi_key_expr$,
691 |raw_msg| $Msg$View::new($pbi$::Private, raw_msg)
692 )
693 }
694 }
695 }
696 )rs");
697 }
698 return;
699 case Kernel::kUpb:
700 ctx.Emit(
701 {
702 {"new_thunk", ThunkName(ctx, msg, "new")},
703 },
704 R"rs(
705 impl $pbr$::UpbTypeConversions for $Msg$ {
706 fn upb_type() -> $pbr$::CType {
707 $pbr$::CType::Message
708 }
709
710 fn to_message_value(
711 val: $pb$::View<'_, Self>) -> $pbr$::upb_MessageValue {
712 $pbr$::upb_MessageValue { msg_val: Some(val.raw_msg()) }
713 }
714
715 unsafe fn into_message_value_fuse_if_required(
716 raw_parent_arena: $pbr$::RawArena,
717 mut val: Self) -> $pbr$::upb_MessageValue {
718 // SAFETY: The arena memory is not freed due to `ManuallyDrop`.
719 let parent_arena = core::mem::ManuallyDrop::new(
720 unsafe { $pbr$::Arena::from_raw(raw_parent_arena) });
721
722 parent_arena.fuse(val.as_mutator_message_ref($pbi$::Private).arena());
723 $pbr$::upb_MessageValue { msg_val: Some(val.raw_msg()) }
724 }
725
726 unsafe fn from_message_value<'msg>(msg: $pbr$::upb_MessageValue)
727 -> $pb$::View<'msg, Self> {
728 $Msg$View::new(
729 $pbi$::Private,
730 unsafe { msg.msg_val }
731 .expect("expected present message value in map"))
732 }
733 }
734 )rs");
735 }
736 }
737
GenerateDefaultInstanceImpl(Context & ctx,const Descriptor & msg)738 void GenerateDefaultInstanceImpl(Context& ctx, const Descriptor& msg) {
739 if (ctx.is_upb()) {
740 ctx.Emit("$pbr$::ScratchSpace::zeroed_block()");
741 } else {
742 ctx.Emit(
743 {{"default_instance_thunk", ThunkName(ctx, msg, "default_instance")}},
744 "unsafe { $default_instance_thunk$() }");
745 }
746 }
747
748 } // namespace
749
GenerateRs(Context & ctx,const Descriptor & msg)750 void GenerateRs(Context& ctx, const Descriptor& msg) {
751 if (msg.map_key() != nullptr) {
752 // Don't generate code for synthetic MapEntry messages.
753 return;
754 }
755 ctx.Emit(
756 {{"Msg", RsSafeName(msg.name())},
757 {"Msg::new", [&] { MessageNew(ctx, msg); }},
758 {"Msg::serialize", [&] { MessageSerialize(ctx, msg); }},
759 {"MsgMut::clear", [&] { MessageMutClear(ctx, msg); }},
760 {"Msg::clear_and_parse", [&] { MessageClearAndParse(ctx, msg); }},
761 {"Msg::drop", [&] { MessageDrop(ctx, msg); }},
762 {"Msg::debug", [&] { MessageDebug(ctx, msg); }},
763 {"MsgMut::merge_from", [&] { MessageMutMergeFrom(ctx, msg); }},
764 {"default_instance_impl",
765 [&] { GenerateDefaultInstanceImpl(ctx, msg); }},
766 {"accessor_fns",
767 [&] {
768 for (int i = 0; i < msg.field_count(); ++i) {
769 GenerateAccessorMsgImpl(ctx, *msg.field(i), AccessorCase::OWNED);
770 }
771 for (int i = 0; i < msg.real_oneof_decl_count(); ++i) {
772 GenerateOneofAccessors(ctx, *msg.real_oneof_decl(i),
773 AccessorCase::OWNED);
774 }
775 }},
776 {"nested_in_msg",
777 [&] {
778 // If we have no nested types, enums, or oneofs, bail out without
779 // emitting an empty mod some_msg.
780 if (msg.nested_type_count() == 0 && msg.enum_type_count() == 0 &&
781 msg.real_oneof_decl_count() == 0) {
782 return;
783 }
784 ctx.Emit({{"mod_name", RsSafeName(CamelToSnakeCase(msg.name()))},
785 {"nested_msgs",
786 [&] {
787 for (int i = 0; i < msg.nested_type_count(); ++i) {
788 GenerateRs(ctx, *msg.nested_type(i));
789 }
790 }},
791 {"nested_enums",
792 [&] {
793 for (int i = 0; i < msg.enum_type_count(); ++i) {
794 GenerateEnumDefinition(ctx, *msg.enum_type(i));
795 }
796 }},
797 {"oneofs",
798 [&] {
799 for (int i = 0; i < msg.real_oneof_decl_count(); ++i) {
800 GenerateOneofDefinition(ctx, *msg.real_oneof_decl(i));
801 }
802 }}},
803 R"rs(
804 pub mod $mod_name$ {
805 $nested_msgs$
806 $nested_enums$
807
808 $oneofs$
809 } // mod $mod_name$
810 )rs");
811 }},
812 {"raw_arena_getter_for_message",
813 [&] {
814 if (ctx.is_upb()) {
815 ctx.Emit({}, R"rs(
816 fn arena(&self) -> &$pbr$::Arena {
817 &self.inner.arena
818 }
819 )rs");
820 }
821 }},
822 {"raw_arena_getter_for_msgmut",
823 [&] {
824 if (ctx.is_upb()) {
825 ctx.Emit({}, R"rs(
826 fn arena(&self) -> &$pbr$::Arena {
827 self.inner.arena()
828 }
829 )rs");
830 }
831 }},
832 {"accessor_fns_for_views",
833 [&] {
834 for (int i = 0; i < msg.field_count(); ++i) {
835 GenerateAccessorMsgImpl(ctx, *msg.field(i), AccessorCase::VIEW);
836 }
837 for (int i = 0; i < msg.real_oneof_decl_count(); ++i) {
838 GenerateOneofAccessors(ctx, *msg.real_oneof_decl(i),
839 AccessorCase::VIEW);
840 }
841 }},
842 {"accessor_fns_for_muts",
843 [&] {
844 for (int i = 0; i < msg.field_count(); ++i) {
845 GenerateAccessorMsgImpl(ctx, *msg.field(i), AccessorCase::MUT);
846 }
847 for (int i = 0; i < msg.real_oneof_decl_count(); ++i) {
848 GenerateOneofAccessors(ctx, *msg.real_oneof_decl(i),
849 AccessorCase::MUT);
850 }
851 }},
852 {"into_proxied_impl", [&] { IntoProxiedForMessage(ctx, msg); }},
853 {"upb_generated_message_trait_impls",
854 [&] { UpbGeneratedMessageTraitImpls(ctx, msg); }},
855 {"repeated_impl", [&] { MessageProxiedInRepeated(ctx, msg); }},
856 {"map_value_impl", [&] { MessageProxiedInMapValue(ctx, msg); }},
857 {"unwrap_upb",
858 [&] {
859 if (ctx.is_upb()) {
860 ctx.Emit(".unwrap_or_else(||$pbr$::ScratchSpace::zeroed_block())");
861 }
862 }},
863 {"upb_arena",
864 [&] {
865 if (ctx.is_upb()) {
866 ctx.Emit(", inner.msg_ref().arena().raw()");
867 }
868 }}},
869 R"rs(
870 #[allow(non_camel_case_types)]
871 pub struct $Msg$ {
872 inner: $pbr$::MessageInner
873 }
874
875 impl $pb$::Message for $Msg$ {}
876
877 impl $std$::default::Default for $Msg$ {
878 fn default() -> Self {
879 Self::new()
880 }
881 }
882
883 impl $pb$::Parse for $Msg$ {
884 fn parse(serialized: &[u8]) -> $Result$<Self, $pb$::ParseError> {
885 Self::parse(serialized)
886 }
887 }
888
889 impl $std$::fmt::Debug for $Msg$ {
890 fn fmt(&self, f: &mut $std$::fmt::Formatter<'_>) -> $std$::fmt::Result {
891 $Msg::debug$
892 }
893 }
894
895 impl $pb$::MergeFrom for $Msg$ {
896 fn merge_from<'src>(&mut self, src: impl $pb$::AsView<Proxied = Self>) {
897 let mut m = self.as_mut();
898 $pb$::MergeFrom::merge_from(&mut m, src)
899 }
900 }
901
902 impl $pb$::Serialize for $Msg$ {
903 fn serialize(&self) -> $Result$<Vec<u8>, $pb$::SerializeError> {
904 $pb$::AsView::as_view(self).serialize()
905 }
906 }
907
908 impl $pb$::Clear for $Msg$ {
909 fn clear(&mut self) {
910 self.as_mut().clear()
911 }
912 }
913
914 impl $pb$::ClearAndParse for $Msg$ {
915 fn clear_and_parse(&mut self, data: &[u8]) -> $Result$<(), $pb$::ParseError> {
916 $Msg::clear_and_parse$
917 }
918 }
919
920 // SAFETY:
921 // - `$Msg$` is `Sync` because it does not implement interior mutability.
922 // Neither does `$Msg$Mut`.
923 unsafe impl Sync for $Msg$ {}
924
925 // SAFETY:
926 // - `$Msg$` is `Send` because it uniquely owns its arena and does
927 // not use thread-local data.
928 unsafe impl Send for $Msg$ {}
929
930 impl $pb$::Proxied for $Msg$ {
931 type View<'msg> = $Msg$View<'msg>;
932 }
933
934 impl $pbi$::SealedInternal for $Msg$ {}
935
936 impl $pb$::MutProxied for $Msg$ {
937 type Mut<'msg> = $Msg$Mut<'msg>;
938 }
939
940 #[derive(Copy, Clone)]
941 #[allow(dead_code)]
942 pub struct $Msg$View<'msg> {
943 msg: $pbr$::RawMessage,
944 _phantom: $Phantom$<&'msg ()>,
945 }
946
947 impl<'msg> $pbi$::SealedInternal for $Msg$View<'msg> {}
948
949 impl<'msg> $pb$::MessageView<'msg> for $Msg$View<'msg> {
950 type Message = $Msg$;
951 }
952
953 impl $std$::fmt::Debug for $Msg$View<'_> {
954 fn fmt(&self, f: &mut $std$::fmt::Formatter<'_>) -> $std$::fmt::Result {
955 $Msg::debug$
956 }
957 }
958
959 impl $pb$::Serialize for $Msg$View<'_> {
960 fn serialize(&self) -> $Result$<Vec<u8>, $pb$::SerializeError> {
961 $Msg::serialize$
962 }
963 }
964
965 impl $std$::default::Default for $Msg$View<'_> {
966 fn default() -> $Msg$View<'static> {
967 $Msg$View::new($pbi$::Private, $default_instance_impl$)
968 }
969 }
970
971 #[allow(dead_code)]
972 impl<'msg> $Msg$View<'msg> {
973 #[doc(hidden)]
974 pub fn new(_private: $pbi$::Private, msg: $pbr$::RawMessage) -> Self {
975 Self { msg, _phantom: $std$::marker::PhantomData }
976 }
977
978 fn raw_msg(&self) -> $pbr$::RawMessage {
979 self.msg
980 }
981
982 pub fn to_owned(&self) -> $Msg$ {
983 $pb$::IntoProxied::into_proxied(*self, $pbi$::Private)
984 }
985
986 $accessor_fns_for_views$
987 }
988
989 // SAFETY:
990 // - `$Msg$View` is `Sync` because it does not support mutation.
991 unsafe impl Sync for $Msg$View<'_> {}
992
993 // SAFETY:
994 // - `$Msg$View` is `Send` because while its alive a `$Msg$Mut` cannot.
995 // - `$Msg$View` does not use thread-local data.
996 unsafe impl Send for $Msg$View<'_> {}
997
998 impl<'msg> $pb$::Proxy<'msg> for $Msg$View<'msg> {}
999 impl<'msg> $pb$::ViewProxy<'msg> for $Msg$View<'msg> {}
1000
1001 impl<'msg> $pb$::AsView for $Msg$View<'msg> {
1002 type Proxied = $Msg$;
1003 fn as_view(&self) -> $pb$::View<'msg, $Msg$> {
1004 *self
1005 }
1006 }
1007
1008 impl<'msg> $pb$::IntoView<'msg> for $Msg$View<'msg> {
1009 fn into_view<'shorter>(self) -> $Msg$View<'shorter>
1010 where
1011 'msg: 'shorter {
1012 self
1013 }
1014 }
1015
1016 $into_proxied_impl$
1017
1018 $repeated_impl$
1019 $map_value_impl$
1020
1021 #[allow(dead_code)]
1022 #[allow(non_camel_case_types)]
1023 pub struct $Msg$Mut<'msg> {
1024 inner: $pbr$::MutatorMessageRef<'msg>,
1025 }
1026
1027 impl<'msg> $pbi$::SealedInternal for $Msg$Mut<'msg> {}
1028
1029 impl<'msg> $pb$::MessageMut<'msg> for $Msg$Mut<'msg> {
1030 type Message = $Msg$;
1031 }
1032
1033 impl $std$::fmt::Debug for $Msg$Mut<'_> {
1034 fn fmt(&self, f: &mut $std$::fmt::Formatter<'_>) -> $std$::fmt::Result {
1035 $Msg::debug$
1036 }
1037 }
1038
1039 impl $pb$::Serialize for $Msg$Mut<'_> {
1040 fn serialize(&self) -> $Result$<Vec<u8>, $pb$::SerializeError> {
1041 $pb$::AsView::as_view(self).serialize()
1042 }
1043 }
1044
1045 impl $pb$::Clear for $Msg$Mut<'_> {
1046 fn clear(&mut self) {
1047 $MsgMut::clear$
1048 }
1049 }
1050
1051 $MsgMut::merge_from$
1052
1053 #[allow(dead_code)]
1054 impl<'msg> $Msg$Mut<'msg> {
1055 #[doc(hidden)]
1056 pub fn from_parent(
1057 _private: $pbi$::Private,
1058 parent: $pbr$::MutatorMessageRef<'msg>,
1059 msg: $pbr$::RawMessage)
1060 -> Self {
1061 Self {
1062 inner: $pbr$::MutatorMessageRef::from_parent(parent, msg)
1063 }
1064 }
1065
1066 #[doc(hidden)]
1067 pub fn new(_private: $pbi$::Private, msg: &'msg mut $pbr$::MessageInner) -> Self {
1068 Self{ inner: $pbr$::MutatorMessageRef::new(msg) }
1069 }
1070
1071 fn raw_msg(&self) -> $pbr$::RawMessage {
1072 self.inner.msg()
1073 }
1074
1075 #[doc(hidden)]
1076 pub fn as_mutator_message_ref(&mut self, _private: $pbi$::Private)
1077 -> $pbr$::MutatorMessageRef<'msg> {
1078 self.inner
1079 }
1080
1081 pub fn to_owned(&self) -> $Msg$ {
1082 $pb$::AsView::as_view(self).to_owned()
1083 }
1084
1085 $raw_arena_getter_for_msgmut$
1086
1087 $accessor_fns_for_muts$
1088 }
1089
1090 // SAFETY:
1091 // - `$Msg$Mut` does not perform any shared mutation.
1092 // - `$Msg$Mut` is not `Send`, and so even in the presence of mutator
1093 // splitting, synchronous access of an arena is impossible.
1094 unsafe impl Sync for $Msg$Mut<'_> {}
1095
1096 impl<'msg> $pb$::Proxy<'msg> for $Msg$Mut<'msg> {}
1097 impl<'msg> $pb$::MutProxy<'msg> for $Msg$Mut<'msg> {}
1098
1099 impl<'msg> $pb$::AsView for $Msg$Mut<'msg> {
1100 type Proxied = $Msg$;
1101 fn as_view(&self) -> $pb$::View<'_, $Msg$> {
1102 $Msg$View { msg: self.raw_msg(), _phantom: $std$::marker::PhantomData }
1103 }
1104 }
1105
1106 impl<'msg> $pb$::IntoView<'msg> for $Msg$Mut<'msg> {
1107 fn into_view<'shorter>(self) -> $pb$::View<'shorter, $Msg$>
1108 where
1109 'msg: 'shorter {
1110 $Msg$View { msg: self.raw_msg(), _phantom: $std$::marker::PhantomData }
1111 }
1112 }
1113
1114 impl<'msg> $pb$::AsMut for $Msg$Mut<'msg> {
1115 type MutProxied = $Msg$;
1116 fn as_mut(&mut self) -> $Msg$Mut<'msg> {
1117 $Msg$Mut { inner: self.inner }
1118 }
1119 }
1120
1121 impl<'msg> $pb$::IntoMut<'msg> for $Msg$Mut<'msg> {
1122 fn into_mut<'shorter>(self) -> $Msg$Mut<'shorter>
1123 where
1124 'msg: 'shorter {
1125 self
1126 }
1127 }
1128
1129 #[allow(dead_code)]
1130 impl $Msg$ {
1131 pub fn new() -> Self {
1132 $Msg::new$
1133 }
1134
1135 fn raw_msg(&self) -> $pbr$::RawMessage {
1136 self.inner.msg
1137 }
1138
1139 #[doc(hidden)]
1140 pub fn as_mutator_message_ref(&mut self, _private: $pbi$::Private) -> $pbr$::MutatorMessageRef {
1141 $pbr$::MutatorMessageRef::new(&mut self.inner)
1142 }
1143
1144 $raw_arena_getter_for_message$
1145
1146 pub fn parse(data: &[u8]) -> $Result$<Self, $pb$::ParseError> {
1147 let mut msg = Self::new();
1148 $pb$::ClearAndParse::clear_and_parse(&mut msg, data).map(|_| msg)
1149 }
1150
1151 pub fn as_view(&self) -> $Msg$View {
1152 $Msg$View::new($pbi$::Private, self.inner.msg)
1153 }
1154
1155 pub fn as_mut(&mut self) -> $Msg$Mut {
1156 $Msg$Mut::new($pbi$::Private, &mut self.inner)
1157 }
1158
1159 $accessor_fns$
1160 } // impl $Msg$
1161
1162 //~ We implement drop unconditionally, so that `$Msg$: Drop` regardless
1163 //~ of kernel.
1164 impl $std$::ops::Drop for $Msg$ {
1165 fn drop(&mut self) {
1166 $Msg::drop$
1167 }
1168 }
1169
1170 impl $std$::clone::Clone for $Msg$ {
1171 fn clone(&self) -> Self {
1172 self.as_view().to_owned()
1173 }
1174 }
1175
1176 impl $pb$::AsView for $Msg$ {
1177 type Proxied = Self;
1178 fn as_view(&self) -> $Msg$View {
1179 self.as_view()
1180 }
1181 }
1182
1183 impl $pb$::AsMut for $Msg$ {
1184 type MutProxied = Self;
1185 fn as_mut(&mut self) -> $Msg$Mut {
1186 self.as_mut()
1187 }
1188 }
1189
1190 $upb_generated_message_trait_impls$
1191
1192 $nested_in_msg$
1193 )rs");
1194
1195 if (ctx.is_cpp()) {
1196 ctx.Emit(
1197 {
1198 {"message_externs", [&] { CppMessageExterns(ctx, msg); }},
1199 {"accessor_externs",
1200 [&] {
1201 for (int i = 0; i < msg.field_count(); ++i) {
1202 GenerateAccessorExternC(ctx, *msg.field(i));
1203 }
1204 }},
1205 {"oneof_externs",
1206 [&] {
1207 for (int i = 0; i < msg.real_oneof_decl_count(); ++i) {
1208 GenerateOneofExternC(ctx, *msg.real_oneof_decl(i));
1209 }
1210 }},
1211 },
1212 R"rs(
1213 extern "C" {
1214 $message_externs$
1215 $accessor_externs$
1216 $oneof_externs$
1217 }
1218 )rs");
1219 } else {
1220 ctx.Emit({{"minitable_symbol_name", UpbMiniTableName(msg)}},
1221 R"rs(
1222 extern "C" {
1223 /// Opaque static extern for this message's MiniTable, generated
1224 /// by the upb C MiniTable codegen. The only valid way to
1225 /// reference this static is with `std::ptr::addr_of!(..)`.
1226 static $minitable_symbol_name$: $pbr$::upb_MiniTable;
1227 }
1228 )rs");
1229 }
1230
1231 ctx.printer().PrintRaw("\n");
1232 if (ctx.is_cpp()) {
1233 ctx.Emit({{"Msg", RsSafeName(msg.name())}}, R"rs(
1234 impl<'a> $Msg$Mut<'a> {
1235 pub unsafe fn __unstable_wrap_cpp_grant_permission_to_break(
1236 msg: &'a mut *mut $std$::ffi::c_void) -> Self {
1237 Self {
1238 inner: $pbr$::MutatorMessageRef::wrap_raw(
1239 $pbr$::RawMessage::new(*msg as *mut _).unwrap())
1240 }
1241 }
1242 pub fn __unstable_cpp_repr_grant_permission_to_break(self) -> *mut $std$::ffi::c_void {
1243 self.raw_msg().as_ptr() as *mut _
1244 }
1245 }
1246
1247 impl<'a> $Msg$View<'a> {
1248 pub fn __unstable_wrap_cpp_grant_permission_to_break(
1249 msg: &'a *const $std$::ffi::c_void) -> Self {
1250 Self::new($pbi$::Private, $pbr$::RawMessage::new(*msg as *mut _).unwrap())
1251 }
1252 pub fn __unstable_cpp_repr_grant_permission_to_break(self) -> *const $std$::ffi::c_void {
1253 self.msg.as_ptr() as *const _
1254 }
1255 }
1256
1257 impl $pb$::OwnedMessageInterop for $Msg$ {
1258 unsafe fn __unstable_take_ownership_of_raw_message(msg: *mut $std$::ffi::c_void) -> Self {
1259 Self { inner: $pbr$::MessageInner { msg: $pbr$::RawMessage::new(msg as *mut _).unwrap() } }
1260 }
1261
1262 fn __unstable_leak_raw_message(self) -> *mut $std$::ffi::c_void {
1263 let s = $std$::mem::ManuallyDrop::new(self);
1264 s.raw_msg().as_ptr() as *mut _
1265 }
1266 }
1267
1268 impl<'a> $pb$::MessageMutInterop<'a> for $Msg$Mut<'a> {
1269 unsafe fn __unstable_wrap_raw_message_mut(
1270 msg: &'a mut *mut $std$::ffi::c_void) -> Self {
1271 Self {
1272 inner: $pbr$::MutatorMessageRef::wrap_raw(
1273 $pbr$::RawMessage::new(*msg as *mut _).unwrap())
1274 }
1275 }
1276 unsafe fn __unstable_wrap_raw_message_mut_unchecked_lifetime(
1277 msg: *mut $std$::ffi::c_void) -> Self {
1278 Self {
1279 inner: $pbr$::MutatorMessageRef::wrap_raw(
1280 $pbr$::RawMessage::new(msg as *mut _).unwrap())
1281 }
1282 }
1283 fn __unstable_as_raw_message_mut(&mut self) -> *mut $std$::ffi::c_void {
1284 self.raw_msg().as_ptr() as *mut _
1285 }
1286 }
1287
1288 impl<'a> $pb$::MessageViewInterop<'a> for $Msg$View<'a> {
1289 unsafe fn __unstable_wrap_raw_message(
1290 msg: &'a *const $std$::ffi::c_void) -> Self {
1291 Self::new($pbi$::Private, $pbr$::RawMessage::new(*msg as *mut _).unwrap())
1292 }
1293 unsafe fn __unstable_wrap_raw_message_unchecked_lifetime(
1294 msg: *const $std$::ffi::c_void) -> Self {
1295 Self::new($pbi$::Private, $pbr$::RawMessage::new(msg as *mut _).unwrap())
1296 }
1297 fn __unstable_as_raw_message(&self) -> *const $std$::ffi::c_void {
1298 self.msg.as_ptr() as *const _
1299 }
1300 }
1301
1302 impl $pbi$::MatcherEq for $Msg$ {
1303 fn matches(&self, o: &Self) -> bool {
1304 $pbi$::MatcherEq::matches(
1305 &$pb$::AsView::as_view(self),
1306 &$pb$::AsView::as_view(o))
1307 }
1308 }
1309
1310 impl<'a> $pbi$::MatcherEq for $Msg$Mut<'a> {
1311 fn matches(&self, o: &Self) -> bool {
1312 $pbi$::MatcherEq::matches(
1313 &$pb$::AsView::as_view(self),
1314 &$pb$::AsView::as_view(o))
1315 }
1316 }
1317
1318 impl<'a> $pbi$::MatcherEq for $Msg$View<'a> {
1319 fn matches(&self, o: &Self) -> bool {
1320 unsafe {
1321 $pbr$::raw_message_equals(self.msg, o.msg)
1322 }
1323 }
1324 }
1325 )rs");
1326 } else {
1327 ctx.Emit({{"Msg", RsSafeName(msg.name())}}, R"rs(
1328 // upb kernel doesn't support any owned message or message mut interop.
1329 impl $pb$::OwnedMessageInterop for $Msg$ {}
1330 impl<'a> $pb$::MessageMutInterop<'a> for $Msg$Mut<'a> {}
1331
1332 impl<'a> $pb$::MessageViewInterop<'a> for $Msg$View<'a> {
1333 unsafe fn __unstable_wrap_raw_message(
1334 msg: &'a *const $std$::ffi::c_void) -> Self {
1335 Self::new($pbi$::Private, $pbr$::RawMessage::new(*msg as *mut _).unwrap())
1336 }
1337 unsafe fn __unstable_wrap_raw_message_unchecked_lifetime(
1338 msg: *const $std$::ffi::c_void) -> Self {
1339 Self::new($pbi$::Private, $pbr$::RawMessage::new(msg as *mut _).unwrap())
1340 }
1341 fn __unstable_as_raw_message(&self) -> *const $std$::ffi::c_void {
1342 self.msg.as_ptr() as *const _
1343 }
1344 }
1345
1346 impl $pbi$::MatcherEq for $Msg$ {
1347 fn matches(&self, o: &Self) -> bool {
1348 $pbi$::MatcherEq::matches(
1349 &$pb$::AsView::as_view(self),
1350 &$pb$::AsView::as_view(o))
1351 }
1352 }
1353
1354 impl<'a> $pbi$::MatcherEq for $Msg$Mut<'a> {
1355 fn matches(&self, o: &Self) -> bool {
1356 $pbi$::MatcherEq::matches(
1357 &$pb$::AsView::as_view(self),
1358 &$pb$::AsView::as_view(o))
1359 }
1360 }
1361
1362 impl<'a> $pbi$::MatcherEq for $Msg$View<'a> {
1363 fn matches(&self, o: &Self) -> bool {
1364 unsafe {
1365 $pbr$::upb_Message_IsEqual(
1366 self.msg,
1367 o.msg,
1368 <$Msg$ as $pbr$::AssociatedMiniTable>::mini_table(),
1369 0)
1370 }
1371 }
1372 }
1373 )rs");
1374 }
1375 } // NOLINT(readability/fn_size)
1376
1377 // Generates code for a particular message in `.pb.thunk.cc`.
GenerateThunksCc(Context & ctx,const Descriptor & msg)1378 void GenerateThunksCc(Context& ctx, const Descriptor& msg) {
1379 ABSL_CHECK(ctx.is_cpp());
1380 if (msg.map_key() != nullptr) {
1381 // Don't generate code for synthetic MapEntry messages.
1382 return;
1383 }
1384
1385 ctx.Emit(
1386 {{"abi", "\"C\""}, // Workaround for syntax highlight bug in VSCode.
1387 {"Msg", RsSafeName(msg.name())},
1388 {"QualifiedMsg", cpp::QualifiedClassName(&msg)},
1389 {"new_thunk", ThunkName(ctx, msg, "new")},
1390 {"default_instance_thunk", ThunkName(ctx, msg, "default_instance")},
1391 {"repeated_new_thunk", ThunkName(ctx, msg, "repeated_new")},
1392 {"repeated_free_thunk", ThunkName(ctx, msg, "repeated_free")},
1393 {"repeated_len_thunk", ThunkName(ctx, msg, "repeated_len")},
1394 {"repeated_get_thunk", ThunkName(ctx, msg, "repeated_get")},
1395 {"repeated_get_mut_thunk", ThunkName(ctx, msg, "repeated_get_mut")},
1396 {"repeated_add_thunk", ThunkName(ctx, msg, "repeated_add")},
1397 {"repeated_clear_thunk", ThunkName(ctx, msg, "repeated_clear")},
1398 {"repeated_copy_from_thunk", ThunkName(ctx, msg, "repeated_copy_from")},
1399 {"repeated_reserve_thunk", ThunkName(ctx, msg, "repeated_reserve")},
1400 {"map_size_info_thunk", ThunkName(ctx, msg, "size_info")},
1401 {"nested_msg_thunks",
1402 [&] {
1403 for (int i = 0; i < msg.nested_type_count(); ++i) {
1404 GenerateThunksCc(ctx, *msg.nested_type(i));
1405 }
1406 }},
1407 {"accessor_thunks",
1408 [&] {
1409 for (int i = 0; i < msg.field_count(); ++i) {
1410 GenerateAccessorThunkCc(ctx, *msg.field(i));
1411 }
1412 }},
1413 {"oneof_thunks",
1414 [&] {
1415 for (int i = 0; i < msg.real_oneof_decl_count(); ++i) {
1416 GenerateOneofThunkCc(ctx, *msg.real_oneof_decl(i));
1417 }
1418 }}},
1419 R"cc(
1420 //~ $abi$ is a workaround for a syntax highlight bug in VSCode.
1421 // However, ~ that confuses clang-format (it refuses to keep the
1422 // newline after ~ `$abi${`). Disabling clang-format for the block.
1423 // clang-format off
1424 extern $abi$ {
1425 void* $new_thunk$() { return new $QualifiedMsg$(); }
1426
1427 const google::protobuf::MessageLite* $default_instance_thunk$() {
1428 return &$QualifiedMsg$::default_instance();
1429 }
1430
1431 void* $repeated_new_thunk$() {
1432 return new google::protobuf::RepeatedPtrField<$QualifiedMsg$>();
1433 }
1434
1435 void $repeated_free_thunk$(void* ptr) {
1436 delete static_cast<google::protobuf::RepeatedPtrField<$QualifiedMsg$>*>(ptr);
1437 }
1438
1439 size_t $repeated_len_thunk$(google::protobuf::RepeatedPtrField<$QualifiedMsg$>* field) {
1440 return field->size();
1441 }
1442 const $QualifiedMsg$* $repeated_get_thunk$(
1443 google::protobuf::RepeatedPtrField<$QualifiedMsg$>* field,
1444 size_t index) {
1445 return &field->Get(index);
1446 }
1447 $QualifiedMsg$* $repeated_get_mut_thunk$(
1448 google::protobuf::RepeatedPtrField<$QualifiedMsg$>* field,
1449 size_t index) {
1450 return field->Mutable(index);
1451 }
1452 $QualifiedMsg$* $repeated_add_thunk$(google::protobuf::RepeatedPtrField<$QualifiedMsg$>* field) {
1453 return field->Add();
1454 }
1455 void $repeated_clear_thunk$(google::protobuf::RepeatedPtrField<$QualifiedMsg$>* field) {
1456 field->Clear();
1457 }
1458 void $repeated_copy_from_thunk$(
1459 google::protobuf::RepeatedPtrField<$QualifiedMsg$>& dst,
1460 const google::protobuf::RepeatedPtrField<$QualifiedMsg$>& src) {
1461 dst = src;
1462 }
1463 void $repeated_reserve_thunk$(
1464 google::protobuf::RepeatedPtrField<$QualifiedMsg$>* field,
1465 size_t additional) {
1466 field->Reserve(field->size() + additional);
1467 }
1468 google::protobuf::internal::MapNodeSizeInfoT $map_size_info_thunk$(int32_t i) {
1469 static constexpr google::protobuf::internal::MapNodeSizeInfoT size_infos[] = {)cc"
1470 // LINT.IfChange(size_info_mapping)
1471 R"cc(
1472 google::protobuf::internal::RustMapHelper::SizeInfo<int32_t, $QualifiedMsg$>(),
1473 google::protobuf::internal::RustMapHelper::SizeInfo<int64_t,
1474 $QualifiedMsg$>(),
1475 google::protobuf::internal::RustMapHelper::SizeInfo<bool, $QualifiedMsg$>(),
1476 google::protobuf::internal::RustMapHelper::SizeInfo<std::string,
1477 $QualifiedMsg$>()
1478 )cc"
1479 // LINT.ThenChange(//depot/google3/third_party/protobuf/rust/cpp.rs:size_info_mapping)
1480 R"cc(
1481 }
1482 ;
1483 return size_infos[i];
1484 }
1485
1486 $accessor_thunks$
1487
1488 $oneof_thunks$
1489 } // extern $abi$
1490 // clang-format on
1491
1492 $nested_msg_thunks$
1493 )cc");
1494 }
1495
1496 } // namespace rust
1497 } // namespace compiler
1498 } // namespace protobuf
1499 } // namespace google
1500