Skip to content

Commit 2c9aada

Browse files
committed
c_str: add .as_ptr & .as_mut_ptr to replace .with_[mut_]ref.
These forms return the pointer directly, rather than the added indirection, indentation, and inefficiencies of the closures in `.with_ref` and `.with_mut_ref`. The two closure functions are deprecated. Replace foo(c_str.with_ref(|p| p)) c_str.with_ref(|p| { foo(p); bar(p); }) with foo(c_str.as_ptr()) let p = c_str.as_ptr(); foo(p); bar(p); This change does mean that one has to be careful to avoid writing `let p = x.to_c_str().as_ptr();` since the `CString` will be freed at the end of the statement. Previously, `with_ref` was used (and `as_ptr` avoided) for this reason, but Rust has strongly moved away from closures to more RAII-style code, and most uses of `.with_ref` where in the form `.with_ref(|p| p)` anyway, that is, they were exactly `.as_ptr`. [breaking-change]
1 parent 6a3695d commit 2c9aada

File tree

1 file changed

+69
-0
lines changed

1 file changed

+69
-0
lines changed

src/librustrt/c_str.rs

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,11 +133,79 @@ impl CString {
133133
c_str.buf
134134
}
135135

136+
/// Return a pointer to the NUL-terminated string data.
137+
///
138+
/// `.as_ptr` returns an internal pointer into the `CString`, and
139+
/// may be invalidated when the `CString` falls out of scope (the
140+
/// destructor will run, freeing the allocation if there is
141+
/// one).
142+
///
143+
/// ```rust
144+
/// let foo = "some string";
145+
///
146+
/// // right
147+
/// let x = foo.to_c_str();
148+
/// let p = x.as_ptr();
149+
///
150+
/// // wrong (the CString will be freed, invalidating `p`)
151+
/// let p = foo.to_c_str().as_ptr();
152+
/// ```
153+
///
154+
/// # Failure
155+
///
156+
/// Fails if the CString is null.
157+
///
158+
/// # Example
159+
///
160+
/// ```rust
161+
/// extern crate libc;
162+
///
163+
/// fn main() {
164+
/// let c_str = "foo bar".to_c_str();
165+
/// unsafe {
166+
/// libc::puts(c_str.as_ptr());
167+
/// }
168+
/// }
169+
/// ```
170+
pub fn as_ptr(&self) -> *const libc::c_char {
171+
if self.buf.is_null() { fail!("CString is null!"); }
172+
173+
self.buf
174+
}
175+
176+
/// Return a mutable pointer to the NUL-terminated string data.
177+
///
178+
/// `.as_mut_ptr` returns an internal pointer into the `CString`, and
179+
/// may be invalidated when the `CString` falls out of scope (the
180+
/// destructor will run, freeing the allocation if there is
181+
/// one).
182+
///
183+
/// ```rust
184+
/// let foo = "some string";
185+
///
186+
/// // right
187+
/// let mut x = foo.to_c_str();
188+
/// let p = x.as_mut_ptr();
189+
///
190+
/// // wrong (the CString will be freed, invalidating `p`)
191+
/// let p = foo.to_c_str().as_mut_ptr();
192+
/// ```
193+
///
194+
/// # Failure
195+
///
196+
/// Fails if the CString is null.
197+
pub fn as_mut_ptr(&mut self) -> *mut libc::c_char {
198+
if self.buf.is_null() { fail!("CString is null!") }
199+
200+
self.buf as *mut _
201+
}
202+
136203
/// Calls a closure with a reference to the underlying `*libc::c_char`.
137204
///
138205
/// # Failure
139206
///
140207
/// Fails if the CString is null.
208+
#[deprecated="use `.as_ptr()`"]
141209
pub fn with_ref<T>(&self, f: |*const libc::c_char| -> T) -> T {
142210
if self.buf.is_null() { fail!("CString is null!"); }
143211
f(self.buf)
@@ -148,6 +216,7 @@ impl CString {
148216
/// # Failure
149217
///
150218
/// Fails if the CString is null.
219+
#[deprecated="use `.as_mut_ptr()`"]
151220
pub fn with_mut_ref<T>(&mut self, f: |*mut libc::c_char| -> T) -> T {
152221
if self.buf.is_null() { fail!("CString is null!"); }
153222
f(self.buf as *mut libc::c_char)

0 commit comments

Comments
 (0)