Repository: dtolnay/cxx (language: rust)

Issue:
rust::String(const char *, size_t);
This would be nice for some FFI use cases. For example, Python:

```
const char* PyUnicode_AsUTF8AndSize(PyObject *unicode, Py_ssize_t *size)

Return a pointer to the UTF-8 encoding of the Unicode object, and store the size of the encoded
representation (in bytes) in size. The size argument can be NULL; in this case no size will be stored.
The returned buffer always has an extra null byte appended (not included in size), regardless of
whether there are any other null code points.
```


Discussion / hints:

Fix patch:
diff --git a/include/cxx.h b/include/cxx.h
index f211b3be1..c3231fd0d 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -29,6 +29,7 @@ class String final {
 
   String(const std::string &);
   String(const char *);
+  String(const char *, size_t);
 
   String &operator=(const String &) noexcept;
   String &operator=(String &&) noexcept;
@@ -58,6 +59,7 @@ class Str final {
 
   Str(const std::string &);
   Str(const char *);
+  Str(const char *, size_t);
   Str(std::string &&) = delete;
 
   Str &operator=(Str) noexcept;
diff --git a/src/cxx.cc b/src/cxx.cc
index eb86d3def..da05ee2f7 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -55,16 +55,11 @@ String::String(String &&other) noexcept {
 
 String::~String() noexcept { cxxbridge03$string$drop(this); }
 
-String::String(const std::string &s) {
-  auto ptr = s.data();
-  auto len = s.length();
-  if (!cxxbridge03$string$from(this, ptr, len)) {
-    panic<std::invalid_argument>("data for rust::String is not utf-8");
-  }
-}
+String::String(const std::string &s) : String(s.data(), s.length()) {}
 
-String::String(const char *s) {
-  auto len = std::strlen(s);
+String::String(const char *s) : String(s, std::strlen(s)) {}
+
+String::String(const char *s, size_t len) {
   if (!cxxbridge03$string$from(this, s, len)) {
     panic<std::invalid_argument>("data for rust::String is not utf-8");
   }
@@ -111,13 +106,11 @@ Str::Str() noexcept : repr(Repr{reinterpret_cast<const char *>(this), 0}) {}
 
 Str::Str(const Str &) noexcept = default;
 
-Str::Str(const std::string &s) : repr(Repr{s.data(), s.length()}) {
-  if (!cxxbridge03$str$valid(this->repr.ptr, this->repr.len)) {
-    panic<std::invalid_argument>("data for rust::Str is not utf-8");
-  }
-}
+Str::Str(const std::string &s) : Str(s.data(), s.length()) {}
+
+Str::Str(const char *s) : Str(s, std::strlen(s)) {}
 
-Str::Str(const char *s) : repr(Repr{s, std::strlen(s)}) {
+Str::Str(const char *s, size_t len) : repr(Repr{s, len}) {
   if (!cxxbridge03$str$valid(this->repr.ptr, this->repr.len)) {
     panic<std::invalid_argument>("data for rust::Str is not utf-8");
   }


Test patch: