]> git.lizzy.rs Git - rust.git/commitdiff
Auto merge of #41258 - clarcharr:str_box_extras, r=Kimundi
authorbors <bors@rust-lang.org>
Wed, 26 Apr 2017 06:18:17 +0000 (06:18 +0000)
committerbors <bors@rust-lang.org>
Wed, 26 Apr 2017 06:18:17 +0000 (06:18 +0000)
More methods for str boxes. (reduce Box<[u8]> ↔ Box<str> transmutes)

This is a follow-up to #41096 that adds safer methods for converting between `Box<str>` 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<Box<str>> for Box<[u8]>`
* `<Box<str>>::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)

1  2 
src/doc/unstable-book/src/SUMMARY.md
src/liballoc/lib.rs
src/libcollections/lib.rs
src/libcollections/string.rs

index 4a5d850d66dc7851922e38890b95084c6666c23b,76196173b11e50a67b3535128e2a7dbb278e6123..2cb376301121821cabbd8c3fa0a6498d9e21c34b
@@@ -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)
      - [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)
      - [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)
      - [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)
      - [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)
      - [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)
      - [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)
      - [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 c70d82392f9148cd8357bed3695a0d04f2b68f86,418a084da67878ff2c375b78cdf7153f70ed051c..fee0e1eb2608380389ae435becb44d565c0e7404
@@@ -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;
index 8d056afdb571a4881ed1e86399fc3cc3294bbb06,c3db76e6c759d7134090993751fee36bdbad76fb..842f2f44fff9e8166652695f93e50fdfdf96ca9c
@@@ -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;
index 0a82fda09cb84dc935d38cb02715b7793aee7c74,69dfb466d707ea38cc8868f9a0c20a8d4f173dc0..aa9628c535a997fb18939a2a7f66a85c61f10acb
  
  #![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
          }
      }
  
 +    /// 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<usize>
 +    {
 +        // 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<str>`.
      ///
      /// This will drop any excess capacity.
      #[stable(feature = "box_str", since = "1.4.0")]
      pub fn into_boxed_str(self) -> Box<str> {
          let slice = self.vec.into_boxed_slice();
-         unsafe { mem::transmute::<Box<[u8]>, Box<str>>(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<char> {
 +        self.iter.next()
 +    }
 +
 +    fn size_hint(&self) -> (usize, Option<usize>) {
 +        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<char> {
 +        self.iter.next_back()
 +    }
 +}