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