1
0
mirror of https://github.com/actix/actix-extras.git synced 2024-11-27 17:22:57 +01:00

port Extensions from http crate #315

This commit is contained in:
Nikolay Kim 2018-06-17 03:22:08 +06:00
parent 33050f55a3
commit 879b2b5bde
4 changed files with 96 additions and 1 deletions

View File

@ -57,6 +57,7 @@ base64 = "0.9"
bitflags = "1.0"
failure = "0.1.1"
h2 = "0.1"
fnv = "1.0.5"
http = "^0.1.5"
httparse = "1.2"
http-range = "0.1"

90
src/extensions.rs Normal file
View File

@ -0,0 +1,90 @@
use std::any::{Any, TypeId};
use std::collections::HashMap;
use std::fmt;
use std::hash::BuildHasherDefault;
use fnv::FnvHasher;
type AnyMap = HashMap<TypeId, Box<Any>, BuildHasherDefault<FnvHasher>>;
/// A type map of request extensions.
pub struct Extensions {
map: AnyMap,
}
impl Extensions {
/// Create an empty `Extensions`.
#[inline]
pub(crate) fn new() -> Extensions {
Extensions {
map: HashMap::default(),
}
}
/// Insert a type into this `Extensions`.
///
/// If a extension of this type already existed, it will
/// be returned.
pub fn insert<T: 'static>(&mut self, val: T) {
self.map.insert(TypeId::of::<T>(), Box::new(val));
}
/// Get a reference to a type previously inserted on this `Extensions`.
pub fn get<T: 'static>(&self) -> Option<&T> {
self.map
.get(&TypeId::of::<T>())
.and_then(|boxed| (&**boxed as &(Any + 'static)).downcast_ref())
}
/// Get a mutable reference to a type previously inserted on this `Extensions`.
pub fn get_mut<T: 'static>(&mut self) -> Option<&mut T> {
self.map
.get_mut(&TypeId::of::<T>())
.and_then(|boxed| (&mut **boxed as &mut (Any + 'static)).downcast_mut())
}
/// Remove a type from this `Extensions`.
///
/// If a extension of this type existed, it will be returned.
pub fn remove<T: 'static>(&mut self) -> Option<T> {
self.map.remove(&TypeId::of::<T>()).and_then(|boxed| {
//TODO: we can use unsafe and remove double checking the type id
(boxed as Box<Any + 'static>)
.downcast()
.ok()
.map(|boxed| *boxed)
})
}
/// Clear the `Extensions` of all inserted extensions.
#[inline]
pub fn clear(&mut self) {
self.map.clear();
}
}
impl fmt::Debug for Extensions {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("Extensions").finish()
}
}
#[test]
fn test_extensions() {
#[derive(Debug, PartialEq)]
struct MyType(i32);
let mut extensions = Extensions::new();
extensions.insert(5i32);
extensions.insert(MyType(10));
assert_eq!(extensions.get(), Some(&5i32));
assert_eq!(extensions.get_mut(), Some(&mut 5i32));
assert_eq!(extensions.remove::<i32>(), Some(5i32));
assert!(extensions.get::<i32>().is_none());
assert_eq!(extensions.get::<bool>(), None);
assert_eq!(extensions.get(), Some(&MyType(10)));
}

View File

@ -9,12 +9,13 @@ use cookie::Cookie;
use failure;
use futures::{Async, Poll, Stream};
use futures_cpupool::CpuPool;
use http::{header, Extensions, HeaderMap, Method, StatusCode, Uri, Version};
use http::{header, HeaderMap, Method, StatusCode, Uri, Version};
use tokio_io::AsyncRead;
use url::{form_urlencoded, Url};
use body::Body;
use error::{CookieParseError, PayloadError, UrlGenerationError};
use extensions::Extensions;
use handler::FromRequest;
use httpmessage::HttpMessage;
use httpresponse::{HttpResponse, HttpResponseBuilder};

View File

@ -97,6 +97,7 @@ extern crate time;
extern crate bitflags;
#[macro_use]
extern crate failure;
extern crate fnv;
#[macro_use]
extern crate lazy_static;
#[macro_use]
@ -155,6 +156,7 @@ mod application;
mod body;
mod context;
mod de;
mod extensions;
mod extractor;
mod handler;
mod header;
@ -188,6 +190,7 @@ pub use application::App;
pub use body::{Binary, Body};
pub use context::HttpContext;
pub use error::{Error, ResponseError, Result};
pub use extensions::Extensions;
pub use extractor::{Form, Path, Query};
pub use handler::{
AsyncResponder, Either, FromRequest, FutureResponse, Responder, State,