mirror of
https://github.com/actix/actix-extras.git
synced 2024-11-24 07:53:00 +01:00
various cleanups and comments
This commit is contained in:
parent
311f0b23a9
commit
2f917f3700
@ -1,4 +1,4 @@
|
|||||||
use std::cell::{RefCell, UnsafeCell};
|
use std::cell::RefCell;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
@ -21,7 +21,7 @@ pub struct HttpApplication<S = ()> {
|
|||||||
prefix: String,
|
prefix: String,
|
||||||
prefix_len: usize,
|
prefix_len: usize,
|
||||||
router: Router,
|
router: Router,
|
||||||
inner: Rc<UnsafeCell<Inner<S>>>,
|
inner: Rc<RefCell<Inner<S>>>,
|
||||||
filters: Option<Vec<Box<Predicate<S>>>>,
|
filters: Option<Vec<Box<Predicate<S>>>>,
|
||||||
middlewares: Rc<RefCell<Vec<Box<Middleware<S>>>>>,
|
middlewares: Rc<RefCell<Vec<Box<Middleware<S>>>>>,
|
||||||
}
|
}
|
||||||
@ -69,17 +69,12 @@ impl<S: 'static> PipelineHandler<S> for Inner<S> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<S: 'static> HttpApplication<S> {
|
impl<S: 'static> HttpApplication<S> {
|
||||||
#[inline]
|
|
||||||
fn as_ref(&self) -> &Inner<S> {
|
|
||||||
unsafe { &*self.inner.get() }
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn get_handler(&self, req: &mut HttpRequest<S>) -> HandlerType {
|
fn get_handler(&self, req: &mut HttpRequest<S>) -> HandlerType {
|
||||||
if let Some(idx) = self.router.recognize(req) {
|
if let Some(idx) = self.router.recognize(req) {
|
||||||
HandlerType::Normal(idx)
|
HandlerType::Normal(idx)
|
||||||
} else {
|
} else {
|
||||||
let inner = self.as_ref();
|
let inner = self.inner.borrow();
|
||||||
req.match_info_mut().set_tail(0);
|
req.match_info_mut().set_tail(0);
|
||||||
|
|
||||||
'outer: for idx in 0..inner.handlers.len() {
|
'outer: for idx in 0..inner.handlers.len() {
|
||||||
@ -131,7 +126,7 @@ impl<S: 'static> HttpApplication<S> {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
pub(crate) fn run(&mut self, mut req: HttpRequest<S>) -> AsyncResult<HttpResponse> {
|
pub(crate) fn run(&mut self, mut req: HttpRequest<S>) -> AsyncResult<HttpResponse> {
|
||||||
let tp = self.get_handler(&mut req);
|
let tp = self.get_handler(&mut req);
|
||||||
unsafe { &mut *self.inner.get() }.handle(req, tp)
|
self.inner.borrow_mut().handle(req, tp)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
@ -340,24 +335,32 @@ where
|
|||||||
T: FromRequest<S> + 'static,
|
T: FromRequest<S> + 'static,
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
let parts: &mut ApplicationParts<S> = unsafe {
|
let parts = self.parts.as_mut().expect("Use after finish");
|
||||||
&mut *(self.parts.as_mut().expect("Use after finish") as *mut _)
|
|
||||||
};
|
|
||||||
|
|
||||||
// get resource handler
|
// get resource handler
|
||||||
for &mut (ref pattern, ref mut handler) in &mut parts.resources {
|
let mut found = false;
|
||||||
if let Some(ref mut handler) = *handler {
|
for &mut (ref pattern, ref handler) in &mut parts.resources {
|
||||||
if pattern.pattern() == path {
|
if handler.is_some() && pattern.pattern() == path {
|
||||||
handler.method(method).with(f);
|
found = true;
|
||||||
return self;
|
break;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut handler = ResourceHandler::default();
|
if !found {
|
||||||
handler.method(method).with(f);
|
let mut handler = ResourceHandler::default();
|
||||||
let pattern = Resource::new(handler.get_name(), path);
|
handler.method(method).with(f);
|
||||||
parts.resources.push((pattern, Some(handler)));
|
let pattern = Resource::new(handler.get_name(), path);
|
||||||
|
parts.resources.push((pattern, Some(handler)));
|
||||||
|
} else {
|
||||||
|
for &mut (ref pattern, ref mut handler) in &mut parts.resources {
|
||||||
|
if let Some(ref mut handler) = *handler {
|
||||||
|
if pattern.pattern() == path {
|
||||||
|
handler.method(method).with(f);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
@ -626,7 +629,7 @@ where
|
|||||||
|
|
||||||
let (router, resources) = Router::new(&prefix, parts.settings, resources);
|
let (router, resources) = Router::new(&prefix, parts.settings, resources);
|
||||||
|
|
||||||
let inner = Rc::new(UnsafeCell::new(Inner {
|
let inner = Rc::new(RefCell::new(Inner {
|
||||||
prefix: prefix_len,
|
prefix: prefix_len,
|
||||||
default: parts.default,
|
default: parts.default,
|
||||||
encoding: parts.encoding,
|
encoding: parts.encoding,
|
||||||
|
14
src/error.rs
14
src/error.rs
@ -3,7 +3,7 @@ use std::io::Error as IoError;
|
|||||||
use std::str::Utf8Error;
|
use std::str::Utf8Error;
|
||||||
use std::string::FromUtf8Error;
|
use std::string::FromUtf8Error;
|
||||||
use std::sync::Mutex;
|
use std::sync::Mutex;
|
||||||
use std::{fmt, io, mem, result};
|
use std::{fmt, io, result};
|
||||||
|
|
||||||
use actix::MailboxError;
|
use actix::MailboxError;
|
||||||
use cookie;
|
use cookie;
|
||||||
@ -22,7 +22,6 @@ pub use url::ParseError as UrlParseError;
|
|||||||
// re-exports
|
// re-exports
|
||||||
pub use cookie::ParseError as CookieParseError;
|
pub use cookie::ParseError as CookieParseError;
|
||||||
|
|
||||||
use body::Body;
|
|
||||||
use handler::Responder;
|
use handler::Responder;
|
||||||
use httprequest::HttpRequest;
|
use httprequest::HttpRequest;
|
||||||
use httpresponse::{HttpResponse, InnerHttpResponse};
|
use httpresponse::{HttpResponse, InnerHttpResponse};
|
||||||
@ -671,16 +670,7 @@ impl<T> InternalError<T> {
|
|||||||
/// Create `InternalError` with predefined `HttpResponse`.
|
/// Create `InternalError` with predefined `HttpResponse`.
|
||||||
pub fn from_response(cause: T, response: HttpResponse) -> Self {
|
pub fn from_response(cause: T, response: HttpResponse) -> Self {
|
||||||
let mut resp = response.into_inner();
|
let mut resp = response.into_inner();
|
||||||
let body = mem::replace(&mut resp.body, Body::Empty);
|
resp.drop_unsupported_body();
|
||||||
match body {
|
|
||||||
Body::Empty => (),
|
|
||||||
Body::Binary(mut bin) => {
|
|
||||||
resp.body = Body::Binary(bin.take().into());
|
|
||||||
}
|
|
||||||
Body::Streaming(_) | Body::Actor(_) => {
|
|
||||||
error!("Streaming or Actor body is not support by error response");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
InternalError {
|
InternalError {
|
||||||
cause,
|
cause,
|
||||||
|
@ -161,7 +161,7 @@ impl IntoHeaderValue for EntityTag {
|
|||||||
fn try_into(self) -> Result<HeaderValue, Self::Error> {
|
fn try_into(self) -> Result<HeaderValue, Self::Error> {
|
||||||
let mut wrt = Writer::new();
|
let mut wrt = Writer::new();
|
||||||
write!(wrt, "{}", self).unwrap();
|
write!(wrt, "{}", self).unwrap();
|
||||||
unsafe { Ok(HeaderValue::from_shared_unchecked(wrt.take())) }
|
HeaderValue::from_shared(wrt.take())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,11 +64,7 @@ impl IntoHeaderValue for HttpDate {
|
|||||||
fn try_into(self) -> Result<HeaderValue, Self::Error> {
|
fn try_into(self) -> Result<HeaderValue, Self::Error> {
|
||||||
let mut wrt = BytesMut::with_capacity(29).writer();
|
let mut wrt = BytesMut::with_capacity(29).writer();
|
||||||
write!(wrt, "{}", self.0.rfc822()).unwrap();
|
write!(wrt, "{}", self.0.rfc822()).unwrap();
|
||||||
unsafe {
|
HeaderValue::from_shared(wrt.get_mut().take().freeze())
|
||||||
Ok(HeaderValue::from_shared_unchecked(
|
|
||||||
wrt.get_mut().take().freeze(),
|
|
||||||
))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -894,7 +894,9 @@ pub(crate) struct InnerHttpResponse {
|
|||||||
error: Option<Error>,
|
error: Option<Error>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// This is here only because `failure::Fail: Send + Sync` which looks insane to me
|
||||||
unsafe impl Sync for InnerHttpResponse {}
|
unsafe impl Sync for InnerHttpResponse {}
|
||||||
|
/// This is here only because `failure::Fail: Send + Sync` which looks insane to me
|
||||||
unsafe impl Send for InnerHttpResponse {}
|
unsafe impl Send for InnerHttpResponse {}
|
||||||
|
|
||||||
impl InnerHttpResponse {
|
impl InnerHttpResponse {
|
||||||
@ -914,6 +916,20 @@ impl InnerHttpResponse {
|
|||||||
error: None,
|
error: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// This is for failure, we can not have Send + Sync on Streaming and Actor response
|
||||||
|
pub(crate) fn drop_unsupported_body(&mut self) {
|
||||||
|
let body = mem::replace(&mut self.body, Body::Empty);
|
||||||
|
match body {
|
||||||
|
Body::Empty => (),
|
||||||
|
Body::Binary(mut bin) => {
|
||||||
|
self.body = Body::Binary(bin.take().into());
|
||||||
|
}
|
||||||
|
Body::Streaming(_) | Body::Actor(_) => {
|
||||||
|
error!("Streaming or Actor body is not support by error response");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Internal use only! unsafe
|
/// Internal use only! unsafe
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
use http::StatusCode;
|
|
||||||
use smallvec::SmallVec;
|
|
||||||
use std;
|
use std;
|
||||||
use std::ops::Index;
|
use std::ops::Index;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
|
use http::StatusCode;
|
||||||
|
use smallvec::SmallVec;
|
||||||
|
|
||||||
use error::{InternalError, ResponseError, UriSegmentError};
|
use error::{InternalError, ResponseError, UriSegmentError};
|
||||||
use uri::Url;
|
use uri::Url;
|
||||||
|
|
||||||
|
@ -124,7 +124,7 @@ impl<S> PipelineInfo<S> {
|
|||||||
impl<S: 'static, H: PipelineHandler<S>> Pipeline<S, H> {
|
impl<S: 'static, H: PipelineHandler<S>> Pipeline<S, H> {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
req: HttpRequest<S>, mws: Rc<RefCell<Vec<Box<Middleware<S>>>>>,
|
req: HttpRequest<S>, mws: Rc<RefCell<Vec<Box<Middleware<S>>>>>,
|
||||||
handler: Rc<UnsafeCell<H>>, htype: HandlerType,
|
handler: Rc<RefCell<H>>, htype: HandlerType,
|
||||||
) -> Pipeline<S, H> {
|
) -> Pipeline<S, H> {
|
||||||
let mut info = PipelineInfo {
|
let mut info = PipelineInfo {
|
||||||
mws,
|
mws,
|
||||||
@ -133,7 +133,7 @@ impl<S: 'static, H: PipelineHandler<S>> Pipeline<S, H> {
|
|||||||
error: None,
|
error: None,
|
||||||
context: None,
|
context: None,
|
||||||
disconnected: None,
|
disconnected: None,
|
||||||
encoding: unsafe { &*handler.get() }.encoding(),
|
encoding: handler.borrow().encoding(),
|
||||||
};
|
};
|
||||||
let state = StartMiddlewares::init(&mut info, handler, htype);
|
let state = StartMiddlewares::init(&mut info, handler, htype);
|
||||||
|
|
||||||
@ -171,13 +171,12 @@ impl<S: 'static, H: PipelineHandler<S>> HttpHandlerTask for Pipeline<S, H> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn poll_io(&mut self, io: &mut Writer) -> Poll<bool, Error> {
|
fn poll_io(&mut self, io: &mut Writer) -> Poll<bool, Error> {
|
||||||
let info: &mut PipelineInfo<_> = unsafe { &mut *(&mut self.0 as *mut _) };
|
let mut state = mem::replace(&mut self.1, PipelineState::None);
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
if self.1.is_response() {
|
if state.is_response() {
|
||||||
let state = mem::replace(&mut self.1, PipelineState::None);
|
|
||||||
if let PipelineState::Response(st) = state {
|
if let PipelineState::Response(st) = state {
|
||||||
match st.poll_io(io, info) {
|
match st.poll_io(io, &mut self.0) {
|
||||||
Ok(state) => {
|
Ok(state) => {
|
||||||
self.1 = state;
|
self.1 = state;
|
||||||
if let Some(error) = self.0.error.take() {
|
if let Some(error) = self.0.error.take() {
|
||||||
@ -193,7 +192,7 @@ impl<S: 'static, H: PipelineHandler<S>> HttpHandlerTask for Pipeline<S, H> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
match self.1 {
|
match state {
|
||||||
PipelineState::None => return Ok(Async::Ready(true)),
|
PipelineState::None => return Ok(Async::Ready(true)),
|
||||||
PipelineState::Error => {
|
PipelineState::Error => {
|
||||||
return Err(
|
return Err(
|
||||||
@ -203,27 +202,32 @@ impl<S: 'static, H: PipelineHandler<S>> HttpHandlerTask for Pipeline<S, H> {
|
|||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
|
|
||||||
match self.1.poll(info) {
|
match state.poll(&mut self.0) {
|
||||||
Some(state) => self.1 = state,
|
Some(st) => state = st,
|
||||||
None => return Ok(Async::NotReady),
|
None => {
|
||||||
|
return {
|
||||||
|
self.1 = state;
|
||||||
|
Ok(Async::NotReady)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn poll_completed(&mut self) -> Poll<(), Error> {
|
fn poll_completed(&mut self) -> Poll<(), Error> {
|
||||||
let info: &mut PipelineInfo<_> = unsafe { &mut *(&mut self.0 as *mut _) };
|
let mut state = mem::replace(&mut self.1, PipelineState::None);
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
match self.1 {
|
match state {
|
||||||
PipelineState::None | PipelineState::Error => {
|
PipelineState::None | PipelineState::Error => {
|
||||||
return Ok(Async::Ready(()))
|
return Ok(Async::Ready(()))
|
||||||
}
|
}
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(state) = self.1.poll(info) {
|
if let Some(st) = state.poll(&mut self.0) {
|
||||||
self.1 = state;
|
state = st;
|
||||||
} else {
|
} else {
|
||||||
|
self.1 = state;
|
||||||
return Ok(Async::NotReady);
|
return Ok(Async::NotReady);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -234,7 +238,7 @@ type Fut = Box<Future<Item = Option<HttpResponse>, Error = Error>>;
|
|||||||
|
|
||||||
/// Middlewares start executor
|
/// Middlewares start executor
|
||||||
struct StartMiddlewares<S, H> {
|
struct StartMiddlewares<S, H> {
|
||||||
hnd: Rc<UnsafeCell<H>>,
|
hnd: Rc<RefCell<H>>,
|
||||||
htype: HandlerType,
|
htype: HandlerType,
|
||||||
fut: Option<Fut>,
|
fut: Option<Fut>,
|
||||||
_s: PhantomData<S>,
|
_s: PhantomData<S>,
|
||||||
@ -242,14 +246,14 @@ struct StartMiddlewares<S, H> {
|
|||||||
|
|
||||||
impl<S: 'static, H: PipelineHandler<S>> StartMiddlewares<S, H> {
|
impl<S: 'static, H: PipelineHandler<S>> StartMiddlewares<S, H> {
|
||||||
fn init(
|
fn init(
|
||||||
info: &mut PipelineInfo<S>, hnd: Rc<UnsafeCell<H>>, htype: HandlerType,
|
info: &mut PipelineInfo<S>, hnd: Rc<RefCell<H>>, htype: HandlerType,
|
||||||
) -> PipelineState<S, H> {
|
) -> PipelineState<S, H> {
|
||||||
// execute middlewares, we need this stage because middlewares could be
|
// execute middlewares, we need this stage because middlewares could be
|
||||||
// non-async and we can move to next state immediately
|
// non-async and we can move to next state immediately
|
||||||
let len = info.mws.borrow().len() as u16;
|
let len = info.mws.borrow().len() as u16;
|
||||||
loop {
|
loop {
|
||||||
if info.count == len {
|
if info.count == len {
|
||||||
let reply = unsafe { &mut *hnd.get() }.handle(info.req().clone(), htype);
|
let reply = hnd.borrow_mut().handle(info.req().clone(), htype);
|
||||||
return WaitingResponse::init(info, reply);
|
return WaitingResponse::init(info, reply);
|
||||||
} else {
|
} else {
|
||||||
let state =
|
let state =
|
||||||
@ -285,7 +289,9 @@ impl<S: 'static, H: PipelineHandler<S>> StartMiddlewares<S, H> {
|
|||||||
}
|
}
|
||||||
loop {
|
loop {
|
||||||
if info.count == len {
|
if info.count == len {
|
||||||
let reply = unsafe { &mut *self.hnd.get() }
|
let reply = self
|
||||||
|
.hnd
|
||||||
|
.borrow_mut()
|
||||||
.handle(info.req().clone(), self.htype);
|
.handle(info.req().clone(), self.htype);
|
||||||
return Some(WaitingResponse::init(info, reply));
|
return Some(WaitingResponse::init(info, reply));
|
||||||
} else {
|
} else {
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::hash::{Hash, Hasher};
|
use std::hash::{Hash, Hasher};
|
||||||
use std::mem;
|
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
use regex::{escape, Regex};
|
use regex::{escape, Regex};
|
||||||
|
use smallvec::SmallVec;
|
||||||
|
|
||||||
use error::UrlGenerationError;
|
use error::UrlGenerationError;
|
||||||
use httprequest::HttpRequest;
|
use httprequest::HttpRequest;
|
||||||
@ -264,9 +264,9 @@ impl Resource {
|
|||||||
pub fn match_with_params<S>(
|
pub fn match_with_params<S>(
|
||||||
&self, req: &mut HttpRequest<S>, plen: usize, insert: bool,
|
&self, req: &mut HttpRequest<S>, plen: usize, insert: bool,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
let mut segments: [ParamItem; 24] = unsafe { mem::uninitialized() };
|
let mut segments: SmallVec<[ParamItem; 5]> = SmallVec::new();
|
||||||
|
|
||||||
let (names, segments_len) = {
|
let names = {
|
||||||
let path = &req.path()[plen..];
|
let path = &req.path()[plen..];
|
||||||
if insert {
|
if insert {
|
||||||
if path.is_empty() {
|
if path.is_empty() {
|
||||||
@ -282,7 +282,6 @@ impl Resource {
|
|||||||
PatternType::Static(ref s) => return s == path,
|
PatternType::Static(ref s) => return s == path,
|
||||||
PatternType::Dynamic(ref re, ref names, _) => {
|
PatternType::Dynamic(ref re, ref names, _) => {
|
||||||
if let Some(captures) = re.captures(path) {
|
if let Some(captures) = re.captures(path) {
|
||||||
let mut idx = 0;
|
|
||||||
let mut passed = false;
|
let mut passed = false;
|
||||||
for capture in captures.iter() {
|
for capture in captures.iter() {
|
||||||
if let Some(ref m) = capture {
|
if let Some(ref m) = capture {
|
||||||
@ -290,14 +289,13 @@ impl Resource {
|
|||||||
passed = true;
|
passed = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
segments[idx] = ParamItem::UrlSegment(
|
segments.push(ParamItem::UrlSegment(
|
||||||
(plen + m.start()) as u16,
|
(plen + m.start()) as u16,
|
||||||
(plen + m.end()) as u16,
|
(plen + m.end()) as u16,
|
||||||
);
|
));
|
||||||
idx += 1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(names, idx)
|
names
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -309,9 +307,11 @@ impl Resource {
|
|||||||
let len = req.path().len();
|
let len = req.path().len();
|
||||||
let params = req.match_info_mut();
|
let params = req.match_info_mut();
|
||||||
params.set_tail(len as u16);
|
params.set_tail(len as u16);
|
||||||
for idx in 0..segments_len {
|
for (idx, segment) in segments.iter().enumerate() {
|
||||||
|
// reason: Router is part of App, which is unique per thread
|
||||||
|
// app is alive during whole life of tthread
|
||||||
let name = unsafe { &*(names[idx].as_str() as *const _) };
|
let name = unsafe { &*(names[idx].as_str() as *const _) };
|
||||||
params.add(name, segments[idx]);
|
params.add(name, *segment);
|
||||||
}
|
}
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
@ -320,9 +320,9 @@ impl Resource {
|
|||||||
pub fn match_prefix_with_params<S>(
|
pub fn match_prefix_with_params<S>(
|
||||||
&self, req: &mut HttpRequest<S>, plen: usize,
|
&self, req: &mut HttpRequest<S>, plen: usize,
|
||||||
) -> Option<usize> {
|
) -> Option<usize> {
|
||||||
let mut segments: [ParamItem; 24] = unsafe { mem::uninitialized() };
|
let mut segments: SmallVec<[ParamItem; 5]> = SmallVec::new();
|
||||||
|
|
||||||
let (names, segments_len, tail_len) = {
|
let (names, tail_len) = {
|
||||||
let path = &req.path()[plen..];
|
let path = &req.path()[plen..];
|
||||||
let path = if path.is_empty() { "/" } else { path };
|
let path = if path.is_empty() { "/" } else { path };
|
||||||
|
|
||||||
@ -334,7 +334,6 @@ impl Resource {
|
|||||||
},
|
},
|
||||||
PatternType::Dynamic(ref re, ref names, len) => {
|
PatternType::Dynamic(ref re, ref names, len) => {
|
||||||
if let Some(captures) = re.captures(path) {
|
if let Some(captures) = re.captures(path) {
|
||||||
let mut idx = 0;
|
|
||||||
let mut pos = 0;
|
let mut pos = 0;
|
||||||
let mut passed = false;
|
let mut passed = false;
|
||||||
for capture in captures.iter() {
|
for capture in captures.iter() {
|
||||||
@ -344,15 +343,14 @@ impl Resource {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
segments[idx] = ParamItem::UrlSegment(
|
segments.push(ParamItem::UrlSegment(
|
||||||
(plen + m.start()) as u16,
|
(plen + m.start()) as u16,
|
||||||
(plen + m.end()) as u16,
|
(plen + m.end()) as u16,
|
||||||
);
|
));
|
||||||
idx += 1;
|
|
||||||
pos = m.end();
|
pos = m.end();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(names, idx, pos + len)
|
(names, pos + len)
|
||||||
} else {
|
} else {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
@ -378,9 +376,11 @@ impl Resource {
|
|||||||
|
|
||||||
let params = req.match_info_mut();
|
let params = req.match_info_mut();
|
||||||
params.set_tail(tail_len as u16);
|
params.set_tail(tail_len as u16);
|
||||||
for idx in 0..segments_len {
|
for (idx, segment) in segments.iter().enumerate() {
|
||||||
|
// reason: Router is part of App, which is unique per thread
|
||||||
|
// app is alive during whole life of tthread
|
||||||
let name = unsafe { &*(names[idx].as_str() as *const _) };
|
let name = unsafe { &*(names[idx].as_str() as *const _) };
|
||||||
params.add(name, segments[idx]);
|
params.add(name, *segment);
|
||||||
}
|
}
|
||||||
Some(tail_len)
|
Some(tail_len)
|
||||||
}
|
}
|
||||||
|
42
src/scope.rs
42
src/scope.rs
@ -226,27 +226,35 @@ impl<S: 'static> Scope<S> {
|
|||||||
R: Responder + 'static,
|
R: Responder + 'static,
|
||||||
T: FromRequest<S> + 'static,
|
T: FromRequest<S> + 'static,
|
||||||
{
|
{
|
||||||
// get resource handler
|
// check if we have resource handler
|
||||||
let slf: &Scope<S> = unsafe { &*(&self as *const _) };
|
let mut found = false;
|
||||||
for &(ref pattern, ref resource) in slf.resources.iter() {
|
for &(ref pattern, _) in self.resources.iter() {
|
||||||
if pattern.pattern() == path {
|
if pattern.pattern() == path {
|
||||||
resource.borrow_mut().method(method).with(f);
|
found = true;
|
||||||
return self;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut handler = ResourceHandler::default();
|
if found {
|
||||||
handler.method(method).with(f);
|
for &(ref pattern, ref resource) in self.resources.iter() {
|
||||||
let pattern = Resource::with_prefix(
|
if pattern.pattern() == path {
|
||||||
handler.get_name(),
|
resource.borrow_mut().method(method).with(f);
|
||||||
path,
|
break;
|
||||||
if path.is_empty() { "" } else { "/" },
|
}
|
||||||
false,
|
}
|
||||||
);
|
} else {
|
||||||
Rc::get_mut(&mut self.resources)
|
let mut handler = ResourceHandler::default();
|
||||||
.expect("Can not use after configuration")
|
handler.method(method).with(f);
|
||||||
.push((pattern, Rc::new(RefCell::new(handler))));
|
let pattern = Resource::with_prefix(
|
||||||
|
handler.get_name(),
|
||||||
|
path,
|
||||||
|
if path.is_empty() { "" } else { "/" },
|
||||||
|
false,
|
||||||
|
);
|
||||||
|
Rc::get_mut(&mut self.resources)
|
||||||
|
.expect("Can not use after configuration")
|
||||||
|
.push((pattern, Rc::new(RefCell::new(handler))));
|
||||||
|
}
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@ use std::ptr::copy_nonoverlapping;
|
|||||||
/// Mask/unmask a frame.
|
/// Mask/unmask a frame.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn apply_mask(buf: &mut [u8], mask: u32) {
|
pub fn apply_mask(buf: &mut [u8], mask: u32) {
|
||||||
apply_mask_fast32(buf, mask)
|
unsafe { apply_mask_fast32(buf, mask) }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A safe unoptimized mask application.
|
/// A safe unoptimized mask application.
|
||||||
@ -20,9 +20,11 @@ fn apply_mask_fallback(buf: &mut [u8], mask: &[u8; 4]) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Faster version of `apply_mask()` which operates on 8-byte blocks.
|
/// Faster version of `apply_mask()` which operates on 8-byte blocks.
|
||||||
|
///
|
||||||
|
/// unsafe because uses pointer math and bit operations for performance
|
||||||
#[inline]
|
#[inline]
|
||||||
#[cfg_attr(feature = "cargo-clippy", allow(cast_lossless))]
|
#[cfg_attr(feature = "cargo-clippy", allow(cast_lossless))]
|
||||||
fn apply_mask_fast32(buf: &mut [u8], mask_u32: u32) {
|
unsafe fn apply_mask_fast32(buf: &mut [u8], mask_u32: u32) {
|
||||||
let mut ptr = buf.as_mut_ptr();
|
let mut ptr = buf.as_mut_ptr();
|
||||||
let mut len = buf.len();
|
let mut len = buf.len();
|
||||||
|
|
||||||
@ -32,10 +34,8 @@ fn apply_mask_fast32(buf: &mut [u8], mask_u32: u32) {
|
|||||||
let n = if head > 4 { head - 4 } else { head };
|
let n = if head > 4 { head - 4 } else { head };
|
||||||
|
|
||||||
let mask_u32 = if n > 0 {
|
let mask_u32 = if n > 0 {
|
||||||
unsafe {
|
xor_mem(ptr, mask_u32, n);
|
||||||
xor_mem(ptr, mask_u32, n);
|
ptr = ptr.offset(head as isize);
|
||||||
ptr = ptr.offset(head as isize);
|
|
||||||
}
|
|
||||||
len -= n;
|
len -= n;
|
||||||
if cfg!(target_endian = "big") {
|
if cfg!(target_endian = "big") {
|
||||||
mask_u32.rotate_left(8 * n as u32)
|
mask_u32.rotate_left(8 * n as u32)
|
||||||
@ -47,11 +47,9 @@ fn apply_mask_fast32(buf: &mut [u8], mask_u32: u32) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
if head > 4 {
|
if head > 4 {
|
||||||
unsafe {
|
*(ptr as *mut u32) ^= mask_u32;
|
||||||
*(ptr as *mut u32) ^= mask_u32;
|
ptr = ptr.offset(4);
|
||||||
ptr = ptr.offset(4);
|
len -= 4;
|
||||||
len -= 4;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
mask_u32
|
mask_u32
|
||||||
} else {
|
} else {
|
||||||
@ -68,27 +66,21 @@ fn apply_mask_fast32(buf: &mut [u8], mask_u32: u32) {
|
|||||||
mask_u64 = mask_u64 << 32 | mask_u32 as u64;
|
mask_u64 = mask_u64 << 32 | mask_u32 as u64;
|
||||||
|
|
||||||
while len >= 8 {
|
while len >= 8 {
|
||||||
unsafe {
|
*(ptr as *mut u64) ^= mask_u64;
|
||||||
*(ptr as *mut u64) ^= mask_u64;
|
ptr = ptr.offset(8);
|
||||||
ptr = ptr.offset(8);
|
len -= 8;
|
||||||
len -= 8;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
while len >= 4 {
|
while len >= 4 {
|
||||||
unsafe {
|
*(ptr as *mut u32) ^= mask_u32;
|
||||||
*(ptr as *mut u32) ^= mask_u32;
|
ptr = ptr.offset(4);
|
||||||
ptr = ptr.offset(4);
|
len -= 4;
|
||||||
len -= 4;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Possible last block.
|
// Possible last block.
|
||||||
if len > 0 {
|
if len > 0 {
|
||||||
unsafe {
|
xor_mem(ptr, mask_u32, len);
|
||||||
xor_mem(ptr, mask_u32, len);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -107,7 +99,7 @@ unsafe fn xor_mem(ptr: *mut u8, mask: u32, len: usize) {
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::{apply_mask_fallback, apply_mask_fast32};
|
use super::{apply_mask, apply_mask_fallback};
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -126,7 +118,7 @@ mod tests {
|
|||||||
apply_mask_fallback(&mut masked, &mask);
|
apply_mask_fallback(&mut masked, &mask);
|
||||||
|
|
||||||
let mut masked_fast = unmasked.clone();
|
let mut masked_fast = unmasked.clone();
|
||||||
apply_mask_fast32(&mut masked_fast, mask_u32);
|
apply_mask(&mut masked_fast, mask_u32);
|
||||||
|
|
||||||
assert_eq!(masked, masked_fast);
|
assert_eq!(masked, masked_fast);
|
||||||
}
|
}
|
||||||
@ -137,7 +129,7 @@ mod tests {
|
|||||||
apply_mask_fallback(&mut masked[1..], &mask);
|
apply_mask_fallback(&mut masked[1..], &mask);
|
||||||
|
|
||||||
let mut masked_fast = unmasked.clone();
|
let mut masked_fast = unmasked.clone();
|
||||||
apply_mask_fast32(&mut masked_fast[1..], mask_u32);
|
apply_mask(&mut masked_fast[1..], mask_u32);
|
||||||
|
|
||||||
assert_eq!(masked, masked_fast);
|
assert_eq!(masked, masked_fast);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user