From f83e23ad7c464c242c2d7ace7212d323980b2bca Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 17 Feb 2015 20:48:07 -0800 Subject: std: Stabilize the `hash` module This commit is an implementation of [RFC 823][rfc] which is another pass over the `std::hash` module for stabilization. The contents of the module were not entirely marked stable, but some portions which remained quite similar to the previous incarnation are now marked `#[stable]`. Specifically: [rfc]: https://github.com/rust-lang/rfcs/blob/master/text/0823-hash-simplification.md * `std::hash` is now stable (the name) * `Hash` is now stable * `Hash::hash` is now stable * `Hasher` is now stable * `SipHasher` is now stable * `SipHasher::new` and `new_with_keys` are now stable * `Hasher for SipHasher` is now stable * Many `Hash` implementations are now stable All other portions of the `hash` module remain `#[unstable]` as they are less commonly used and were recently redesigned. This commit is a breaking change due to the modifications to the `std::hash` API and more details can be found on the [RFC][rfc]. Closes #22467 [breaking-change] --- src/libstd/sys/common/wtf8.rs | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) (limited to 'src/libstd/sys/common') diff --git a/src/libstd/sys/common/wtf8.rs b/src/libstd/sys/common/wtf8.rs index b610f6c370b..c4f2de7fb45 100644 --- a/src/libstd/sys/common/wtf8.rs +++ b/src/libstd/sys/common/wtf8.rs @@ -31,7 +31,8 @@ use ascii::*; use borrow::Cow; use cmp; use fmt; -use hash::{Hash, Writer, Hasher}; +use hash::{Hash, Hasher}; +#[cfg(stage0)] use hash::Writer; use iter::FromIterator; use mem; use num::Int; @@ -794,13 +795,22 @@ impl<'a> Iterator for EncodeWide<'a> { } } +#[cfg(stage0)] impl Hash for CodePoint { #[inline] fn hash(&self, state: &mut S) { self.value.hash(state) } } +#[cfg(not(stage0))] +impl Hash for CodePoint { + #[inline] + fn hash(&self, state: &mut H) { + self.value.hash(state) + } +} +#[cfg(stage0)] impl Hash for Wtf8Buf { #[inline] fn hash(&self, state: &mut S) { @@ -808,7 +818,16 @@ impl Hash for Wtf8Buf { 0xfeu8.hash(state) } } +#[cfg(not(stage0))] +impl Hash for Wtf8Buf { + #[inline] + fn hash(&self, state: &mut H) { + state.write(&self.bytes); + 0xfeu8.hash(state) + } +} +#[cfg(stage0)] impl<'a, S: Writer + Hasher> Hash for Wtf8 { #[inline] fn hash(&self, state: &mut S) { @@ -816,6 +835,14 @@ impl<'a, S: Writer + Hasher> Hash for Wtf8 { 0xfeu8.hash(state) } } +#[cfg(not(stage0))] +impl Hash for Wtf8 { + #[inline] + fn hash(&self, state: &mut H) { + state.write(&self.bytes); + 0xfeu8.hash(state) + } +} impl AsciiExt for Wtf8 { type Owned = Wtf8Buf; -- cgit 1.4.1-3-g733a5 From 4a9d190423f67a00053f4b5c9869f0ccbdfcc689 Mon Sep 17 00:00:00 2001 From: Alexis Date: Wed, 18 Feb 2015 10:04:30 -0500 Subject: make Extend use IntoIterator This breaks all implementors of Extend, as they must now accept IntoIterator instead of Iterator. The fix for this is generally trivial (change the bound, and maybe call into_iter() on the argument to get the old argument). Users of Extend should be unaffected because Iterators are IntoIterator. [breaking-change] --- src/libcollections/binary_heap.rs | 3 ++- src/libcollections/bit.rs | 7 ++++--- src/libcollections/btree/map.rs | 2 +- src/libcollections/btree/set.rs | 2 +- src/libcollections/enum_set.rs | 4 ++-- src/libcollections/linked_list.rs | 4 ++-- src/libcollections/string.rs | 8 +++++--- src/libcollections/vec.rs | 3 ++- src/libcollections/vec_deque.rs | 4 ++-- src/libcollections/vec_map.rs | 2 +- src/libcore/iter.rs | 2 +- src/libstd/collections/hash/map.rs | 2 +- src/libstd/collections/hash/set.rs | 2 +- src/libstd/path.rs | 4 ++-- src/libstd/sys/common/wtf8.rs | 5 +++-- src/libsyntax/util/small_vector.rs | 4 ++-- 16 files changed, 32 insertions(+), 26 deletions(-) (limited to 'src/libstd/sys/common') diff --git a/src/libcollections/binary_heap.rs b/src/libcollections/binary_heap.rs index 6196d94b5a6..2f994e94ccc 100644 --- a/src/libcollections/binary_heap.rs +++ b/src/libcollections/binary_heap.rs @@ -677,7 +677,8 @@ impl<'a, T> IntoIterator for &'a BinaryHeap where T: Ord { #[stable(feature = "rust1", since = "1.0.0")] impl Extend for BinaryHeap { - fn extend>(&mut self, iter: Iter) { + fn extend>(&mut self, iterable: I) { + let iter = iterable.into_iter(); let (lower, _) = iter.size_hint(); self.reserve(lower); diff --git a/src/libcollections/bit.rs b/src/libcollections/bit.rs index a2e36155933..c1d79d82043 100644 --- a/src/libcollections/bit.rs +++ b/src/libcollections/bit.rs @@ -934,7 +934,8 @@ impl FromIterator for BitVec { #[stable(feature = "rust1", since = "1.0.0")] impl Extend for BitVec { #[inline] - fn extend>(&mut self, iterator: I) { + fn extend>(&mut self, iterable: I) { + let iterator = iterable.into_iter(); let (min, _) = iterator.size_hint(); self.reserve(min); for element in iterator { @@ -1143,8 +1144,8 @@ impl FromIterator for BitSet { #[stable(feature = "rust1", since = "1.0.0")] impl Extend for BitSet { #[inline] - fn extend>(&mut self, iterator: I) { - for i in iterator { + fn extend>(&mut self, iter: I) { + for i in iter { self.insert(i); } } diff --git a/src/libcollections/btree/map.rs b/src/libcollections/btree/map.rs index 96052156df0..9273d50db85 100644 --- a/src/libcollections/btree/map.rs +++ b/src/libcollections/btree/map.rs @@ -836,7 +836,7 @@ impl FromIterator<(K, V)> for BTreeMap { #[stable(feature = "rust1", since = "1.0.0")] impl Extend<(K, V)> for BTreeMap { #[inline] - fn extend>(&mut self, iter: T) { + fn extend>(&mut self, iter: T) { for (k, v) in iter { self.insert(k, v); } diff --git a/src/libcollections/btree/set.rs b/src/libcollections/btree/set.rs index 7ef887b70cc..d2241a67464 100644 --- a/src/libcollections/btree/set.rs +++ b/src/libcollections/btree/set.rs @@ -503,7 +503,7 @@ impl<'a, T> IntoIterator for &'a BTreeSet { #[stable(feature = "rust1", since = "1.0.0")] impl Extend for BTreeSet { #[inline] - fn extend>(&mut self, iter: Iter) { + fn extend>(&mut self, iter: Iter) { for elem in iter { self.insert(elem); } diff --git a/src/libcollections/enum_set.rs b/src/libcollections/enum_set.rs index d5403ca5d9b..3f8c0121faf 100644 --- a/src/libcollections/enum_set.rs +++ b/src/libcollections/enum_set.rs @@ -268,8 +268,8 @@ impl<'a, E> IntoIterator for &'a EnumSet where E: CLike { } impl Extend for EnumSet { - fn extend>(&mut self, iterator: I) { - for element in iterator { + fn extend>(&mut self, iter: I) { + for element in iter { self.insert(element); } } diff --git a/src/libcollections/linked_list.rs b/src/libcollections/linked_list.rs index 550c1450b93..0ec1371c73c 100644 --- a/src/libcollections/linked_list.rs +++ b/src/libcollections/linked_list.rs @@ -872,8 +872,8 @@ impl<'a, T> IntoIterator for &'a mut LinkedList { #[stable(feature = "rust1", since = "1.0.0")] impl Extend for LinkedList { - fn extend>(&mut self, iterator: T) { - for elt in iterator { self.push_back(elt); } + fn extend>(&mut self, iter: T) { + for elt in iter { self.push_back(elt); } } } diff --git a/src/libcollections/string.rs b/src/libcollections/string.rs index 69fd28d1723..dc1158ecaf8 100644 --- a/src/libcollections/string.rs +++ b/src/libcollections/string.rs @@ -21,7 +21,7 @@ use core::default::Default; use core::error::Error; use core::fmt; use core::hash; -use core::iter::FromIterator; +use core::iter::{IntoIterator, FromIterator}; use core::mem; use core::ops::{self, Deref, Add, Index}; use core::ptr; @@ -728,7 +728,8 @@ impl<'a> FromIterator<&'a str> for String { #[unstable(feature = "collections", reason = "waiting on Extend stabilization")] impl Extend for String { - fn extend>(&mut self, iterator: I) { + fn extend>(&mut self, iterable: I) { + let iterator = iterable.into_iter(); let (lower_bound, _) = iterator.size_hint(); self.reserve(lower_bound); for ch in iterator { @@ -740,7 +741,8 @@ impl Extend for String { #[unstable(feature = "collections", reason = "waiting on Extend stabilization")] impl<'a> Extend<&'a str> for String { - fn extend>(&mut self, iterator: I) { + fn extend>(&mut self, iterable: I) { + let iterator = iterable.into_iter(); // A guess that at least one byte per iterator element will be needed. let (lower_bound, _) = iterator.size_hint(); self.reserve(lower_bound); diff --git a/src/libcollections/vec.rs b/src/libcollections/vec.rs index bde733644b5..e4b090e4dd7 100644 --- a/src/libcollections/vec.rs +++ b/src/libcollections/vec.rs @@ -1480,7 +1480,8 @@ impl<'a, T> IntoIterator for &'a mut Vec { #[unstable(feature = "collections", reason = "waiting on Extend stability")] impl Extend for Vec { #[inline] - fn extend>(&mut self, iterator: I) { + fn extend>(&mut self, iterable: I) { + let iterator = iterable.into_iter(); let (lower, _) = iterator.size_hint(); self.reserve(lower); for element in iterator { diff --git a/src/libcollections/vec_deque.rs b/src/libcollections/vec_deque.rs index 76b2d5b968e..cc01e800f60 100644 --- a/src/libcollections/vec_deque.rs +++ b/src/libcollections/vec_deque.rs @@ -1741,8 +1741,8 @@ impl<'a, T> IntoIterator for &'a mut VecDeque { #[stable(feature = "rust1", since = "1.0.0")] impl Extend for VecDeque { - fn extend>(&mut self, iterator: T) { - for elt in iterator { + fn extend>(&mut self, iter: T) { + for elt in iter { self.push_back(elt); } } diff --git a/src/libcollections/vec_map.rs b/src/libcollections/vec_map.rs index 82ccfd0614f..7085111d6a8 100644 --- a/src/libcollections/vec_map.rs +++ b/src/libcollections/vec_map.rs @@ -700,7 +700,7 @@ impl<'a, T> IntoIterator for &'a mut VecMap { #[stable(feature = "rust1", since = "1.0.0")] impl Extend<(usize, V)> for VecMap { - fn extend>(&mut self, iter: Iter) { + fn extend>(&mut self, iter: I) { for (k, v) in iter { self.insert(k, v); } diff --git a/src/libcore/iter.rs b/src/libcore/iter.rs index fffba1561a3..2e9977cd3eb 100644 --- a/src/libcore/iter.rs +++ b/src/libcore/iter.rs @@ -147,7 +147,7 @@ impl IntoIterator for I { pub trait Extend { /// Extend a container with the elements yielded by an arbitrary iterator #[stable(feature = "rust1", since = "1.0.0")] - fn extend>(&mut self, iterator: T); + fn extend>(&mut self, iterable: T); } /// An extension trait providing numerous methods applicable to all iterators. diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs index 1b9f8b99017..61b531054a0 100644 --- a/src/libstd/collections/hash/map.rs +++ b/src/libstd/collections/hash/map.rs @@ -1570,7 +1570,7 @@ impl Extend<(K, V)> for HashMap S: HashState, H: hash::Hasher { - fn extend>(&mut self, iter: T) { + fn extend>(&mut self, iter: T) { for (k, v) in iter { self.insert(k, v); } diff --git a/src/libstd/collections/hash/set.rs b/src/libstd/collections/hash/set.rs index 5fbbcb3b347..f5e57b78d2a 100644 --- a/src/libstd/collections/hash/set.rs +++ b/src/libstd/collections/hash/set.rs @@ -636,7 +636,7 @@ impl Extend for HashSet S: HashState, H: hash::Hasher { - fn extend>(&mut self, iter: I) { + fn extend>(&mut self, iter: I) { for k in iter { self.insert(k); } diff --git a/src/libstd/path.rs b/src/libstd/path.rs index 1d992668900..f25cc83b93e 100755 --- a/src/libstd/path.rs +++ b/src/libstd/path.rs @@ -110,7 +110,7 @@ use core::prelude::*; use ascii::*; use borrow::BorrowFrom; use cmp; -use iter; +use iter::{self, IntoIterator}; use mem; use ops::{self, Deref}; use string::CowString; @@ -961,7 +961,7 @@ impl<'a, P: ?Sized + 'a> iter::FromIterator<&'a P> for PathBuf where P: AsPath { } impl<'a, P: ?Sized + 'a> iter::Extend<&'a P> for PathBuf where P: AsPath { - fn extend>(&mut self, iter: I) { + fn extend>(&mut self, iter: I) { for p in iter { self.push(p) } diff --git a/src/libstd/sys/common/wtf8.rs b/src/libstd/sys/common/wtf8.rs index b610f6c370b..e7cb67c6287 100644 --- a/src/libstd/sys/common/wtf8.rs +++ b/src/libstd/sys/common/wtf8.rs @@ -32,7 +32,7 @@ use borrow::Cow; use cmp; use fmt; use hash::{Hash, Writer, Hasher}; -use iter::FromIterator; +use iter::{FromIterator, IntoIterator}; use mem; use num::Int; use ops; @@ -368,7 +368,8 @@ impl FromIterator for Wtf8Buf { /// This replaces surrogate code point pairs with supplementary code points, /// like concatenating ill-formed UTF-16 strings effectively would. impl Extend for Wtf8Buf { - fn extend>(&mut self, iterator: T) { + fn extend>(&mut self, iterable: T) { + let iterator = iterable.into_iter(); let (low, _high) = iterator.size_hint(); // Lower bound of one byte per code point (ASCII only) self.bytes.reserve(low); diff --git a/src/libsyntax/util/small_vector.rs b/src/libsyntax/util/small_vector.rs index b2009a7e848..6a1fb4008ad 100644 --- a/src/libsyntax/util/small_vector.rs +++ b/src/libsyntax/util/small_vector.rs @@ -11,7 +11,7 @@ use self::SmallVectorRepr::*; use self::IntoIterRepr::*; -use std::iter::FromIterator; +use std::iter::{IntoIterator, FromIterator}; use std::mem; use std::slice; use std::vec; @@ -38,7 +38,7 @@ impl FromIterator for SmallVector { } impl Extend for SmallVector { - fn extend>(&mut self, iter: I) { + fn extend>(&mut self, iter: I) { for val in iter { self.push(val); } -- cgit 1.4.1-3-g733a5 From 66613e26b95438c02e2f5c273c557515454121f7 Mon Sep 17 00:00:00 2001 From: Alexis Date: Wed, 18 Feb 2015 13:06:21 -0500 Subject: make FromIterator use IntoIterator This breaks all implementors of FromIterator, as they must now accept IntoIterator instead of Iterator. The fix for this is generally trivial (change the bound, and maybe call into_iter() on the argument to get the old argument). Users of FromIterator should be unaffected because Iterators are IntoIterator. [breaking-change] --- src/libcollections/binary_heap.rs | 4 ++-- src/libcollections/bit.rs | 12 ++++++------ src/libcollections/btree/map.rs | 2 +- src/libcollections/btree/set.rs | 2 +- src/libcollections/enum_set.rs | 4 ++-- src/libcollections/linked_list.rs | 6 +++--- src/libcollections/string.rs | 8 ++++---- src/libcollections/vec.rs | 5 +++-- src/libcollections/vec_deque.rs | 3 ++- src/libcollections/vec_map.rs | 2 +- src/libcore/iter.rs | 4 ++-- src/libcore/option.rs | 6 +++--- src/libcore/result.rs | 7 ++++--- src/librustc/middle/check_match.rs | 6 +++--- src/libstd/collections/hash/map.rs | 3 ++- src/libstd/collections/hash/set.rs | 3 ++- src/libstd/path.rs | 2 +- src/libstd/sys/common/wtf8.rs | 4 ++-- src/libsyntax/owned_slice.rs | 6 +++--- src/libsyntax/util/small_vector.rs | 2 +- 20 files changed, 48 insertions(+), 43 deletions(-) (limited to 'src/libstd/sys/common') diff --git a/src/libcollections/binary_heap.rs b/src/libcollections/binary_heap.rs index 2f994e94ccc..9f549fd7237 100644 --- a/src/libcollections/binary_heap.rs +++ b/src/libcollections/binary_heap.rs @@ -650,8 +650,8 @@ impl<'a, T: 'a> ExactSizeIterator for Drain<'a, T> {} #[stable(feature = "rust1", since = "1.0.0")] impl FromIterator for BinaryHeap { - fn from_iter>(iter: Iter) -> BinaryHeap { - BinaryHeap::from_vec(iter.collect()) + fn from_iter>(iter: I) -> BinaryHeap { + BinaryHeap::from_vec(iter.into_iter().collect()) } } diff --git a/src/libcollections/bit.rs b/src/libcollections/bit.rs index c1d79d82043..f4b65aab38b 100644 --- a/src/libcollections/bit.rs +++ b/src/libcollections/bit.rs @@ -924,9 +924,9 @@ impl Default for BitVec { #[stable(feature = "rust1", since = "1.0.0")] impl FromIterator for BitVec { - fn from_iter>(iterator: I) -> BitVec { - let mut ret = BitVec::new(); - ret.extend(iterator); + fn from_iter>(iter: I) -> BitVec { + let mut ret = Bitv::new(); + ret.extend(iter); ret } } @@ -1134,9 +1134,9 @@ impl Default for BitSet { #[stable(feature = "rust1", since = "1.0.0")] impl FromIterator for BitSet { - fn from_iter>(iterator: I) -> BitSet { - let mut ret = BitSet::new(); - ret.extend(iterator); + fn from_iter>(iter: I) -> BitSet { + let mut ret = BitvSet::new(); + ret.extend(iter); ret } } diff --git a/src/libcollections/btree/map.rs b/src/libcollections/btree/map.rs index 9273d50db85..262084d5a91 100644 --- a/src/libcollections/btree/map.rs +++ b/src/libcollections/btree/map.rs @@ -826,7 +826,7 @@ mod stack { #[stable(feature = "rust1", since = "1.0.0")] impl FromIterator<(K, V)> for BTreeMap { - fn from_iter>(iter: T) -> BTreeMap { + fn from_iter>(iter: T) -> BTreeMap { let mut map = BTreeMap::new(); map.extend(iter); map diff --git a/src/libcollections/btree/set.rs b/src/libcollections/btree/set.rs index d2241a67464..61497186623 100644 --- a/src/libcollections/btree/set.rs +++ b/src/libcollections/btree/set.rs @@ -473,7 +473,7 @@ impl BTreeSet { #[stable(feature = "rust1", since = "1.0.0")] impl FromIterator for BTreeSet { - fn from_iter>(iter: Iter) -> BTreeSet { + fn from_iter>(iter: I) -> BTreeSet { let mut set = BTreeSet::new(); set.extend(iter); set diff --git a/src/libcollections/enum_set.rs b/src/libcollections/enum_set.rs index 3f8c0121faf..140c9edb5a3 100644 --- a/src/libcollections/enum_set.rs +++ b/src/libcollections/enum_set.rs @@ -250,9 +250,9 @@ impl Iterator for Iter { } impl FromIterator for EnumSet { - fn from_iter>(iterator: I) -> EnumSet { + fn from_iter>(iter: I) -> EnumSet { let mut ret = EnumSet::new(); - ret.extend(iterator); + ret.extend(iter); ret } } diff --git a/src/libcollections/linked_list.rs b/src/libcollections/linked_list.rs index 0ec1371c73c..bd8f508b70f 100644 --- a/src/libcollections/linked_list.rs +++ b/src/libcollections/linked_list.rs @@ -834,9 +834,9 @@ impl DoubleEndedIterator for IntoIter { #[stable(feature = "rust1", since = "1.0.0")] impl FromIterator for LinkedList { - fn from_iter>(iterator: T) -> LinkedList { - let mut ret = LinkedList::new(); - ret.extend(iterator); + fn from_iter>(iter: T) -> LinkedList { + let mut ret = DList::new(); + ret.extend(iter); ret } } diff --git a/src/libcollections/string.rs b/src/libcollections/string.rs index dc1158ecaf8..627c357d8b3 100644 --- a/src/libcollections/string.rs +++ b/src/libcollections/string.rs @@ -709,18 +709,18 @@ impl Error for FromUtf16Error { #[stable(feature = "rust1", since = "1.0.0")] impl FromIterator for String { - fn from_iter>(iterator: I) -> String { + fn from_iter>(iter: I) -> String { let mut buf = String::new(); - buf.extend(iterator); + buf.extend(iter); buf } } #[stable(feature = "rust1", since = "1.0.0")] impl<'a> FromIterator<&'a str> for String { - fn from_iter>(iterator: I) -> String { + fn from_iter>(iter: I) -> String { let mut buf = String::new(); - buf.extend(iterator); + buf.extend(iter); buf } } diff --git a/src/libcollections/vec.rs b/src/libcollections/vec.rs index e4b090e4dd7..dd10a7582fb 100644 --- a/src/libcollections/vec.rs +++ b/src/libcollections/vec.rs @@ -1407,7 +1407,8 @@ impl ops::DerefMut for Vec { #[stable(feature = "rust1", since = "1.0.0")] impl FromIterator for Vec { #[inline] - fn from_iter>(mut iterator: I) -> Vec { + fn from_iter>(iterable: I) -> Vec { + let mut iterator = iterable.into_iter(); let (lower, _) = iterator.size_hint(); let mut vector = Vec::with_capacity(lower); @@ -1651,7 +1652,7 @@ pub type CowVec<'a, T> = Cow<'a, Vec, [T]>; #[unstable(feature = "collections")] impl<'a, T> FromIterator for CowVec<'a, T> where T: Clone { - fn from_iter>(it: I) -> CowVec<'a, T> { + fn from_iter>(it: I) -> CowVec<'a, T> { Cow::Owned(FromIterator::from_iter(it)) } } diff --git a/src/libcollections/vec_deque.rs b/src/libcollections/vec_deque.rs index cc01e800f60..c281d5de027 100644 --- a/src/libcollections/vec_deque.rs +++ b/src/libcollections/vec_deque.rs @@ -1701,7 +1701,8 @@ impl IndexMut for VecDeque { #[stable(feature = "rust1", since = "1.0.0")] impl FromIterator for VecDeque { - fn from_iter>(iterator: T) -> VecDeque { + fn from_iter>(iterable: T) -> VecDeque { + let iterator = iterable.into_iter(); let (lower, _) = iterator.size_hint(); let mut deq = VecDeque::with_capacity(lower); deq.extend(iterator); diff --git a/src/libcollections/vec_map.rs b/src/libcollections/vec_map.rs index 7085111d6a8..4431bfddbd7 100644 --- a/src/libcollections/vec_map.rs +++ b/src/libcollections/vec_map.rs @@ -661,7 +661,7 @@ impl fmt::Debug for VecMap { #[stable(feature = "rust1", since = "1.0.0")] impl FromIterator<(usize, V)> for VecMap { - fn from_iter>(iter: Iter) -> VecMap { + fn from_iter>(iter: I) -> VecMap { let mut map = VecMap::new(); map.extend(iter); map diff --git a/src/libcore/iter.rs b/src/libcore/iter.rs index 2e9977cd3eb..355bf3a28cb 100644 --- a/src/libcore/iter.rs +++ b/src/libcore/iter.rs @@ -113,9 +113,9 @@ impl<'a, I: Iterator + ?Sized> Iterator for &'a mut I { #[rustc_on_unimplemented="a collection of type `{Self}` cannot be \ built from an iterator over elements of type `{A}`"] pub trait FromIterator { - /// Build a container with elements from an external iterator. + /// Build a container with elements from something iterable. #[stable(feature = "rust1", since = "1.0.0")] - fn from_iter>(iterator: T) -> Self; + fn from_iter>(iterator: T) -> Self; } /// Conversion into an `Iterator` diff --git a/src/libcore/option.rs b/src/libcore/option.rs index 9a89682127f..abfef72a5db 100644 --- a/src/libcore/option.rs +++ b/src/libcore/option.rs @@ -149,7 +149,7 @@ use clone::Clone; use cmp::{Eq, Ord}; use default::Default; use iter::{ExactSizeIterator}; -use iter::{Iterator, IteratorExt, DoubleEndedIterator, FromIterator}; +use iter::{Iterator, IteratorExt, DoubleEndedIterator, FromIterator, IntoIterator}; use mem; use ops::{Deref, FnOnce}; use result::Result::{Ok, Err}; @@ -909,7 +909,7 @@ impl> FromIterator> for Option { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - fn from_iter>>(iter: I) -> Option { + fn from_iter>>(iter: I) -> Option { // FIXME(#11084): This could be replaced with Iterator::scan when this // performance bug is closed. @@ -934,7 +934,7 @@ impl> FromIterator> for Option { } } - let mut adapter = Adapter { iter: iter, found_none: false }; + let mut adapter = Adapter { iter: iter.into_iter(), found_none: false }; let v: V = FromIterator::from_iter(adapter.by_ref()); if adapter.found_none { diff --git a/src/libcore/result.rs b/src/libcore/result.rs index 1a874ee178b..23e936a75d7 100644 --- a/src/libcore/result.rs +++ b/src/libcore/result.rs @@ -230,7 +230,8 @@ use self::Result::{Ok, Err}; use clone::Clone; use fmt; -use iter::{Iterator, IteratorExt, DoubleEndedIterator, FromIterator, ExactSizeIterator}; +use iter::{Iterator, IteratorExt, DoubleEndedIterator, + FromIterator, ExactSizeIterator, IntoIterator}; use ops::{FnMut, FnOnce}; use option::Option::{self, None, Some}; use slice::AsSlice; @@ -906,7 +907,7 @@ impl> FromIterator> for Result { /// assert!(res == Ok(vec!(2, 3))); /// ``` #[inline] - fn from_iter>>(iter: I) -> Result { + fn from_iter>>(iter: I) -> Result { // FIXME(#11084): This could be replaced with Iterator::scan when this // performance bug is closed. @@ -931,7 +932,7 @@ impl> FromIterator> for Result { } } - let mut adapter = Adapter { iter: iter, err: None }; + let mut adapter = Adapter { iter: iter.into_iter(), err: None }; let v: V = FromIterator::from_iter(adapter.by_ref()); match adapter.err { diff --git a/src/librustc/middle/check_match.rs b/src/librustc/middle/check_match.rs index 03456f85290..3b29c43ce8c 100644 --- a/src/librustc/middle/check_match.rs +++ b/src/librustc/middle/check_match.rs @@ -25,7 +25,7 @@ use middle::ty::*; use middle::ty; use std::cmp::Ordering; use std::fmt; -use std::iter::{range_inclusive, AdditiveIterator, FromIterator, repeat}; +use std::iter::{range_inclusive, AdditiveIterator, FromIterator, IntoIterator, repeat}; use std::num::Float; use std::slice; use syntax::ast::{self, DUMMY_NODE_ID, NodeId, Pat}; @@ -94,8 +94,8 @@ impl<'a> fmt::Debug for Matrix<'a> { } impl<'a> FromIterator> for Matrix<'a> { - fn from_iter>>(iterator: T) -> Matrix<'a> { - Matrix(iterator.collect()) + fn from_iter>>(iter: T) -> Matrix<'a> { + Matrix(iter.into_iter().collect()) } } diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs index 61b531054a0..0ce5b164ca1 100644 --- a/src/libstd/collections/hash/map.rs +++ b/src/libstd/collections/hash/map.rs @@ -1555,7 +1555,8 @@ impl FromIterator<(K, V)> for HashMap S: HashState + Default, H: hash::Hasher { - fn from_iter>(iter: T) -> HashMap { + fn from_iter>(iterable: T) -> HashMap { + let iter = iterable.into_iter(); let lower = iter.size_hint().0; let mut map = HashMap::with_capacity_and_hash_state(lower, Default::default()); diff --git a/src/libstd/collections/hash/set.rs b/src/libstd/collections/hash/set.rs index f5e57b78d2a..593248fd5c6 100644 --- a/src/libstd/collections/hash/set.rs +++ b/src/libstd/collections/hash/set.rs @@ -622,7 +622,8 @@ impl FromIterator for HashSet S: HashState + Default, H: hash::Hasher { - fn from_iter>(iter: I) -> HashSet { + fn from_iter>(iterable: I) -> HashSet { + let iter = iterable.into_iter(); let lower = iter.size_hint().0; let mut set = HashSet::with_capacity_and_hash_state(lower, Default::default()); set.extend(iter); diff --git a/src/libstd/path.rs b/src/libstd/path.rs index f25cc83b93e..2ad07462f20 100755 --- a/src/libstd/path.rs +++ b/src/libstd/path.rs @@ -953,7 +953,7 @@ impl PathBuf { } impl<'a, P: ?Sized + 'a> iter::FromIterator<&'a P> for PathBuf where P: AsPath { - fn from_iter>(iter: I) -> PathBuf { + fn from_iter>(iter: I) -> PathBuf { let mut buf = PathBuf::new(""); buf.extend(iter); buf diff --git a/src/libstd/sys/common/wtf8.rs b/src/libstd/sys/common/wtf8.rs index e7cb67c6287..da5ab8e434a 100644 --- a/src/libstd/sys/common/wtf8.rs +++ b/src/libstd/sys/common/wtf8.rs @@ -356,9 +356,9 @@ impl Wtf8Buf { /// This replaces surrogate code point pairs with supplementary code points, /// like concatenating ill-formed UTF-16 strings effectively would. impl FromIterator for Wtf8Buf { - fn from_iter>(iterator: T) -> Wtf8Buf { + fn from_iter>(iter: T) -> Wtf8Buf { let mut string = Wtf8Buf::new(); - string.extend(iterator); + string.extend(iter); string } } diff --git a/src/libsyntax/owned_slice.rs b/src/libsyntax/owned_slice.rs index 0f9a56baa17..f5201d4a8bc 100644 --- a/src/libsyntax/owned_slice.rs +++ b/src/libsyntax/owned_slice.rs @@ -10,7 +10,7 @@ use std::default::Default; use std::fmt; -use std::iter::FromIterator; +use std::iter::{IntoIterator, FromIterator}; use std::ops::Deref; use std::vec; use serialize::{Encodable, Decodable, Encoder, Decoder}; @@ -77,8 +77,8 @@ impl Clone for OwnedSlice { } impl FromIterator for OwnedSlice { - fn from_iter>(iter: I) -> OwnedSlice { - OwnedSlice::from_vec(iter.collect()) + fn from_iter>(iter: I) -> OwnedSlice { + OwnedSlice::from_vec(iter.into_iter().collect()) } } diff --git a/src/libsyntax/util/small_vector.rs b/src/libsyntax/util/small_vector.rs index 6a1fb4008ad..0a39d380904 100644 --- a/src/libsyntax/util/small_vector.rs +++ b/src/libsyntax/util/small_vector.rs @@ -30,7 +30,7 @@ enum SmallVectorRepr { } impl FromIterator for SmallVector { - fn from_iter>(iter: I) -> SmallVector { + fn from_iter>(iter: I) -> SmallVector { let mut v = SmallVector::zero(); v.extend(iter); v -- cgit 1.4.1-3-g733a5 From 1860ee521aa6096eb7f5410a64b53311fb0d2d0e Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 17 Feb 2015 22:47:40 -0800 Subject: std: Implement CString-related RFCs This commit is an implementation of [RFC 592][r592] and [RFC 840][r840]. These two RFCs tweak the behavior of `CString` and add a new `CStr` unsized slice type to the module. [r592]: https://github.com/rust-lang/rfcs/blob/master/text/0592-c-str-deref.md [r840]: https://github.com/rust-lang/rfcs/blob/master/text/0840-no-panic-in-c-string.md The new `CStr` type is only constructable via two methods: 1. By `deref`'ing from a `CString` 2. Unsafely via `CStr::from_ptr` The purpose of `CStr` is to be an unsized type which is a thin pointer to a `libc::c_char` (currently it is a fat pointer slice due to implementation limitations). Strings from C can be safely represented with a `CStr` and an appropriate lifetime as well. Consumers of `&CString` should now consume `&CStr` instead to allow producers to pass in C-originating strings instead of just Rust-allocated strings. A new constructor was added to `CString`, `new`, which takes `T: IntoBytes` instead of separate `from_slice` and `from_vec` methods (both have been deprecated in favor of `new`). The `new` method returns a `Result` instead of panicking. The error variant contains the relevant information about where the error happened and bytes (if present). Conversions are provided to the `io::Error` and `old_io::IoError` types via the `FromError` trait which translate to `InvalidInput`. This is a breaking change due to the modification of existing `#[unstable]` APIs and new deprecation, and more detailed information can be found in the two RFCs. Notable breakage includes: * All construction of `CString` now needs to use `new` and handle the outgoing `Result`. * Usage of `CString` as a byte slice now explicitly needs a `.as_bytes()` call. * The `as_slice*` methods have been removed in favor of just having the `as_bytes*` methods. Closes #22469 Closes #22470 [breaking-change] --- src/doc/trpl/ffi.md | 4 +- src/librustc/metadata/loader.rs | 2 +- src/librustc_llvm/archive_ro.rs | 4 +- src/librustc_llvm/lib.rs | 2 +- src/librustc_trans/back/lto.rs | 2 +- src/librustc_trans/back/write.rs | 28 +- src/librustc_trans/trans/asm.rs | 4 +- src/librustc_trans/trans/base.rs | 22 +- src/librustc_trans/trans/builder.rs | 4 +- src/librustc_trans/trans/common.rs | 7 +- src/librustc_trans/trans/context.rs | 10 +- src/librustc_trans/trans/debuginfo.rs | 50 ++-- src/librustc_trans/trans/foreign.rs | 6 +- src/librustc_trans/trans/glue.rs | 2 +- src/librustc_trans/trans/type_.rs | 2 +- src/librustdoc/flock.rs | 2 +- src/librustdoc/html/markdown.rs | 4 +- src/libstd/dynamic_lib.rs | 8 +- src/libstd/ffi/c_str.rs | 402 ++++++++++++++++++++++----- src/libstd/ffi/mod.rs | 4 +- src/libstd/old_io/net/pipe.rs | 6 +- src/libstd/old_io/process.rs | 26 +- src/libstd/rt/args.rs | 9 +- src/libstd/sys/common/net.rs | 17 +- src/libstd/sys/common/net2.rs | 2 +- src/libstd/sys/unix/backtrace.rs | 6 +- src/libstd/sys/unix/ext.rs | 12 +- src/libstd/sys/unix/fs.rs | 42 +-- src/libstd/sys/unix/fs2.rs | 44 +-- src/libstd/sys/unix/mod.rs | 5 +- src/libstd/sys/unix/net.rs | 4 +- src/libstd/sys/unix/os.rs | 28 +- src/libstd/sys/unix/pipe.rs | 6 +- src/libstd/sys/unix/process2.rs | 8 +- src/libstd/sys/unix/thread.rs | 6 +- src/libsyntax/diagnostic.rs | 35 +-- src/test/run-pass/c-stack-returning-int64.rs | 4 +- src/test/run-pass/foreign-fn-linkname.rs | 2 +- src/test/run-pass/rename-directory.rs | 6 +- src/test/run-pass/variadic-ffi.rs | 8 +- 40 files changed, 555 insertions(+), 290 deletions(-) (limited to 'src/libstd/sys/common') diff --git a/src/doc/trpl/ffi.md b/src/doc/trpl/ffi.md index f2b95f19edc..60750160f5f 100644 --- a/src/doc/trpl/ffi.md +++ b/src/doc/trpl/ffi.md @@ -435,8 +435,8 @@ extern { } 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); diff --git a/src/librustc/metadata/loader.rs b/src/librustc/metadata/loader.rs index 3158ccd0765..89f19b6c47c 100644 --- a/src/librustc/metadata/loader.rs +++ b/src/librustc/metadata/loader.rs @@ -744,7 +744,7 @@ fn get_metadata_section_imp(is_osx: bool, filename: &Path) -> Result Option { 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 @@ -44,7 +44,7 @@ impl ArchiveRO { 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() { diff --git a/src/librustc_llvm/lib.rs b/src/librustc_llvm/lib.rs index aa90d7c851b..c3fe23eff46 100644 --- a/src/librustc_llvm/lib.rs +++ b/src/librustc_llvm/lib.rs @@ -2149,7 +2149,7 @@ impl Drop for TargetData { } 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()) } } diff --git a/src/librustc_trans/back/lto.rs b/src/librustc_trans/back/lto.rs index c88e76f4270..9d604695cf7 100644 --- a/src/librustc_trans/back/lto.rs +++ b/src/librustc_trans/back/lto.rs @@ -140,7 +140,7 @@ pub fn run(sess: &session::Session, llmod: ModuleRef, // Internalize everything but the reachable symbols of the current module let cstrs: Vec = 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(); diff --git a/src/librustc_trans/back/write.rs b/src/librustc_trans/back/write.rs index 9934d9993d6..20cd1624a8c 100644 --- a/src/librustc_trans/back/write.rs +++ b/src/librustc_trans/back/write.rs @@ -22,7 +22,7 @@ use syntax::codemap; 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; @@ -49,7 +49,7 @@ pub fn llvm_err(handler: &diagnostic::Handler, msg: String) -> ! { 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!("{}: {}", @@ -67,7 +67,7 @@ pub fn write_output_file( 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 { @@ -221,13 +221,13 @@ fn create_target_machine(sess: &Session) -> TargetMachineRef { 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, @@ -380,7 +380,7 @@ unsafe extern "C" fn diagnostic_handler(info: DiagnosticInfoRef, user: *mut c_vo } 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 { @@ -424,7 +424,7 @@ unsafe fn optimize_and_codegen(cgcx: &CodegenContext, 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()); } @@ -440,7 +440,7 @@ unsafe fn optimize_and_codegen(cgcx: &CodegenContext, // 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")); } @@ -453,7 +453,7 @@ unsafe fn optimize_and_codegen(cgcx: &CodegenContext, } 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)); } @@ -477,7 +477,7 @@ unsafe fn optimize_and_codegen(cgcx: &CodegenContext, 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()); } }, @@ -511,7 +511,7 @@ unsafe fn optimize_and_codegen(cgcx: &CodegenContext, 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()); } @@ -519,7 +519,7 @@ unsafe fn optimize_and_codegen(cgcx: &CodegenContext, 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()); }) @@ -1004,7 +1004,7 @@ unsafe fn configure_llvm(sess: &Session) { 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); }; diff --git a/src/librustc_trans/trans/asm.rs b/src/librustc_trans/trans/asm.rs index e419be65fc4..53c21d04a92 100644 --- a/src/librustc_trans/trans/asm.rs +++ b/src/librustc_trans/trans/asm.rs @@ -120,8 +120,8 @@ pub fn trans_inline_asm<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, ia: &ast::InlineAsm) 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(), diff --git a/src/librustc_trans/trans/base.rs b/src/librustc_trans/trans/base.rs index 7f7b5cd8006..e136f61ce1c 100644 --- a/src/librustc_trans/trans/base.rs +++ b/src/librustc_trans/trans/base.rs @@ -86,7 +86,7 @@ use util::nodemap::NodeMap; 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; @@ -186,7 +186,7 @@ impl<'a, 'tcx> Drop for StatRecorder<'a, 'tcx> { 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()) }; @@ -340,7 +340,7 @@ pub fn get_extern_const<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, did: ast::DefId, 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 @@ -2788,7 +2788,7 @@ pub fn get_item_val(ccx: &CrateContext, id: ast::NodeId) -> ValueRef { &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()); @@ -2826,7 +2826,7 @@ pub fn get_item_val(ccx: &CrateContext, id: ast::NodeId) -> ValueRef { §)[]); } unsafe { - let buf = CString::from_slice(sect.as_bytes()); + let buf = CString::new(sect.as_bytes()).unwrap(); llvm::LLVMSetSection(v, buf.as_ptr()); } }, @@ -2993,7 +2993,7 @@ pub fn write_metadata(cx: &SharedCrateContext, krate: &ast::Crate) -> Vec { 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()) @@ -3001,7 +3001,7 @@ pub fn write_metadata(cx: &SharedCrateContext, krate: &ast::Crate) -> Vec { 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; @@ -3039,8 +3039,8 @@ fn internalize_symbols(cx: &SharedCrateContext, reachable: &HashSet) { 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); } } @@ -3056,8 +3056,8 @@ fn internalize_symbols(cx: &SharedCrateContext, reachable: &HashSet) { 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); diff --git a/src/librustc_trans/trans/builder.rs b/src/librustc_trans/trans/builder.rs index e268c2f0d5c..3bd0479c0d8 100644 --- a/src/librustc_trans/trans/builder.rs +++ b/src/librustc_trans/trans/builder.rs @@ -431,7 +431,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { 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()) } @@ -786,7 +786,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { 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, diff --git a/src/librustc_trans/trans/common.rs b/src/librustc_trans/trans/common.rs index d658003702d..85ba3f938fd 100644 --- a/src/librustc_trans/trans/common.rs +++ b/src/librustc_trans/trans/common.rs @@ -488,7 +488,7 @@ impl<'a, 'tcx> FunctionContext<'a, 'tcx> { opt_node_id: Option) -> 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()); @@ -761,7 +761,7 @@ pub fn C_integral(t: Type, u: u64, sign_extend: bool) -> ValueRef { 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()) } } @@ -839,7 +839,8 @@ pub fn C_cstr(cx: &CrateContext, s: InternedString, null_terminated: bool) -> Va !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); diff --git a/src/librustc_trans/trans/context.rs b/src/librustc_trans/trans/context.rs index 96506291b5a..cd5aed6d846 100644 --- a/src/librustc_trans/trans/context.rs +++ b/src/librustc_trans/trans/context.rs @@ -225,15 +225,15 @@ impl<'a, 'tcx> Iterator for CrateContextMaybeIterator<'a, 'tcx> { 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) } diff --git a/src/librustc_trans/trans/debuginfo.rs b/src/librustc_trans/trans/debuginfo.rs index 23498089c58..653ad1b2b63 100644 --- a/src/librustc_trans/trans/debuginfo.rs +++ b/src/librustc_trans/trans/debuginfo.rs @@ -809,8 +809,8 @@ pub fn create_global_var_metadata(cx: &CrateContext, 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, @@ -1379,8 +1379,8 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, 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), @@ -1501,7 +1501,7 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, 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), @@ -1535,7 +1535,7 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, 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), @@ -1601,7 +1601,7 @@ fn compile_unit_metadata(cx: &CrateContext) -> DIDescriptor { path_bytes.insert(1, prefix[1]); } - CString::from_vec(path_bytes) + CString::new(path_bytes).unwrap() } _ => fallback_path(cx) } @@ -1614,8 +1614,8 @@ fn compile_unit_metadata(cx: &CrateContext) -> DIDescriptor { (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 { @@ -1632,7 +1632,7 @@ fn compile_unit_metadata(cx: &CrateContext) -> DIDescriptor { }; 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() } } @@ -1658,7 +1658,7 @@ fn declare_local<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, 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}, _) => { @@ -1724,8 +1724,8 @@ fn file_metadata(cx: &CrateContext, full_path: &str) -> DIFile { 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()) @@ -1800,7 +1800,7 @@ fn basic_type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, 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), @@ -1820,7 +1820,7 @@ fn pointer_type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, 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), @@ -2445,7 +2445,7 @@ fn prepare_enum_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, .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), @@ -2475,7 +2475,7 @@ fn prepare_enum_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, 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), @@ -2518,8 +2518,8 @@ fn prepare_enum_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, .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), @@ -2644,7 +2644,8 @@ fn set_members_of_composite_type(cx: &CrateContext, 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), @@ -2681,8 +2682,8 @@ fn create_struct_stub(cx: &CrateContext, 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 @@ -3971,8 +3972,7 @@ fn namespace_for_item(cx: &CrateContext, def_id: ast::DefId) -> Rc 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), @@ -4020,7 +4020,7 @@ fn namespace_for_item(cx: &CrateContext, def_id: ast::DefId) -> Rc 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()) } } diff --git a/src/librustc_trans/trans/glue.rs b/src/librustc_trans/trans/glue.rs index af90e1ec5c5..9e6867d4829 100644 --- a/src/librustc_trans/trans/glue.rs +++ b/src/librustc_trans/trans/glue.rs @@ -513,7 +513,7 @@ pub fn declare_tydesc<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) 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()) diff --git a/src/librustc_trans/trans/type_.rs b/src/librustc_trans/trans/type_.rs index e3e4ca62c26..ad83135a0d4 100644 --- a/src/librustc_trans/trans/type_.rs +++ b/src/librustc_trans/trans/type_.rs @@ -163,7 +163,7 @@ impl Type { } 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())) } diff --git a/src/librustdoc/flock.rs b/src/librustdoc/flock.rs index a7cf5eb8918..eba915af519 100644 --- a/src/librustdoc/flock.rs +++ b/src/librustdoc/flock.rs @@ -112,7 +112,7 @@ mod imp { 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) diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index c513fe2e8eb..3ceaec5f53d 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -236,7 +236,7 @@ pub fn render(w: &mut fmt::Formatter, s: &str, print_toc: bool) -> fmt::Result { 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()); }) } @@ -293,7 +293,7 @@ pub fn render(w: &mut fmt::Formatter, s: &str, print_toc: bool) -> fmt::Result { 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()) } } diff --git a/src/libstd/dynamic_lib.rs b/src/libstd/dynamic_lib.rs index c5dd66630b4..b0fb9c29403 100644 --- a/src/libstd/dynamic_lib.rs +++ b/src/libstd/dynamic_lib.rs @@ -112,7 +112,7 @@ impl DynamicLibrary { // 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()) }); @@ -187,7 +187,7 @@ mod test { mod dl { use prelude::v1::*; - use ffi::{self, CString}; + use ffi::{CString, CStr}; use str; use libc; use ptr; @@ -206,7 +206,7 @@ mod dl { 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 } @@ -231,7 +231,7 @@ mod dl { 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()) }; diff --git a/src/libstd/ffi/c_str.rs b/src/libstd/ffi/c_str.rs index 45089176cba..70c14ef1978 100644 --- a/src/libstd/ffi/c_str.rs +++ b/src/libstd/ffi/c_str.rs @@ -8,18 +8,25 @@ // 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. @@ -44,8 +51,8 @@ use vec::Vec; /// 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()); /// } @@ -53,19 +60,135 @@ use vec::Vec; /// ``` #[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] pub struct CString { - inner: Vec, + inner: Vec, +} + +/// 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); + +/// 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; } 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: T) -> Result { + 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()) } @@ -77,11 +200,15 @@ impl CString { /// /// # 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) -> 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 @@ -91,31 +218,29 @@ impl CString { /// is made that `v` contains no 0 bytes. pub unsafe fn from_vec_unchecked(mut v: Vec) -> 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()) } } } @@ -126,54 +251,172 @@ impl fmt::Debug for CString { } } -/// 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 { 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 for io::Error { + fn from_error(_: NulError) -> io::Error { + io::Error::new(io::ErrorKind::InvalidInput, + "data provided contains a nul byte", None) + } +} + +impl FromError 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 { + 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 { self.as_bytes().to_vec() } +} +impl<'a> IntoBytes for &'a [u8] { + fn into_bytes(self) -> Vec { self.to_vec() } +} +impl IntoBytes for String { + fn into_bytes(self) -> Vec { self.into_bytes() } +} +impl IntoBytes for Vec { + fn into_bytes(self) -> Vec { self } +} + #[cfg(test)] mod tests { use prelude::v1::*; @@ -193,21 +436,19 @@ mod tests { #[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() { @@ -219,7 +460,16 @@ mod tests { #[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"); + } + } } diff --git a/src/libstd/ffi/mod.rs b/src/libstd/ffi/mod.rs index 07a4f17796c..1bff6afb776 100644 --- a/src/libstd/ffi/mod.rs +++ b/src/libstd/ffi/mod.rs @@ -14,8 +14,10 @@ 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; diff --git a/src/libstd/old_io/net/pipe.rs b/src/libstd/old_io/net/pipe.rs index 6b32d936c05..392a253d733 100644 --- a/src/libstd/old_io/net/pipe.rs +++ b/src/libstd/old_io/net/pipe.rs @@ -55,7 +55,7 @@ impl UnixStream { /// stream.write(&[1, 2, 3]); /// ``` pub fn connect(path: P) -> IoResult { - 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 }) } @@ -77,7 +77,7 @@ impl UnixStream { 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 }) } @@ -184,7 +184,7 @@ impl UnixListener { /// # } /// ``` pub fn bind(path: P) -> IoResult { - 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 }) } diff --git a/src/libstd/old_io/process.rs b/src/libstd/old_io/process.rs index ea6510c61b7..c761bf705a8 100644 --- a/src/libstd/old_io/process.rs +++ b/src/libstd/old_io/process.rs @@ -204,7 +204,7 @@ impl Command { /// otherwise configure the process. pub fn new(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, @@ -219,14 +219,14 @@ impl Command { /// 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 } @@ -239,8 +239,8 @@ impl Command { // 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() } @@ -254,8 +254,8 @@ impl Command { 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 } @@ -263,7 +263,7 @@ impl Command { /// 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 } @@ -276,15 +276,15 @@ impl Command { -> &'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 } @@ -1226,7 +1226,7 @@ mod tests { 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()); } } diff --git a/src/libstd/rt/args.rs b/src/libstd/rt/args.rs index c2f5133eaf3..61f5bd0f013 100644 --- a/src/libstd/rt/args.rs +++ b/src/libstd/rt/args.rs @@ -49,7 +49,7 @@ mod imp { use libc; use mem; - use ffi; + use ffi::CStr; use sync::{StaticMutex, MUTEX_INIT}; @@ -96,10 +96,11 @@ mod imp { unsafe { mem::transmute(&GLOBAL_ARGS_PTR) } } - unsafe fn load_argc_and_argv(argc: int, argv: *const *const u8) -> Vec> { + unsafe fn load_argc_and_argv(argc: isize, + argv: *const *const u8) -> Vec> { 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() } diff --git a/src/libstd/sys/common/net.rs b/src/libstd/sys/common/net.rs index 7325e0a5ac8..e2ac5ac24f8 100644 --- a/src/libstd/sys/common/net.rs +++ b/src/libstd/sys/common/net.rs @@ -12,8 +12,7 @@ use prelude::v1::*; 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}; @@ -235,9 +234,15 @@ pub fn get_host_addresses(host: Option<&str>, servname: Option<&str>, 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| { @@ -325,8 +330,8 @@ pub fn get_address_name(addr: IpAddr) -> Result { } 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()) } } diff --git a/src/libstd/sys/common/net2.rs b/src/libstd/sys/common/net2.rs index 5af59ec6d2b..713f79c5d08 100644 --- a/src/libstd/sys/common/net2.rs +++ b/src/libstd/sys/common/net2.rs @@ -121,7 +121,7 @@ impl Drop for LookupHost { pub fn lookup_host(host: &str) -> io::Result { 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 _, diff --git a/src/libstd/sys/unix/backtrace.rs b/src/libstd/sys/unix/backtrace.rs index 5e512e9261b..8b560339f30 100644 --- a/src/libstd/sys/unix/backtrace.rs +++ b/src/libstd/sys/unix/backtrace.rs @@ -85,7 +85,7 @@ use prelude::v1::*; -use ffi; +use ffi::CStr; use old_io::IoResult; use libc; use mem; @@ -233,7 +233,7 @@ fn print(w: &mut Writer, idx: int, addr: *mut libc::c_void) -> IoResult<()> { 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() })) } } @@ -364,7 +364,7 @@ fn print(w: &mut Writer, idx: int, addr: *mut libc::c_void) -> IoResult<()> { 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() })) } } diff --git a/src/libstd/sys/unix/ext.rs b/src/libstd/sys/unix/ext.rs index bbbe022fbaf..b8b9dcfb3c6 100644 --- a/src/libstd/sys/unix/ext.rs +++ b/src/libstd/sys/unix/ext.rs @@ -33,7 +33,7 @@ use prelude::v1::*; -use ffi::{CString, OsStr, OsString}; +use ffi::{CString, NulError, OsStr, OsString}; use fs::{self, Permissions, OpenOptions}; use net; use mem; @@ -155,7 +155,7 @@ pub trait OsStrExt { fn as_bytes(&self) -> &[u8]; /// Convert the `OsStr` slice into a `CString`. - fn to_cstring(&self) -> CString; + fn to_cstring(&self) -> Result; } impl OsStrExt for OsStr { @@ -166,8 +166,8 @@ 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::new(self.as_bytes()) } } @@ -249,5 +249,7 @@ impl ExitStatusExt for process::ExitStatus { /// 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}; } diff --git a/src/libstd/sys/unix/fs.rs b/src/libstd/sys/unix/fs.rs index 0ee2b5b6809..5c847002d23 100644 --- a/src/libstd/sys/unix/fs.rs +++ b/src/libstd/sys/unix/fs.rs @@ -12,7 +12,7 @@ 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}; @@ -151,8 +151,8 @@ impl Drop for FileDesc { } } -fn cstr(path: &Path) -> CString { - CString::from_slice(path.as_vec()) +fn cstr(path: &Path) -> IoResult { + Ok(try!(CString::new(path.as_vec()))) } pub fn open(path: &Path, fm: FileMode, fa: FileAccess) -> IoResult { @@ -170,7 +170,7 @@ pub fn open(path: &Path, fm: FileMode, fa: FileAccess) -> IoResult { 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)), @@ -178,7 +178,7 @@ pub fn open(path: &Path, fm: FileMode, fa: FileAccess) -> IoResult { } 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) }) } @@ -203,7 +203,7 @@ pub fn readdir(p: &Path) -> IoResult> { let mut buf = Vec::::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 { @@ -212,7 +212,7 @@ pub fn readdir(p: &Path) -> IoResult> { 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); @@ -223,39 +223,39 @@ pub fn readdir(p: &Path) -> IoResult> { } 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 { - 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 { @@ -276,14 +276,14 @@ pub fn readlink(p: &Path) -> IoResult { } 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()) }) } @@ -331,7 +331,7 @@ fn mkstat(stat: &libc::stat) -> FileStat { } pub fn stat(p: &Path) -> IoResult { - 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)), @@ -340,7 +340,7 @@ pub fn stat(p: &Path) -> IoResult { } pub fn lstat(p: &Path) -> IoResult { - 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)), @@ -349,7 +349,7 @@ pub fn lstat(p: &Path) -> IoResult { } 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, diff --git a/src/libstd/sys/unix/fs2.rs b/src/libstd/sys/unix/fs2.rs index e5904b074bc..92a47c6c385 100644 --- a/src/libstd/sys/unix/fs2.rs +++ b/src/libstd/sys/unix/fs2.rs @@ -12,7 +12,7 @@ use core::prelude::*; 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; @@ -147,8 +147,7 @@ impl DirEntry { 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() } } } @@ -204,7 +203,7 @@ impl File { (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) })); @@ -268,19 +267,20 @@ impl File { 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 { + 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 { 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() { @@ -292,32 +292,32 @@ pub fn readdir(p: &Path) -> io::Result { } 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) })); @@ -325,7 +325,7 @@ pub fn chown(p: &Path, uid: isize, gid: isize) -> io::Result<()> { } pub fn readlink(p: &Path) -> io::Result { - 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 { @@ -343,35 +343,35 @@ pub fn readlink(p: &Path) -> io::Result { } 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 { - 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 { - 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(()) diff --git a/src/libstd/sys/unix/mod.rs b/src/libstd/sys/unix/mod.rs index 850189140d1..b79ad7031fa 100644 --- a/src/libstd/sys/unix/mod.rs +++ b/src/libstd/sys/unix/mod.rs @@ -17,7 +17,7 @@ use prelude::v1::*; -use ffi; +use ffi::CStr; use io::{self, ErrorKind}; use libc; use num::{Int, SignedInt}; @@ -91,7 +91,8 @@ pub fn last_gai_error(s: libc::c_int) -> IoError { 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 } diff --git a/src/libstd/sys/unix/net.rs b/src/libstd/sys/unix/net.rs index 54aec7cf4b1..83b6a14b78d 100644 --- a/src/libstd/sys/unix/net.rs +++ b/src/libstd/sys/unix/net.rs @@ -10,7 +10,7 @@ use prelude::v1::*; -use ffi; +use ffi::CStr; use io; use libc::{self, c_int, size_t}; use str; @@ -31,7 +31,7 @@ pub fn cvt_gai(err: c_int) -> io::Result<()> { 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, diff --git a/src/libstd/sys/unix/os.rs b/src/libstd/sys/unix/os.rs index df03841276e..ad56555997f 100644 --- a/src/libstd/sys/unix/os.rs +++ b/src/libstd/sys/unix/os.rs @@ -14,7 +14,7 @@ use prelude::v1::*; 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}; @@ -88,7 +88,7 @@ pub fn error_string(errno: i32) -> String { } 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() } } @@ -98,13 +98,13 @@ pub fn getcwd() -> IoResult { 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(()), @@ -211,7 +211,7 @@ pub fn current_exe() -> IoResult { 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())) } } } @@ -266,7 +266,7 @@ pub fn args() -> Args { 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::>() }; @@ -324,7 +324,7 @@ pub fn args() -> Args { 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())) } } @@ -380,7 +380,7 @@ pub fn env() -> Env { } 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 _ } @@ -397,20 +397,20 @@ pub fn env() -> Env { pub fn getenv(k: &OsStr) -> Option { 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()); } @@ -419,7 +419,7 @@ pub fn setenv(k: &OsStr, v: &OsStr) { 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()); } @@ -480,7 +480,7 @@ pub fn home_dir() -> Option { _ => 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)) } } diff --git a/src/libstd/sys/unix/pipe.rs b/src/libstd/sys/unix/pipe.rs index 45d5b1506c3..3c9cdc65975 100644 --- a/src/libstd/sys/unix/pipe.rs +++ b/src/libstd/sys/unix/pipe.rs @@ -38,7 +38,7 @@ fn addr_to_sockaddr_un(addr: &CString, mem::size_of::()); 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, @@ -47,8 +47,8 @@ fn addr_to_sockaddr_un(addr: &CString, }) } 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 diff --git a/src/libstd/sys/unix/process2.rs b/src/libstd/sys/unix/process2.rs index 5e2c207f375..0e78efa2096 100644 --- a/src/libstd/sys/unix/process2.rs +++ b/src/libstd/sys/unix/process2.rs @@ -46,7 +46,7 @@ pub struct Command { 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, @@ -57,10 +57,10 @@ impl Command { } 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>(&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() { @@ -79,7 +79,7 @@ impl Command { 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()) } } diff --git a/src/libstd/sys/unix/thread.rs b/src/libstd/sys/unix/thread.rs index 82c52471d10..c90ba7645fe 100644 --- a/src/libstd/sys/unix/thread.rs +++ b/src/libstd/sys/unix/thread.rs @@ -237,7 +237,7 @@ pub unsafe fn create(stack: uint, p: Thunk) -> io::Result { 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"] @@ -255,14 +255,14 @@ pub unsafe fn set_name(name: &str) { 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()); } diff --git a/src/libsyntax/diagnostic.rs b/src/libsyntax/diagnostic.rs index 83a4d938bb5..b7a758a00d5 100644 --- a/src/libsyntax/diagnostic.rs +++ b/src/libsyntax/diagnostic.rs @@ -618,22 +618,25 @@ fn print_macro_backtrace(w: &mut EmitterWriter, 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)) } diff --git a/src/test/run-pass/c-stack-returning-int64.rs b/src/test/run-pass/c-stack-returning-int64.rs index 22c322b86c9..d18a3055b9c 100644 --- a/src/test/run-pass/c-stack-returning-int64.rs +++ b/src/test/run-pass/c-stack-returning-int64.rs @@ -24,12 +24,12 @@ mod mlibc { } 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 } } diff --git a/src/test/run-pass/foreign-fn-linkname.rs b/src/test/run-pass/foreign-fn-linkname.rs index dff1a1eaa04..25d0cbbcdb6 100644 --- a/src/test/run-pass/foreign-fn-linkname.rs +++ b/src/test/run-pass/foreign-fn-linkname.rs @@ -24,7 +24,7 @@ mod mlibc { 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 } diff --git a/src/test/run-pass/rename-directory.rs b/src/test/run-pass/rename-directory.rs index 12e4f27a64f..1282720d4cb 100644 --- a/src/test/run-pass/rename-directory.rs +++ b/src/test/run-pass/rename-directory.rs @@ -31,12 +31,12 @@ fn rename_directory() { 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, diff --git a/src/test/run-pass/variadic-ffi.rs b/src/test/run-pass/variadic-ffi.rs index a729fedb271..85f6ef0ddcd 100644 --- a/src/test/run-pass/variadic-ffi.rs +++ b/src/test/run-pass/variadic-ffi.rs @@ -29,11 +29,11 @@ pub fn main() { 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()); }); @@ -44,11 +44,11 @@ pub fn main() { // 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()); }); -- cgit 1.4.1-3-g733a5