mirror of https://github.com/rwf2/Rocket.git
Use 'ref-cast' for safer transparent casting.
This commit is contained in:
parent
d89c7024ed
commit
3ced188f7d
|
@ -34,6 +34,7 @@ cookie = { version = "0.14.0", features = ["percent-encode"] }
|
|||
pear = "0.1"
|
||||
unicode-xid = "0.2"
|
||||
log = "0.4"
|
||||
ref-cast = "1.0"
|
||||
|
||||
[dev-dependencies]
|
||||
rocket = { version = "0.5.0-dev", path = "../lib" }
|
||||
|
|
|
@ -5,6 +5,8 @@ use std::cmp::Ordering;
|
|||
use std::str::Utf8Error;
|
||||
use std::fmt;
|
||||
|
||||
use ref_cast::RefCast;
|
||||
|
||||
use crate::uncased::UncasedStr;
|
||||
|
||||
/// A reference to a string inside of a raw HTTP message.
|
||||
|
@ -50,7 +52,7 @@ use crate::uncased::UncasedStr;
|
|||
/// [`FromParam`]: rocket::request::FromParam
|
||||
/// [`FromFormValue`]: rocket::request::FromFormValue
|
||||
#[repr(transparent)]
|
||||
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
#[derive(RefCast, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub struct RawStr(str);
|
||||
|
||||
impl RawStr {
|
||||
|
@ -352,10 +354,7 @@ impl RawStr {
|
|||
impl<'a> From<&'a str> for &'a RawStr {
|
||||
#[inline(always)]
|
||||
fn from(string: &'a str) -> &'a RawStr {
|
||||
// This is simply a `newtype`-like transformation. The `repr(C)` ensures
|
||||
// that this is safe and correct. Note this exact pattern appears often
|
||||
// in the standard library.
|
||||
unsafe { &*(string as *const str as *const RawStr) }
|
||||
RawStr::ref_cast(string)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -10,6 +10,8 @@ use std::cmp::Ordering;
|
|||
use std::hash::{Hash, Hasher};
|
||||
use std::fmt;
|
||||
|
||||
use ref_cast::RefCast;
|
||||
|
||||
/// A reference to an uncased (case-preserving) ASCII string. This is typically
|
||||
/// created from an `&str` as follows:
|
||||
///
|
||||
|
@ -19,8 +21,8 @@ use std::fmt;
|
|||
///
|
||||
/// let ascii_ref: &UncasedStr = "Hello, world!".into();
|
||||
/// ```
|
||||
#[repr(C)]
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, RefCast)]
|
||||
#[repr(transparent)]
|
||||
pub struct UncasedStr(str);
|
||||
|
||||
impl UncasedStr {
|
||||
|
@ -39,10 +41,7 @@ impl UncasedStr {
|
|||
/// ```
|
||||
#[inline(always)]
|
||||
pub fn new(string: &str) -> &UncasedStr {
|
||||
// This is simply a `newtype`-like transformation. The `repr(C)` ensures
|
||||
// that this is safe and correct. Note this exact pattern appears often
|
||||
// in the standard library.
|
||||
unsafe { &*(string as *const str as *const UncasedStr) }
|
||||
UncasedStr::ref_cast(string)
|
||||
}
|
||||
|
||||
/// Returns `self` as an `&str`.
|
||||
|
@ -62,7 +61,8 @@ impl UncasedStr {
|
|||
&self.0
|
||||
}
|
||||
|
||||
/// Converts a `Box<UncasedStr>` into an `Uncased` without copying or allocating.
|
||||
/// Converts a `Box<UncasedStr>` into an `Uncased` without copying or
|
||||
/// allocating.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
|
@ -76,9 +76,8 @@ impl UncasedStr {
|
|||
/// ```
|
||||
#[inline(always)]
|
||||
pub fn into_uncased(self: Box<UncasedStr>) -> Uncased<'static> {
|
||||
// This is the inverse of a `newtype`-like transformation. The `repr(C)`
|
||||
// ensures that this is safe and correct. Note this exact pattern
|
||||
// appears often in the standard library.
|
||||
// This is the inverse of a `newtype`-like transformation. The
|
||||
// `repr(transparent)` ensures that this is safe and correct.
|
||||
unsafe {
|
||||
let raw_str = Box::into_raw(self) as *mut str;
|
||||
Uncased::from(Box::from_raw(raw_str).into_string())
|
||||
|
|
|
@ -200,9 +200,9 @@ impl<'a> Origin<'a> {
|
|||
// For this to be correct and safe, we need to ensure that:
|
||||
//
|
||||
// 1. No `&mut` references to `string` are created after this line.
|
||||
// 2. `string` isn't dropped by `copy_of_str` is live.
|
||||
// 2. `string` isn't dropped while `copy_of_str` is live.
|
||||
//
|
||||
// These two facts can be easily verified. An `&mut` can be created
|
||||
// These two facts can be easily verified. An `&mut` can't be created
|
||||
// because `string` isn't `mut`. Then, `string` is clearly not dropped
|
||||
// since it's passed in to `source`.
|
||||
let copy_of_str = unsafe { &*(string.as_str() as *const str) };
|
||||
|
|
|
@ -40,6 +40,7 @@ binascii = "0.1"
|
|||
pear = "0.1"
|
||||
atty = "0.2"
|
||||
async-trait = "0.1"
|
||||
ref-cast = "1.0"
|
||||
|
||||
[build-dependencies]
|
||||
yansi = "0.5"
|
||||
|
|
|
@ -8,6 +8,7 @@ use futures::future::FutureExt;
|
|||
use futures::stream::StreamExt;
|
||||
use futures::future::{Future, BoxFuture};
|
||||
use tokio::sync::{mpsc, oneshot};
|
||||
use ref_cast::RefCast;
|
||||
|
||||
use yansi::Paint;
|
||||
use state::Container;
|
||||
|
@ -56,6 +57,7 @@ enum PreLaunchOp {
|
|||
/// A frozen view into the contents of an instance of `Rocket`.
|
||||
///
|
||||
/// Obtained via [`Rocket::inspect()`].
|
||||
#[derive(RefCast)]
|
||||
#[repr(transparent)]
|
||||
pub struct Cargo(Rocket);
|
||||
|
||||
|
@ -150,10 +152,7 @@ impl Rocket {
|
|||
panic!("internal error: immutable launch state with manifest");
|
||||
}
|
||||
|
||||
// This is simply a `newtype`-like transformation. The
|
||||
// `repr(transparent)` on `Cargo` ensures that this is safe and
|
||||
// correct. Note that this exact pattern appears often in `std`.
|
||||
unsafe { &*(self as *const Rocket as *const Cargo) }
|
||||
Cargo::ref_cast(self)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue