Skip to content

Commit 6c3251f

Browse files
committed
Add string_view API for c++17
1 parent 1c534cf commit 6c3251f

File tree

3 files changed

+81
-0
lines changed

3 files changed

+81
-0
lines changed

include/cxx.h

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,45 @@
1515
#include <basetsd.h>
1616
#endif
1717

18+
#ifdef CXXBRIDGE_HAS_STRING_VIEW
19+
#error "string_view gets auto-detected"
20+
#endif
21+
22+
// clang-format off
23+
// detect if string_view supported (C++17 required)
24+
#ifdef __has_include
25+
#if __has_include(<version>)
26+
// gcc >= 9, clang >= 9, msvc >= 19.22
27+
#include <version>
28+
#if __cpp_lib_string_view >= 201603L
29+
#define CXXBRIDGE_HAS_STRING_VIEW
30+
#endif
31+
#else
32+
// no <version> include
33+
#if defined(__cpp_lib_string_view) && __cpp_lib_string_view >= 201603L
34+
// gcc: 8, clang: 5 - 8, msvc: 19.15 - 19.21
35+
#define CXXBRIDGE_HAS_STRING_VIEW
36+
#else
37+
// only include if compiled with c++17
38+
#if (__GNUC__ >= 7 && __cplusplus >= 201703L) || (_MSVC_LANG >= 201703L)
39+
// gcc: 7, msvc: 19.14
40+
#define CXXBRIDGE_HAS_STRING_VIEW
41+
#endif
42+
#endif
43+
#endif
44+
#else
45+
// no __has_include
46+
#if _MSC_VER >= 1910L && _MSVC_LANG > 201402L
47+
// msvc: 19.10 requires c++latest (!)
48+
#define CPPBRIDGE_HAS_STRING_VIEW
49+
#endif
50+
#endif
51+
// clang-format on
52+
53+
#ifdef CXXBRIDGE_HAS_STRING_VIEW
54+
#include <string_view>
55+
#endif
56+
1857
namespace rust {
1958
inline namespace cxxbridge1 {
2059

@@ -34,6 +73,9 @@ class String final {
3473
String(String &&) noexcept;
3574
~String() noexcept;
3675

76+
#ifdef CXXBRIDGE_HAS_STRING_VIEW
77+
String(std::string_view sv) : String(sv.data(), sv.length()) {}
78+
#endif
3779
String(const std::string &);
3880
String(const char *);
3981
String(const char *, size_t);
@@ -42,6 +84,11 @@ class String final {
4284
String &operator=(String &&) noexcept;
4385

4486
explicit operator std::string() const;
87+
#ifdef CXXBRIDGE_HAS_STRING_VIEW
88+
explicit operator std::string_view() const noexcept {
89+
return {this->data(), this->size()};
90+
}
91+
#endif
4592

4693
// Note: no null terminator.
4794
const char *data() const noexcept;
@@ -71,13 +118,21 @@ class String final {
71118
class Str final {
72119
public:
73120
Str() noexcept;
121+
#ifdef CXXBRIDGE_HAS_STRING_VIEW
122+
Str(std::string_view sv) : Str(sv.data(), sv.length()) {}
123+
#endif
74124
Str(const std::string &);
75125
Str(const char *);
76126
Str(const char *, size_t);
77127

78128
Str &operator=(const Str &) noexcept = default;
79129

80130
explicit operator std::string() const;
131+
#ifdef CXXBRIDGE_HAS_STRING_VIEW
132+
explicit operator std::string_view() const noexcept {
133+
return {this->data(), this->size()};
134+
}
135+
#endif
81136

82137
// Note: no null terminator.
83138
const char *data() const noexcept;

tests/ffi/lib.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,8 +216,10 @@ pub mod ffi {
216216
fn r_take_ref_r(r: &R);
217217
fn r_take_ref_c(c: &C);
218218
fn r_take_str(s: &str);
219+
fn r_take_empty_str(s: &str);
219220
fn r_take_slice_char(s: &[c_char]);
220221
fn r_take_rust_string(s: String);
222+
fn r_take_empty_rust_string(s: String);
221223
fn r_take_unique_ptr_string(s: UniquePtr<CxxString>);
222224
fn r_take_ref_vector(v: &CxxVector<u8>);
223225
fn r_take_ref_empty_vector(v: &CxxVector<u64>);
@@ -470,10 +472,18 @@ fn r_take_str(s: &str) {
470472
assert_eq!(s, "2020");
471473
}
472474

475+
fn r_take_empty_str(s: &str) {
476+
assert_eq!(s.len(), 0);
477+
}
478+
473479
fn r_take_rust_string(s: String) {
474480
assert_eq!(s, "2020");
475481
}
476482

483+
fn r_take_empty_rust_string(s: String) {
484+
assert_eq!(s.len(), 0);
485+
}
486+
477487
fn r_take_slice_char(s: &[c_char]) {
478488
assert_eq!(s.len(), 5);
479489
let s = cast::c_char_to_unsigned(s);

tests/ffi/tests.cc

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -624,8 +624,24 @@ extern "C" const char *cxx_run_test() noexcept {
624624
r_take_unique_ptr(std::unique_ptr<C>(new C{2020}));
625625
r_take_ref_c(C{2020});
626626
r_take_str(rust::Str("2020"));
627+
r_take_empty_str(rust::Str{""});
628+
r_take_empty_str(rust::Str{nullptr, 0});
629+
#ifdef CXXBRIDGE_HAS_STRING_VIEW
630+
r_take_str(std::string_view{"2020"});
631+
r_take_empty_str(std::string_view{});
632+
r_take_empty_str(std::string_view{""});
633+
ASSERT(static_cast<std::string_view>(rust::Str{"2020"}) == "2020");
634+
#endif
627635
r_take_slice_char(rust::Slice<const char>(SLICE_DATA, sizeof(SLICE_DATA)));
628636
r_take_rust_string(rust::String("2020"));
637+
r_take_empty_rust_string(rust::String{""});
638+
r_take_empty_rust_string(rust::String{nullptr, 0});
639+
#ifdef CXXBRIDGE_HAS_STRING_VIEW
640+
r_take_rust_string(std::string_view{"2020"});
641+
r_take_empty_rust_string(std::string_view{});
642+
r_take_empty_rust_string(std::string_view{""});
643+
ASSERT(static_cast<std::string_view>(rust::String{"2020"}) == "2020");
644+
#endif
629645
r_take_unique_ptr_string(
630646
std::unique_ptr<std::string>(new std::string("2020")));
631647
r_take_ref_vector(std::vector<uint8_t>{20, 2, 0});

0 commit comments

Comments
 (0)