Skip to content

Commit

Permalink
rust-timer simulated merge of f305b20
Browse files Browse the repository at this point in the history
Original message:
Rollup merge of rust-lang#74021 - 1011X:master, r=dtolnay

impl Index<RangeFrom> for CStr

This change implements (partial) slicing for `CStr`.

Since a `CStr` must end in a null byte, it's not possible to trim from the right and still have a valid `CStr`. But, it *is* possible to trim from the left. This lets us be a bit more flexible and treat them more like strings.

```rust
let string = CStr::from_bytes_with_nul(b"Hello World!\0");
let result = CStr::from_bytes_with_nul(b"World!\0");
assert_eq!(&string[6..], result);
```
  • Loading branch information
rust-timer committed Jul 22, 2020
1 parent 669cfad commit 430994c
Show file tree
Hide file tree
Showing 5 changed files with 283 additions and 3 deletions.
4 changes: 4 additions & 0 deletions src/libcore/task/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,7 @@ pub use self::poll::Poll;
mod wake;
#[stable(feature = "futures_api", since = "1.36.0")]
pub use self::wake::{Context, RawWaker, RawWakerVTable, Waker};

mod ready;
#[unstable(feature = "ready_macro", issue = "70922")]
pub use ready::ready;
60 changes: 60 additions & 0 deletions src/libcore/task/ready.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/// Extracts the successful type of a `Poll<T>`.
///
/// This macro bakes in propagation of `Pending` signals by returning early.
///
/// # Examples
///
/// ```
/// #![feature(future_readiness_fns)]
/// #![feature(ready_macro)]
///
/// use core::task::{ready, Context, Poll};
/// use core::future::{self, Future};
/// use core::pin::Pin;
///
/// pub fn do_poll(cx: &mut Context<'_>) -> Poll<()> {
/// let mut fut = future::ready(42);
/// let fut = Pin::new(&mut fut);
///
/// let num = ready!(fut.poll(cx));
/// # drop(num);
/// // ... use num
///
/// Poll::Ready(())
/// }
/// ```
///
/// The `ready!` call expands to:
///
/// ```
/// # #![feature(future_readiness_fns)]
/// # #![feature(ready_macro)]
/// #
/// # use core::task::{Context, Poll};
/// # use core::future::{self, Future};
/// # use core::pin::Pin;
/// #
/// # pub fn do_poll(cx: &mut Context<'_>) -> Poll<()> {
/// # let mut fut = future::ready(42);
/// # let fut = Pin::new(&mut fut);
/// #
/// let num = match fut.poll(cx) {
/// Poll::Ready(t) => t,
/// Poll::Pending => return Poll::Pending,
/// };
/// # drop(num);
/// # // ... use num
/// #
/// # Poll::Ready(())
/// # }
/// ```
#[unstable(feature = "ready_macro", issue = "70922")]
#[rustc_macro_transparency = "semitransparent"]
pub macro ready($e:expr) {
match $e {
$crate::task::Poll::Ready(t) => t,
$crate::task::Poll::Pending => {
return $crate::task::Poll::Pending;
}
}
}
38 changes: 38 additions & 0 deletions src/libstd/ffi/c_str.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1551,6 +1551,27 @@ impl ops::Index<ops::RangeFull> for CString {
}
}

#[stable(feature = "cstr_range_from", since = "1.47.0")]
impl ops::Index<ops::RangeFrom<usize>> for CStr {
type Output = CStr;

fn index(&self, index: ops::RangeFrom<usize>) -> &CStr {
let bytes = self.to_bytes_with_nul();
// we need to manually check the starting index to account for the null
// byte, since otherwise we could get an empty string that doesn't end
// in a null.
if index.start < bytes.len() {
unsafe { CStr::from_bytes_with_nul_unchecked(&bytes[index.start..]) }
} else {
panic!(
"index out of bounds: the len is {} but the index is {}",
bytes.len(),
index.start
);
}
}
}

#[stable(feature = "cstring_asref", since = "1.7.0")]
impl AsRef<CStr> for CStr {
#[inline]
Expand Down Expand Up @@ -1747,4 +1768,21 @@ mod tests {

assert_eq!(CSTR.to_str().unwrap(), "Hello, world!");
}

#[test]
fn cstr_index_from() {
let original = b"Hello, world!\0";
let cstr = CStr::from_bytes_with_nul(original).unwrap();
let result = CStr::from_bytes_with_nul(&original[7..]).unwrap();

assert_eq!(&cstr[7..], result);
}

#[test]
#[should_panic]
fn cstr_index_from_empty() {
let original = b"Hello, world!\0";
let cstr = CStr::from_bytes_with_nul(original).unwrap();
let _ = &cstr[original.len()..];
}
}
183 changes: 180 additions & 3 deletions src/libstd/keyword_docs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1497,11 +1497,188 @@ mod super_keyword {}

