Split up cpp_api.h/.cc into smaller units.

PiperOrigin-RevId: 647663342
pull/17265/head
Protobuf Team Bot 9 months ago committed by Copybara-Service
parent 219e8ead2f
commit 419760f873
  1. 15
      rust/cpp_kernel/BUILD
  2. 23
      rust/cpp_kernel/debug.cc
  3. 18
      rust/cpp_kernel/debug.h
  4. 39
      rust/cpp_kernel/map.cc
  5. 104
      rust/cpp_kernel/map.h
  6. 68
      rust/cpp_kernel/repeated.cc
  7. 11
      rust/cpp_kernel/rust_alloc_for_cpp_api.h
  8. 64
      rust/cpp_kernel/serialized_data.h
  9. 26
      rust/cpp_kernel/strings.cc
  10. 50
      rust/cpp_kernel/strings.h
  11. 3
      rust/test/cpp/interop/test_utils.cc
  12. 4
      src/google/protobuf/compiler/rust/generator.cc

@ -4,8 +4,19 @@ load("@rules_rust//rust:defs.bzl", "rust_library")
cc_library( cc_library(
name = "cpp_api", name = "cpp_api",
srcs = ["cpp_api.cc"], srcs = [
hdrs = ["cpp_api.h"], "debug.cc",
"map.cc",
"repeated.cc",
"strings.cc",
],
hdrs = [
"debug.h",
"map.h",
"rust_alloc_for_cpp_api.h",
"serialized_data.h",
"strings.h",
],
visibility = [ visibility = [
"//rust:__subpackages__", "//rust:__subpackages__",
"//src/google/protobuf:__subpackages__", "//src/google/protobuf:__subpackages__",

@ -0,0 +1,23 @@
#include "rust/cpp_kernel/debug.h"
#include <string>
#include "google/protobuf/message.h"
#include "google/protobuf/message_lite.h"
#include "rust/cpp_kernel/strings.h"
extern "C" {
google::protobuf::rust_internal::RustStringRawParts utf8_debug_string(
const google::protobuf::Message* msg) {
std::string text = google::protobuf::Utf8Format(*msg);
return google::protobuf::rust_internal::RustStringRawParts(text);
}
google::protobuf::rust_internal::RustStringRawParts utf8_debug_string_lite(
const google::protobuf::MessageLite* msg) {
std::string text = google::protobuf::Utf8Format(*msg);
return google::protobuf::rust_internal::RustStringRawParts(text);
}
} // extern "C"

@ -0,0 +1,18 @@
#ifndef GOOGLE_PROTOBUF_RUST_CPP_KERNEL_DEBUG_H__
#define GOOGLE_PROTOBUF_RUST_CPP_KERNEL_DEBUG_H__
#include "google/protobuf/message.h"
#include "google/protobuf/message_lite.h"
#include "rust/cpp_kernel/strings.h"
extern "C" {
google::protobuf::rust_internal::RustStringRawParts utf8_debug_string(
const google::protobuf::Message* msg);
google::protobuf::rust_internal::RustStringRawParts utf8_debug_string_lite(
const google::protobuf::MessageLite* msg);
} // extern "C"
#endif // GOOGLE_PROTOBUF_RUST_CPP_KERNEL_DEBUG_H__

@ -0,0 +1,39 @@
#include "rust/cpp_kernel/map.h"
#include <cstdint>
#include <string>
#include "google/protobuf/map.h"
#include "rust/cpp_kernel/strings.h"
extern "C" {
void __rust_proto_thunk__UntypedMapIterator_increment(
google::protobuf::internal::UntypedMapIterator* iter) {
iter->PlusPlus();
}
__PB_RUST_EXPOSE_SCALAR_MAP_METHODS_FOR_VALUE_TYPE(int32_t, i32, int32_t, value,
cpp_value);
__PB_RUST_EXPOSE_SCALAR_MAP_METHODS_FOR_VALUE_TYPE(uint32_t, u32, uint32_t,
value, cpp_value);
__PB_RUST_EXPOSE_SCALAR_MAP_METHODS_FOR_VALUE_TYPE(float, f32, float, value,
cpp_value);
__PB_RUST_EXPOSE_SCALAR_MAP_METHODS_FOR_VALUE_TYPE(double, f64, double, value,
cpp_value);
__PB_RUST_EXPOSE_SCALAR_MAP_METHODS_FOR_VALUE_TYPE(bool, bool, bool, value,
cpp_value);
__PB_RUST_EXPOSE_SCALAR_MAP_METHODS_FOR_VALUE_TYPE(uint64_t, u64, uint64_t,
value, cpp_value);
__PB_RUST_EXPOSE_SCALAR_MAP_METHODS_FOR_VALUE_TYPE(int64_t, i64, int64_t, value,
cpp_value);
__PB_RUST_EXPOSE_SCALAR_MAP_METHODS_FOR_VALUE_TYPE(
std::string, ProtoBytes, google::protobuf::rust_internal::PtrAndLen,
std::string(value.ptr, value.len),
google::protobuf::rust_internal::PtrAndLen(cpp_value.data(), cpp_value.size()));
__PB_RUST_EXPOSE_SCALAR_MAP_METHODS_FOR_VALUE_TYPE(
std::string, ProtoString, google::protobuf::rust_internal::PtrAndLen,
std::string(value.ptr, value.len),
google::protobuf::rust_internal::PtrAndLen(cpp_value.data(), cpp_value.size()));
} // extern "C"

@ -1,79 +1,5 @@
// Protocol Buffers - Google's data interchange format #ifndef GOOGLE_PROTOBUF_RUST_CPP_KERNEL_MAP_H__
// Copyright 2023 Google LLC. All rights reserved. #define GOOGLE_PROTOBUF_RUST_CPP_KERNEL_MAP_H__
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file or at
// https://developers.google.com/open-source/licenses/bsd
// This file contains support code for generated C++ thunks.
#ifndef GOOGLE_PROTOBUF_RUST_CPP_KERNEL_CPP_H__
#define GOOGLE_PROTOBUF_RUST_CPP_KERNEL_CPP_H__
#include <climits>
#include <cstddef>
#include <cstdint>
#include <cstring>
#include <string>
#include "absl/log/absl_check.h"
#include "absl/log/absl_log.h"
#include "google/protobuf/message.h"
#include "google/protobuf/message_lite.h"
namespace google {
namespace protobuf {
namespace rust_internal {
// Represents serialized Protobuf wire format data.
//
// Only to be used to transfer serialized data from C++ to Rust under these
// assumptions:
// * Rust and C++ versions of this struct are ABI compatible.
// * Rust version owns and frees its data.
// * The data were allocated using the Rust allocator.
//
extern "C" struct SerializedData {
// Owns the memory, must be freed by Rust.
const uint8_t* data;
size_t len;
SerializedData(const uint8_t* data, size_t len) : data(data), len(len) {}
};
// Allocates memory using the current Rust global allocator.
//
// This function is defined in `rust_alloc_for_cpp_api.rs`.
extern "C" void* __pb_rust_alloc(size_t size, size_t align);
inline bool SerializeMsg(const google::protobuf::MessageLite* msg, SerializedData* out) {
ABSL_DCHECK(msg->IsInitialized());
size_t len = msg->ByteSizeLong();
if (len > INT_MAX) {
ABSL_LOG(ERROR) << msg->GetTypeName()
<< " exceeded maximum protobuf size of 2GB: " << len;
return false;
}
uint8_t* bytes = static_cast<uint8_t*>(__pb_rust_alloc(len, alignof(char)));
if (bytes == nullptr) {
ABSL_LOG(FATAL) << "Rust allocator failed to allocate memory.";
}
if (!msg->SerializeWithCachedSizesToArray(bytes)) {
return false;
}
*out = SerializedData(bytes, len);
return true;
}
// Represents an ABI-stable version of &[u8]/string_view (borrowed slice of
// bytes) for FFI use only.
struct PtrAndLen {
/// Borrows the memory.
const char* ptr;
size_t len;
PtrAndLen(const char* ptr, size_t len) : ptr(ptr), len(len) {}
};
// Defines concrete thunks to access typed map methods from Rust. // Defines concrete thunks to access typed map methods from Rust.
#define __PB_RUST_EXPOSE_SCALAR_MAP_METHODS( \ #define __PB_RUST_EXPOSE_SCALAR_MAP_METHODS( \
@ -161,28 +87,4 @@ struct PtrAndLen {
google::protobuf::rust_internal::PtrAndLen(cpp_key.data(), cpp_key.size()), \ google::protobuf::rust_internal::PtrAndLen(cpp_key.data(), cpp_key.size()), \
value_ty, rust_value_ty, ffi_value_ty, to_cpp_value, to_ffi_value); value_ty, rust_value_ty, ffi_value_ty, to_cpp_value, to_ffi_value);
// Represents an owned string for FFI purposes. #endif // GOOGLE_PROTOBUF_RUST_CPP_KERNEL_MAP_H__
//
// This must only be used to transfer a string from C++ to Rust. The
// below invariants must hold:
// * Rust and C++ versions of this struct are ABI compatible.
// * The data were allocated using the Rust allocator and are 1 byte aligned.
// * The data is valid UTF-8.
struct RustStringRawParts {
// Owns the memory.
const char* data;
size_t len;
RustStringRawParts() = delete;
// Copies src.
explicit RustStringRawParts(std::string src);
};
extern "C" RustStringRawParts utf8_debug_string(const google::protobuf::Message* msg);
extern "C" RustStringRawParts utf8_debug_string_lite(
const google::protobuf::MessageLite* msg);
} // namespace rust_internal
} // namespace protobuf
} // namespace google
#endif // GOOGLE_PROTOBUF_RUST_CPP_KERNEL_CPP_H__

@ -1,15 +1,13 @@
#include "rust/cpp_kernel/cpp_api.h"
#include <cstddef> #include <cstddef>
#include <cstdint> #include <cstdint>
#include <cstring> #include <cstring>
#include <string> #include <string>
#include "google/protobuf/map.h"
#include "google/protobuf/message.h" #include "google/protobuf/message.h"
#include "google/protobuf/message_lite.h" #include "google/protobuf/message_lite.h"
#include "google/protobuf/repeated_field.h" #include "google/protobuf/repeated_field.h"
#include "google/protobuf/repeated_ptr_field.h" #include "google/protobuf/repeated_ptr_field.h"
#include "rust/cpp_kernel/strings.h"
extern "C" { extern "C" {
#define expose_repeated_field_methods(ty, rust_ty) \ #define expose_repeated_field_methods(ty, rust_ty) \
@ -106,66 +104,4 @@ expose_repeated_ptr_field_methods(ProtoBytes);
#undef expose_repeated_ptr_field_methods #undef expose_repeated_ptr_field_methods
void __rust_proto_thunk__UntypedMapIterator_increment( } // extern "C"
google::protobuf::internal::UntypedMapIterator* iter) {
iter->PlusPlus();
}
__PB_RUST_EXPOSE_SCALAR_MAP_METHODS_FOR_VALUE_TYPE(int32_t, i32, int32_t, value,
cpp_value);
__PB_RUST_EXPOSE_SCALAR_MAP_METHODS_FOR_VALUE_TYPE(uint32_t, u32, uint32_t,
value, cpp_value);
__PB_RUST_EXPOSE_SCALAR_MAP_METHODS_FOR_VALUE_TYPE(float, f32, float, value,
cpp_value);
__PB_RUST_EXPOSE_SCALAR_MAP_METHODS_FOR_VALUE_TYPE(double, f64, double, value,
cpp_value);
__PB_RUST_EXPOSE_SCALAR_MAP_METHODS_FOR_VALUE_TYPE(bool, bool, bool, value,
cpp_value);
__PB_RUST_EXPOSE_SCALAR_MAP_METHODS_FOR_VALUE_TYPE(uint64_t, u64, uint64_t,
value, cpp_value);
__PB_RUST_EXPOSE_SCALAR_MAP_METHODS_FOR_VALUE_TYPE(int64_t, i64, int64_t, value,
cpp_value);
__PB_RUST_EXPOSE_SCALAR_MAP_METHODS_FOR_VALUE_TYPE(
std::string, ProtoBytes, google::protobuf::rust_internal::PtrAndLen,
std::string(value.ptr, value.len),
google::protobuf::rust_internal::PtrAndLen(cpp_value.data(), cpp_value.size()));
__PB_RUST_EXPOSE_SCALAR_MAP_METHODS_FOR_VALUE_TYPE(
std::string, ProtoString, google::protobuf::rust_internal::PtrAndLen,
std::string(value.ptr, value.len),
google::protobuf::rust_internal::PtrAndLen(cpp_value.data(), cpp_value.size()));
#undef expose_scalar_map_methods
#undef expose_map_methods
google::protobuf::rust_internal::RustStringRawParts utf8_debug_string(
const google::protobuf::Message* msg) {
std::string text = google::protobuf::Utf8Format(*msg);
return google::protobuf::rust_internal::RustStringRawParts(text);
}
google::protobuf::rust_internal::RustStringRawParts utf8_debug_string_lite(
const google::protobuf::MessageLite* msg) {
std::string text = google::protobuf::Utf8Format(*msg);
return google::protobuf::rust_internal::RustStringRawParts(text);
}
}
namespace google {
namespace protobuf {
namespace rust_internal {
RustStringRawParts::RustStringRawParts(std::string src) {
if (src.empty()) {
data = nullptr;
len = 0;
} else {
void* data_ = google::protobuf::rust_internal::__pb_rust_alloc(src.length(), 1);
std::memcpy(data_, src.data(), src.length());
data = static_cast<char*>(data_);
len = src.length();
}
}
} // namespace rust_internal
} // namespace protobuf
} // namespace google

@ -0,0 +1,11 @@
#ifndef GOOGLE_PROTOBUF_RUST_CPP_KERNEL_RUST_ALLOC_FOR_CPP_API_H__
#define GOOGLE_PROTOBUF_RUST_CPP_KERNEL_RUST_ALLOC_FOR_CPP_API_H__
#include <cstddef>
// Allocates memory using the current Rust global allocator.
//
// This function is defined in `rust_alloc_for_cpp_api.rs`.
extern "C" void* __pb_rust_alloc(size_t size, size_t align);
#endif // GOOGLE_PROTOBUF_RUST_CPP_KERNEL_RUST_ALLOC_FOR_CPP_API_H__

@ -0,0 +1,64 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2024 Google LLC. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file or at
// https://developers.google.com/open-source/licenses/bsd
#ifndef GOOGLE_PROTOBUF_RUST_CPP_KERNEL_SERIALIZED_DATA_H__
#define GOOGLE_PROTOBUF_RUST_CPP_KERNEL_SERIALIZED_DATA_H__
#include <climits>
#include <cstddef>
#include <cstdint>
#include <cstring>
#include "absl/log/absl_check.h"
#include "absl/log/absl_log.h"
#include "google/protobuf/message_lite.h"
#include "rust/cpp_kernel/rust_alloc_for_cpp_api.h"
namespace google {
namespace protobuf {
namespace rust_internal {
// Represents serialized Protobuf wire format data.
//
// Only to be used to transfer serialized data from C++ to Rust under these
// assumptions:
// * Rust and C++ versions of this struct are ABI compatible.
// * Rust version owns and frees its data.
// * The data were allocated using the Rust allocator.
//
extern "C" struct SerializedData {
// Owns the memory, must be freed by Rust.
const uint8_t* data;
size_t len;
SerializedData(const uint8_t* data, size_t len) : data(data), len(len) {}
};
inline bool SerializeMsg(const google::protobuf::MessageLite* msg, SerializedData* out) {
ABSL_DCHECK(msg->IsInitialized());
size_t len = msg->ByteSizeLong();
if (len > INT_MAX) {
ABSL_LOG(ERROR) << msg->GetTypeName()
<< " exceeded maximum protobuf size of 2GB: " << len;
return false;
}
uint8_t* bytes = static_cast<uint8_t*>(__pb_rust_alloc(len, alignof(char)));
if (bytes == nullptr) {
ABSL_LOG(FATAL) << "Rust allocator failed to allocate memory.";
}
if (!msg->SerializeWithCachedSizesToArray(bytes)) {
return false;
}
*out = SerializedData(bytes, len);
return true;
}
} // namespace rust_internal
} // namespace protobuf
} // namespace google
#endif // GOOGLE_PROTOBUF_RUST_CPP_KERNEL_SERIALIZED_DATA_H__

@ -0,0 +1,26 @@
#include "rust/cpp_kernel/strings.h"
#include <cstring>
#include <string>
#include "rust/cpp_kernel/rust_alloc_for_cpp_api.h"
namespace google {
namespace protobuf {
namespace rust_internal {
RustStringRawParts::RustStringRawParts(std::string src) {
if (src.empty()) {
data = nullptr;
len = 0;
} else {
void* d = __pb_rust_alloc(src.length(), 1);
std::memcpy(d, src.data(), src.length());
data = static_cast<char*>(d);
len = src.length();
}
}
} // namespace rust_internal
} // namespace protobuf
} // namespace google

@ -0,0 +1,50 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2024 Google LLC. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file or at
// https://developers.google.com/open-source/licenses/bsd
#ifndef GOOGLE_PROTOBUF_RUST_CPP_KERNEL_STRINGS_H__
#define GOOGLE_PROTOBUF_RUST_CPP_KERNEL_STRINGS_H__
#include <cstddef>
#include <cstring>
#include <string>
namespace google {
namespace protobuf {
namespace rust_internal {
// Represents an ABI-stable version of &[u8]/string_view (borrowed slice of
// bytes) for FFI use only.
struct PtrAndLen {
/// Borrows the memory.
const char* ptr;
size_t len;
PtrAndLen(const char* ptr, size_t len) : ptr(ptr), len(len) {}
};
// Represents an owned string for FFI purposes.
//
// This must only be used to transfer a string from C++ to Rust. The
// below invariants must hold:
// * Rust and C++ versions of this struct are ABI compatible.
// * The data were allocated using the Rust allocator and are 1 byte aligned.
// * The data is valid UTF-8.
struct RustStringRawParts {
// Owns the memory.
const char* data;
size_t len;
RustStringRawParts() = delete;
// Copies src.
explicit RustStringRawParts(std::string src);
};
} // namespace rust_internal
} // namespace protobuf
} // namespace google
#endif // GOOGLE_PROTOBUF_RUST_CPP_KERNEL_STRINGS_H__

@ -10,7 +10,8 @@
#include "absl/log/absl_check.h" #include "absl/log/absl_check.h"
#include "absl/strings/string_view.h" #include "absl/strings/string_view.h"
#include "rust/cpp_kernel/cpp_api.h" #include "rust/cpp_kernel/serialized_data.h"
#include "rust/cpp_kernel/strings.h"
#include "google/protobuf/unittest.pb.h" #include "google/protobuf/unittest.pb.h"
using google::protobuf::rust_internal::SerializedData; using google::protobuf::rust_internal::SerializedData;

@ -217,7 +217,9 @@ bool RustGenerator::Generate(const FileDescriptor* file,
R"cc( R"cc(
#include "$proto_h$" #include "$proto_h$"
$proto_deps_h$ $proto_deps_h$
#include "google/protobuf/rust/cpp_kernel/cpp_api.h" #include "google/protobuf/rust/cpp_kernel/map.h"
#include "google/protobuf/rust/cpp_kernel/serialized_data.h"
#include "google/protobuf/rust/cpp_kernel/strings.h"
)cc"); )cc");
} }

Loading…
Cancel
Save