]> git.lizzy.rs Git - rust.git/blob - src/libstd/ffi/c_str.rs
convert: remove FromError, use From<E> instead
[rust.git] / src / libstd / ffi / c_str.rs
1 // Copyright 2012 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 #![unstable(feature = "std_misc")]
12
13 use convert::Into;
14 use cmp::{PartialEq, Eq, PartialOrd, Ord, Ordering};
15 use error::Error;
16 use fmt;
17 use io;
18 use iter::Iterator;
19 use libc;
20 use mem;
21 #[allow(deprecated)]
22 use old_io;
23 use ops::Deref;
24 use option::Option::{self, Some, None};
25 use result::Result::{self, Ok, Err};
26 use slice;
27 use string::String;
28 use vec::Vec;
29
30 /// A type representing an owned C-compatible string
31 ///
32 /// This type serves the primary purpose of being able to safely generate a
33 /// C-compatible string from a Rust byte slice or vector. An instance of this
34 /// type is a static guarantee that the underlying bytes contain no interior 0
35 /// bytes and the final byte is 0.
36 ///
37 /// A `CString` is created from either a byte slice or a byte vector. After
38 /// being created, a `CString` predominately inherits all of its methods from
39 /// the `Deref` implementation to `[libc::c_char]`. Note that the underlying
40 /// array is represented as an array of `libc::c_char` as opposed to `u8`. A
41 /// `u8` slice can be obtained with the `as_bytes` method.  Slices produced from
42 /// a `CString` do *not* contain the trailing nul terminator unless otherwise
43 /// specified.
44 ///
45 /// # Examples
46 ///
47 /// ```no_run
48 /// # #![feature(libc)]
49 /// # extern crate libc;
50 /// # fn main() {
51 /// use std::ffi::CString;
52 /// use libc;
53 ///
54 /// extern {
55 ///     fn my_printer(s: *const libc::c_char);
56 /// }
57 ///
58 /// let to_print = &b"Hello, world!"[..];
59 /// let c_to_print = CString::new(to_print).unwrap();
60 /// unsafe {
61 ///     my_printer(c_to_print.as_ptr());
62 /// }
63 /// # }
64 /// ```
65 #[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
66 #[stable(feature = "rust1", since = "1.0.0")]
67 pub struct CString {
68     inner: Vec<u8>,
69 }
70
71 /// Representation of a borrowed C string.
72 ///
73 /// This dynamically sized type is only safely constructed via a borrowed
74 /// version of an instance of `CString`. This type can be constructed from a raw
75 /// C string as well and represents a C string borrowed from another location.
76 ///
77 /// Note that this structure is **not** `repr(C)` and is not recommended to be
78 /// placed in the signatures of FFI functions. Instead safe wrappers of FFI
79 /// functions may leverage the unsafe `from_ptr` constructor to provide a safe
80 /// interface to other consumers.
81 ///
82 /// # Examples
83 ///
84 /// Inspecting a foreign C string
85 ///
86 /// ```no_run
87 /// # #![feature(libc)]
88 /// extern crate libc;
89 /// use std::ffi::CStr;
90 ///
91 /// extern { fn my_string() -> *const libc::c_char; }
92 ///
93 /// fn main() {
94 ///     unsafe {
95 ///         let slice = CStr::from_ptr(my_string());
96 ///         println!("string length: {}", slice.to_bytes().len());
97 ///     }
98 /// }
99 /// ```
100 ///
101 /// Passing a Rust-originating C string
102 ///
103 /// ```no_run
104 /// # #![feature(libc)]
105 /// extern crate libc;
106 /// use std::ffi::{CString, CStr};
107 ///
108 /// fn work(data: &CStr) {
109 ///     extern { fn work_with(data: *const libc::c_char); }
110 ///
111 ///     unsafe { work_with(data.as_ptr()) }
112 /// }
113 ///
114 /// fn main() {
115 ///     let s = CString::new("data data data data").unwrap();
116 ///     work(&s);
117 /// }
118 /// ```
119 #[derive(Hash)]
120 #[stable(feature = "rust1", since = "1.0.0")]
121 pub struct CStr {
122     // FIXME: this should not be represented with a DST slice but rather with
123     //        just a raw `libc::c_char` along with some form of marker to make
124     //        this an unsized type. Essentially `sizeof(&CStr)` should be the
125     //        same as `sizeof(&c_char)` but `CStr` should be an unsized type.
126     inner: [libc::c_char]
127 }
128
129 /// An error returned from `CString::new` to indicate that a nul byte was found
130 /// in the vector provided.
131 #[derive(Clone, PartialEq, Debug)]
132 #[stable(feature = "rust1", since = "1.0.0")]
133 pub struct NulError(usize, Vec<u8>);
134
135 /// A conversion trait used by the constructor of `CString` for types that can
136 /// be converted to a vector of bytes.
137 #[deprecated(since = "1.0.0", reason = "use std::convert::Into<Vec<u8>> instead")]
138 #[unstable(feature = "std_misc")]
139 pub trait IntoBytes {
140     /// Consumes this container, returning a vector of bytes.
141     fn into_bytes(self) -> Vec<u8>;
142 }
143
144 impl CString {
145     /// Create a new C-compatible string from a container of bytes.
146     ///
147     /// This method will consume the provided data and use the underlying bytes
148     /// to construct a new string, ensuring that there is a trailing 0 byte.
149     ///
150     /// # Examples
151     ///
152     /// ```no_run
153     /// # #![feature(libc)]
154     /// extern crate libc;
155     /// use std::ffi::CString;
156     ///
157     /// extern { fn puts(s: *const libc::c_char); }
158     ///
159     /// fn main() {
160     ///     let to_print = CString::new("Hello!").unwrap();
161     ///     unsafe {
162     ///         puts(to_print.as_ptr());
163     ///     }
164     /// }
165     /// ```
166     ///
167     /// # Errors
168     ///
169     /// This function will return an error if the bytes yielded contain an
170     /// internal 0 byte. The error returned will contain the bytes as well as
171     /// the position of the nul byte.
172     #[stable(feature = "rust1", since = "1.0.0")]
173     pub fn new<T: Into<Vec<u8>>>(t: T) -> Result<CString, NulError> {
174         let bytes = t.into();
175         match bytes.iter().position(|x| *x == 0) {
176             Some(i) => Err(NulError(i, bytes)),
177             None => Ok(unsafe { CString::from_vec_unchecked(bytes) }),
178         }
179     }
180
181     /// Create a new C-compatible string from a byte slice.
182     ///
183     /// This method will copy the data of the slice provided into a new
184     /// allocation, ensuring that there is a trailing 0 byte.
185     ///
186     /// # Examples
187     ///
188     /// ```no_run
189     /// # #![feature(libc)]
190     /// extern crate libc;
191     /// use std::ffi::CString;
192     ///
193     /// extern { fn puts(s: *const libc::c_char); }
194     ///
195     /// fn main() {
196     ///     let to_print = CString::new("Hello!").unwrap();
197     ///     unsafe {
198     ///         puts(to_print.as_ptr());
199     ///     }
200     /// }
201     /// ```
202     ///
203     /// # Panics
204     ///
205     /// This function will panic if the provided slice contains any
206     /// interior nul bytes.
207     #[unstable(feature = "std_misc")]
208     #[deprecated(since = "1.0.0", reason = "use CString::new instead")]
209     #[allow(deprecated)]
210     pub fn from_slice(v: &[u8]) -> CString {
211         CString::from_vec(v.to_vec())
212     }
213
214     /// Create a C-compatible string from a byte vector.
215     ///
216     /// This method will consume ownership of the provided vector, appending a 0
217     /// byte to the end after verifying that there are no interior 0 bytes.
218     ///
219     /// # Panics
220     ///
221     /// This function will panic if the provided slice contains any
222     /// interior nul bytes.
223     #[unstable(feature = "std_misc")]
224     #[deprecated(since = "1.0.0", reason = "use CString::new instead")]
225     pub fn from_vec(v: Vec<u8>) -> CString {
226         match v.iter().position(|x| *x == 0) {
227             Some(i) => panic!("null byte found in slice at: {}", i),
228             None => unsafe { CString::from_vec_unchecked(v) },
229         }
230     }
231
232     /// Create a C-compatible string from a byte vector without checking for
233     /// interior 0 bytes.
234     ///
235     /// This method is equivalent to `from_vec` except that no runtime assertion
236     /// is made that `v` contains no 0 bytes.
237     #[stable(feature = "rust1", since = "1.0.0")]
238     pub unsafe fn from_vec_unchecked(mut v: Vec<u8>) -> CString {
239         v.push(0);
240         CString { inner: v }
241     }
242
243     /// Returns the contents of this `CString` as a slice of bytes.
244     ///
245     /// The returned slice does **not** contain the trailing nul separator and
246     /// it is guaranteed to not have any interior nul bytes.
247     #[stable(feature = "rust1", since = "1.0.0")]
248     pub fn as_bytes(&self) -> &[u8] {
249         &self.inner[..self.inner.len() - 1]
250     }
251
252     /// Equivalent to the `as_bytes` function except that the returned slice
253     /// includes the trailing nul byte.
254     #[stable(feature = "rust1", since = "1.0.0")]
255     pub fn as_bytes_with_nul(&self) -> &[u8] {
256         &self.inner
257     }
258 }
259
260 #[stable(feature = "rust1", since = "1.0.0")]
261 impl Deref for CString {
262     type Target = CStr;
263
264     fn deref(&self) -> &CStr {
265         unsafe { mem::transmute(self.as_bytes_with_nul()) }
266     }
267 }
268
269 #[stable(feature = "rust1", since = "1.0.0")]
270 impl fmt::Debug for CString {
271     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
272         fmt::Debug::fmt(&String::from_utf8_lossy(self.as_bytes()), f)
273     }
274 }
275
276 impl NulError {
277     /// Returns the position of the nul byte in the slice that was provided to
278     /// `CString::from_vec`.
279     #[stable(feature = "rust1", since = "1.0.0")]
280     pub fn nul_position(&self) -> usize { self.0 }
281
282     /// Consumes this error, returning the underlying vector of bytes which
283     /// generated the error in the first place.
284     #[stable(feature = "rust1", since = "1.0.0")]
285     pub fn into_vec(self) -> Vec<u8> { self.1 }
286 }
287
288 #[stable(feature = "rust1", since = "1.0.0")]
289 impl Error for NulError {
290     fn description(&self) -> &str { "nul byte found in data" }
291 }
292
293 #[stable(feature = "rust1", since = "1.0.0")]
294 impl fmt::Display for NulError {
295     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
296         write!(f, "nul byte found in provided data at position: {}", self.0)
297     }
298 }
299
300 #[stable(feature = "rust1", since = "1.0.0")]
301 impl From<NulError> for io::Error {
302     fn from(_: NulError) -> io::Error {
303         io::Error::new(io::ErrorKind::InvalidInput,
304                        "data provided contains a nul byte", None)
305     }
306 }
307
308 #[stable(feature = "rust1", since = "1.0.0")]
309 #[allow(deprecated)]
310 impl From<NulError> for old_io::IoError {
311     fn from(_: NulError) -> old_io::IoError {
312         old_io::IoError {
313             kind: old_io::IoErrorKind::InvalidInput,
314             desc: "data provided contains a nul byte",
315             detail: None
316         }
317     }
318 }
319
320 impl CStr {
321     /// Cast a raw C string to a safe C string wrapper.
322     ///
323     /// This function will cast the provided `ptr` to the `CStr` wrapper which
324     /// allows inspection and interoperation of non-owned C strings. This method
325     /// is unsafe for a number of reasons:
326     ///
327     /// * There is no guarantee to the validity of `ptr`
328     /// * The returned lifetime is not guaranteed to be the actual lifetime of
329     ///   `ptr`
330     /// * There is no guarantee that the memory pointed to by `ptr` contains a
331     ///   valid nul terminator byte at the end of the string.
332     ///
333     /// > **Note**: This operation is intended to be a 0-cost cast but it is
334     /// > currently implemented with an up-front calculation of the length of
335     /// > the string. This is not guaranteed to always be the case.
336     ///
337     /// # Examples
338     ///
339     /// ```no_run
340     /// # #![feature(libc)]
341     /// # extern crate libc;
342     /// # fn main() {
343     /// use std::ffi::CStr;
344     /// use std::str;
345     /// use libc;
346     ///
347     /// extern {
348     ///     fn my_string() -> *const libc::c_char;
349     /// }
350     ///
351     /// unsafe {
352     ///     let slice = CStr::from_ptr(my_string());
353     ///     println!("string returned: {}",
354     ///              str::from_utf8(slice.to_bytes()).unwrap());
355     /// }
356     /// # }
357     /// ```
358     #[stable(feature = "rust1", since = "1.0.0")]
359     pub unsafe fn from_ptr<'a>(ptr: *const libc::c_char) -> &'a CStr {
360         let len = libc::strlen(ptr);
361         mem::transmute(slice::from_raw_parts(ptr, len as usize + 1))
362     }
363
364     /// Return the inner pointer to this C string.
365     ///
366     /// The returned pointer will be valid for as long as `self` is and points
367     /// to a contiguous region of memory terminated with a 0 byte to represent
368     /// the end of the string.
369     #[stable(feature = "rust1", since = "1.0.0")]
370     pub fn as_ptr(&self) -> *const libc::c_char {
371         self.inner.as_ptr()
372     }
373
374     /// Convert this C string to a byte slice.
375     ///
376     /// This function will calculate the length of this string (which normally
377     /// requires a linear amount of work to be done) and then return the
378     /// resulting slice of `u8` elements.
379     ///
380     /// The returned slice will **not** contain the trailing nul that this C
381     /// string has.
382     ///
383     /// > **Note**: This method is currently implemented as a 0-cost cast, but
384     /// > it is planned to alter its definition in the future to perform the
385     /// > length calculation whenever this method is called.
386     #[stable(feature = "rust1", since = "1.0.0")]
387     pub fn to_bytes(&self) -> &[u8] {
388         let bytes = self.to_bytes_with_nul();
389         &bytes[..bytes.len() - 1]
390     }
391
392     /// Convert this C string to a byte slice containing the trailing 0 byte.
393     ///
394     /// This function is the equivalent of `to_bytes` except that it will retain
395     /// the trailing nul instead of chopping it off.
396     ///
397     /// > **Note**: This method is currently implemented as a 0-cost cast, but
398     /// > it is planned to alter its definition in the future to perform the
399     /// > length calculation whenever this method is called.
400     #[stable(feature = "rust1", since = "1.0.0")]
401     pub fn to_bytes_with_nul(&self) -> &[u8] {
402         unsafe { mem::transmute::<&[libc::c_char], &[u8]>(&self.inner) }
403     }
404 }
405
406 #[stable(feature = "rust1", since = "1.0.0")]
407 impl PartialEq for CStr {
408     fn eq(&self, other: &CStr) -> bool {
409         self.to_bytes().eq(other.to_bytes())
410     }
411 }
412 #[stable(feature = "rust1", since = "1.0.0")]
413 impl Eq for CStr {}
414 #[stable(feature = "rust1", since = "1.0.0")]
415 impl PartialOrd for CStr {
416     fn partial_cmp(&self, other: &CStr) -> Option<Ordering> {
417         self.to_bytes().partial_cmp(&other.to_bytes())
418     }
419 }
420 #[stable(feature = "rust1", since = "1.0.0")]
421 impl Ord for CStr {
422     fn cmp(&self, other: &CStr) -> Ordering {
423         self.to_bytes().cmp(&other.to_bytes())
424     }
425 }
426
427 /// Deprecated in favor of `CStr`
428 #[unstable(feature = "std_misc")]
429 #[deprecated(since = "1.0.0", reason = "use CStr::from_ptr(p).to_bytes() instead")]
430 pub unsafe fn c_str_to_bytes<'a>(raw: &'a *const libc::c_char) -> &'a [u8] {
431     let len = libc::strlen(*raw);
432     slice::from_raw_parts(*(raw as *const _ as *const *const u8), len as usize)
433 }
434
435 /// Deprecated in favor of `CStr`
436 #[unstable(feature = "std_misc")]
437 #[deprecated(since = "1.0.0",
438              reason = "use CStr::from_ptr(p).to_bytes_with_nul() instead")]
439 pub unsafe fn c_str_to_bytes_with_nul<'a>(raw: &'a *const libc::c_char)
440                                           -> &'a [u8] {
441     let len = libc::strlen(*raw) + 1;
442     slice::from_raw_parts(*(raw as *const _ as *const *const u8), len as usize)
443 }
444
445 #[allow(deprecated)]
446 impl<'a> IntoBytes for &'a str {
447     fn into_bytes(self) -> Vec<u8> { self.as_bytes().to_vec() }
448 }
449 #[allow(deprecated)]
450 impl<'a> IntoBytes for &'a [u8] {
451     fn into_bytes(self) -> Vec<u8> { self.to_vec() }
452 }
453 #[allow(deprecated)]
454 impl IntoBytes for String {
455     fn into_bytes(self) -> Vec<u8> { self.into_bytes() }
456 }
457 #[allow(deprecated)]
458 impl IntoBytes for Vec<u8> {
459     fn into_bytes(self) -> Vec<u8> { self }
460 }
461
462 #[cfg(test)]
463 mod tests {
464     use prelude::v1::*;
465     use super::*;
466     use libc;
467
468     #[test]
469     fn c_to_rust() {
470         let data = b"123\0";
471         let ptr = data.as_ptr() as *const libc::c_char;
472         unsafe {
473             assert_eq!(CStr::from_ptr(ptr).to_bytes(), b"123");
474             assert_eq!(CStr::from_ptr(ptr).to_bytes_with_nul(), b"123\0");
475         }
476     }
477
478     #[test]
479     fn simple() {
480         let s = CString::new("1234").unwrap();
481         assert_eq!(s.as_bytes(), b"1234");
482         assert_eq!(s.as_bytes_with_nul(), b"1234\0");
483     }
484
485     #[test]
486     fn build_with_zero1() {
487         assert!(CString::new(&b"\0"[..]).is_err());
488     }
489     #[test]
490     fn build_with_zero2() {
491         assert!(CString::new(vec![0]).is_err());
492     }
493
494     #[test]
495     fn build_with_zero3() {
496         unsafe {
497             let s = CString::from_vec_unchecked(vec![0]);
498             assert_eq!(s.as_bytes(), b"\0");
499         }
500     }
501
502     #[test]
503     fn formatted() {
504         let s = CString::new(&b"12"[..]).unwrap();
505         assert_eq!(format!("{:?}", s), "\"12\"");
506     }
507
508     #[test]
509     fn borrowed() {
510         unsafe {
511             let s = CStr::from_ptr(b"12\0".as_ptr() as *const _);
512             assert_eq!(s.to_bytes(), b"12");
513             assert_eq!(s.to_bytes_with_nul(), b"12\0");
514         }
515     }
516 }