#[doc(keyword = "trait")]
//
/// A common interface for a class of types.
/// A common interface for a group of types.
///
/// The documentation for this keyword is [not yet complete]. Pull requests welcome!
/// A `trait` is like an interface that data types can implement. When a type
/// implements a trait it can be treated abstractly as that trait using generics
/// or trait objects.
///
/// [not yet complete]: https://github.com/rust-lang/rust/issues/34601
/// Traits can be made up of three varieties of associated items:
///
/// - functions and methods
/// - types
/// - constants
///
/// Traits may also contain additional type parameters. Those type parameters
/// or the trait itself can be constrained by other traits.
///
/// Traits can serve as markers or carry other logical semantics that
/// aren't expressed through their items. When a type implements that
/// trait it is promising to uphold its contract. [`Send`] and [`Sync`] are two
/// such marker traits present in the standard library.
///
/// See the [Reference][Ref-Traits] for a lot more information on traits.
///
/// # Examples
///
/// Traits are declared using the `trait` keyword. Types can implement them
/// using [`impl`] `Trait` [`for`] `Type`:
///
/// ```rust
/// trait Zero {
/// const ZERO: Self;
/// fn is_zero(&self) -> bool;
/// }
///
/// impl Zero for i32 {
/// const ZERO: Self = 0;
///
/// fn is_zero(&self) -> bool {
/// *self == Self::ZERO
/// }
/// }
///
/// assert_eq!(i32::ZERO, 0);
/// assert!(i32::ZERO.is_zero());
/// assert!(!4.is_zero());
/// ```
///
/// With an associated type:
///
/// ```rust
/// trait Builder {
/// type Built;
///
/// fn build(&self) -> Self::Built;
/// }
/// ```
///
/// Traits can be generic, with constraints or without:
///
/// ```rust
/// trait MaybeFrom<T> {
/// fn maybe_from(value: T) -> Option<Self>
/// where
/// Self: Sized;
/// }
/// ```
///
/// Traits can build upon the requirements of other traits. In the example
/// below `Iterator` is a **supertrait** and `ThreeIterator` is a **subtrait**:
///
/// ```rust
/// trait ThreeIterator: std::iter::Iterator {
/// fn next_three(&mut self) -> Option<[Self::Item; 3]>;
/// }
/// ```
///
/// Traits can be used in functions, as parameters:
///
/// ```rust
/// # #![allow(dead_code)]
/// fn debug_iter<I: Iterator>(it: I) where I::Item: std::fmt::Debug {
/// for elem in it {
/// println!("{:#?}", elem);
/// }
/// }
///
/// // u8_len_1, u8_len_2 and u8_len_3 are equivalent
///
/// fn u8_len_1(val: impl Into<Vec<u8>>) -> usize {
/// val.into().len()
/// }
///
/// fn u8_len_2<T: Into<Vec<u8>>>(val: T) -> usize {
/// val.into().len()
/// }
///
/// fn u8_len_3<T>(val: T) -> usize
/// where
/// T: Into<Vec<u8>>,
/// {
/// val.into().len()
/// }
/// ```
///
/// Or as return types:
///
/// ```rust
/// # #![allow(dead_code)]
/// fn from_zero_to(v: u8) -> impl Iterator<Item = u8> {
/// (0..v).into_iter()
/// }
/// ```
///
/// The use of the [`impl`] keyword in this position allows the function writer
/// to hide the concrete type as an implementation detail which can change
/// without breaking user's code.
///
/// # Trait objects
///
/// A *trait object* is an opaque value of another type that implements a set of
/// traits. A trait object implements all specified traits as well as their
/// supertraits (if any).
///
/// The syntax is the following: `dyn BaseTrait + AutoTrait1 + ... AutoTraitN`.
/// Only one `BaseTrait` can be used so this will not compile:
///
/// ```rust,compile_fail,E0225
/// trait A {}
/// trait B {}
///
/// let _: Box<dyn A + B>;
/// ```
///
/// Neither will this, which is a syntax error:
///
/// ```rust,compile_fail
/// trait A {}
/// trait B {}
///
/// let _: Box<dyn A + dyn B>;
/// ```
///
/// On the other hand, this is correct:
///
/// ```rust
/// trait A {}
///
/// let _: Box<dyn A + Send + Sync>;
/// ```
///
/// The [Reference][Ref-Trait-Objects] has more information about trait objects,
/// their limitations and the differences between editions.
///
/// # Unsafe traits
///
/// Some traits may be unsafe to implement. Using the [`unsafe`] keyword in
/// front of the trait's declaration is used to mark this:
///
/// ```rust
/// unsafe trait UnsafeTrait {}
///
/// unsafe impl UnsafeTrait for i32 {}
/// ```
///
/// # Differences between the 2015 and 2018 editions
///
/// In the 2015 edition parameters pattern where not needed for traits:
///
/// ```rust,edition2015
/// trait Tr {
/// fn f(i32);
/// }
/// ```
///
/// This behavior is no longer valid in edition 2018.
///
/// [`for`]: keyword.for.html
/// [`impl`]: keyword.impl.html
/// [`unsafe`]: keyword.unsafe.html
/// [`Send`]: marker/trait.Send.html
/// [`Sync`]: marker/trait.Sync.html
/// [Ref-Traits]: ../reference/items/traits.html
/// [Ref-Trait-Objects]: ../reference/types/trait-object.html
mod trait_keyword {}

#[doc(keyword = "true")]
Expand Down
1 change: 1 addition & 0 deletions src/libstd/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,7 @@
#![feature(ptr_internals)]
#![feature(raw)]
#![feature(raw_ref_macros)]
#![feature(ready_macro)]
#![feature(renamed_spin_loop)]
#![feature(rustc_attrs)]
#![feature(rustc_private)]
Expand Down

0 comments on commit 430994c

Please sign in to comment.