From ea7197e2cf921211fb3b82ad45452c2095f5a589 Mon Sep 17 00:00:00 2001
From: Patrick Walton <pcwalton@mimiga.net>
Date: Wed, 16 Mar 2011 18:40:51 -0700
Subject: [PATCH] rustc: Add str_from_cstr() and str_from_buf() functions to
 the standard library, as well as a test case

---
 src/Makefile                     |  1 +
 src/lib/_str.rs                  | 10 ++++++++++
 src/rt/rust_builtin.cpp          | 23 +++++++++++++++++++++++
 src/test/run-pass/lib-str-buf.rs | 14 ++++++++++++++
 4 files changed, 48 insertions(+)
 create mode 100644 src/test/run-pass/lib-str-buf.rs

diff --git a/src/Makefile b/src/Makefile
index 99ef8adce5a..16437310b76 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -498,6 +498,7 @@ TEST_XFAILS_RUSTC := $(addprefix test/run-pass/, \
                         lib-sha1.rs \
                         lib-sort.rs \
                         lib-str.rs \
+                        lib-str-buf.rs \
                         lib-task.rs \
                         lib-uint.rs \
                         lib-vec-str-conversions.rs \
diff --git a/src/lib/_str.rs b/src/lib/_str.rs
index db9413b9278..93d0a9f286a 100644
--- a/src/lib/_str.rs
+++ b/src/lib/_str.rs
@@ -8,6 +8,8 @@ native "rust" mod rustrt {
     fn str_byte_len(str s) -> uint;
     fn str_alloc(uint n_bytes) -> str;
     fn str_from_vec(vec[u8] b) -> str;
+    fn str_from_cstr(sbuf cstr) -> str;
+    fn str_from_buf(sbuf buf, uint len) -> str;
     fn refcount[T](str s) -> uint;
 }
 
@@ -115,6 +117,14 @@ fn unsafe_from_byte(u8 u) -> str {
     ret rustrt.str_from_vec(vec(u));
 }
 
+unsafe fn str_from_cstr(sbuf cstr) -> str {
+    ret rustrt.str_from_cstr(cstr);
+}
+
+unsafe fn str_from_buf(sbuf buf, uint len) -> str {
+    ret rustrt.str_from_buf(buf, len);
+}
+
 
 fn refcount(str s) -> uint {
     auto r = rustrt.refcount[u8](s);
diff --git a/src/rt/rust_builtin.cpp b/src/rt/rust_builtin.cpp
index fcea449ddd9..1f17fc8c075 100644
--- a/src/rt/rust_builtin.cpp
+++ b/src/rt/rust_builtin.cpp
@@ -207,6 +207,29 @@ str_from_vec(rust_task *task, rust_vec *v)
     return st;
 }
 
+extern "C" CDECL rust_str *
+str_from_cstr(rust_task *task, char *sbuf)
+{
+    size_t len = strlen(sbuf) + 1;
+    rust_str *st = vec_alloc_with_data(task, len, len, 1, sbuf);
+    if (!st) {
+        task->fail(2);
+        return NULL;
+    }
+    return st;
+}
+
+extern "C" CDECL rust_str *
+str_from_buf(rust_task *task, char *buf, unsigned int len) {
+    rust_str *st = vec_alloc_with_data(task, len + 1, len, 1, buf);
+    if (!st) {
+        task->fail(2);
+        return NULL;
+    }
+    st->data[st->fill++] = '\0';
+    return st;
+}
+
 extern "C" CDECL void *
 rand_new(rust_task *task)
 {
diff --git a/src/test/run-pass/lib-str-buf.rs b/src/test/run-pass/lib-str-buf.rs
new file mode 100644
index 00000000000..7ba19e925d7
--- /dev/null
+++ b/src/test/run-pass/lib-str-buf.rs
@@ -0,0 +1,14 @@
+// -*- rust -*-
+
+use std;
+import std._str;
+
+fn main() {
+    auto s = "hello";
+    auto sb = _str.rustrt.str_buf(s);
+    auto s_cstr = _str.rustrt.str_from_cstr(sb);
+    check (_str.eq(s_cstr, s));
+    auto s_buf = _str.rustrt.str_from_buf(sb, 5u);
+    check (_str.eq(s_buf, s));
+}
+