From: bors Date: Wed, 26 Apr 2017 06:18:17 +0000 (+0000) Subject: Auto merge of #41258 - clarcharr:str_box_extras, r=Kimundi X-Git-Url: https://git.lizzy.rs/?a=commitdiff_plain;h=dad9814eb0964a92494fef9ce23b80353dc14c46;hp=-c;p=rust.git Auto merge of #41258 - clarcharr:str_box_extras, r=Kimundi More methods for str boxes. (reduce Box<[u8]> ↔ Box transmutes) This is a follow-up to #41096 that adds safer methods for converting between `Box` and `Box<[u8]>`. They're gated under a different feature from the `&mut str` methods because they may be too niche to include in public APIs, although having them internally helps reduce the number of transmutes the standard library uses. What's added: * `From> for Box<[u8]>` * `>::into_boxed_bytes` (just calls `Into::into`) * `alloc::str` (new module) * `from_boxed_utf8` and `from_boxed_utf8_unchecked`, defined in `alloc:str`, exported in `collections::str` * exports `from_utf8_mut` in `collections::str` (missed from previous PR) --- dad9814eb0964a92494fef9ce23b80353dc14c46 diff --combined src/doc/unstable-book/src/SUMMARY.md index 4a5d850d66d,76196173b11..2cb37630112 --- a/src/doc/unstable-book/src/SUMMARY.md +++ b/src/doc/unstable-book/src/SUMMARY.md @@@ -72,7 -72,6 +72,7 @@@ - [proc_macro](language-features/proc-macro.md) - [quote](language-features/quote.md) - [relaxed_adts](language-features/relaxed-adts.md) + - [repr_align](language-features/repr-align.md) - [repr_simd](language-features/repr-simd.md) - [rustc_attrs](language-features/rustc-attrs.md) - [rustc_diagnostic_macros](language-features/rustc-diagnostic-macros.md) @@@ -102,8 -101,11 +102,8 @@@ - [alloc_system](library-features/alloc-system.md) - [alloc](library-features/alloc.md) - [as_c_str](library-features/as-c-str.md) - - [as_unsafe_cell](library-features/as-unsafe-cell.md) - [ascii_ctype](library-features/ascii-ctype.md) - - [binary_heap_extras](library-features/binary-heap-extras.md) - [binary_heap_peek_mut_pop](library-features/binary-heap-peek-mut-pop.md) - - [borrow_state](library-features/borrow-state.md) - [box_heap](library-features/box-heap.md) - [c_void_variant](library-features/c-void-variant.md) - [char_escape_debug](library-features/char-escape-debug.md) @@@ -128,12 -130,14 +128,12 @@@ - [derive_clone_copy](library-features/derive-clone-copy.md) - [derive_eq](library-features/derive-eq.md) - [discriminant_value](library-features/discriminant-value.md) - - [enumset](library-features/enumset.md) - [error_type_id](library-features/error-type-id.md) - [exact_size_is_empty](library-features/exact-size-is-empty.md) - [fd](library-features/fd.md) - [fd_read](library-features/fd-read.md) - [fixed_size_array](library-features/fixed-size-array.md) - [float_bits_conv](library-features/float-bits-conv.md) - - [float_extras](library-features/float-extras.md) - [flt2dec](library-features/flt2dec.md) - [fmt_flags_align](library-features/fmt-flags-align.md) - [fmt_internals](library-features/fmt-internals.md) @@@ -153,6 -157,7 +153,6 @@@ - [io_error_internals](library-features/io-error-internals.md) - [io](library-features/io.md) - [ip](library-features/ip.md) - - [is_unique](library-features/is-unique.md) - [iter_rfind](library-features/iter-rfind.md) - [libstd_io_internals](library-features/libstd-io-internals.md) - [libstd_sys_internals](library-features/libstd-sys-internals.md) @@@ -160,7 -165,7 +160,7 @@@ - [linked_list_extras](library-features/linked-list-extras.md) - [lookup_host](library-features/lookup-host.md) - [manually_drop](library-features/manually-drop.md) - - [map_entry_recover_keys](library-features/map-entry-recover-keys.md) + - [more_io_inner_methods](library-features/more-io-inner-methods.md) - [mpsc_select](library-features/mpsc-select.md) - [n16](library-features/n16.md) - [never_type_impls](library-features/never-type-impls.md) @@@ -183,6 -188,7 +183,6 @@@ - [rand](library-features/rand.md) - [range_contains](library-features/range-contains.md) - [raw](library-features/raw.md) - - [rc_would_unwrap](library-features/rc-would-unwrap.md) - [retain_hash_collection](library-features/retain-hash-collection.md) - [reverse_cmp_key](library-features/reverse-cmp-key.md) - [rt](library-features/rt.md) @@@ -196,12 -202,12 +196,13 @@@ - [slice_rsplit](library-features/slice-rsplit.md) - [sort_internals](library-features/sort-internals.md) - [sort_unstable](library-features/sort-unstable.md) + - [splice](library-features/splice.md) - [step_by](library-features/step-by.md) - [step_trait](library-features/step-trait.md) - [str_checked_slicing](library-features/str-checked-slicing.md) - [str_escape](library-features/str-escape.md) - [str_internals](library-features/str-internals.md) + - [str_box_extras](library-features/str-box-extras.md) - [str_mut_extras](library-features/str-mut-extras.md) - [test](library-features/test.md) - [thread_id](library-features/thread-id.md) @@@ -219,3 -225,5 +220,3 @@@ - [windows_handle](library-features/windows-handle.md) - [windows_net](library-features/windows-net.md) - [windows_stdio](library-features/windows-stdio.md) - - [zero_one](library-features/zero-one.md) ->>>>>> Add top level sections to the Unstable Book. diff --combined src/liballoc/lib.rs index c70d82392f9,418a084da67..fee0e1eb260 --- a/src/liballoc/lib.rs +++ b/src/liballoc/lib.rs @@@ -87,7 -87,6 +87,7 @@@ #![feature(needs_allocator)] #![feature(optin_builtin_traits)] #![feature(placement_in_syntax)] +#![cfg_attr(stage0, feature(pub_restricted))] #![feature(shared)] #![feature(staged_api)] #![feature(unboxed_closures)] @@@ -129,6 -128,8 +129,8 @@@ mod boxed_test pub mod arc; pub mod rc; pub mod raw_vec; + #[unstable(feature = "str_box_extras", issue = "41119")] + pub mod str; pub mod oom; pub use oom::oom; diff --combined src/libcollections/lib.rs index 8d056afdb57,c3db76e6c75..842f2f44fff --- a/src/libcollections/lib.rs +++ b/src/libcollections/lib.rs @@@ -60,6 -60,7 +60,7 @@@ #![feature(specialization)] #![feature(staged_api)] #![feature(str_internals)] + #![feature(str_box_extras)] #![feature(str_mut_extras)] #![feature(trusted_len)] #![feature(unicode)] @@@ -89,6 -90,9 +90,6 @@@ pub use btree_set::BTreeSet #[doc(no_inline)] pub use linked_list::LinkedList; #[doc(no_inline)] -#[allow(deprecated)] -pub use enum_set::EnumSet; -#[doc(no_inline)] pub use vec_deque::VecDeque; #[doc(no_inline)] pub use string::String; @@@ -104,6 -108,7 +105,6 @@@ mod macros pub mod binary_heap; mod btree; pub mod borrow; -pub mod enum_set; pub mod fmt; pub mod linked_list; pub mod range; diff --combined src/libcollections/string.rs index 0a82fda09cb,69dfb466d70..aa9628c535a --- a/src/libcollections/string.rs +++ b/src/libcollections/string.rs @@@ -56,10 -56,11 +56,11 @@@ #![stable(feature = "rust1", since = "1.0.0")] + use alloc::str as alloc_str; + use core::fmt; use core::hash; use core::iter::{FromIterator, FusedIterator}; - use core::mem; use core::ops::{self, Add, AddAssign, Index, IndexMut}; use core::ptr; use core::str as core_str; @@@ -1316,7 -1317,7 +1317,7 @@@ impl String self.vec.clear() } - /// Create a draining iterator that removes the specified range in the string + /// Creates a draining iterator that removes the specified range in the string /// and yields the removed chars. /// /// Note: The element range is removed even if the iterator is not @@@ -1382,71 -1383,6 +1383,71 @@@ } } + /// Creates a splicing iterator that removes the specified range in the string, + /// replaces with the given string, and yields the removed chars. + /// The given string doesn’t need to be the same length as the range. + /// + /// Note: The element range is removed when the `Splice` is dropped, + /// even if the iterator is not consumed until the end. + /// + /// # Panics + /// + /// Panics if the starting point or end point do not lie on a [`char`] + /// boundary, or if they're out of bounds. + /// + /// [`char`]: ../../std/primitive.char.html + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(splice)] + /// let mut s = String::from("α is alpha, β is beta"); + /// let beta_offset = s.find('β').unwrap_or(s.len()); + /// + /// // Replace the range up until the β from the string + /// let t: String = s.splice(..beta_offset, "Α is capital alpha; ").collect(); + /// assert_eq!(t, "α is alpha, "); + /// assert_eq!(s, "Α is capital alpha; β is beta"); + /// ``` + #[unstable(feature = "splice", reason = "recently added", issue = "32310")] + pub fn splice<'a, 'b, R>(&'a mut self, range: R, replace_with: &'b str) -> Splice<'a, 'b> + where R: RangeArgument + { + // Memory safety + // + // The String version of Splice does not have the memory safety issues + // of the vector version. The data is just plain bytes. + // Because the range removal happens in Drop, if the Splice iterator is leaked, + // the removal will not happen. + let len = self.len(); + let start = match range.start() { + Included(&n) => n, + Excluded(&n) => n + 1, + Unbounded => 0, + }; + let end = match range.end() { + Included(&n) => n + 1, + Excluded(&n) => n, + Unbounded => len, + }; + + // Take out two simultaneous borrows. The &mut String won't be accessed + // until iteration is over, in Drop. + let self_ptr = self as *mut _; + // slicing does the appropriate bounds checks + let chars_iter = self[start..end].chars(); + + Splice { + start: start, + end: end, + iter: chars_iter, + string: self_ptr, + replace_with: replace_with + } + } + /// Converts this `String` into a `Box`. /// /// This will drop any excess capacity. @@@ -1463,7 -1399,7 +1464,7 @@@ #[stable(feature = "box_str", since = "1.4.0")] pub fn into_boxed_str(self) -> Box { let slice = self.vec.into_boxed_slice(); - unsafe { mem::transmute::, Box>(slice) } + unsafe { alloc_str::from_boxed_utf8_unchecked(slice) } } } @@@ -2210,61 -2146,3 +2211,61 @@@ impl<'a> DoubleEndedIterator for Drain< #[unstable(feature = "fused", issue = "35602")] impl<'a> FusedIterator for Drain<'a> {} + +/// A splicing iterator for `String`. +/// +/// This struct is created by the [`splice()`] method on [`String`]. See its +/// documentation for more. +/// +/// [`splice()`]: struct.String.html#method.splice +/// [`String`]: struct.String.html +#[derive(Debug)] +#[unstable(feature = "splice", reason = "recently added", issue = "32310")] +pub struct Splice<'a, 'b> { + /// Will be used as &'a mut String in the destructor + string: *mut String, + /// Start of part to remove + start: usize, + /// End of part to remove + end: usize, + /// Current remaining range to remove + iter: Chars<'a>, + replace_with: &'b str, +} + +#[unstable(feature = "splice", reason = "recently added", issue = "32310")] +unsafe impl<'a, 'b> Sync for Splice<'a, 'b> {} +#[unstable(feature = "splice", reason = "recently added", issue = "32310")] +unsafe impl<'a, 'b> Send for Splice<'a, 'b> {} + +#[unstable(feature = "splice", reason = "recently added", issue = "32310")] +impl<'a, 'b> Drop for Splice<'a, 'b> { + fn drop(&mut self) { + unsafe { + let vec = (*self.string).as_mut_vec(); + vec.splice(self.start..self.end, self.replace_with.bytes()); + } + } +} + +#[unstable(feature = "splice", reason = "recently added", issue = "32310")] +impl<'a, 'b> Iterator for Splice<'a, 'b> { + type Item = char; + + #[inline] + fn next(&mut self) -> Option { + self.iter.next() + } + + fn size_hint(&self) -> (usize, Option) { + self.iter.size_hint() + } +} + +#[unstable(feature = "splice", reason = "recently added", issue = "32310")] +impl<'a, 'b> DoubleEndedIterator for Splice<'a, 'b> { + #[inline] + fn next_back(&mut self) -> Option { + self.iter.next_back() + } +}