Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions smoke/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)

include(FetchContent)
include(CheckCXXSourceCompiles)

set(PROTOCYTE_REPO_ROOT "${CMAKE_CURRENT_LIST_DIR}/..")
set(PROTOCYTE_SMOKE_PROTO_DIR "${CMAKE_CURRENT_LIST_DIR}/proto")
Expand Down Expand Up @@ -42,6 +43,29 @@ set(PROTOCYTE_GENERATED_FILES
"${PROTOCYTE_GENERATED_DIR}/protocyte/runtime/runtime.hpp"
)

check_cxx_source_compiles([=[
#include <version>
#if !defined(__cpp_lib_format) || __cpp_lib_format < 201907L
#error "std::format is unavailable"
#endif
#include <format>
#include <string_view>
#include <type_traits>

int main() {
using Formatter = ::std::formatter<::std::string_view, char>;
static_assert(::std::is_default_constructible_v<Formatter>);
const auto formatted = ::std::format("{}", ::std::string_view {"ok"});
return formatted == "ok" ? 0 : 1;
}
]=] PROTOCYTE_SMOKE_HAS_STD_FORMAT)

function(protocyte_smoke_enable_std_format_if_available target_name)
if(PROTOCYTE_SMOKE_HAS_STD_FORMAT)
target_compile_definitions("${target_name}" PRIVATE PROTOCYTE_ENABLE_STD_FORMAT=1)
endif()
endfunction()

if(PROTOCYTE_SMOKE_REGENERATE OR PROTOCYTE_SMOKE_BUILD_BENCHMARKS)
set(PROTOCYTE_FETCH_PROTOBUF "${PROTOCYTE_SMOKE_FETCH_PROTOBUF}")
else()
Expand Down Expand Up @@ -212,6 +236,7 @@ target_compile_definitions(
PROTOCYTE_ENABLE_HOSTED_ALLOCATOR=1
PROTOCYTE_ENABLE_STD_STRING_VIEW=1
)
protocyte_smoke_enable_std_format_if_available(protocyte_host_smoke)
target_compile_features(protocyte_host_smoke PRIVATE cxx_std_20)
target_link_libraries(protocyte_host_smoke PRIVATE Catch2::Catch2WithMain)

Expand Down Expand Up @@ -239,6 +264,7 @@ if(PROTOCYTE_SMOKE_BUILD_BENCHMARKS)
PROTOCYTE_ENABLE_HOSTED_ALLOCATOR=1
PROTOCYTE_ENABLE_STD_STRING_VIEW=1
)
protocyte_smoke_enable_std_format_if_available(protocyte_host_benchmark)
target_compile_features(protocyte_host_benchmark PRIVATE cxx_std_20)
target_link_libraries(protocyte_host_benchmark PRIVATE benchmark::benchmark_main)

