mirror of
https://github.com/actix/actix-extras.git
synced 2024-12-01 02:44:37 +01:00
Fix some unsoundness
This improves the sound implementation of `fn route`. Previously this function would iterate twice but we can reduce the overhead without using `unsafe`.
This commit is contained in:
parent
2f917f3700
commit
234c60d473
@ -335,33 +335,34 @@ where
|
|||||||
T: FromRequest<S> + 'static,
|
T: FromRequest<S> + 'static,
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
let parts = self.parts.as_mut().expect("Use after finish");
|
let parts: &mut ApplicationParts<S> = self.parts.as_mut().expect("Use after finish");
|
||||||
|
|
||||||
// get resource handler
|
let out = {
|
||||||
let mut found = false;
|
// get resource handler
|
||||||
for &mut (ref pattern, ref handler) in &mut parts.resources {
|
let mut iterator = parts.resources.iter_mut();
|
||||||
if handler.is_some() && pattern.pattern() == path {
|
|
||||||
found = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if !found {
|
loop {
|
||||||
let mut handler = ResourceHandler::default();
|
if let Some(&mut (ref pattern, ref mut handler)) = iterator.next() {
|
||||||
handler.method(method).with(f);
|
if let Some(ref mut handler) = *handler {
|
||||||
let pattern = Resource::new(handler.get_name(), path);
|
if pattern.pattern() == path {
|
||||||
parts.resources.push((pattern, Some(handler)));
|
handler.method(method).with(f);
|
||||||
} else {
|
break None;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
let mut handler = ResourceHandler::default();
|
||||||
|
handler.method(method).with(f);
|
||||||
|
let pattern = Resource::new(handler.get_name(), path);
|
||||||
|
break Some((pattern, Some(handler)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some(out) = out {
|
||||||
|
parts.resources.push(out);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
//! Multipart requests support
|
//! Multipart requests support
|
||||||
use std::cell::RefCell;
|
use std::cell::{RefCell, UnsafeCell};
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use std::{cmp, fmt};
|
use std::{cmp, fmt};
|
||||||
@ -590,7 +590,7 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct PayloadRef<S> {
|
struct PayloadRef<S> {
|
||||||
payload: Rc<PayloadHelper<S>>,
|
payload: Rc<UnsafeCell<PayloadHelper<S>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S> PayloadRef<S>
|
impl<S> PayloadRef<S>
|
||||||
@ -599,7 +599,7 @@ where
|
|||||||
{
|
{
|
||||||
fn new(payload: PayloadHelper<S>) -> PayloadRef<S> {
|
fn new(payload: PayloadHelper<S>) -> PayloadRef<S> {
|
||||||
PayloadRef {
|
PayloadRef {
|
||||||
payload: Rc::new(payload),
|
payload: Rc::new(payload.into()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -609,7 +609,7 @@ where
|
|||||||
{
|
{
|
||||||
if s.current() {
|
if s.current() {
|
||||||
let payload: &mut PayloadHelper<S> =
|
let payload: &mut PayloadHelper<S> =
|
||||||
unsafe { &mut *(self.payload.as_ref() as *const _ as *mut _) };
|
unsafe { &mut *self.payload.get() };
|
||||||
Some(payload)
|
Some(payload)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
|
@ -73,12 +73,11 @@ impl<T: AsyncWrite, H: 'static> H1Writer<T, H> {
|
|||||||
self.flags.contains(Flags::KEEPALIVE) && !self.flags.contains(Flags::UPGRADE)
|
self.flags.contains(Flags::KEEPALIVE) && !self.flags.contains(Flags::UPGRADE)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_data(&mut self, data: &[u8]) -> io::Result<usize> {
|
fn write_data(stream: &mut T, data: &[u8]) -> io::Result<usize> {
|
||||||
let mut written = 0;
|
let mut written = 0;
|
||||||
while written < data.len() {
|
while written < data.len() {
|
||||||
match self.stream.write(&data[written..]) {
|
match stream.write(&data[written..]) {
|
||||||
Ok(0) => {
|
Ok(0) => {
|
||||||
self.disconnected();
|
|
||||||
return Err(io::Error::new(io::ErrorKind::WriteZero, ""));
|
return Err(io::Error::new(io::ErrorKind::WriteZero, ""));
|
||||||
}
|
}
|
||||||
Ok(n) => {
|
Ok(n) => {
|
||||||
@ -243,7 +242,16 @@ impl<T: AsyncWrite, H: 'static> Writer for H1Writer<T, H> {
|
|||||||
if self.flags.contains(Flags::UPGRADE) {
|
if self.flags.contains(Flags::UPGRADE) {
|
||||||
if self.buffer.is_empty() {
|
if self.buffer.is_empty() {
|
||||||
let pl: &[u8] = payload.as_ref();
|
let pl: &[u8] = payload.as_ref();
|
||||||
let n = self.write_data(pl)?;
|
let n = match Self::write_data(&mut self.stream, pl) {
|
||||||
|
Err(err) => {
|
||||||
|
if err.kind() == io::ErrorKind::WriteZero {
|
||||||
|
self.disconnected();
|
||||||
|
}
|
||||||
|
|
||||||
|
return Err(err);
|
||||||
|
}
|
||||||
|
Ok(val) => val,
|
||||||
|
};
|
||||||
if n < pl.len() {
|
if n < pl.len() {
|
||||||
self.buffer.extend_from_slice(&pl[n..]);
|
self.buffer.extend_from_slice(&pl[n..]);
|
||||||
return Ok(WriterState::Done);
|
return Ok(WriterState::Done);
|
||||||
@ -284,9 +292,18 @@ impl<T: AsyncWrite, H: 'static> Writer for H1Writer<T, H> {
|
|||||||
#[inline]
|
#[inline]
|
||||||
fn poll_completed(&mut self, shutdown: bool) -> Poll<(), io::Error> {
|
fn poll_completed(&mut self, shutdown: bool) -> Poll<(), io::Error> {
|
||||||
if !self.buffer.is_empty() {
|
if !self.buffer.is_empty() {
|
||||||
let buf: &[u8] =
|
let written = {
|
||||||
unsafe { &mut *(self.buffer.as_ref() as *const _ as *mut _) };
|
match Self::write_data(&mut self.stream, self.buffer.as_ref()) {
|
||||||
let written = self.write_data(buf)?;
|
Err(err) => {
|
||||||
|
if err.kind() == io::ErrorKind::WriteZero {
|
||||||
|
self.disconnected();
|
||||||
|
}
|
||||||
|
|
||||||
|
return Err(err);
|
||||||
|
}
|
||||||
|
Ok(val) => val,
|
||||||
|
}
|
||||||
|
};
|
||||||
let _ = self.buffer.split_to(written);
|
let _ = self.buffer.split_to(written);
|
||||||
if shutdown && !self.buffer.is_empty()
|
if shutdown && !self.buffer.is_empty()
|
||||||
|| (self.buffer.len() > self.buffer_capacity)
|
|| (self.buffer.len() > self.buffer_capacity)
|
||||||
|
Loading…
Reference in New Issue
Block a user