• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #ifndef GOOGLE_PROTOBUF_RUST_CPP_KERNEL_MAP_H__
2 #define GOOGLE_PROTOBUF_RUST_CPP_KERNEL_MAP_H__
3 
4 #include <memory>
5 #include <type_traits>
6 
7 #include "google/protobuf/map.h"
8 #include "google/protobuf/message_lite.h"
9 #include "rust/cpp_kernel/strings.h"
10 
11 namespace google {
12 namespace protobuf {
13 namespace rust {
14 
15 // String and bytes values are passed across the FFI boundary as owned raw
16 // pointers when we do map insertions. Unlike other types, they have to be
17 // explicitly deleted. This MakeCleanup() helper does nothing by default, but
18 // for std::string pointers it returns a std::unique_ptr to take ownership of
19 // the raw pointer.
20 template <typename T>
MakeCleanup(T value)21 auto MakeCleanup(T value) {
22   if constexpr (std::is_same<T, std::string*>::value) {
23     return std::unique_ptr<std::string>(value);
24   } else {
25     return 0;
26   }
27 }
28 
29 }  // namespace rust
30 }  // namespace protobuf
31 }  // namespace google
32 
33 // Defines concrete thunks to access typed map methods from Rust.
34 #define __PB_RUST_EXPOSE_SCALAR_MAP_METHODS(                                  \
35     key_ty, rust_key_ty, ffi_key_ty, to_cpp_key, to_ffi_key, value_ty,        \
36     rust_value_ty, ffi_view_ty, ffi_value_ty, to_cpp_value, to_ffi_value)     \
37   google::protobuf::Map<key_ty, value_ty>*                                              \
38       proto2_rust_thunk_Map_##rust_key_ty##_##rust_value_ty##_new() {         \
39     return new google::protobuf::Map<key_ty, value_ty>();                               \
40   }                                                                           \
41   void proto2_rust_thunk_Map_##rust_key_ty##_##rust_value_ty##_free(          \
42       google::protobuf::Map<key_ty, value_ty>* m) {                                     \
43     delete m;                                                                 \
44   }                                                                           \
45   void proto2_rust_thunk_Map_##rust_key_ty##_##rust_value_ty##_clear(         \
46       google::protobuf::Map<key_ty, value_ty>* m) {                                     \
47     m->clear();                                                               \
48   }                                                                           \
49   size_t proto2_rust_thunk_Map_##rust_key_ty##_##rust_value_ty##_size(        \
50       const google::protobuf::Map<key_ty, value_ty>* m) {                               \
51     return m->size();                                                         \
52   }                                                                           \
53   bool proto2_rust_thunk_Map_##rust_key_ty##_##rust_value_ty##_insert(        \
54       google::protobuf::Map<key_ty, value_ty>* m, ffi_key_ty key, ffi_value_ty value) { \
55     auto cleanup = google::protobuf::rust::MakeCleanup(value);                          \
56     (void)cleanup;                                                            \
57     auto iter_and_inserted = m->try_emplace(to_cpp_key, to_cpp_value);        \
58     if (!iter_and_inserted.second) {                                          \
59       iter_and_inserted.first->second = to_cpp_value;                         \
60     }                                                                         \
61     return iter_and_inserted.second;                                          \
62   }                                                                           \
63   bool proto2_rust_thunk_Map_##rust_key_ty##_##rust_value_ty##_get(           \
64       const google::protobuf::Map<key_ty, value_ty>* m, ffi_key_ty key,                 \
65       ffi_view_ty* value) {                                                   \
66     auto cpp_key = to_cpp_key;                                                \
67     auto it = m->find(cpp_key);                                               \
68     if (it == m->end()) {                                                     \
69       return false;                                                           \
70     }                                                                         \
71     auto& cpp_value = it->second;                                             \
72     *value = to_ffi_value;                                                    \
73     return true;                                                              \
74   }                                                                           \
75   google::protobuf::internal::UntypedMapIterator                                        \
76       proto2_rust_thunk_Map_##rust_key_ty##_##rust_value_ty##_iter(           \
77           const google::protobuf::Map<key_ty, value_ty>* m) {                           \
78     return google::protobuf::internal::UntypedMapIterator::FromTyped(m->cbegin());      \
79   }                                                                           \
80   void proto2_rust_thunk_Map_##rust_key_ty##_##rust_value_ty##_iter_get(      \
81       const google::protobuf::internal::UntypedMapIterator* iter, ffi_key_ty* key,      \
82       ffi_view_ty* value) {                                                   \
83     auto typed_iter =                                                         \
84         iter->ToTyped<google::protobuf::Map<key_ty, value_ty>::const_iterator>();       \
85     const auto& cpp_key = typed_iter->first;                                  \
86     const auto& cpp_value = typed_iter->second;                               \
87     *key = to_ffi_key;                                                        \
88     *value = to_ffi_value;                                                    \
89   }                                                                           \
90   bool proto2_rust_thunk_Map_##rust_key_ty##_##rust_value_ty##_remove(        \
91       google::protobuf::Map<key_ty, value_ty>* m, ffi_key_ty key, ffi_view_ty* value) { \
92     auto cpp_key = to_cpp_key;                                                \
93     auto num_removed = m->erase(cpp_key);                                     \
94     return num_removed > 0;                                                   \
95   }
96 
97 // Defines the map thunks for all supported key types for a given value type.
98 #define __PB_RUST_EXPOSE_SCALAR_MAP_METHODS_FOR_VALUE_TYPE(                 \
99     value_ty, rust_value_ty, ffi_view_ty, ffi_value_ty, to_cpp_value,       \
100     to_ffi_value)                                                           \
101   __PB_RUST_EXPOSE_SCALAR_MAP_METHODS(                                      \
102       int32_t, i32, int32_t, key, cpp_key, value_ty, rust_value_ty,         \
103       ffi_view_ty, ffi_value_ty, to_cpp_value, to_ffi_value);               \
104   __PB_RUST_EXPOSE_SCALAR_MAP_METHODS(                                      \
105       uint32_t, u32, uint32_t, key, cpp_key, value_ty, rust_value_ty,       \
106       ffi_view_ty, ffi_value_ty, to_cpp_value, to_ffi_value);               \
107   __PB_RUST_EXPOSE_SCALAR_MAP_METHODS(                                      \
108       bool, bool, bool, key, cpp_key, value_ty, rust_value_ty, ffi_view_ty, \
109       ffi_value_ty, to_cpp_value, to_ffi_value);                            \
110   __PB_RUST_EXPOSE_SCALAR_MAP_METHODS(                                      \
111       uint64_t, u64, uint64_t, key, cpp_key, value_ty, rust_value_ty,       \
112       ffi_view_ty, ffi_value_ty, to_cpp_value, to_ffi_value);               \
113   __PB_RUST_EXPOSE_SCALAR_MAP_METHODS(                                      \
114       int64_t, i64, int64_t, key, cpp_key, value_ty, rust_value_ty,         \
115       ffi_view_ty, ffi_value_ty, to_cpp_value, to_ffi_value);               \
116   __PB_RUST_EXPOSE_SCALAR_MAP_METHODS(                                      \
117       std::string, ProtoString, google::protobuf::rust::PtrAndLen,                    \
118       std::string(key.ptr, key.len),                                        \
119       (google::protobuf::rust::PtrAndLen{cpp_key.data(), cpp_key.size()}), value_ty,  \
120       rust_value_ty, ffi_view_ty, ffi_value_ty, to_cpp_value, to_ffi_value);
121 
122 #endif  // GOOGLE_PROTOBUF_RUST_CPP_KERNEL_MAP_H__
123