Expand Down Expand Up @@ -268,6 +294,7 @@ if(PROTOCYTE_SMOKE_BUILD_BENCHMARKS)
PROTOCYTE_ENABLE_HOSTED_ALLOCATOR=1
PROTOCYTE_ENABLE_STD_STRING_VIEW=1
)
protocyte_smoke_enable_std_format_if_available(protocyte_host_protobuf_benchmark)
target_compile_features(protocyte_host_protobuf_benchmark PRIVATE cxx_std_20)
target_link_libraries(
protocyte_host_protobuf_benchmark
Expand Down
29 changes: 28 additions & 1 deletion smoke/generated/protocyte/runtime/runtime.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,14 @@
#include <new>
#include <type_traits>

#if PROTOCYTE_ENABLE_STD_STRING_VIEW
#if PROTOCYTE_ENABLE_STD_FORMAT
#include <version>
#if defined(__cpp_lib_format) && __cpp_lib_format >= 201907L
#include <format>
#endif
#endif

#if PROTOCYTE_ENABLE_STD_STRING_VIEW || PROTOCYTE_ENABLE_STD_FORMAT || PROTOCYTE_ENABLE_FMT_FORMAT
#include <string_view>
#endif

Expand Down Expand Up @@ -2974,6 +2981,12 @@ namespace protocyte {
typename Config::Bytes bytes_;
};

#if PROTOCYTE_ENABLE_FMT_FORMAT
template<class Config> std::string_view format_as(const String<Config> &value) noexcept {
return ::std::string_view {value.data(), value.size()};
}
#endif

template<class T, class Config> struct Box {
using Context = typename Config::Context;

Expand Down Expand Up @@ -4299,4 +4312,18 @@ namespace protocyte {

} // namespace protocyte

#if PROTOCYTE_ENABLE_STD_FORMAT && defined(__cpp_lib_format) && __cpp_lib_format >= 201907L
namespace std {

template<class Config> struct formatter<::protocyte::String<Config>, char>
: public ::std::formatter<::std::string_view, char> {
template<class FormatContext> auto format(const ::protocyte::String<Config> &value, FormatContext &ctx) const {
return ::std::formatter<::std::string_view, char>::format(::std::string_view {value.data(), value.size()},
ctx);
}
};

} // namespace std
#endif

#endif // PROTOCYTE_RUNTIME_RUNTIME_HPP
8 changes: 8 additions & 0 deletions smoke/src/host_smoke.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2621,6 +2621,10 @@ TEST_CASE("byte setters accept contiguous byte containers", "[smoke][runtime][by
CHECK(converted_span == std::string_view {"hello"});
#if defined(__cpp_lib_format)
CHECK(std::format("{}", message.f_string()) == "hello");
#if PROTOCYTE_ENABLE_STD_FORMAT
CHECK(std::format("{}", message.mutable_f_string()) == "hello");
CHECK(std::format("{:>8}", message.mutable_f_string()) == " hello");
#endif
#endif
const std::string_view converted_string = message.mutable_f_string();
CHECK(converted_string == converted_span);
Expand All @@ -2635,6 +2639,10 @@ TEST_CASE("byte setters accept contiguous byte containers", "[smoke][runtime][by
REQUIRE(embedded_nul_string_view);
CHECK(message.f_string().size() == 3u);
CHECK(view_equal(message.f_string(), *embedded_nul_string_view));
#if defined(__cpp_lib_format) && PROTOCYTE_ENABLE_STD_FORMAT
const auto formatted_embedded_nul = std::format("{}", message.mutable_f_string());
CHECK(formatted_embedded_nul == std::string {"a\0b", 3u});
#endif

const char *c_string_payload = "hello from pointer";
require_success(message.set_f_string(c_string_payload));
Expand Down
29 changes: 28 additions & 1 deletion src/protocyte/runtime/runtime.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,14 @@
#include <new>
#include <type_traits>

#if PROTOCYTE_ENABLE_STD_STRING_VIEW
#if PROTOCYTE_ENABLE_STD_FORMAT
#include <version>
#if defined(__cpp_lib_format) && __cpp_lib_format >= 201907L
#include <format>
#endif
#endif

#if PROTOCYTE_ENABLE_STD_STRING_VIEW || PROTOCYTE_ENABLE_STD_FORMAT || PROTOCYTE_ENABLE_FMT_FORMAT
#include <string_view>
#endif

Expand Down Expand Up @@ -2974,6 +2981,12 @@ namespace protocyte {
typename Config::Bytes bytes_;
};

#if PROTOCYTE_ENABLE_FMT_FORMAT
template<class Config> std::string_view format_as(const String<Config> &value) noexcept {
return ::std::string_view {value.data(), value.size()};
}
#endif

template<class T, class Config> struct Box {
using Context = typename Config::Context;

Expand Down Expand Up @@ -4299,4 +4312,18 @@ namespace protocyte {

} // namespace protocyte

#if PROTOCYTE_ENABLE_STD_FORMAT && defined(__cpp_lib_format) && __cpp_lib_format >= 201907L
namespace std {

template<class Config> struct formatter<::protocyte::String<Config>, char>
: public ::std::formatter<::std::string_view, char> {
template<class FormatContext> auto format(const ::protocyte::String<Config> &value, FormatContext &ctx) const {
return ::std::formatter<::std::string_view, char>::format(::std::string_view {value.data(), value.size()},
ctx);
}
};

} // namespace std
#endif

#endif // PROTOCYTE_RUNTIME_RUNTIME_HPP
19 changes: 19 additions & 0 deletions tests/test_cmake.py
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,25 @@ def test_cmake_requires_python_314_for_codegen_wrapper() -> None:
assert "find_package(Python3 3.14 COMPONENTS Interpreter REQUIRED)" in functions


def test_smoke_cmake_gates_std_format_opt_in_on_compile_probe() -> None:
smoke_cmake = (Path(__file__).resolve().parents[1] / "smoke" / "CMakeLists.txt").read_text(encoding="utf-8")

assert "include(CheckCXXSourceCompiles)" in smoke_cmake
assert "check_cxx_source_compiles(" in smoke_cmake
assert "#include <version>" in smoke_cmake
assert "#if !defined(__cpp_lib_format) || __cpp_lib_format < 201907L" in smoke_cmake
assert '#error "std::format is unavailable"' in smoke_cmake
assert "#include <format>" in smoke_cmake
assert "#include <string_view>" in smoke_cmake
assert "::std::formatter<::std::string_view, char>" in smoke_cmake
assert "::std::format(\"{}\", ::std::string_view {\"ok\"})" in smoke_cmake
assert "PROTOCYTE_SMOKE_HAS_STD_FORMAT" in smoke_cmake
assert "if(PROTOCYTE_SMOKE_HAS_STD_FORMAT)" in smoke_cmake
assert "target_compile_definitions(\"${target_name}\" PRIVATE PROTOCYTE_ENABLE_STD_FORMAT=1)" in smoke_cmake
assert "\n PROTOCYTE_ENABLE_STD_FORMAT=1" not in smoke_cmake
assert "\n PROTOCYTE_ENABLE_STD_FORMAT=1" not in smoke_cmake


def test_prerelease_cmake_version_file_marks_versioned_requests_unsuitable() -> None:
template = (
Path(__file__).resolve().parents[1] / "cmake" / "protocyteConfigVersionPrerelease.cmake.in"
Expand Down
11 changes: 10 additions & 1 deletion tests/test_plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -183,8 +183,11 @@ def test_runtime_byte_containers_use_bulk_copy_helpers() -> None:
)[0]

assert "#include <cstring>" in runtime_header
assert "#if PROTOCYTE_ENABLE_STD_STRING_VIEW\n#include <string_view>\n#endif" in runtime_header
assert "#if PROTOCYTE_ENABLE_STD_FORMAT\n#include <version>\n#if defined(__cpp_lib_format) && __cpp_lib_format >= 201907L\n#include <format>\n#endif\n#endif" in runtime_header
assert "#if PROTOCYTE_ENABLE_STD_STRING_VIEW || PROTOCYTE_ENABLE_STD_FORMAT || PROTOCYTE_ENABLE_FMT_FORMAT\n#include <string_view>\n#endif" in runtime_header
assert "#ifdef PROTOCYTE_ENABLE_STD_STRING_VIEW" not in runtime_header
assert "#ifdef PROTOCYTE_ENABLE_STD_FORMAT" not in runtime_header
assert "#ifdef PROTOCYTE_ENABLE_FMT_FORMAT" not in runtime_header
assert "inline void copy_bytes(u8 *dst, const u8 *src, const usize count) noexcept" in runtime_header
assert "if (!count || dst == src)" in runtime_header
assert "::std::memmove(dst, src, count);" in runtime_header
Expand Down Expand Up @@ -218,6 +221,12 @@ def test_runtime_byte_containers_use_bulk_copy_helpers() -> None:
assert "const char *data() const noexcept" in string_body
assert "usize length() const noexcept { return size(); }" in string_body
assert "operator ::std::string_view() const noexcept { return view(); }" in string_body
assert "#if PROTOCYTE_ENABLE_FMT_FORMAT\n template<class Config> std::string_view format_as(const String<Config> &value) noexcept" in runtime_header
assert "return ::std::string_view {value.data(), value.size()};" in runtime_header
assert "#if PROTOCYTE_ENABLE_STD_FORMAT && defined(__cpp_lib_format) && __cpp_lib_format >= 201907L\nnamespace std {" in runtime_header
assert "template<class Config> struct formatter<::protocyte::String<Config>, char>" in runtime_header
assert "public ::std::formatter<::std::string_view, char>" in runtime_header
assert "auto format(const ::protocyte::String<Config> &value, FormatContext &ctx) const" in runtime_header
assert "Status assign(const Span<const char> view) noexcept" in string_body
assert "Status assign(const Span<const u8> view) noexcept" in string_body
assert "copy_bytes(out, data_ + pos_, count);" in slice_reader_body
Expand Down
Loading