mirror of
https://github.com/fafhrd91/actix-net
synced 2025-08-13 07:18:22 +02:00
Compare commits
9 Commits
utils-v0.3
...
connect-v0
Author | SHA1 | Date | |
---|---|---|---|
|
b9d8a215b4 | ||
|
51c4dfe5cb | ||
|
a60112c71e | ||
|
bd814d6f80 | ||
|
a4e0c71baa | ||
|
b9ea445e70 | ||
|
ba2901269d | ||
|
5cbc29306a | ||
|
33cd51aabf |
@@ -1,6 +1,16 @@
|
|||||||
# Changes
|
# Changes
|
||||||
|
|
||||||
## [0.1.2] - 2019-04-xx
|
## [0.1.3] - 2019-04-11
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
* Start trust-dns default resolver on first use
|
||||||
|
|
||||||
|
## [0.1.2] - 2019-04-04
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
* Log error if dns system config could not be loaded.
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "actix-connect"
|
name = "actix-connect"
|
||||||
version = "0.1.2"
|
version = "0.1.3"
|
||||||
authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
|
authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
|
||||||
description = "Actix Connector - tcp connector service"
|
description = "Actix Connector - tcp connector service"
|
||||||
keywords = ["network", "framework", "async", "futures"]
|
keywords = ["network", "framework", "async", "futures"]
|
||||||
@@ -30,9 +30,9 @@ ssl = ["openssl", "tokio-openssl"]
|
|||||||
uri = ["http"]
|
uri = ["http"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
actix-service = "0.3.4"
|
actix-service = "0.3.6"
|
||||||
actix-codec = "0.1.1"
|
actix-codec = "0.1.2"
|
||||||
actix-utils = "0.3.4"
|
actix-utils = "0.3.5"
|
||||||
derive_more = "0.14.0"
|
derive_more = "0.14.0"
|
||||||
either = "1.5.1"
|
either = "1.5.1"
|
||||||
futures = "0.1.25"
|
futures = "0.1.25"
|
||||||
@@ -40,7 +40,7 @@ http = { version = "0.1.16", optional = true }
|
|||||||
log = "0.4"
|
log = "0.4"
|
||||||
tokio-tcp = "0.1.3"
|
tokio-tcp = "0.1.3"
|
||||||
tokio-current-thread = "0.1.5"
|
tokio-current-thread = "0.1.5"
|
||||||
trust-dns-resolver = { version="0.11.0-alpha.2", default-features = false }
|
trust-dns-resolver = { version="0.11.0-alpha.3", default-features = false }
|
||||||
|
|
||||||
# openssl
|
# openssl
|
||||||
openssl = { version="0.10", optional = true }
|
openssl = { version="0.10", optional = true }
|
||||||
|
@@ -8,6 +8,8 @@
|
|||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate log;
|
extern crate log;
|
||||||
|
|
||||||
|
use std::cell::RefCell;
|
||||||
|
|
||||||
mod connect;
|
mod connect;
|
||||||
mod connector;
|
mod connector;
|
||||||
mod error;
|
mod error;
|
||||||
@@ -17,6 +19,8 @@ pub mod ssl;
|
|||||||
#[cfg(feature = "uri")]
|
#[cfg(feature = "uri")]
|
||||||
mod uri;
|
mod uri;
|
||||||
|
|
||||||
|
pub use trust_dns_resolver::config::{ResolverConfig, ResolverOpts};
|
||||||
|
pub use trust_dns_resolver::system_conf::read_system_conf;
|
||||||
pub use trust_dns_resolver::{error::ResolveError, AsyncResolver};
|
pub use trust_dns_resolver::{error::ResolveError, AsyncResolver};
|
||||||
|
|
||||||
pub use self::connect::{Address, Connect, Connection};
|
pub use self::connect::{Address, Connect, Connection};
|
||||||
@@ -26,8 +30,6 @@ pub use self::resolver::{Resolver, ResolverFactory};
|
|||||||
|
|
||||||
use actix_service::{NewService, Service, ServiceExt};
|
use actix_service::{NewService, Service, ServiceExt};
|
||||||
use tokio_tcp::TcpStream;
|
use tokio_tcp::TcpStream;
|
||||||
use trust_dns_resolver::config::{ResolverConfig, ResolverOpts};
|
|
||||||
use trust_dns_resolver::system_conf::read_system_conf;
|
|
||||||
|
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
#[deprecated(since = "0.1.2", note = "please use `actix_connect::TcpConnector`")]
|
#[deprecated(since = "0.1.2", note = "please use `actix_connect::TcpConnector`")]
|
||||||
@@ -46,16 +48,34 @@ pub fn start_resolver(cfg: ResolverConfig, opts: ResolverOpts) -> AsyncResolver
|
|||||||
resolver
|
resolver
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn start_default_resolver() -> AsyncResolver {
|
thread_local! {
|
||||||
let (cfg, opts) = if let Ok((cfg, opts)) = read_system_conf() {
|
static DEFAULT_RESOLVER: RefCell<Option<AsyncResolver>> = RefCell::new(None);
|
||||||
(cfg, opts)
|
}
|
||||||
} else {
|
|
||||||
(ResolverConfig::default(), ResolverOpts::default())
|
|
||||||
};
|
|
||||||
|
|
||||||
let (resolver, bg) = AsyncResolver::new(cfg, opts);
|
pub(crate) fn get_default_resolver() -> AsyncResolver {
|
||||||
tokio_current_thread::spawn(bg);
|
DEFAULT_RESOLVER.with(|cell| {
|
||||||
resolver
|
if let Some(ref resolver) = *cell.borrow() {
|
||||||
|
return resolver.clone();
|
||||||
|
}
|
||||||
|
|
||||||
|
let (cfg, opts) = match read_system_conf() {
|
||||||
|
Ok((cfg, opts)) => (cfg, opts),
|
||||||
|
Err(e) => {
|
||||||
|
log::error!("TRust-DNS can not load system config: {}", e);
|
||||||
|
(ResolverConfig::default(), ResolverOpts::default())
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let (resolver, bg) = AsyncResolver::new(cfg, opts);
|
||||||
|
tokio_current_thread::spawn(bg);
|
||||||
|
|
||||||
|
*cell.borrow_mut() = Some(resolver.clone());
|
||||||
|
resolver
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn start_default_resolver() -> AsyncResolver {
|
||||||
|
get_default_resolver()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create tcp connector service
|
/// Create tcp connector service
|
||||||
|
@@ -10,10 +10,11 @@ use trust_dns_resolver::{AsyncResolver, Background};
|
|||||||
|
|
||||||
use crate::connect::{Address, Connect};
|
use crate::connect::{Address, Connect};
|
||||||
use crate::error::ConnectError;
|
use crate::error::ConnectError;
|
||||||
|
use crate::get_default_resolver;
|
||||||
|
|
||||||
/// DNS Resolver Service factory
|
/// DNS Resolver Service factory
|
||||||
pub struct ResolverFactory<T> {
|
pub struct ResolverFactory<T> {
|
||||||
resolver: AsyncResolver,
|
resolver: Option<AsyncResolver>,
|
||||||
_t: PhantomData<T>,
|
_t: PhantomData<T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -21,13 +22,18 @@ impl<T> ResolverFactory<T> {
|
|||||||
/// Create new resolver instance with custom configuration and options.
|
/// Create new resolver instance with custom configuration and options.
|
||||||
pub fn new(resolver: AsyncResolver) -> Self {
|
pub fn new(resolver: AsyncResolver) -> Self {
|
||||||
ResolverFactory {
|
ResolverFactory {
|
||||||
resolver,
|
resolver: Some(resolver),
|
||||||
_t: PhantomData,
|
_t: PhantomData,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn resolver(&self) -> &AsyncResolver {
|
impl<T> Default for ResolverFactory<T> {
|
||||||
&self.resolver
|
fn default() -> Self {
|
||||||
|
ResolverFactory {
|
||||||
|
resolver: None,
|
||||||
|
_t: PhantomData,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -58,7 +64,7 @@ impl<T: Address> NewService for ResolverFactory<T> {
|
|||||||
|
|
||||||
/// DNS Resolver Service
|
/// DNS Resolver Service
|
||||||
pub struct Resolver<T> {
|
pub struct Resolver<T> {
|
||||||
resolver: AsyncResolver,
|
resolver: Option<AsyncResolver>,
|
||||||
_t: PhantomData<T>,
|
_t: PhantomData<T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -66,7 +72,16 @@ impl<T> Resolver<T> {
|
|||||||
/// Create new resolver instance with custom configuration and options.
|
/// Create new resolver instance with custom configuration and options.
|
||||||
pub fn new(resolver: AsyncResolver) -> Self {
|
pub fn new(resolver: AsyncResolver) -> Self {
|
||||||
Resolver {
|
Resolver {
|
||||||
resolver,
|
resolver: Some(resolver),
|
||||||
|
_t: PhantomData,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Default for Resolver<T> {
|
||||||
|
fn default() -> Self {
|
||||||
|
Resolver {
|
||||||
|
resolver: None,
|
||||||
_t: PhantomData,
|
_t: PhantomData,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -100,7 +115,10 @@ impl<T: Address> Service for Resolver<T> {
|
|||||||
Either::B(ok(req))
|
Either::B(ok(req))
|
||||||
} else {
|
} else {
|
||||||
trace!("DNS resolver: resolving host {:?}", req.host());
|
trace!("DNS resolver: resolving host {:?}", req.host());
|
||||||
Either::A(ResolverFuture::new(req, &self.resolver))
|
if self.resolver.is_none() {
|
||||||
|
self.resolver = Some(get_default_resolver());
|
||||||
|
}
|
||||||
|
Either::A(ResolverFuture::new(req, self.resolver.as_ref().unwrap()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,5 +1,12 @@
|
|||||||
# Changes
|
# Changes
|
||||||
|
|
||||||
|
## [0.3.6] - 2019-04-07
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
* Poll boxed service call result immediately
|
||||||
|
|
||||||
|
|
||||||
## [0.3.5] - 2019-03-29
|
## [0.3.5] - 2019-03-29
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "actix-service"
|
name = "actix-service"
|
||||||
version = "0.3.5"
|
version = "0.3.6"
|
||||||
authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
|
authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
|
||||||
description = "Actix Service"
|
description = "Actix Service"
|
||||||
keywords = ["network", "framework", "async", "futures"]
|
keywords = ["network", "framework", "async", "futures"]
|
||||||
|
@@ -1,12 +1,14 @@
|
|||||||
|
use futures::future::{err, ok, Either, FutureResult};
|
||||||
|
use futures::{Async, Future, IntoFuture, Poll};
|
||||||
|
|
||||||
use crate::{NewService, Service};
|
use crate::{NewService, Service};
|
||||||
use futures::{Future, IntoFuture, Poll};
|
|
||||||
|
|
||||||
pub type BoxedService<Req, Res, Err> = Box<
|
pub type BoxedService<Req, Res, Err> = Box<
|
||||||
Service<
|
Service<
|
||||||
Request = Req,
|
Request = Req,
|
||||||
Response = Res,
|
Response = Res,
|
||||||
Error = Err,
|
Error = Err,
|
||||||
Future = Box<Future<Item = Res, Error = Err>>,
|
Future = Either<FutureResult<Res, Err>, Box<Future<Item = Res, Error = Err>>>,
|
||||||
>,
|
>,
|
||||||
>;
|
>;
|
||||||
|
|
||||||
@@ -125,13 +127,21 @@ where
|
|||||||
type Request = Req;
|
type Request = Req;
|
||||||
type Response = Res;
|
type Response = Res;
|
||||||
type Error = Err;
|
type Error = Err;
|
||||||
type Future = Box<Future<Item = Self::Response, Error = Self::Error>>;
|
type Future = Either<
|
||||||
|
FutureResult<Self::Response, Self::Error>,
|
||||||
|
Box<Future<Item = Self::Response, Error = Self::Error>>,
|
||||||
|
>;
|
||||||
|
|
||||||
fn poll_ready(&mut self) -> Poll<(), Self::Error> {
|
fn poll_ready(&mut self) -> Poll<(), Self::Error> {
|
||||||
self.0.poll_ready()
|
self.0.poll_ready()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn call(&mut self, req: Self::Request) -> Self::Future {
|
fn call(&mut self, req: Self::Request) -> Self::Future {
|
||||||
Box::new(self.0.call(req))
|
let mut fut = self.0.call(req);
|
||||||
|
match fut.poll() {
|
||||||
|
Ok(Async::Ready(res)) => Either::A(ok(res)),
|
||||||
|
Err(e) => Either::A(err(e)),
|
||||||
|
Ok(Async::NotReady) => Either::B(Box::new(fut)),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -6,9 +6,16 @@ use futures::{Async, Future, IntoFuture, Poll};
|
|||||||
use crate::transform_err::{TransformFromErr, TransformMapInitErr};
|
use crate::transform_err::{TransformFromErr, TransformMapInitErr};
|
||||||
use crate::{IntoNewService, NewService, Service};
|
use crate::{IntoNewService, NewService, Service};
|
||||||
|
|
||||||
/// `Transform` service factory.
|
/// The `Transform` trait defines the interface of a Service factory. `Transform`
|
||||||
|
/// is often implemented for middleware, defining how to manufacture a
|
||||||
|
/// middleware Service. A Service that is manufactured by the factory takes
|
||||||
|
/// the Service that follows it during execution as a parameter, assuming
|
||||||
|
/// ownership of the next Service. A Service can be a variety of types, such
|
||||||
|
/// as (but not limited to) another middleware Service, an extractor Service,
|
||||||
|
/// other helper Services, or the request handler endpoint Service.
|
||||||
|
///
|
||||||
|
/// A Service is created by the factory during server initialization.
|
||||||
///
|
///
|
||||||
/// Transform factory creates service that wraps other services.
|
|
||||||
/// `Config` is a service factory configuration type.
|
/// `Config` is a service factory configuration type.
|
||||||
pub trait Transform<S> {
|
pub trait Transform<S> {
|
||||||
/// Requests handled by the service.
|
/// Requests handled by the service.
|
||||||
@@ -33,7 +40,7 @@ pub trait Transform<S> {
|
|||||||
/// The future response value.
|
/// The future response value.
|
||||||
type Future: Future<Item = Self::Transform, Error = Self::InitError>;
|
type Future: Future<Item = Self::Transform, Error = Self::InitError>;
|
||||||
|
|
||||||
/// Create and return a new service value asynchronously.
|
/// Creates and returns a new Service component, asynchronously
|
||||||
fn new_transform(&self, service: S) -> Self::Future;
|
fn new_transform(&self, service: S) -> Self::Future;
|
||||||
|
|
||||||
/// Map this service's factory error to a different error,
|
/// Map this service's factory error to a different error,
|
||||||
|
@@ -1,5 +1,11 @@
|
|||||||
# Changes
|
# Changes
|
||||||
|
|
||||||
|
## [0.1.2] - 2019-04-07
|
||||||
|
|
||||||
|
* Export `Quoter` type
|
||||||
|
|
||||||
|
* Allow to reset `Path` instance
|
||||||
|
|
||||||
## [0.1.1] - 2019-04-03
|
## [0.1.1] - 2019-04-03
|
||||||
|
|
||||||
* Get dynamic segment by name instead of iterator.
|
* Get dynamic segment by name instead of iterator.
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "actix-router"
|
name = "actix-router"
|
||||||
version = "0.1.1"
|
version = "0.1.2"
|
||||||
authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
|
authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
|
||||||
description = "Path router"
|
description = "Path router"
|
||||||
keywords = ["actix"]
|
keywords = ["actix"]
|
||||||
|
@@ -39,7 +39,7 @@ impl<T: AsRef<[u8]>> ResourcePath for string::String<T> {
|
|||||||
mod url;
|
mod url;
|
||||||
|
|
||||||
#[cfg(feature = "http")]
|
#[cfg(feature = "http")]
|
||||||
pub use self::url::Url;
|
pub use self::url::{Quoter, Url};
|
||||||
|
|
||||||
#[cfg(feature = "http")]
|
#[cfg(feature = "http")]
|
||||||
mod http_support {
|
mod http_support {
|
||||||
|
@@ -51,16 +51,19 @@ impl<T: ResourcePath> Path<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
/// Get reference to inner path instance
|
/// Get reference to inner path instance
|
||||||
pub fn get_ref(&self) -> &T {
|
pub fn get_ref(&self) -> &T {
|
||||||
&self.path
|
&self.path
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
/// Get mutable reference to inner path instance
|
/// Get mutable reference to inner path instance
|
||||||
pub fn get_mut(&mut self) -> &mut T {
|
pub fn get_mut(&mut self) -> &mut T {
|
||||||
&mut self.path
|
&mut self.path
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
/// Path
|
/// Path
|
||||||
pub fn path(&self) -> &str {
|
pub fn path(&self) -> &str {
|
||||||
let skip = self.skip as usize;
|
let skip = self.skip as usize;
|
||||||
@@ -72,13 +75,22 @@ impl<T: ResourcePath> Path<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Reset inner path
|
#[inline]
|
||||||
|
/// Set new path
|
||||||
pub fn set(&mut self, path: T) {
|
pub fn set(&mut self, path: T) {
|
||||||
self.skip = 0;
|
self.skip = 0;
|
||||||
self.path = path;
|
self.path = path;
|
||||||
self.segments.clear();
|
self.segments.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
/// Reset state
|
||||||
|
pub fn reset(&mut self) {
|
||||||
|
self.skip = 0;
|
||||||
|
self.segments.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
/// Skip first `n` chars in path
|
/// Skip first `n` chars in path
|
||||||
pub fn skip(&mut self, n: u16) {
|
pub fn skip(&mut self, n: u16) {
|
||||||
self.skip = self.skip + n;
|
self.skip = self.skip + n;
|
||||||
@@ -99,11 +111,13 @@ impl<T: ResourcePath> Path<T> {
|
|||||||
.push((Rc::new(name.to_string()), PathItem::Static(value)));
|
.push((Rc::new(name.to_string()), PathItem::Static(value)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
/// Check if there are any matched patterns
|
/// Check if there are any matched patterns
|
||||||
pub fn is_empty(&self) -> bool {
|
pub fn is_empty(&self) -> bool {
|
||||||
self.segments.is_empty()
|
self.segments.is_empty()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
/// Check number of extracted parameters
|
/// Check number of extracted parameters
|
||||||
pub fn len(&self) -> usize {
|
pub fn len(&self) -> usize {
|
||||||
self.segments.len()
|
self.segments.len()
|
||||||
|
@@ -118,6 +118,7 @@ impl ResourceDef {
|
|||||||
&self.pattern
|
&self.pattern
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
/// Check if path matchs this pattern?
|
/// Check if path matchs this pattern?
|
||||||
pub fn is_match(&self, path: &str) -> bool {
|
pub fn is_match(&self, path: &str) -> bool {
|
||||||
match self.tp {
|
match self.tp {
|
||||||
|
@@ -1,5 +1,3 @@
|
|||||||
use std::rc::Rc;
|
|
||||||
|
|
||||||
use crate::ResourcePath;
|
use crate::ResourcePath;
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
@@ -39,7 +37,7 @@ thread_local! {
|
|||||||
#[derive(Default, Clone, Debug)]
|
#[derive(Default, Clone, Debug)]
|
||||||
pub struct Url {
|
pub struct Url {
|
||||||
uri: http::Uri,
|
uri: http::Uri,
|
||||||
path: Option<Rc<String>>,
|
path: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Url {
|
impl Url {
|
||||||
@@ -49,6 +47,13 @@ impl Url {
|
|||||||
Url { uri, path }
|
Url { uri, path }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn with_quoter(uri: http::Uri, quoter: &Quoter) -> Url {
|
||||||
|
Url {
|
||||||
|
path: quoter.requote(uri.path().as_bytes()),
|
||||||
|
uri,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn uri(&self) -> &http::Uri {
|
pub fn uri(&self) -> &http::Uri {
|
||||||
&self.uri
|
&self.uri
|
||||||
}
|
}
|
||||||
@@ -61,19 +66,27 @@ impl Url {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
pub fn update(&mut self, uri: &http::Uri) {
|
pub fn update(&mut self, uri: &http::Uri) {
|
||||||
self.uri = uri.clone();
|
self.uri = uri.clone();
|
||||||
self.path = DEFAULT_QUOTER.with(|q| q.requote(uri.path().as_bytes()));
|
self.path = DEFAULT_QUOTER.with(|q| q.requote(uri.path().as_bytes()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn update_with_quoter(&mut self, uri: &http::Uri, quoter: &Quoter) {
|
||||||
|
self.uri = uri.clone();
|
||||||
|
self.path = quoter.requote(uri.path().as_bytes());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ResourcePath for Url {
|
impl ResourcePath for Url {
|
||||||
|
#[inline]
|
||||||
fn path(&self) -> &str {
|
fn path(&self) -> &str {
|
||||||
self.path()
|
self.path()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) struct Quoter {
|
pub struct Quoter {
|
||||||
safe_table: [u8; 16],
|
safe_table: [u8; 16],
|
||||||
protected_table: [u8; 16],
|
protected_table: [u8; 16],
|
||||||
}
|
}
|
||||||
@@ -108,7 +121,7 @@ impl Quoter {
|
|||||||
q
|
q
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn requote(&self, val: &[u8]) -> Option<Rc<String>> {
|
pub fn requote(&self, val: &[u8]) -> Option<String> {
|
||||||
let mut has_pct = 0;
|
let mut has_pct = 0;
|
||||||
let mut pct = [b'%', 0, 0];
|
let mut pct = [b'%', 0, 0];
|
||||||
let mut idx = 0;
|
let mut idx = 0;
|
||||||
@@ -160,7 +173,7 @@ impl Quoter {
|
|||||||
if let Some(data) = cloned {
|
if let Some(data) = cloned {
|
||||||
// Unsafe: we get data from http::Uri, which does utf-8 checks already
|
// Unsafe: we get data from http::Uri, which does utf-8 checks already
|
||||||
// this code only decodes valid pct encoded values
|
// this code only decodes valid pct encoded values
|
||||||
Some(Rc::new(unsafe { String::from_utf8_unchecked(data) }))
|
Some(unsafe { String::from_utf8_unchecked(data) })
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user