}
fn main() {
- let prompt = CString::from_slice(b"[my-awesome-shell] $");
- unsafe {
+ let prompt = CString::new("[my-awesome-shell] $").unwrap();
+ unsafe {
rl_prompt = prompt.as_ptr();
println!("{:?}", rl_prompt);
}
}
unsafe {
- let buf = CString::from_slice(filename.as_vec());
+ let buf = CString::new(filename.as_vec()).unwrap();
let mb = llvm::LLVMRustCreateMemoryBufferWithContentsOfFile(buf.as_ptr());
if mb as int == 0 {
return Err(format!("error reading library: '{}'",
/// raised.
pub fn open(dst: &Path) -> Option<ArchiveRO> {
unsafe {
- let s = CString::from_slice(dst.as_vec());
+ let s = CString::new(dst.as_vec()).unwrap();
let ar = ::LLVMRustOpenArchive(s.as_ptr());
if ar.is_null() {
None
pub fn read<'a>(&'a self, file: &str) -> Option<&'a [u8]> {
unsafe {
let mut size = 0 as libc::size_t;
- let file = CString::from_slice(file.as_bytes());
+ let file = CString::new(file).unwrap();
let ptr = ::LLVMRustArchiveReadSection(self.ptr, file.as_ptr(),
&mut size);
if ptr.is_null() {
}
pub fn mk_target_data(string_rep: &str) -> TargetData {
- let string_rep = CString::from_slice(string_rep.as_bytes());
+ let string_rep = CString::new(string_rep).unwrap();
TargetData {
lltd: unsafe { LLVMCreateTargetData(string_rep.as_ptr()) }
}
// Internalize everything but the reachable symbols of the current module
let cstrs: Vec<CString> = reachable.iter().map(|s| {
- CString::from_slice(s.as_bytes())
+ CString::new(s.clone()).unwrap()
}).collect();
let arr: Vec<*const libc::c_char> = cstrs.iter().map(|c| c.as_ptr()).collect();
let ptr = arr.as_ptr();
use syntax::diagnostic;
use syntax::diagnostic::{Emitter, Handler, Level, mk_handler};
-use std::ffi::{self, CString};
+use std::ffi::{CStr, CString};
use std::old_io::Command;
use std::old_io::fs;
use std::iter::Unfold;
if cstr == ptr::null() {
handler.fatal(&msg[]);
} else {
- let err = ffi::c_str_to_bytes(&cstr);
+ let err = CStr::from_ptr(cstr).to_bytes();
let err = String::from_utf8_lossy(err).to_string();
libc::free(cstr as *mut _);
handler.fatal(&format!("{}: {}",
output: &Path,
file_type: llvm::FileType) {
unsafe {
- let output_c = CString::from_slice(output.as_vec());
+ let output_c = CString::new(output.as_vec()).unwrap();
let result = llvm::LLVMRustWriteOutputFile(
target, pm, m, output_c.as_ptr(), file_type);
if !result {
let triple = &sess.target.target.llvm_target[];
let tm = unsafe {
- let triple = CString::from_slice(triple.as_bytes());
+ let triple = CString::new(triple.as_bytes()).unwrap();
let cpu = match sess.opts.cg.target_cpu {
Some(ref s) => &**s,
None => &*sess.target.target.options.cpu
};
- let cpu = CString::from_slice(cpu.as_bytes());
- let features = CString::from_slice(target_feature(sess).as_bytes());
+ let cpu = CString::new(cpu.as_bytes()).unwrap();
+ let features = CString::new(target_feature(sess).as_bytes()).unwrap();
llvm::LLVMRustCreateTargetMachine(
triple.as_ptr(), cpu.as_ptr(), features.as_ptr(),
code_model,
}
llvm::diagnostic::Optimization(opt) => {
- let pass_name = str::from_utf8(ffi::c_str_to_bytes(&opt.pass_name))
+ let pass_name = str::from_utf8(CStr::from_ptr(opt.pass_name).to_bytes())
.ok()
.expect("got a non-UTF8 pass name from LLVM");
let enabled = match cgcx.remark {
if config.emit_no_opt_bc {
let ext = format!("{}.no-opt.bc", name_extra);
let out = output_names.with_extension(&ext);
- let out = CString::from_slice(out.as_vec());
+ let out = CString::new(out.as_vec()).unwrap();
llvm::LLVMWriteBitcodeToFile(llmod, out.as_ptr());
}
// If we're verifying or linting, add them to the function pass
// manager.
let addpass = |pass: &str| {
- let pass = CString::from_slice(pass.as_bytes());
+ let pass = CString::new(pass).unwrap();
llvm::LLVMRustAddPass(fpm, pass.as_ptr())
};
if !config.no_verify { assert!(addpass("verify")); }
}
for pass in &config.passes {
- let pass = CString::from_slice(pass.as_bytes());
+ let pass = CString::new(pass.clone()).unwrap();
if !llvm::LLVMRustAddPass(mpm, pass.as_ptr()) {
cgcx.handler.warn(&format!("unknown pass {:?}, ignoring", pass));
}
if config.emit_lto_bc {
let name = format!("{}.lto.bc", name_extra);
let out = output_names.with_extension(&name);
- let out = CString::from_slice(out.as_vec());
+ let out = CString::new(out.as_vec()).unwrap();
llvm::LLVMWriteBitcodeToFile(llmod, out.as_ptr());
}
},
if config.emit_bc {
let ext = format!("{}.bc", name_extra);
let out = output_names.with_extension(&ext);
- let out = CString::from_slice(out.as_vec());
+ let out = CString::new(out.as_vec()).unwrap();
llvm::LLVMWriteBitcodeToFile(llmod, out.as_ptr());
}
if config.emit_ir {
let ext = format!("{}.ll", name_extra);
let out = output_names.with_extension(&ext);
- let out = CString::from_slice(out.as_vec());
+ let out = CString::new(out.as_vec()).unwrap();
with_codegen(tm, llmod, config.no_builtins, |cpm| {
llvm::LLVMRustPrintModule(cpm, llmod, out.as_ptr());
})
let mut llvm_args = Vec::new();
{
let mut add = |arg: &str| {
- let s = CString::from_slice(arg.as_bytes());
+ let s = CString::new(arg).unwrap();
llvm_args.push(s.as_ptr());
llvm_c_strs.push(s);
};
ast::AsmIntel => llvm::AD_Intel
};
- let asm = CString::from_slice(ia.asm.as_bytes());
- let constraints = CString::from_slice(constraints.as_bytes());
+ let asm = CString::new(ia.asm.as_bytes()).unwrap();
+ let constraints = CString::new(constraints).unwrap();
let r = InlineAsmCall(bcx,
asm.as_ptr(),
constraints.as_ptr(),
use arena::TypedArena;
use libc::{c_uint, uint64_t};
-use std::ffi::{self, CString};
+use std::ffi::{CStr, CString};
use std::cell::{Cell, RefCell};
use std::collections::HashSet;
use std::mem;
pub fn decl_fn(ccx: &CrateContext, name: &str, cc: llvm::CallConv,
ty: Type, output: ty::FnOutput) -> ValueRef {
- let buf = CString::from_slice(name.as_bytes());
+ let buf = CString::new(name).unwrap();
let llfn: ValueRef = unsafe {
llvm::LLVMGetOrInsertFunction(ccx.llmod(), buf.as_ptr(), ty.to_ref())
};
None => ()
}
unsafe {
- let buf = CString::from_slice(name.as_bytes());
+ let buf = CString::new(name.clone()).unwrap();
let c = llvm::LLVMAddGlobal(ccx.llmod(), ty.to_ref(), buf.as_ptr());
// Thread-local statics in some other crate need to *always* be linked
// against in a thread-local fashion, so we need to be sure to apply the
&format!("Illegal null byte in export_name \
value: `{}`", sym)[]);
}
- let buf = CString::from_slice(sym.as_bytes());
+ let buf = CString::new(sym.clone()).unwrap();
let g = llvm::LLVMAddGlobal(ccx.llmod(), llty,
buf.as_ptr());
§)[]);
}
unsafe {
- let buf = CString::from_slice(sect.as_bytes());
+ let buf = CString::new(sect.as_bytes()).unwrap();
llvm::LLVMSetSection(v, buf.as_ptr());
}
},
let name = format!("rust_metadata_{}_{}",
cx.link_meta().crate_name,
cx.link_meta().crate_hash);
- let buf = CString::from_vec(name.into_bytes());
+ let buf = CString::new(name).unwrap();
let llglobal = unsafe {
llvm::LLVMAddGlobal(cx.metadata_llmod(), val_ty(llconst).to_ref(),
buf.as_ptr())
unsafe {
llvm::LLVMSetInitializer(llglobal, llconst);
let name = loader::meta_section_name(cx.sess().target.target.options.is_like_osx);
- let name = CString::from_slice(name.as_bytes());
+ let name = CString::new(name).unwrap();
llvm::LLVMSetSection(llglobal, name.as_ptr())
}
return metadata;
continue
}
- let name = ffi::c_str_to_bytes(&llvm::LLVMGetValueName(val))
- .to_vec();
+ let name = CStr::from_ptr(llvm::LLVMGetValueName(val))
+ .to_bytes().to_vec();
declared.insert(name);
}
}
continue
}
- let name = ffi::c_str_to_bytes(&llvm::LLVMGetValueName(val))
- .to_vec();
+ let name = CStr::from_ptr(llvm::LLVMGetValueName(val))
+ .to_bytes().to_vec();
if !declared.contains(&name) &&
!reachable.contains(str::from_utf8(&name).unwrap()) {
llvm::SetLinkage(val, llvm::InternalLinkage);
if name.is_empty() {
llvm::LLVMBuildAlloca(self.llbuilder, ty.to_ref(), noname())
} else {
- let name = CString::from_slice(name.as_bytes());
+ let name = CString::new(name).unwrap();
llvm::LLVMBuildAlloca(self.llbuilder, ty.to_ref(),
name.as_ptr())
}
let comment_text = format!("{} {}", "#",
sanitized.replace("\n", "\n\t# "));
self.count_insn("inlineasm");
- let comment_text = CString::from_vec(comment_text.into_bytes());
+ let comment_text = CString::new(comment_text).unwrap();
let asm = unsafe {
llvm::LLVMConstInlineAsm(Type::func(&[], &Type::void(self.ccx)).to_ref(),
comment_text.as_ptr(), noname(), False,
opt_node_id: Option<ast::NodeId>)
-> Block<'a, 'tcx> {
unsafe {
- let name = CString::from_slice(name.as_bytes());
+ let name = CString::new(name).unwrap();
let llbb = llvm::LLVMAppendBasicBlockInContext(self.ccx.llcx(),
self.llfn,
name.as_ptr());
pub fn C_floating(s: &str, t: Type) -> ValueRef {
unsafe {
- let s = CString::from_slice(s.as_bytes());
+ let s = CString::new(s).unwrap();
llvm::LLVMConstRealOfString(t.to_ref(), s.as_ptr())
}
}
!null_terminated as Bool);
let gsym = token::gensym("str");
- let buf = CString::from_vec(format!("str{}", gsym.usize()).into_bytes());
+ let buf = CString::new(format!("str{}", gsym.usize()));
+ let buf = buf.unwrap();
let g = llvm::LLVMAddGlobal(cx.llmod(), val_ty(sc).to_ref(), buf.as_ptr());
llvm::LLVMSetInitializer(g, sc);
llvm::LLVMSetGlobalConstant(g, True);
unsafe fn create_context_and_module(sess: &Session, mod_name: &str) -> (ContextRef, ModuleRef) {
let llcx = llvm::LLVMContextCreate();
- let mod_name = CString::from_slice(mod_name.as_bytes());
+ let mod_name = CString::new(mod_name).unwrap();
let llmod = llvm::LLVMModuleCreateWithNameInContext(mod_name.as_ptr(), llcx);
- let data_layout = &*sess.target.target.data_layout;
- let data_layout = CString::from_slice(data_layout.as_bytes());
+ let data_layout = sess.target.target.data_layout.as_bytes();
+ let data_layout = CString::new(data_layout).unwrap();
llvm::LLVMSetDataLayout(llmod, data_layout.as_ptr());
- let llvm_target = &*sess.target.target.llvm_target;
- let llvm_target = CString::from_slice(llvm_target.as_bytes());
+ let llvm_target = sess.target.target.llvm_target.as_bytes();
+ let llvm_target = CString::new(llvm_target).unwrap();
llvm::LLVMRustSetNormalizedTarget(llmod, llvm_target.as_ptr());
(llcx, llmod)
}
namespace_node.mangled_name_of_contained_item(&var_name[]);
let var_scope = namespace_node.scope;
- let var_name = CString::from_slice(var_name.as_bytes());
- let linkage_name = CString::from_slice(linkage_name.as_bytes());
+ let var_name = CString::new(var_name).unwrap();
+ let linkage_name = CString::new(linkage_name).unwrap();
unsafe {
llvm::LLVMDIBuilderCreateStaticVariable(DIB(cx),
var_scope,
let is_local_to_unit = is_node_local_to_unit(cx, fn_ast_id);
- let function_name = CString::from_slice(function_name.as_bytes());
- let linkage_name = CString::from_slice(linkage_name.as_bytes());
+ let function_name = CString::new(function_name).unwrap();
+ let linkage_name = CString::new(linkage_name).unwrap();
let fn_metadata = unsafe {
llvm::LLVMDIBuilderCreateFunction(
DIB(cx),
let ident = special_idents::type_self;
let ident = token::get_ident(ident);
- let name = CString::from_slice(ident.as_bytes());
+ let name = CString::new(ident.as_bytes()).unwrap();
let param_metadata = unsafe {
llvm::LLVMDIBuilderCreateTemplateTypeParameter(
DIB(cx),
if cx.sess().opts.debuginfo == FullDebugInfo {
let actual_type_metadata = type_metadata(cx, actual_type, codemap::DUMMY_SP);
let ident = token::get_ident(ident);
- let name = CString::from_slice(ident.as_bytes());
+ let name = CString::new(ident.as_bytes()).unwrap();
let param_metadata = unsafe {
llvm::LLVMDIBuilderCreateTemplateTypeParameter(
DIB(cx),
path_bytes.insert(1, prefix[1]);
}
- CString::from_vec(path_bytes)
+ CString::new(path_bytes).unwrap()
}
_ => fallback_path(cx)
}
(option_env!("CFG_VERSION")).expect("CFG_VERSION"));
let compile_unit_name = compile_unit_name.as_ptr();
- let work_dir = CString::from_slice(work_dir.as_vec());
- let producer = CString::from_slice(producer.as_bytes());
+ let work_dir = CString::new(work_dir.as_vec()).unwrap();
+ let producer = CString::new(producer).unwrap();
let flags = "\0";
let split_name = "\0";
return unsafe {
};
fn fallback_path(cx: &CrateContext) -> CString {
- CString::from_slice(cx.link_meta().crate_name.as_bytes())
+ CString::new(cx.link_meta().crate_name.clone()).unwrap()
}
}
CapturedVariable => (0, DW_TAG_auto_variable)
};
- let name = CString::from_slice(name.as_bytes());
+ let name = CString::new(name.as_bytes()).unwrap();
match (variable_access, [].as_slice()) {
(DirectVariable { alloca }, address_operations) |
(IndirectVariable {alloca, address_operations}, _) => {
full_path
};
- let file_name = CString::from_slice(file_name.as_bytes());
- let work_dir = CString::from_slice(work_dir.as_bytes());
+ let file_name = CString::new(file_name).unwrap();
+ let work_dir = CString::new(work_dir).unwrap();
let file_metadata = unsafe {
llvm::LLVMDIBuilderCreateFile(DIB(cx), file_name.as_ptr(),
work_dir.as_ptr())
let llvm_type = type_of::type_of(cx, t);
let (size, align) = size_and_align_of(cx, llvm_type);
- let name = CString::from_slice(name.as_bytes());
+ let name = CString::new(name).unwrap();
let ty_metadata = unsafe {
llvm::LLVMDIBuilderCreateBasicType(
DIB(cx),
let pointer_llvm_type = type_of::type_of(cx, pointer_type);
let (pointer_size, pointer_align) = size_and_align_of(cx, pointer_llvm_type);
let name = compute_debuginfo_type_name(cx, pointer_type, false);
- let name = CString::from_slice(name.as_bytes());
+ let name = CString::new(name).unwrap();
let ptr_metadata = unsafe {
llvm::LLVMDIBuilderCreatePointerType(
DIB(cx),
.iter()
.map(|v| {
let token = token::get_name(v.name);
- let name = CString::from_slice(token.as_bytes());
+ let name = CString::new(token.as_bytes()).unwrap();
unsafe {
llvm::LLVMDIBuilderCreateEnumerator(
DIB(cx),
codemap::DUMMY_SP);
let discriminant_name = get_enum_discriminant_name(cx, enum_def_id);
- let name = CString::from_slice(discriminant_name.as_bytes());
+ let name = CString::new(discriminant_name.as_bytes()).unwrap();
let discriminant_type_metadata = unsafe {
llvm::LLVMDIBuilderCreateEnumerationType(
DIB(cx),
.borrow()
.get_unique_type_id_as_string(unique_type_id);
- let enum_name = CString::from_slice(enum_name.as_bytes());
- let unique_type_id_str = CString::from_slice(unique_type_id_str.as_bytes());
+ let enum_name = CString::new(enum_name).unwrap();
+ let unique_type_id_str = CString::new(unique_type_id_str.as_bytes()).unwrap();
let enum_metadata = unsafe {
llvm::LLVMDIBuilderCreateUnionType(
DIB(cx),
ComputedMemberOffset => machine::llelement_offset(cx, composite_llvm_type, i)
};
- let member_name = CString::from_slice(member_description.name.as_bytes());
+ let member_name = member_description.name.as_bytes();
+ let member_name = CString::new(member_name).unwrap();
unsafe {
llvm::LLVMDIBuilderCreateMemberType(
DIB(cx),
let unique_type_id_str = debug_context(cx).type_map
.borrow()
.get_unique_type_id_as_string(unique_type_id);
- let name = CString::from_slice(struct_type_name.as_bytes());
- let unique_type_id = CString::from_slice(unique_type_id_str.as_bytes());
+ let name = CString::new(struct_type_name).unwrap();
+ let unique_type_id = CString::new(unique_type_id_str.as_bytes()).unwrap();
let metadata_stub = unsafe {
// LLVMDIBuilderCreateStructType() wants an empty array. A null
// pointer will lead to hard to trace and debug LLVM assertions
None => ptr::null_mut()
};
let namespace_name = token::get_name(name);
- let namespace_name = CString::from_slice(namespace_name
- .as_bytes());
+ let namespace_name = CString::new(namespace_name.as_bytes()).unwrap();
let scope = unsafe {
llvm::LLVMDIBuilderCreateNameSpace(
DIB(cx),
/// .debug_gdb_scripts global is referenced, so it isn't removed by the linker.
pub fn insert_reference_to_gdb_debug_scripts_section_global(ccx: &CrateContext) {
if needs_gdb_debug_scripts_section(ccx) {
- let empty = CString::from_slice(b"");
+ let empty = CString::new(b"").unwrap();
let gdb_debug_scripts_section_global =
get_or_insert_gdb_debug_scripts_section_global(ccx);
unsafe {
};
unsafe {
// Declare a symbol `foo` with the desired linkage.
- let buf = CString::from_slice(ident.as_bytes());
+ let buf = CString::new(ident.as_bytes()).unwrap();
let g1 = llvm::LLVMAddGlobal(ccx.llmod(), llty2.to_ref(),
buf.as_ptr());
llvm::SetLinkage(g1, linkage);
// zero.
let mut real_name = "_rust_extern_with_linkage_".to_string();
real_name.push_str(&ident);
- let real_name = CString::from_vec(real_name.into_bytes());
+ let real_name = CString::new(real_name).unwrap();
let g2 = llvm::LLVMAddGlobal(ccx.llmod(), llty.to_ref(),
real_name.as_ptr());
llvm::SetLinkage(g2, llvm::InternalLinkage);
}
None => unsafe {
// Generate an external declaration.
- let buf = CString::from_slice(ident.as_bytes());
+ let buf = CString::new(ident.as_bytes()).unwrap();
llvm::LLVMAddGlobal(ccx.llmod(), llty.to_ref(), buf.as_ptr())
}
}
let llalign = llalign_of(ccx, llty);
let name = mangle_internal_name_by_type_and_seq(ccx, t, "tydesc");
debug!("+++ declare_tydesc {} {}", ppaux::ty_to_string(ccx.tcx(), t), name);
- let buf = CString::from_slice(name.as_bytes());
+ let buf = CString::new(name.clone()).unwrap();
let gvar = unsafe {
llvm::LLVMAddGlobal(ccx.llmod(), ccx.tydesc_type().to_ref(),
buf.as_ptr())
}
pub fn named_struct(ccx: &CrateContext, name: &str) -> Type {
- let name = CString::from_slice(name.as_bytes());
+ let name = CString::new(name).unwrap();
ty!(llvm::LLVMStructCreateNamed(ccx.llcx(), name.as_ptr()))
}
impl Lock {
pub fn new(p: &Path) -> Lock {
- let buf = CString::from_slice(p.as_vec());
+ let buf = CString::from_slice(p.as_vec()).unwrap();
let fd = unsafe {
libc::open(buf.as_ptr(), libc::O_RDWR | libc::O_CREAT,
libc::S_IRWXU)
s.push_str(&highlight::highlight(&text,
None,
Some("rust-example-rendered")));
- let output = CString::from_vec(s.into_bytes());
+ let output = CString::from_vec(s.into_bytes()).unwrap();
hoedown_buffer_puts(ob, output.as_ptr());
})
}
format!("{} ", sec)
});
- let text = CString::from_vec(text.into_bytes());
+ let text = CString::from_vec(text.into_bytes()).unwrap();
unsafe { hoedown_buffer_puts(ob, text.as_ptr()) }
}
// This function should have a lifetime constraint of 'a on
// T but that feature is still unimplemented
- let raw_string = CString::from_slice(symbol.as_bytes());
+ let raw_string = CString::new(symbol).unwrap();
let maybe_symbol_value = dl::check_for_errors_in(|| {
dl::symbol(self.handle, raw_string.as_ptr())
});
mod dl {
use prelude::v1::*;
- use ffi::{self, CString};
+ use ffi::{CString, CStr};
use str;
use libc;
use ptr;
const LAZY: libc::c_int = 1;
unsafe fn open_external(filename: &[u8]) -> *mut u8 {
- let s = CString::from_slice(filename);
+ let s = CString::new(filename).unwrap();
dlopen(s.as_ptr(), LAZY) as *mut u8
}
let ret = if ptr::null() == last_error {
Ok(result)
} else {
- let s = ffi::c_str_to_bytes(&last_error);
+ let s = CStr::from_ptr(last_error).to_bytes();
Err(str::from_utf8(s).unwrap().to_string())
};
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use cmp::{PartialEq, Eq, PartialOrd, Ord, Ordering};
+use error::{Error, FromError};
use fmt;
+use io;
use iter::IteratorExt;
use libc;
use mem;
+use old_io;
use ops::Deref;
+use option::Option::{self, Some, None};
+use result::Result::{self, Ok, Err};
use slice::{self, SliceExt};
+use str::StrExt;
use string::String;
use vec::Vec;
-/// A type representing a C-compatible string
+/// A type representing an owned C-compatible string
///
-/// This type serves the primary purpose of being able to generate a
+/// This type serves the primary purpose of being able to safely generate a
/// C-compatible string from a Rust byte slice or vector. An instance of this
/// type is a static guarantee that the underlying bytes contain no interior 0
/// bytes and the final byte is 0.
/// fn my_printer(s: *const libc::c_char);
/// }
///
-/// let to_print = "Hello, world!";
-/// let c_to_print = CString::from_slice(to_print.as_bytes());
+/// let to_print = b"Hello, world!";
+/// let c_to_print = CString::new(to_print).unwrap();
/// unsafe {
/// my_printer(c_to_print.as_ptr());
/// }
/// ```
#[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
pub struct CString {
- inner: Vec<libc::c_char>,
+ inner: Vec<u8>,
+}
+
+/// Representation of a borrowed C string.
+///
+/// This dynamically sized type is only safely constructed via a borrowed
+/// version of an instance of `CString`. This type can be constructed from a raw
+/// C string as well and represents a C string borrowed from another location.
+///
+/// Note that this structure is **not** `repr(C)` and is not recommended to be
+/// placed in the signatures of FFI functions. Instead safe wrappers of FFI
+/// functions may leverage the unsafe `from_ptr` constructor to provide a safe
+/// interface to other consumers.
+///
+/// # Examples
+///
+/// Inspecting a foreign C string
+///
+/// ```no_run
+/// extern crate libc;
+/// use std::ffi::CStr;
+///
+/// extern { fn my_string() -> *const libc::c_char; }
+///
+/// fn main() {
+/// unsafe {
+/// let slice = CStr::from_ptr(my_string());
+/// println!("string length: {}", slice.to_bytes().len());
+/// }
+/// }
+/// ```
+///
+/// Passing a Rust-originating C string
+///
+/// ```no_run
+/// extern crate libc;
+/// use std::ffi::{CString, CStr};
+///
+/// fn work(data: &CStr) {
+/// extern { fn work_with(data: *const libc::c_char); }
+///
+/// unsafe { work_with(data.as_ptr()) }
+/// }
+///
+/// fn main() {
+/// let s = CString::from_slice(b"data data data data").unwrap();
+/// work(&s);
+/// }
+/// ```
+#[derive(Hash)]
+pub struct CStr {
+ inner: [libc::c_char]
+}
+
+/// An error returned from `CString::new` to indicate that a nul byte was found
+/// in the vector provided.
+#[derive(Clone, PartialEq, Debug)]
+pub struct NulError(usize, Vec<u8>);
+
+/// A conversion trait used by the constructor of `CString` for types that can
+/// be converted to a vector of bytes.
+pub trait IntoBytes {
+ /// Consumes this container, returning a vector of bytes.
+ fn into_bytes(self) -> Vec<u8>;
}
impl CString {
+ /// Create a new C-compatible string from a container of bytes.
+ ///
+ /// This method will consume the provided data and use the underlying bytes
+ /// to construct a new string, ensuring that there is a trailing 0 byte.
+ ///
+ /// # Examples
+ ///
+ /// ```no_run
+ /// extern crate libc;
+ /// use std::ffi::CString;
+ ///
+ /// extern { fn puts(s: *const libc::c_char); }
+ ///
+ /// fn main() {
+ /// let to_print = CString::from_slice(b"Hello!").unwrap();
+ /// unsafe {
+ /// puts(to_print.as_ptr());
+ /// }
+ /// }
+ /// ```
+ ///
+ /// # Errors
+ ///
+ /// This function will return an error if the bytes yielded contain an
+ /// internal 0 byte. The error returned will contain the bytes as well as
+ /// the position of the nul byte.
+ pub fn new<T: IntoBytes>(t: T) -> Result<CString, NulError> {
+ let bytes = t.into_bytes();
+ match bytes.iter().position(|x| *x == 0) {
+ Some(i) => Err(NulError(i, bytes)),
+ None => Ok(unsafe { CString::from_vec_unchecked(bytes) }),
+ }
+ }
+
/// Create a new C-compatible string from a byte slice.
///
/// This method will copy the data of the slice provided into a new
/// allocation, ensuring that there is a trailing 0 byte.
///
+ /// # Examples
+ ///
+ /// ```no_run
+ /// extern crate libc;
+ /// use std::ffi::CString;
+ ///
+ /// extern { fn puts(s: *const libc::c_char); }
+ ///
+ /// fn main() {
+ /// let to_print = CString::from_slice(b"Hello!").unwrap();
+ /// unsafe {
+ /// puts(to_print.as_ptr());
+ /// }
+ /// }
+ /// ```
+ ///
/// # Panics
///
- /// This function will panic if there are any 0 bytes already in the slice
- /// provided.
+ /// This function will panic if the provided slice contains any
+ /// interior nul bytes.
+ #[unstable(feature = "std_misc")]
+ #[deprecated(since = "1.0.0", reason = "use CString::new instead")]
+ #[allow(deprecated)]
pub fn from_slice(v: &[u8]) -> CString {
CString::from_vec(v.to_vec())
}
///
/// # Panics
///
- /// This function will panic if there are any 0 bytes already in the vector
- /// provided.
+ /// This function will panic if the provided slice contains any
+ /// interior nul bytes.
+ #[unstable(feature = "std_misc")]
+ #[deprecated(since = "1.0.0", reason = "use CString::new instead")]
pub fn from_vec(v: Vec<u8>) -> CString {
- assert!(!v.iter().any(|&x| x == 0));
- unsafe { CString::from_vec_unchecked(v) }
+ match v.iter().position(|x| *x == 0) {
+ Some(i) => panic!("null byte found in slice at: {}", i),
+ None => unsafe { CString::from_vec_unchecked(v) },
+ }
}
/// Create a C-compatible string from a byte vector without checking for
/// is made that `v` contains no 0 bytes.
pub unsafe fn from_vec_unchecked(mut v: Vec<u8>) -> CString {
v.push(0);
- CString { inner: mem::transmute(v) }
+ CString { inner: v }
}
- /// Create a view into this C string which includes the trailing nul
- /// terminator at the end of the string.
- pub fn as_slice_with_nul(&self) -> &[libc::c_char] { &self.inner }
-
- /// Similar to the `as_slice` method, but returns a `u8` slice instead of a
- /// `libc::c_char` slice.
+ /// Returns the contents of this `CString` as a slice of bytes.
+ ///
+ /// The returned slice does **not** contain the trailing nul separator and
+ /// it is guaranteet to not have any interior nul bytes.
pub fn as_bytes(&self) -> &[u8] {
- unsafe { mem::transmute(&**self) }
+ &self.inner[..self.inner.len() - 1]
}
- /// Equivalent to `as_slice_with_nul` except that the type returned is a
- /// `u8` slice instead of a `libc::c_char` slice.
+ /// Equivalent to the `as_bytes` function except that the returned slice
+ /// includes the trailing nul byte.
pub fn as_bytes_with_nul(&self) -> &[u8] {
- unsafe { mem::transmute(self.as_slice_with_nul()) }
+ &self.inner
}
}
impl Deref for CString {
- type Target = [libc::c_char];
+ type Target = CStr;
- fn deref(&self) -> &[libc::c_char] {
- &self.inner[..(self.inner.len() - 1)]
+ fn deref(&self) -> &CStr {
+ unsafe { mem::transmute(self.as_bytes_with_nul()) }
}
}
}
}
-/// Interpret a C string as a byte slice.
-///
-/// This function will calculate the length of the C string provided, and it
-/// will then return a corresponding slice for the contents of the C string not
-/// including the nul terminator.
-///
-/// This function will tie the lifetime of the returned slice to the lifetime of
-/// the pointer provided. This is done to help prevent the slice from escaping
-/// the lifetime of the pointer itself. If a longer lifetime is needed, then
-/// `mem::copy_lifetime` should be used.
-///
-/// This function is unsafe because there is no guarantee of the validity of the
-/// pointer `raw` or a guarantee that a nul terminator will be found.
-///
-/// # Example
-///
-/// ```no_run
-/// # extern crate libc;
-/// # fn main() {
-/// use std::ffi;
-/// use std::str;
-/// use libc;
-///
-/// extern {
-/// fn my_string() -> *const libc::c_char;
-/// }
-///
-/// unsafe {
-/// let to_print = my_string();
-/// let slice = ffi::c_str_to_bytes(&to_print);
-/// println!("string returned: {}", str::from_utf8(slice).unwrap());
-/// }
-/// # }
-/// ```
+impl NulError {
+ /// Returns the position of the nul byte in the slice that was provided to
+ /// `CString::from_vec`.
+ pub fn nul_position(&self) -> usize { self.0 }
+
+ /// Consumes this error, returning the underlying vector of bytes which
+ /// generated the error in the first place.
+ pub fn into_vec(self) -> Vec<u8> { self.1 }
+}
+
+impl Error for NulError {
+ fn description(&self) -> &str { "nul byte found in data" }
+}
+
+impl fmt::Display for NulError {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "nul byte found in provided data at position: {}", self.0)
+ }
+}
+
+impl FromError<NulError> for io::Error {
+ fn from_error(_: NulError) -> io::Error {
+ io::Error::new(io::ErrorKind::InvalidInput,
+ "data provided contains a nul byte", None)
+ }
+}
+
+impl FromError<NulError> for old_io::IoError {
+ fn from_error(_: NulError) -> old_io::IoError {
+ old_io::IoError {
+ kind: old_io::IoErrorKind::InvalidInput,
+ desc: "data provided contains a nul byte",
+ detail: None
+ }
+ }
+}
+
+impl CStr {
+ /// Cast a raw C string to a safe C string wrapper.
+ ///
+ /// This function will cast the provided `ptr` to the `CStr` wrapper which
+ /// allows inspection and interoperation of non-owned C strings. This method
+ /// is unsafe for a number of reasons:
+ ///
+ /// * There is no guarantee to the validity of `ptr`
+ /// * The returned lifetime is not guaranteed to be the actual lifetime of
+ /// `ptr`
+ /// * There is no guarantee that the memory pointed to by `ptr` contains a
+ /// valid nul terminator byte at the end of the string.
+ ///
+ /// > **Note**: This operation is intended to be a 0-cost cast but it is
+ /// > currently implemented with an up-front calculation of the length of
+ /// > the string. This is not guaranteed to always be the case.
+ ///
+ /// # Example
+ ///
+ /// ```no_run
+ /// # extern crate libc;
+ /// # fn main() {
+ /// use std::ffi::CStr;
+ /// use std::str;
+ /// use libc;
+ ///
+ /// extern {
+ /// fn my_string() -> *const libc::c_char;
+ /// }
+ ///
+ /// unsafe {
+ /// let slice = CStr::from_ptr(my_string());
+ /// println!("string returned: {}",
+ /// str::from_utf8(slice.to_bytes()).unwrap());
+ /// }
+ /// # }
+ /// ```
+ pub unsafe fn from_ptr<'a>(ptr: *const libc::c_char) -> &'a CStr {
+ let len = libc::strlen(ptr);
+ mem::transmute(slice::from_raw_parts(ptr, len as usize + 1))
+ }
+
+ /// Return the inner pointer to this C string.
+ ///
+ /// The returned pointer will be valid for as long as `self` is and points
+ /// to a continguous region of memory terminated with a 0 byte to represent
+ /// the end of the string.
+ pub fn as_ptr(&self) -> *const libc::c_char {
+ self.inner.as_ptr()
+ }
+
+ /// Convert this C string to a byte slice.
+ ///
+ /// This function will calculate the length of this string (which normally
+ /// requires a linear amount of work to be done) and then return the
+ /// resulting slice of `u8` elements.
+ ///
+ /// The returned slice will **not** contain the trailing nul that this C
+ /// string has.
+ ///
+ /// > **Note**: This method is currently implemented as a 0-cost cast, but
+ /// > it is planned to alter its definition in the future to perform the
+ /// > length calculation whenever this method is called.
+ pub fn to_bytes(&self) -> &[u8] {
+ let bytes = self.to_bytes_with_nul();
+ &bytes[..bytes.len() - 1]
+ }
+
+ /// Convert this C string to a byte slice containing the trailing 0 byte.
+ ///
+ /// This function is the equivalent of `to_bytes` except that it will retain
+ /// the trailing nul instead of chopping it off.
+ ///
+ /// > **Note**: This method is currently implemented as a 0-cost cast, but
+ /// > it is planned to alter its definition in the future to perform the
+ /// > length calculation whenever this method is called.
+ pub fn to_bytes_with_nul(&self) -> &[u8] {
+ unsafe { mem::transmute::<&[libc::c_char], &[u8]>(&self.inner) }
+ }
+}
+
+impl PartialEq for CStr {
+ fn eq(&self, other: &CStr) -> bool {
+ self.to_bytes().eq(&other.to_bytes())
+ }
+}
+impl Eq for CStr {}
+impl PartialOrd for CStr {
+ fn partial_cmp(&self, other: &CStr) -> Option<Ordering> {
+ self.to_bytes().partial_cmp(&other.to_bytes())
+ }
+}
+impl Ord for CStr {
+ fn cmp(&self, other: &CStr) -> Ordering {
+ self.to_bytes().cmp(&other.to_bytes())
+ }
+}
+
+/// Deprecated in favor of `CStr`
+#[unstable(feature = "std_misc")]
+#[deprecated(since = "1.0.0", reason = "use CStr::from_ptr(p).to_bytes() instead")]
pub unsafe fn c_str_to_bytes<'a>(raw: &'a *const libc::c_char) -> &'a [u8] {
let len = libc::strlen(*raw);
slice::from_raw_parts(*(raw as *const _ as *const *const u8), len as usize)
}
-/// Interpret a C string as a byte slice with the nul terminator.
-///
-/// This function is identical to `from_raw_buf` except that the returned slice
-/// will include the nul terminator of the string.
-pub unsafe fn c_str_to_bytes_with_nul<'a>(raw: &'a *const libc::c_char) -> &'a [u8] {
+/// Deprecated in favor of `CStr`
+#[unstable(feature = "std_misc")]
+#[deprecated(since = "1.0.0",
+ reason = "use CStr::from_ptr(p).to_bytes_with_nul() instead")]
+pub unsafe fn c_str_to_bytes_with_nul<'a>(raw: &'a *const libc::c_char)
+ -> &'a [u8] {
let len = libc::strlen(*raw) + 1;
slice::from_raw_parts(*(raw as *const _ as *const *const u8), len as usize)
}
+impl<'a> IntoBytes for &'a str {
+ fn into_bytes(self) -> Vec<u8> { self.as_bytes().to_vec() }
+}
+impl<'a> IntoBytes for &'a [u8] {
+ fn into_bytes(self) -> Vec<u8> { self.to_vec() }
+}
+impl IntoBytes for String {
+ fn into_bytes(self) -> Vec<u8> { self.into_bytes() }
+}
+impl IntoBytes for Vec<u8> {
+ fn into_bytes(self) -> Vec<u8> { self }
+}
+
#[cfg(test)]
mod tests {
use prelude::v1::*;
#[test]
fn simple() {
- let s = CString::from_slice(b"1234");
+ let s = CString::from_slice(b"1234").unwrap();
assert_eq!(s.as_bytes(), b"1234");
assert_eq!(s.as_bytes_with_nul(), b"1234\0");
- unsafe {
- assert_eq!(&*s,
- mem::transmute::<_, &[libc::c_char]>(b"1234"));
- assert_eq!(s.as_slice_with_nul(),
- mem::transmute::<_, &[libc::c_char]>(b"1234\0"));
- }
}
- #[should_fail] #[test]
- fn build_with_zero1() { CString::from_slice(b"\0"); }
- #[should_fail] #[test]
- fn build_with_zero2() { CString::from_vec(vec![0]); }
+ #[test]
+ fn build_with_zero1() {
+ assert!(CString::from_slice(b"\0").is_err());
+ }
+ #[test]
+ fn build_with_zero2() {
+ assert!(CString::from_vec(vec![0]).is_err());
+ }
#[test]
fn build_with_zero3() {
#[test]
fn formatted() {
- let s = CString::from_slice(b"12");
+ let s = CString::from_slice(b"12").unwrap();
assert_eq!(format!("{:?}", s), "\"12\"");
}
+
+ #[test]
+ fn borrowed() {
+ unsafe {
+ let s = CStr::from_ptr(b"12\0".as_ptr() as *const _);
+ assert_eq!(s.to_bytes(), b"12");
+ assert_eq!(s.to_bytes_with_nul(), b"12\0");
+ }
+ }
}
reason = "module just underwent fairly large reorganization and the dust \
still needs to settle")]
-pub use self::c_str::CString;
+pub use self::c_str::{CString, CStr, NulError, IntoBytes};
+#[allow(deprecated)]
pub use self::c_str::c_str_to_bytes;
+#[allow(deprecated)]
pub use self::c_str::c_str_to_bytes_with_nul;
pub use self::os_str::OsString;
/// stream.write(&[1, 2, 3]);
/// ```
pub fn connect<P: BytesContainer>(path: P) -> IoResult<UnixStream> {
- let path = CString::from_slice(path.container_as_bytes());
+ let path = try!(CString::new(path.container_as_bytes()));
UnixStreamImp::connect(&path, None)
.map(|inner| UnixStream { inner: inner })
}
return Err(standard_error(TimedOut));
}
- let path = CString::from_slice(path.container_as_bytes());
+ let path = try!(CString::new(path.container_as_bytes()));
UnixStreamImp::connect(&path, Some(timeout.num_milliseconds() as u64))
.map(|inner| UnixStream { inner: inner })
}
/// # }
/// ```
pub fn bind<P: BytesContainer>(path: P) -> IoResult<UnixListener> {
- let path = CString::from_slice(path.container_as_bytes());
+ let path = try!(CString::new(path.container_as_bytes()));
UnixListenerImp::bind(&path)
.map(|inner| UnixListener { inner: inner })
}
/// otherwise configure the process.
pub fn new<T: BytesContainer>(program: T) -> Command {
Command {
- program: CString::from_slice(program.container_as_bytes()),
+ program: CString::new(program.container_as_bytes()).unwrap(),
args: Vec::new(),
env: None,
cwd: None,
/// Add an argument to pass to the program.
pub fn arg<'a, T: BytesContainer>(&'a mut self, arg: T) -> &'a mut Command {
- self.args.push(CString::from_slice(arg.container_as_bytes()));
+ self.args.push(CString::new(arg.container_as_bytes()).unwrap());
self
}
/// Add multiple arguments to pass to the program.
pub fn args<'a, T: BytesContainer>(&'a mut self, args: &[T]) -> &'a mut Command {
self.args.extend(args.iter().map(|arg| {
- CString::from_slice(arg.container_as_bytes())
+ CString::new(arg.container_as_bytes()).unwrap()
}));
self
}
// if the env is currently just inheriting from the parent's,
// materialize the parent's env into a hashtable.
self.env = Some(os::env_as_bytes().into_iter().map(|(k, v)| {
- (EnvKey(CString::from_slice(&k)),
- CString::from_slice(&v))
+ (EnvKey(CString::new(k).unwrap()),
+ CString::new(v).unwrap())
}).collect());
self.env.as_mut().unwrap()
}
pub fn env<'a, T, U>(&'a mut self, key: T, val: U)
-> &'a mut Command
where T: BytesContainer, U: BytesContainer {
- let key = EnvKey(CString::from_slice(key.container_as_bytes()));
- let val = CString::from_slice(val.container_as_bytes());
+ let key = EnvKey(CString::new(key.container_as_bytes()).unwrap());
+ let val = CString::new(val.container_as_bytes()).unwrap();
self.get_env_map().insert(key, val);
self
}
/// Removes an environment variable mapping.
pub fn env_remove<'a, T>(&'a mut self, key: T) -> &'a mut Command
where T: BytesContainer {
- let key = EnvKey(CString::from_slice(key.container_as_bytes()));
+ let key = EnvKey(CString::new(key.container_as_bytes()).unwrap());
self.get_env_map().remove(&key);
self
}
-> &'a mut Command
where T: BytesContainer, U: BytesContainer {
self.env = Some(env.iter().map(|&(ref k, ref v)| {
- (EnvKey(CString::from_slice(k.container_as_bytes())),
- CString::from_slice(v.container_as_bytes()))
+ (EnvKey(CString::new(k.container_as_bytes()).unwrap()),
+ CString::new(v.container_as_bytes()).unwrap())
}).collect());
self
}
/// Set the working directory for the child process.
pub fn cwd<'a>(&'a mut self, dir: &Path) -> &'a mut Command {
- self.cwd = Some(CString::from_slice(dir.as_vec()));
+ self.cwd = Some(CString::new(dir.as_vec()).unwrap());
self
}
cmd.env("path", "foo");
cmd.env("Path", "bar");
let env = &cmd.env.unwrap();
- let val = env.get(&EnvKey(CString::from_slice(b"PATH")));
- assert!(val.unwrap() == &CString::from_slice(b"bar"));
+ let val = env.get(&EnvKey(CString::new(b"PATH").unwrap()));
+ assert!(val.unwrap() == &CString::new(b"bar").unwrap());
}
}
use libc;
use mem;
- use ffi;
+ use ffi::CStr;
use sync::{StaticMutex, MUTEX_INIT};
unsafe { mem::transmute(&GLOBAL_ARGS_PTR) }
}
- unsafe fn load_argc_and_argv(argc: int, argv: *const *const u8) -> Vec<Vec<u8>> {
+ unsafe fn load_argc_and_argv(argc: isize,
+ argv: *const *const u8) -> Vec<Vec<u8>> {
let argv = argv as *const *const libc::c_char;
- (0..argc as uint).map(|i| {
- ffi::c_str_to_bytes(&*argv.offset(i as int)).to_vec()
+ (0..argc).map(|i| {
+ CStr::from_ptr(*argv.offset(i)).to_bytes().to_vec()
}).collect()
}
use self::SocketStatus::*;
use self::InAddr::*;
-use ffi::CString;
-use ffi;
+use ffi::{CString, CStr};
use old_io::net::addrinfo;
use old_io::net::ip::{SocketAddr, IpAddr, Ipv4Addr, Ipv6Addr};
use old_io::{IoResult, IoError};
assert!(host.is_some() || servname.is_some());
- let c_host = host.map(|x| CString::from_slice(x.as_bytes()));
+ let c_host = match host {
+ Some(x) => Some(try!(CString::new(x))),
+ None => None,
+ };
let c_host = c_host.as_ref().map(|x| x.as_ptr()).unwrap_or(null());
- let c_serv = servname.map(|x| CString::from_slice(x.as_bytes()));
+ let c_serv = match servname {
+ Some(x) => Some(try!(CString::new(x))),
+ None => None,
+ };
let c_serv = c_serv.as_ref().map(|x| x.as_ptr()).unwrap_or(null());
let hint = hint.map(|hint| {
}
unsafe {
- Ok(str::from_utf8(ffi::c_str_to_bytes(&hostbuf.as_ptr()))
- .unwrap().to_string())
+ let data = CStr::from_ptr(hostbuf.as_ptr());
+ Ok(str::from_utf8(data.to_bytes()).unwrap().to_string())
}
}
pub fn lookup_host(host: &str) -> io::Result<LookupHost> {
init();
- let c_host = CString::from_slice(host.as_bytes());
+ let c_host = try!(CString::new(host));
let mut res = 0 as *mut _;
unsafe {
try!(cvt_gai(getaddrinfo(c_host.as_ptr(), 0 as *const _, 0 as *const _,
use prelude::v1::*;
-use ffi;
+use ffi::CStr;
use old_io::IoResult;
use libc;
use mem;
output(w, idx,addr, None)
} else {
output(w, idx, addr, Some(unsafe {
- ffi::c_str_to_bytes(&info.dli_sname)
+ CStr::from_ptr(info.dli_sname).to_bytes()
}))
}
}
if ret == 0 || data.is_null() {
output(w, idx, addr, None)
} else {
- output(w, idx, addr, Some(unsafe { ffi::c_str_to_bytes(&data) }))
+ output(w, idx, addr, Some(unsafe { CStr::from_ptr(data).to_bytes() }))
}
}
use prelude::v1::*;
-use ffi::{CString, OsStr, OsString};
+use ffi::{CString, NulError, OsStr, OsString};
use fs::{self, Permissions, OpenOptions};
use net;
use mem;
fn as_bytes(&self) -> &[u8];
/// Convert the `OsStr` slice into a `CString`.
- fn to_cstring(&self) -> CString;
+ fn to_cstring(&self) -> Result<CString, NulError>;
}
impl OsStrExt for OsStr {
&self.as_inner().inner
}
- fn to_cstring(&self) -> CString {
- CString::from_slice(self.as_bytes())
+ fn to_cstring(&self) -> Result<CString, NulError> {
+ CString::new(self.as_bytes())
}
}
/// Includes all extension traits, and some important type definitions.
pub mod prelude {
#[doc(no_inline)]
- pub use super::{Fd, AsRawFd, OsStrExt, OsStringExt, PermissionsExt, CommandExt, ExitStatusExt};
+ pub use super::{Fd, AsRawFd, OsStrExt, OsStringExt, PermissionsExt};
+ #[doc(no_inline)]
+ pub use super::{CommandExt, ExitStatusExt};
}
use prelude::v1::*;
-use ffi::{self, CString};
+use ffi::{CString, CStr};
use old_io::{FilePermission, Write, UnstableFileStat, Open, FileAccess, FileMode};
use old_io::{IoResult, FileStat, SeekStyle};
use old_io::{Read, Truncate, SeekCur, SeekSet, ReadWrite, SeekEnd, Append};
}
}
-fn cstr(path: &Path) -> CString {
- CString::from_slice(path.as_vec())
+fn cstr(path: &Path) -> IoResult<CString> {
+ Ok(try!(CString::new(path.as_vec())))
}
pub fn open(path: &Path, fm: FileMode, fa: FileAccess) -> IoResult<FileDesc> {
libc::S_IRUSR | libc::S_IWUSR),
};
- let path = cstr(path);
+ let path = try!(cstr(path));
match retry(|| unsafe { libc::open(path.as_ptr(), flags, mode) }) {
-1 => Err(super::last_error()),
fd => Ok(FileDesc::new(fd, true)),
}
pub fn mkdir(p: &Path, mode: uint) -> IoResult<()> {
- let p = cstr(p);
+ let p = try!(cstr(p));
mkerr_libc(unsafe { libc::mkdir(p.as_ptr(), mode as libc::mode_t) })
}
let mut buf = Vec::<u8>::with_capacity(size as uint);
let ptr = buf.as_mut_ptr() as *mut dirent_t;
- let p = CString::from_slice(p.as_vec());
+ let p = try!(CString::new(p.as_vec()));
let dir_ptr = unsafe {opendir(p.as_ptr())};
if dir_ptr as uint != 0 {
while unsafe { readdir_r(dir_ptr, ptr, &mut entry_ptr) == 0 } {
if entry_ptr.is_null() { break }
paths.push(unsafe {
- Path::new(ffi::c_str_to_bytes(&rust_list_dir_val(entry_ptr)))
+ Path::new(CStr::from_ptr(rust_list_dir_val(entry_ptr)).to_bytes())
});
}
assert_eq!(unsafe { closedir(dir_ptr) }, 0);
}
pub fn unlink(p: &Path) -> IoResult<()> {
- let p = cstr(p);
+ let p = try!(cstr(p));
mkerr_libc(unsafe { libc::unlink(p.as_ptr()) })
}
pub fn rename(old: &Path, new: &Path) -> IoResult<()> {
- let old = cstr(old);
- let new = cstr(new);
+ let old = try!(cstr(old));
+ let new = try!(cstr(new));
mkerr_libc(unsafe {
libc::rename(old.as_ptr(), new.as_ptr())
})
}
pub fn chmod(p: &Path, mode: uint) -> IoResult<()> {
- let p = cstr(p);
+ let p = try!(cstr(p));
mkerr_libc(retry(|| unsafe {
libc::chmod(p.as_ptr(), mode as libc::mode_t)
}))
}
pub fn rmdir(p: &Path) -> IoResult<()> {
- let p = cstr(p);
+ let p = try!(cstr(p));
mkerr_libc(unsafe { libc::rmdir(p.as_ptr()) })
}
pub fn chown(p: &Path, uid: int, gid: int) -> IoResult<()> {
- let p = cstr(p);
+ let p = try!(cstr(p));
mkerr_libc(retry(|| unsafe {
libc::chown(p.as_ptr(), uid as libc::uid_t, gid as libc::gid_t)
}))
}
pub fn readlink(p: &Path) -> IoResult<Path> {
- let c_path = cstr(p);
+ let c_path = try!(cstr(p));
let p = c_path.as_ptr();
let mut len = unsafe { libc::pathconf(p as *mut _, libc::_PC_NAME_MAX) };
if len == -1 {
}
pub fn symlink(src: &Path, dst: &Path) -> IoResult<()> {
- let src = cstr(src);
- let dst = cstr(dst);
+ let src = try!(cstr(src));
+ let dst = try!(cstr(dst));
mkerr_libc(unsafe { libc::symlink(src.as_ptr(), dst.as_ptr()) })
}
pub fn link(src: &Path, dst: &Path) -> IoResult<()> {
- let src = cstr(src);
- let dst = cstr(dst);
+ let src = try!(cstr(src));
+ let dst = try!(cstr(dst));
mkerr_libc(unsafe { libc::link(src.as_ptr(), dst.as_ptr()) })
}
}
pub fn stat(p: &Path) -> IoResult<FileStat> {
- let p = cstr(p);
+ let p = try!(cstr(p));
let mut stat: libc::stat = unsafe { mem::zeroed() };
match unsafe { libc::stat(p.as_ptr(), &mut stat) } {
0 => Ok(mkstat(&stat)),
}
pub fn lstat(p: &Path) -> IoResult<FileStat> {
- let p = cstr(p);
+ let p = try!(cstr(p));
let mut stat: libc::stat = unsafe { mem::zeroed() };
match unsafe { libc::lstat(p.as_ptr(), &mut stat) } {
0 => Ok(mkstat(&stat)),
}
pub fn utime(p: &Path, atime: u64, mtime: u64) -> IoResult<()> {
- let p = cstr(p);
+ let p = try!(cstr(p));
let buf = libc::utimbuf {
actime: (atime / 1000) as libc::time_t,
modtime: (mtime / 1000) as libc::time_t,
use io::prelude::*;
use os::unix::prelude::*;
-use ffi::{self, CString, OsString, AsOsStr, OsStr};
+use ffi::{CString, CStr, OsString, AsOsStr, OsStr};
use io::{self, Error, Seek, SeekFrom};
use libc::{self, c_int, c_void, size_t, off_t, c_char, mode_t};
use mem;
fn rust_list_dir_val(ptr: *mut libc::dirent_t) -> *const c_char;
}
unsafe {
- let ptr = rust_list_dir_val(self.dirent);
- ffi::c_str_to_bytes(mem::copy_lifetime(self, &ptr))
+ CStr::from_ptr(rust_list_dir_val(self.dirent)).to_bytes()
}
}
}
(true, false) |
(false, false) => libc::O_RDONLY,
};
- let path = cstr(path);
+ let path = try!(cstr(path));
let fd = try!(cvt_r(|| unsafe {
libc::open(path.as_ptr(), flags, opts.mode)
}));
pub fn fd(&self) -> &FileDesc { &self.0 }
}
-fn cstr(path: &Path) -> CString {
- CString::from_slice(path.as_os_str().as_bytes())
+fn cstr(path: &Path) -> io::Result<CString> {
+ let cstring = try!(path.as_os_str().to_cstring());
+ Ok(cstring)
}
pub fn mkdir(p: &Path) -> io::Result<()> {
- let p = cstr(p);
+ let p = try!(cstr(p));
try!(cvt(unsafe { libc::mkdir(p.as_ptr(), 0o777) }));
Ok(())
}
pub fn readdir(p: &Path) -> io::Result<ReadDir> {
let root = Rc::new(p.to_path_buf());
- let p = cstr(p);
+ let p = try!(cstr(p));
unsafe {
let ptr = libc::opendir(p.as_ptr());
if ptr.is_null() {
}
pub fn unlink(p: &Path) -> io::Result<()> {
- let p = cstr(p);
+ let p = try!(cstr(p));
try!(cvt(unsafe { libc::unlink(p.as_ptr()) }));
Ok(())
}
pub fn rename(old: &Path, new: &Path) -> io::Result<()> {
- let old = cstr(old);
- let new = cstr(new);
+ let old = try!(cstr(old));
+ let new = try!(cstr(new));
try!(cvt(unsafe { libc::rename(old.as_ptr(), new.as_ptr()) }));
Ok(())
}
pub fn set_perm(p: &Path, perm: FilePermissions) -> io::Result<()> {
- let p = cstr(p);
+ let p = try!(cstr(p));
try!(cvt_r(|| unsafe { libc::chmod(p.as_ptr(), perm.mode) }));
Ok(())
}
pub fn rmdir(p: &Path) -> io::Result<()> {
- let p = cstr(p);
+ let p = try!(cstr(p));
try!(cvt(unsafe { libc::rmdir(p.as_ptr()) }));
Ok(())
}
pub fn chown(p: &Path, uid: isize, gid: isize) -> io::Result<()> {
- let p = cstr(p);
+ let p = try!(cstr(p));
try!(cvt_r(|| unsafe {
libc::chown(p.as_ptr(), uid as libc::uid_t, gid as libc::gid_t)
}));
}
pub fn readlink(p: &Path) -> io::Result<PathBuf> {
- let c_path = cstr(p);
+ let c_path = try!(cstr(p));
let p = c_path.as_ptr();
let mut len = unsafe { libc::pathconf(p as *mut _, libc::_PC_NAME_MAX) };
if len < 0 {
}
pub fn symlink(src: &Path, dst: &Path) -> io::Result<()> {
- let src = cstr(src);
- let dst = cstr(dst);
+ let src = try!(cstr(src));
+ let dst = try!(cstr(dst));
try!(cvt(unsafe { libc::symlink(src.as_ptr(), dst.as_ptr()) }));
Ok(())
}
pub fn link(src: &Path, dst: &Path) -> io::Result<()> {
- let src = cstr(src);
- let dst = cstr(dst);
+ let src = try!(cstr(src));
+ let dst = try!(cstr(dst));
try!(cvt(unsafe { libc::link(src.as_ptr(), dst.as_ptr()) }));
Ok(())
}
pub fn stat(p: &Path) -> io::Result<FileAttr> {
- let p = cstr(p);
+ let p = try!(cstr(p));
let mut stat: libc::stat = unsafe { mem::zeroed() };
try!(cvt(unsafe { libc::stat(p.as_ptr(), &mut stat) }));
Ok(FileAttr { stat: stat })
}
pub fn lstat(p: &Path) -> io::Result<FileAttr> {
- let p = cstr(p);
+ let p = try!(cstr(p));
let mut stat: libc::stat = unsafe { mem::zeroed() };
try!(cvt(unsafe { libc::lstat(p.as_ptr(), &mut stat) }));
Ok(FileAttr { stat: stat })
}
pub fn utimes(p: &Path, atime: u64, mtime: u64) -> io::Result<()> {
- let p = cstr(p);
+ let p = try!(cstr(p));
let buf = [super::ms_to_timeval(atime), super::ms_to_timeval(mtime)];
try!(cvt(unsafe { c::utimes(p.as_ptr(), buf.as_ptr()) }));
Ok(())
use prelude::v1::*;
-use ffi;
+use ffi::CStr;
use io::{self, ErrorKind};
use libc;
use num::{Int, SignedInt};
let mut err = decode_error(s);
err.detail = Some(unsafe {
- str::from_utf8(ffi::c_str_to_bytes(&gai_strerror(s))).unwrap().to_string()
+ let data = CStr::from_ptr(gai_strerror(s));
+ str::from_utf8(data.to_bytes()).unwrap().to_string()
});
err
}
use prelude::v1::*;
-use ffi;
+use ffi::CStr;
use io;
use libc::{self, c_int, size_t};
use str;
if err == 0 { return Ok(()) }
let detail = unsafe {
- str::from_utf8(ffi::c_str_to_bytes(&c::gai_strerror(err))).unwrap()
+ str::from_utf8(CStr::from_ptr(c::gai_strerror(err)).to_bytes()).unwrap()
.to_string()
};
Err(io::Error::new(io::ErrorKind::Other,
use os::unix::*;
use error::Error as StdError;
-use ffi::{self, CString, OsString, OsStr, AsOsStr};
+use ffi::{CString, CStr, OsString, OsStr, AsOsStr};
use fmt;
use iter;
use libc::{self, c_int, c_char, c_void};
}
let p = p as *const _;
- str::from_utf8(ffi::c_str_to_bytes(&p)).unwrap().to_string()
+ str::from_utf8(CStr::from_ptr(p).to_bytes()).unwrap().to_string()
}
}
if libc::getcwd(buf.as_mut_ptr(), buf.len() as libc::size_t).is_null() {
Err(IoError::last_error())
} else {
- Ok(Path::new(ffi::c_str_to_bytes(&buf.as_ptr())))
+ Ok(Path::new(CStr::from_ptr(buf.as_ptr()).to_bytes()))
}
}
}
pub fn chdir(p: &Path) -> IoResult<()> {
- let p = CString::from_slice(p.as_vec());
+ let p = CString::new(p.as_vec()).unwrap();
unsafe {
match libc::chdir(p.as_ptr()) == (0 as c_int) {
true => Ok(()),
if v.is_null() {
Err(IoError::last_error())
} else {
- Ok(Path::new(ffi::c_str_to_bytes(&v).to_vec()))
+ Ok(Path::new(CStr::from_ptr(&v).to_bytes().to_vec()))
}
}
}
let (argc, argv) = (*_NSGetArgc() as isize,
*_NSGetArgv() as *const *const c_char);
range(0, argc as isize).map(|i| {
- let bytes = ffi::c_str_to_bytes(&*argv.offset(i)).to_vec();
+ let bytes = CStr::from_ptr(&*argv.offset(i)).to_bytes().to_vec();
OsStringExt::from_vec(bytes)
}).collect::<Vec<_>>()
};
let tmp = objc_msgSend(args, object_at_sel, i);
let utf_c_str: *const libc::c_char =
mem::transmute(objc_msgSend(tmp, utf8_sel));
- let bytes = ffi::c_str_to_bytes(&utf_c_str);
+ let bytes = CStr::from_ptr(utf_c_str).to_bytes();
res.push(OsString::from_str(str::from_utf8(bytes).unwrap()))
}
}
}
let mut result = Vec::new();
while *environ != ptr::null() {
- result.push(parse(ffi::c_str_to_bytes(&*environ)));
+ result.push(parse(CStr::from_ptr(*environ).to_bytes()));
environ = environ.offset(1);
}
Env { iter: result.into_iter(), _dont_send_or_sync_me: 0 as *mut _ }
pub fn getenv(k: &OsStr) -> Option<OsString> {
unsafe {
- let s = CString::from_slice(k.as_bytes());
+ let s = k.to_cstring().unwrap();
let s = libc::getenv(s.as_ptr()) as *const _;
if s.is_null() {
None
} else {
- Some(OsStringExt::from_vec(ffi::c_str_to_bytes(&s).to_vec()))
+ Some(OsStringExt::from_vec(CStr::from_ptr(s).to_bytes().to_vec()))
}
}
}
pub fn setenv(k: &OsStr, v: &OsStr) {
unsafe {
- let k = CString::from_slice(k.as_bytes());
- let v = CString::from_slice(v.as_bytes());
+ let k = k.to_cstring().unwrap();
+ let v = v.to_cstring().unwrap();
if libc::funcs::posix01::unistd::setenv(k.as_ptr(), v.as_ptr(), 1) != 0 {
panic!("failed setenv: {}", IoError::last_error());
}
pub fn unsetenv(n: &OsStr) {
unsafe {
- let nbuf = CString::from_slice(n.as_bytes());
+ let nbuf = n.to_cstring().unwrap();
if libc::funcs::posix01::unistd::unsetenv(nbuf.as_ptr()) != 0 {
panic!("failed unsetenv: {}", IoError::last_error());
}
_ => return None
}
let ptr = passwd.pw_dir as *const _;
- let bytes = ffi::c_str_to_bytes(&ptr).to_vec();
+ let bytes = CStr::from_ptr(ptr).to_bytes().to_vec();
return Some(OsStringExt::from_vec(bytes))
}
}
mem::size_of::<libc::sockaddr_un>());
let s = unsafe { &mut *(storage as *mut _ as *mut libc::sockaddr_un) };
- let len = addr.len();
+ let len = addr.as_bytes().len();
if len > s.sun_path.len() - 1 {
return Err(IoError {
kind: old_io::InvalidInput,
})
}
s.sun_family = libc::AF_UNIX as libc::sa_family_t;
- for (slot, value) in s.sun_path.iter_mut().zip(addr.iter()) {
- *slot = *value;
+ for (slot, value) in s.sun_path.iter_mut().zip(addr.as_bytes().iter()) {
+ *slot = *value as libc::c_char;
}
// count the null terminator
impl Command {
pub fn new(program: &OsStr) -> Command {
Command {
- program: program.to_cstring(),
+ program: program.to_cstring().unwrap(),
args: Vec::new(),
env: None,
cwd: None,
}
pub fn arg(&mut self, arg: &OsStr) {
- self.args.push(arg.to_cstring())
+ self.args.push(arg.to_cstring().unwrap())
}
pub fn args<'a, I: Iterator<Item = &'a OsStr>>(&mut self, args: I) {
- self.args.extend(args.map(OsStrExt::to_cstring))
+ self.args.extend(args.map(|s| OsStrExt::to_cstring(s).unwrap()))
}
fn init_env_map(&mut self) {
if self.env.is_none() {
self.env = Some(HashMap::new())
}
pub fn cwd(&mut self, dir: &OsStr) {
- self.cwd = Some(dir.to_cstring())
+ self.cwd = Some(dir.to_cstring().unwrap())
}
}
pub unsafe fn set_name(name: &str) {
// pthread_setname_np() since glibc 2.12
// availability autodetected via weak linkage
- let cname = CString::from_slice(name.as_bytes());
+ let cname = CString::new(name).unwrap();
type F = unsafe extern "C" fn(libc::pthread_t, *const libc::c_char) -> libc::c_int;
extern {
#[linkage = "extern_weak"]
target_os = "openbsd"))]
pub unsafe fn set_name(name: &str) {
// pthread_set_name_np() since almost forever on all BSDs
- let cname = CString::from_slice(name.as_bytes());
+ let cname = CString::new(name).unwrap();
pthread_set_name_np(pthread_self(), cname.as_ptr());
}
#[cfg(any(target_os = "macos", target_os = "ios"))]
pub unsafe fn set_name(name: &str) {
// pthread_setname_np() since OS X 10.6 and iOS 3.2
- let cname = CString::from_slice(name.as_bytes());
+ let cname = CString::new(name).unwrap();
pthread_setname_np(cname.as_ptr());
}
cm: &codemap::CodeMap,
sp: Span)
-> old_io::IoResult<()> {
- let cs = try!(cm.with_expn_info(sp.expn_id, |expn_info| match expn_info {
- Some(ei) => {
- let ss = ei.callee.span.map_or(String::new(), |span| cm.span_to_string(span));
- let (pre, post) = match ei.callee.format {
- codemap::MacroAttribute => ("#[", "]"),
- codemap::MacroBang => ("", "!")
- };
- try!(print_diagnostic(w, &ss[], Note,
- &format!("in expansion of {}{}{}", pre,
- ei.callee.name,
- post)[], None));
- let ss = cm.span_to_string(ei.call_site);
- try!(print_diagnostic(w, &ss[], Note, "expansion site", None));
- Ok(Some(ei.call_site))
- }
- None => Ok(None)
+ let cs = try!(cm.with_expn_info(sp.expn_id, |expn_info| -> old_io::IoResult<_> {
+ match expn_info {
+ Some(ei) => {
+ let ss = ei.callee.span.map_or(String::new(),
+ |span| cm.span_to_string(span));
+ let (pre, post) = match ei.callee.format {
+ codemap::MacroAttribute => ("#[", "]"),
+ codemap::MacroBang => ("", "!")
+ };
+ try!(print_diagnostic(w, &ss[], Note,
+ &format!("in expansion of {}{}{}", pre,
+ ei.callee.name,
+ post)[], None));
+ let ss = cm.span_to_string(ei.call_site);
+ try!(print_diagnostic(w, &ss[], Note, "expansion site", None));
+ Ok(Some(ei.call_site))
+ }
+ None => Ok(None)
+ }
}));
cs.map_or(Ok(()), |call_site| print_macro_backtrace(w, cm, call_site))
}
}
fn atol(s: String) -> int {
- let c = CString::from_slice(s.as_bytes());
+ let c = CString::from_slice(s.as_bytes()).unwrap();
unsafe { mlibc::atol(c.as_ptr()) as int }
}
fn atoll(s: String) -> i64 {
- let c = CString::from_slice(s.as_bytes());
+ let c = CString::from_slice(s.as_bytes()).unwrap();
unsafe { mlibc::atoll(c.as_ptr()) as i64 }
}
fn strlen(str: String) -> uint {
// C string is terminated with a zero
- let s = CString::from_slice(str.as_bytes());
+ let s = CString::from_slice(str.as_bytes()).unwrap();
unsafe {
mlibc::my_strlen(s.as_ptr()) as uint
}
let test_file = &old_path.join("temp.txt");
/* Write the temp input file */
- let fromp = CString::from_slice(test_file.as_vec());
- let modebuf = CString::from_slice(b"w+b");
+ let fromp = CString::from_slice(test_file.as_vec()).unwrap();
+ let modebuf = CString::from_slice(b"w+b").unwrap();
let ostream = libc::fopen(fromp.as_ptr(), modebuf.as_ptr());
assert!((ostream as uint != 0u));
let s = "hello".to_string();
- let buf = CString::from_slice(b"hello");
+ let buf = CString::from_slice(b"hello").unwrap();
let write_len = libc::fwrite(buf.as_ptr() as *mut _,
1u as libc::size_t,
(s.len() + 1u) as libc::size_t,
unsafe {
// Call with just the named parameter
- let c = CString::from_slice(b"Hello World\n");
+ let c = CString::from_slice(b"Hello World\n").unwrap();
check("Hello World\n", |s| sprintf(s, c.as_ptr()));
// Call with variable number of arguments
- let c = CString::from_slice(b"%d %f %c %s\n");
+ let c = CString::from_slice(b"%d %f %c %s\n").unwrap();
check("42 42.500000 a %d %f %c %s\n\n", |s| {
sprintf(s, c.as_ptr(), 42, 42.5f64, 'a' as c_int, c.as_ptr());
});
// A function that takes a function pointer
unsafe fn call(p: unsafe extern fn(*mut c_char, *const c_char, ...) -> c_int) {
// Call with just the named parameter
- let c = CString::from_slice(b"Hello World\n");
+ let c = CString::from_slice(b"Hello World\n").unwrap();
check("Hello World\n", |s| sprintf(s, c.as_ptr()));
// Call with variable number of arguments
- let c = CString::from_slice(b"%d %f %c %s\n");
+ let c = CString::from_slice(b"%d %f %c %s\n").unwrap();
check("42 42.500000 a %d %f %c %s\n\n", |s| {
sprintf(s, c.as_ptr(), 42, 42.5f64, 'a' as c_int, c.as_ptr());
});