mirror of
https://github.com/fafhrd91/actix-net
synced 2024-11-23 20:51:06 +01:00
Check code style with rustfmt on CI (#164)
This commit is contained in:
parent
0dca1a705a
commit
8ace9264b7
1
.github/PULL_REQUEST_TEMPLATE.md
vendored
1
.github/PULL_REQUEST_TEMPLATE.md
vendored
@ -12,6 +12,7 @@ Check your PR fulfills the following:
|
||||
- [ ] Tests for the changes have been added / updated.
|
||||
- [ ] Documentation comments have been added / updated.
|
||||
- [ ] A changelog entry has been made for the appropriate packages.
|
||||
- [ ] Format code with the latest stable rustfmt
|
||||
|
||||
|
||||
## Overview
|
||||
|
34
.github/workflows/clippy-fmt.yml
vendored
Normal file
34
.github/workflows/clippy-fmt.yml
vendored
Normal file
@ -0,0 +1,34 @@
|
||||
on:
|
||||
pull_request:
|
||||
types: [opened, synchronize, reopened]
|
||||
|
||||
name: Clippy and rustfmt Check
|
||||
jobs:
|
||||
clippy_check:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: stable
|
||||
components: rustfmt
|
||||
profile: minimal
|
||||
override: true
|
||||
- name: Check with rustfmt
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: fmt
|
||||
args: --all -- --check
|
||||
|
||||
- uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: nightly
|
||||
components: clippy
|
||||
profile: minimal
|
||||
override: true
|
||||
- name: Check with Clippy
|
||||
uses: actions-rs/clippy-check@v1
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
args: --all-features --all --tests
|
20
.github/workflows/clippy.yml
vendored
20
.github/workflows/clippy.yml
vendored
@ -1,20 +0,0 @@
|
||||
on:
|
||||
pull_request:
|
||||
types: [opened, synchronize, reopened]
|
||||
|
||||
name: Clippy Check
|
||||
jobs:
|
||||
clippy_check:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@master
|
||||
- uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: nightly
|
||||
components: clippy
|
||||
profile: minimal
|
||||
override: true
|
||||
- uses: actions-rs/clippy-check@v1
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
args: --all-features --all --tests
|
@ -1,4 +1,4 @@
|
||||
use bytes::{Bytes, BytesMut, Buf};
|
||||
use bytes::{Buf, Bytes, BytesMut};
|
||||
use std::io;
|
||||
|
||||
use super::{Decoder, Encoder};
|
||||
|
@ -271,7 +271,10 @@ impl<T, U> Framed<T, U> {
|
||||
}
|
||||
|
||||
/// Flush write buffer to underlying I/O stream.
|
||||
pub fn flush<I>(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), U::Error>>
|
||||
pub fn flush<I>(
|
||||
mut self: Pin<&mut Self>,
|
||||
cx: &mut Context<'_>,
|
||||
) -> Poll<Result<(), U::Error>>
|
||||
where
|
||||
T: AsyncWrite,
|
||||
U: Encoder<I>,
|
||||
@ -304,7 +307,10 @@ impl<T, U> Framed<T, U> {
|
||||
}
|
||||
|
||||
/// Flush write buffer and shutdown underlying I/O stream.
|
||||
pub fn close<I>(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), U::Error>>
|
||||
pub fn close<I>(
|
||||
mut self: Pin<&mut Self>,
|
||||
cx: &mut Context<'_>,
|
||||
) -> Poll<Result<(), U::Error>>
|
||||
where
|
||||
T: AsyncWrite,
|
||||
U: Encoder<I>,
|
||||
|
@ -1,28 +1,26 @@
|
||||
use actix_service::boxed::BoxFuture;
|
||||
use actix_service::IntoService;
|
||||
use actix_service::Service;
|
||||
/// Benchmark various implementations of and_then
|
||||
|
||||
use criterion::{criterion_main, Criterion};
|
||||
use futures_util::future::join_all;
|
||||
use futures_util::future::TryFutureExt;
|
||||
use std::cell::{RefCell, UnsafeCell};
|
||||
use std::task::{Context, Poll};
|
||||
use std::rc::Rc;
|
||||
use actix_service::{Service};
|
||||
use actix_service::IntoService;
|
||||
use std::future::Future;
|
||||
use std::pin::Pin;
|
||||
use futures_util::future::TryFutureExt;
|
||||
use actix_service::boxed::BoxFuture;
|
||||
|
||||
use std::rc::Rc;
|
||||
use std::task::{Context, Poll};
|
||||
|
||||
/*
|
||||
* Test services A,B for AndThen service implementations
|
||||
*/
|
||||
|
||||
async fn svc1(_: ()) -> Result<usize, ()> {
|
||||
Ok(1)
|
||||
Ok(1)
|
||||
}
|
||||
|
||||
async fn svc2(req: usize) -> Result<usize, ()> {
|
||||
Ok(req + 1)
|
||||
Ok(req + 1)
|
||||
}
|
||||
|
||||
/*
|
||||
@ -30,45 +28,44 @@ async fn svc2(req: usize) -> Result<usize, ()> {
|
||||
* Cut down version of actix_service::AndThenService based on actix-service::Cell
|
||||
*/
|
||||
|
||||
struct AndThenUC<A, B>(Rc<UnsafeCell<(A, B)>>);
|
||||
|
||||
struct AndThenUC<A,B>(Rc<UnsafeCell<(A, B)>>);
|
||||
|
||||
impl<A,B> AndThenUC<A,B> {
|
||||
fn new(a: A, b: B) -> Self
|
||||
where
|
||||
A: Service,
|
||||
B: Service<Request = A::Response, Error = A::Error>,
|
||||
{
|
||||
Self(Rc::new(UnsafeCell::new((a,b))))
|
||||
}
|
||||
impl<A, B> AndThenUC<A, B> {
|
||||
fn new(a: A, b: B) -> Self
|
||||
where
|
||||
A: Service,
|
||||
B: Service<Request = A::Response, Error = A::Error>,
|
||||
{
|
||||
Self(Rc::new(UnsafeCell::new((a, b))))
|
||||
}
|
||||
}
|
||||
|
||||
impl<A,B> Clone for AndThenUC<A,B> {
|
||||
fn clone(&self) -> Self {
|
||||
Self(self.0.clone())
|
||||
}
|
||||
impl<A, B> Clone for AndThenUC<A, B> {
|
||||
fn clone(&self) -> Self {
|
||||
Self(self.0.clone())
|
||||
}
|
||||
}
|
||||
|
||||
impl<A,B> Service for AndThenUC<A,B>
|
||||
impl<A, B> Service for AndThenUC<A, B>
|
||||
where
|
||||
A: Service,
|
||||
B: Service<Request = A::Response, Error = A::Error>
|
||||
B: Service<Request = A::Response, Error = A::Error>,
|
||||
{
|
||||
type Request = A::Request;
|
||||
type Response = B::Response;
|
||||
type Error = A::Error;
|
||||
type Future = AndThenServiceResponse<A,B>;
|
||||
type Request = A::Request;
|
||||
type Response = B::Response;
|
||||
type Error = A::Error;
|
||||
type Future = AndThenServiceResponse<A, B>;
|
||||
|
||||
fn poll_ready(&mut self, _: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
|
||||
Poll::Ready(Ok(()))
|
||||
}
|
||||
fn poll_ready(&mut self, _: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
|
||||
Poll::Ready(Ok(()))
|
||||
}
|
||||
|
||||
fn call(&mut self, req: A::Request) -> Self::Future {
|
||||
let fut = unsafe { &mut *(*self.0).get() }.0.call(req);
|
||||
AndThenServiceResponse {
|
||||
state: State::A(fut, Some(self.0.clone()))
|
||||
}
|
||||
}
|
||||
fn call(&mut self, req: A::Request) -> Self::Future {
|
||||
let fut = unsafe { &mut *(*self.0).get() }.0.call(req);
|
||||
AndThenServiceResponse {
|
||||
state: State::A(fut, Some(self.0.clone())),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[pin_project::pin_project]
|
||||
@ -117,157 +114,156 @@ where
|
||||
this.state.set(State::Empty);
|
||||
r
|
||||
}),
|
||||
StateProj::Empty => panic!("future must not be polled after it returned `Poll::Ready`"),
|
||||
StateProj::Empty => {
|
||||
panic!("future must not be polled after it returned `Poll::Ready`")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* AndThenRC - AndThen service based on RefCell
|
||||
*/
|
||||
|
||||
struct AndThenRC<A,B>(Rc<RefCell<(A, B)>>);
|
||||
struct AndThenRC<A, B>(Rc<RefCell<(A, B)>>);
|
||||
|
||||
impl<A,B> AndThenRC<A,B> {
|
||||
fn new(a: A, b: B) -> Self
|
||||
where
|
||||
A: Service,
|
||||
B: Service<Request = A::Response, Error = A::Error>,
|
||||
{
|
||||
Self(Rc::new(RefCell::new((a,b))))
|
||||
}
|
||||
}
|
||||
|
||||
impl<A,B> Clone for AndThenRC<A,B> {
|
||||
fn clone(&self) -> Self {
|
||||
Self(self.0.clone())
|
||||
}
|
||||
}
|
||||
|
||||
impl<A,B> Service for AndThenRC<A,B>
|
||||
where
|
||||
A: Service,
|
||||
B: Service<Request = A::Response, Error = A::Error>
|
||||
{
|
||||
type Request = A::Request;
|
||||
type Response = B::Response;
|
||||
type Error = A::Error;
|
||||
type Future = AndThenServiceResponseRC<A,B>;
|
||||
|
||||
fn poll_ready(&mut self, _: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
|
||||
Poll::Ready(Ok(()))
|
||||
}
|
||||
|
||||
fn call(&mut self, req: A::Request) -> Self::Future {
|
||||
let fut = self.0.borrow_mut().0.call(req);
|
||||
AndThenServiceResponseRC {
|
||||
state: StateRC::A(fut, Some(self.0.clone()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[pin_project::pin_project]
|
||||
pub(crate) struct AndThenServiceResponseRC<A, B>
|
||||
where
|
||||
A: Service,
|
||||
B: Service<Request = A::Response, Error = A::Error>,
|
||||
{
|
||||
#[pin]
|
||||
state: StateRC<A, B>,
|
||||
}
|
||||
|
||||
#[pin_project::pin_project(project = StateRCProj)]
|
||||
enum StateRC<A, B>
|
||||
where
|
||||
A: Service,
|
||||
B: Service<Request = A::Response, Error = A::Error>,
|
||||
{
|
||||
A(#[pin] A::Future, Option<Rc<RefCell<(A, B)>>>),
|
||||
B(#[pin] B::Future),
|
||||
Empty,
|
||||
}
|
||||
|
||||
impl<A, B> Future for AndThenServiceResponseRC<A, B>
|
||||
where
|
||||
A: Service,
|
||||
B: Service<Request = A::Response, Error = A::Error>,
|
||||
{
|
||||
type Output = Result<B::Response, A::Error>;
|
||||
impl<A, B> AndThenRC<A, B> {
|
||||
fn new(a: A, b: B) -> Self
|
||||
where
|
||||
A: Service,
|
||||
B: Service<Request = A::Response, Error = A::Error>,
|
||||
{
|
||||
Self(Rc::new(RefCell::new((a, b))))
|
||||
}
|
||||
}
|
||||
|
||||
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
let mut this = self.as_mut().project();
|
||||
impl<A, B> Clone for AndThenRC<A, B> {
|
||||
fn clone(&self) -> Self {
|
||||
Self(self.0.clone())
|
||||
}
|
||||
}
|
||||
|
||||
match this.state.as_mut().project() {
|
||||
StateRCProj::A(fut, b) => match fut.poll(cx)? {
|
||||
Poll::Ready(res) => {
|
||||
let b = b.take().unwrap();
|
||||
this.state.set(StateRC::Empty); // drop fut A
|
||||
let fut = b.borrow_mut().1.call(res);
|
||||
this.state.set(StateRC::B(fut));
|
||||
self.poll(cx)
|
||||
}
|
||||
Poll::Pending => Poll::Pending,
|
||||
},
|
||||
StateRCProj::B(fut) => fut.poll(cx).map(|r| {
|
||||
this.state.set(StateRC::Empty);
|
||||
r
|
||||
}),
|
||||
StateRCProj::Empty => panic!("future must not be polled after it returned `Poll::Ready`"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<A, B> Service for AndThenRC<A, B>
|
||||
where
|
||||
A: Service,
|
||||
B: Service<Request = A::Response, Error = A::Error>,
|
||||
{
|
||||
type Request = A::Request;
|
||||
type Response = B::Response;
|
||||
type Error = A::Error;
|
||||
type Future = AndThenServiceResponseRC<A, B>;
|
||||
|
||||
/*
|
||||
* AndThenRCFuture - AndThen service based on RefCell
|
||||
fn poll_ready(&mut self, _: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
|
||||
Poll::Ready(Ok(()))
|
||||
}
|
||||
|
||||
fn call(&mut self, req: A::Request) -> Self::Future {
|
||||
let fut = self.0.borrow_mut().0.call(req);
|
||||
AndThenServiceResponseRC {
|
||||
state: StateRC::A(fut, Some(self.0.clone())),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[pin_project::pin_project]
|
||||
pub(crate) struct AndThenServiceResponseRC<A, B>
|
||||
where
|
||||
A: Service,
|
||||
B: Service<Request = A::Response, Error = A::Error>,
|
||||
{
|
||||
#[pin]
|
||||
state: StateRC<A, B>,
|
||||
}
|
||||
|
||||
#[pin_project::pin_project(project = StateRCProj)]
|
||||
enum StateRC<A, B>
|
||||
where
|
||||
A: Service,
|
||||
B: Service<Request = A::Response, Error = A::Error>,
|
||||
{
|
||||
A(#[pin] A::Future, Option<Rc<RefCell<(A, B)>>>),
|
||||
B(#[pin] B::Future),
|
||||
Empty,
|
||||
}
|
||||
|
||||
impl<A, B> Future for AndThenServiceResponseRC<A, B>
|
||||
where
|
||||
A: Service,
|
||||
B: Service<Request = A::Response, Error = A::Error>,
|
||||
{
|
||||
type Output = Result<B::Response, A::Error>;
|
||||
|
||||
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
let mut this = self.as_mut().project();
|
||||
|
||||
match this.state.as_mut().project() {
|
||||
StateRCProj::A(fut, b) => match fut.poll(cx)? {
|
||||
Poll::Ready(res) => {
|
||||
let b = b.take().unwrap();
|
||||
this.state.set(StateRC::Empty); // drop fut A
|
||||
let fut = b.borrow_mut().1.call(res);
|
||||
this.state.set(StateRC::B(fut));
|
||||
self.poll(cx)
|
||||
}
|
||||
Poll::Pending => Poll::Pending,
|
||||
},
|
||||
StateRCProj::B(fut) => fut.poll(cx).map(|r| {
|
||||
this.state.set(StateRC::Empty);
|
||||
r
|
||||
}),
|
||||
StateRCProj::Empty => {
|
||||
panic!("future must not be polled after it returned `Poll::Ready`")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* AndThenRCFuture - AndThen service based on RefCell
|
||||
* and standard futures::future::and_then combinator in a Box
|
||||
*/
|
||||
|
||||
struct AndThenRCFuture<A,B>(Rc<RefCell<(A, B)>>);
|
||||
struct AndThenRCFuture<A, B>(Rc<RefCell<(A, B)>>);
|
||||
|
||||
impl<A,B> AndThenRCFuture<A,B> {
|
||||
fn new(a: A, b: B) -> Self
|
||||
where
|
||||
A: Service,
|
||||
B: Service<Request = A::Response, Error = A::Error>,
|
||||
{
|
||||
Self(Rc::new(RefCell::new((a,b))))
|
||||
}
|
||||
}
|
||||
|
||||
impl<A,B> Clone for AndThenRCFuture<A,B> {
|
||||
fn clone(&self) -> Self {
|
||||
Self(self.0.clone())
|
||||
}
|
||||
}
|
||||
|
||||
impl<A,B> Service for AndThenRCFuture<A,B>
|
||||
where
|
||||
A: Service + 'static,
|
||||
A::Future: 'static,
|
||||
B: Service<Request = A::Response, Error = A::Error> + 'static,
|
||||
B::Future: 'static
|
||||
{
|
||||
type Request = A::Request;
|
||||
type Response = B::Response;
|
||||
type Error = A::Error;
|
||||
type Future = BoxFuture<Self::Response, Self::Error>;
|
||||
|
||||
fn poll_ready(&mut self, _: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
|
||||
Poll::Ready(Ok(()))
|
||||
}
|
||||
|
||||
fn call(&mut self, req: A::Request) -> Self::Future {
|
||||
let fut = self.0.borrow_mut().0.call(req);
|
||||
let core = self.0.clone();
|
||||
let fut2 = move |res| (*core).borrow_mut().1.call(res);
|
||||
Box::pin(
|
||||
fut.and_then(fut2)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl<A, B> AndThenRCFuture<A, B> {
|
||||
fn new(a: A, b: B) -> Self
|
||||
where
|
||||
A: Service,
|
||||
B: Service<Request = A::Response, Error = A::Error>,
|
||||
{
|
||||
Self(Rc::new(RefCell::new((a, b))))
|
||||
}
|
||||
}
|
||||
|
||||
impl<A, B> Clone for AndThenRCFuture<A, B> {
|
||||
fn clone(&self) -> Self {
|
||||
Self(self.0.clone())
|
||||
}
|
||||
}
|
||||
|
||||
impl<A, B> Service for AndThenRCFuture<A, B>
|
||||
where
|
||||
A: Service + 'static,
|
||||
A::Future: 'static,
|
||||
B: Service<Request = A::Response, Error = A::Error> + 'static,
|
||||
B::Future: 'static,
|
||||
{
|
||||
type Request = A::Request;
|
||||
type Response = B::Response;
|
||||
type Error = A::Error;
|
||||
type Future = BoxFuture<Self::Response, Self::Error>;
|
||||
|
||||
fn poll_ready(&mut self, _: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
|
||||
Poll::Ready(Ok(()))
|
||||
}
|
||||
|
||||
fn call(&mut self, req: A::Request) -> Self::Future {
|
||||
let fut = self.0.borrow_mut().0.call(req);
|
||||
let core = self.0.clone();
|
||||
let fut2 = move |res| (*core).borrow_mut().1.call(res);
|
||||
Box::pin(fut.and_then(fut2))
|
||||
}
|
||||
}
|
||||
|
||||
/// Criterion Benchmark for async Service
|
||||
/// Should be used from within criterion group:
|
||||
@ -296,9 +292,7 @@ where
|
||||
// exclude request generation, it appears it takes significant time vs call (3us vs 1us)
|
||||
let start = std::time::Instant::now();
|
||||
// benchmark body
|
||||
rt.block_on(async move {
|
||||
join_all(srvs.iter_mut().map(|srv| srv.call(()))).await
|
||||
});
|
||||
rt.block_on(async move { join_all(srvs.iter_mut().map(|srv| srv.call(()))).await });
|
||||
let elapsed = start.elapsed();
|
||||
// check that at least first request succeeded
|
||||
elapsed
|
||||
@ -306,15 +300,34 @@ where
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
pub fn service_benches() {
|
||||
let mut criterion: ::criterion::Criterion<_> =
|
||||
::criterion::Criterion::default().configure_from_args();
|
||||
bench_async_service(&mut criterion, AndThenUC::new(svc1.into_service(), svc2.into_service()), "AndThen with UnsafeCell");
|
||||
bench_async_service(&mut criterion, AndThenRC::new(svc1.into_service(), svc2.into_service()), "AndThen with RefCell");
|
||||
bench_async_service(&mut criterion, AndThenUC::new(svc1.into_service(), svc2.into_service()), "AndThen with UnsafeCell");
|
||||
bench_async_service(&mut criterion, AndThenRC::new(svc1.into_service(), svc2.into_service()), "AndThen with RefCell");
|
||||
bench_async_service(&mut criterion, AndThenRCFuture::new(svc1.into_service(), svc2.into_service()), "AndThen with RefCell via future::and_then");
|
||||
bench_async_service(
|
||||
&mut criterion,
|
||||
AndThenUC::new(svc1.into_service(), svc2.into_service()),
|
||||
"AndThen with UnsafeCell",
|
||||
);
|
||||
bench_async_service(
|
||||
&mut criterion,
|
||||
AndThenRC::new(svc1.into_service(), svc2.into_service()),
|
||||
"AndThen with RefCell",
|
||||
);
|
||||
bench_async_service(
|
||||
&mut criterion,
|
||||
AndThenUC::new(svc1.into_service(), svc2.into_service()),
|
||||
"AndThen with UnsafeCell",
|
||||
);
|
||||
bench_async_service(
|
||||
&mut criterion,
|
||||
AndThenRC::new(svc1.into_service(), svc2.into_service()),
|
||||
"AndThen with RefCell",
|
||||
);
|
||||
bench_async_service(
|
||||
&mut criterion,
|
||||
AndThenRCFuture::new(svc1.into_service(), svc2.into_service()),
|
||||
"AndThen with RefCell via future::and_then",
|
||||
);
|
||||
}
|
||||
|
||||
criterion_main!(service_benches);
|
||||
|
@ -1,73 +1,72 @@
|
||||
use actix_service::Service;
|
||||
use criterion::{criterion_main, Criterion};
|
||||
use futures_util::future::join_all;
|
||||
use std::cell::{RefCell, UnsafeCell};
|
||||
use std::task::{Context, Poll};
|
||||
use std::rc::Rc;
|
||||
use actix_service::{Service};
|
||||
use futures_util::future::{ok, Ready};
|
||||
use std::cell::{RefCell, UnsafeCell};
|
||||
use std::rc::Rc;
|
||||
use std::task::{Context, Poll};
|
||||
|
||||
struct SrvUC(Rc<UnsafeCell<usize>>);
|
||||
|
||||
impl Default for SrvUC {
|
||||
fn default() -> Self {
|
||||
Self(Rc::new(UnsafeCell::new(0)))
|
||||
}
|
||||
fn default() -> Self {
|
||||
Self(Rc::new(UnsafeCell::new(0)))
|
||||
}
|
||||
}
|
||||
|
||||
impl Clone for SrvUC {
|
||||
fn clone(&self) -> Self {
|
||||
Self(self.0.clone())
|
||||
}
|
||||
fn clone(&self) -> Self {
|
||||
Self(self.0.clone())
|
||||
}
|
||||
}
|
||||
|
||||
impl Service for SrvUC {
|
||||
type Request = ();
|
||||
type Response = usize;
|
||||
type Error = ();
|
||||
type Future = Ready<Result<Self::Response, ()>>;
|
||||
type Request = ();
|
||||
type Response = usize;
|
||||
type Error = ();
|
||||
type Future = Ready<Result<Self::Response, ()>>;
|
||||
|
||||
fn poll_ready(&mut self, _: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
|
||||
Poll::Ready(Ok(()))
|
||||
}
|
||||
fn poll_ready(&mut self, _: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
|
||||
Poll::Ready(Ok(()))
|
||||
}
|
||||
|
||||
fn call(&mut self, _: ()) -> Self::Future {
|
||||
unsafe { *(*self.0).get() = *(*self.0).get() + 1 };
|
||||
ok(unsafe { *self.0.get() })
|
||||
}
|
||||
fn call(&mut self, _: ()) -> Self::Future {
|
||||
unsafe { *(*self.0).get() = *(*self.0).get() + 1 };
|
||||
ok(unsafe { *self.0.get() })
|
||||
}
|
||||
}
|
||||
|
||||
struct SrvRC(Rc<RefCell<usize>>);
|
||||
|
||||
impl Default for SrvRC {
|
||||
fn default() -> Self {
|
||||
Self(Rc::new(RefCell::new(0)))
|
||||
}
|
||||
fn default() -> Self {
|
||||
Self(Rc::new(RefCell::new(0)))
|
||||
}
|
||||
}
|
||||
|
||||
impl Clone for SrvRC {
|
||||
fn clone(&self) -> Self {
|
||||
Self(self.0.clone())
|
||||
}
|
||||
fn clone(&self) -> Self {
|
||||
Self(self.0.clone())
|
||||
}
|
||||
}
|
||||
|
||||
impl Service for SrvRC {
|
||||
type Request = ();
|
||||
type Response = usize;
|
||||
type Error = ();
|
||||
type Future = Ready<Result<Self::Response, ()>>;
|
||||
type Request = ();
|
||||
type Response = usize;
|
||||
type Error = ();
|
||||
type Future = Ready<Result<Self::Response, ()>>;
|
||||
|
||||
fn poll_ready(&mut self, _: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
|
||||
Poll::Ready(Ok(()))
|
||||
}
|
||||
fn poll_ready(&mut self, _: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
|
||||
Poll::Ready(Ok(()))
|
||||
}
|
||||
|
||||
fn call(&mut self, _: ()) -> Self::Future {
|
||||
let prev = *self.0.borrow();
|
||||
*(*self.0).borrow_mut() = prev + 1;
|
||||
ok(*self.0.borrow())
|
||||
}
|
||||
fn call(&mut self, _: ()) -> Self::Future {
|
||||
let prev = *self.0.borrow();
|
||||
*(*self.0).borrow_mut() = prev + 1;
|
||||
ok(*self.0.borrow())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Criterion Benchmark for async Service
|
||||
/// Should be used from within criterion group:
|
||||
/// ```rust,ignore
|
||||
@ -95,9 +94,7 @@ where
|
||||
// exclude request generation, it appears it takes significant time vs call (3us vs 1us)
|
||||
let start = std::time::Instant::now();
|
||||
// benchmark body
|
||||
rt.block_on(async move {
|
||||
join_all(srvs.iter_mut().map(|srv| srv.call(()))).await
|
||||
});
|
||||
rt.block_on(async move { join_all(srvs.iter_mut().map(|srv| srv.call(()))).await });
|
||||
let elapsed = start.elapsed();
|
||||
// check that at least first request succeeded
|
||||
elapsed
|
||||
@ -105,7 +102,6 @@ where
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
pub fn service_benches() {
|
||||
let mut criterion: ::criterion::Criterion<_> =
|
||||
::criterion::Criterion::default().configure_from_args();
|
||||
|
@ -1,12 +1,11 @@
|
||||
use std::cell::RefCell;
|
||||
use std::future::Future;
|
||||
use std::pin::Pin;
|
||||
use std::rc::Rc;
|
||||
use std::cell::RefCell;
|
||||
use std::task::{Context, Poll};
|
||||
|
||||
use super::{Service, ServiceFactory};
|
||||
|
||||
|
||||
/// Service for the `and_then` combinator, chaining a computation onto the end
|
||||
/// of another service which completes successfully.
|
||||
///
|
||||
@ -103,7 +102,9 @@ where
|
||||
this.state.set(State::Empty);
|
||||
r
|
||||
}),
|
||||
StateProj::Empty => panic!("future must not be polled after it returned `Poll::Ready`"),
|
||||
StateProj::Empty => {
|
||||
panic!("future must not be polled after it returned `Poll::Ready`")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +1,8 @@
|
||||
use std::cell::RefCell;
|
||||
use std::future::Future;
|
||||
use std::marker::PhantomData;
|
||||
use std::pin::Pin;
|
||||
use std::rc::Rc;
|
||||
use std::cell::RefCell;
|
||||
use std::task::{Context, Poll};
|
||||
|
||||
use crate::{Service, ServiceFactory};
|
||||
@ -31,7 +31,7 @@ where
|
||||
/// Create new `Apply` combinator
|
||||
pub(crate) fn new(a: A, b: B, f: F) -> Self {
|
||||
Self {
|
||||
srv: Rc::new(RefCell::new((a, b, f))),
|
||||
srv: Rc::new(RefCell::new((a, b, f))),
|
||||
r: PhantomData,
|
||||
}
|
||||
}
|
||||
@ -142,7 +142,9 @@ where
|
||||
this.state.set(State::Empty);
|
||||
r
|
||||
}),
|
||||
StateProj::Empty => panic!("future must not be polled after it returned `Poll::Ready`"),
|
||||
StateProj::Empty => {
|
||||
panic!("future must not be polled after it returned `Poll::Ready`")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -296,10 +298,9 @@ mod tests {
|
||||
|
||||
#[actix_rt::test]
|
||||
async fn test_service() {
|
||||
let mut srv = pipeline(ok)
|
||||
.and_then_apply_fn(Srv, |req: &'static str, s| {
|
||||
s.call(()).map_ok(move |res| (req, res))
|
||||
});
|
||||
let mut srv = pipeline(ok).and_then_apply_fn(Srv, |req: &'static str, s| {
|
||||
s.call(()).map_ok(move |res| (req, res))
|
||||
});
|
||||
let res = lazy(|cx| srv.poll_ready(cx)).await;
|
||||
assert_eq!(res, Poll::Ready(Ok(())));
|
||||
|
||||
@ -310,11 +311,10 @@ mod tests {
|
||||
|
||||
#[actix_rt::test]
|
||||
async fn test_service_factory() {
|
||||
let new_srv = pipeline_factory(|| ok::<_, ()>(fn_service(ok)))
|
||||
.and_then_apply_fn(
|
||||
|| ok(Srv),
|
||||
|req: &'static str, s| s.call(()).map_ok(move |res| (req, res)),
|
||||
);
|
||||
let new_srv = pipeline_factory(|| ok::<_, ()>(fn_service(ok))).and_then_apply_fn(
|
||||
|| ok(Srv),
|
||||
|req: &'static str, s| s.call(()).map_ok(move |res| (req, res)),
|
||||
);
|
||||
let mut srv = new_srv.new_service(()).await.unwrap();
|
||||
let res = lazy(|cx| srv.poll_ready(cx)).await;
|
||||
assert_eq!(res, Poll::Ready(Ok(())));
|
||||
|
@ -1,9 +1,9 @@
|
||||
use std::cell::RefCell;
|
||||
use std::future::Future;
|
||||
use std::marker::PhantomData;
|
||||
use std::pin::Pin;
|
||||
use std::task::{Context, Poll};
|
||||
use std::rc::Rc;
|
||||
use std::cell::RefCell;
|
||||
use std::task::{Context, Poll};
|
||||
|
||||
use crate::{Service, ServiceFactory};
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
use std::cell::RefCell;
|
||||
use std::future::Future;
|
||||
use std::pin::Pin;
|
||||
use std::rc::Rc;
|
||||
use std::cell::RefCell;
|
||||
use std::task::{Context, Poll};
|
||||
|
||||
use super::{Service, ServiceFactory};
|
||||
@ -102,7 +102,9 @@ where
|
||||
this.state.set(State::Empty);
|
||||
r
|
||||
}),
|
||||
StateProj::Empty => panic!("future must not be polled after it returned `Poll::Ready`"),
|
||||
StateProj::Empty => {
|
||||
panic!("future must not be polled after it returned `Poll::Ready`")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -7,9 +7,13 @@ use crate::ResourcePath;
|
||||
macro_rules! unsupported_type {
|
||||
($trait_fn:ident, $name:expr) => {
|
||||
fn $trait_fn<V>(self, _: V) -> Result<V::Value, Self::Error>
|
||||
where V: Visitor<'de>
|
||||
where
|
||||
V: Visitor<'de>,
|
||||
{
|
||||
Err(de::value::Error::custom(concat!("unsupported type: ", $name)))
|
||||
Err(de::value::Error::custom(concat!(
|
||||
"unsupported type: ",
|
||||
$name
|
||||
)))
|
||||
}
|
||||
};
|
||||
}
|
||||
@ -17,20 +21,25 @@ macro_rules! unsupported_type {
|
||||
macro_rules! parse_single_value {
|
||||
($trait_fn:ident, $visit_fn:ident, $tp:tt) => {
|
||||
fn $trait_fn<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||
where V: Visitor<'de>
|
||||
where
|
||||
V: Visitor<'de>,
|
||||
{
|
||||
if self.path.len() != 1 {
|
||||
Err(de::value::Error::custom(
|
||||
format!("wrong number of parameters: {} expected 1",
|
||||
self.path.len()).as_str()))
|
||||
format!("wrong number of parameters: {} expected 1", self.path.len())
|
||||
.as_str(),
|
||||
))
|
||||
} else {
|
||||
let v = self.path[0].parse().map_err(
|
||||
|_| de::value::Error::custom(
|
||||
format!("can not parse {:?} to a {}", &self.path[0], $tp)))?;
|
||||
let v = self.path[0].parse().map_err(|_| {
|
||||
de::value::Error::custom(format!(
|
||||
"can not parse {:?} to a {}",
|
||||
&self.path[0], $tp
|
||||
))
|
||||
})?;
|
||||
visitor.$visit_fn(v)
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
pub struct PathDeserializer<'de, T: ResourcePath + 'de> {
|
||||
@ -268,14 +277,15 @@ impl<'de> Deserializer<'de> for Key<'de> {
|
||||
macro_rules! parse_value {
|
||||
($trait_fn:ident, $visit_fn:ident, $tp:tt) => {
|
||||
fn $trait_fn<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||
where V: Visitor<'de>
|
||||
where
|
||||
V: Visitor<'de>,
|
||||
{
|
||||
let v = self.value.parse().map_err(
|
||||
|_| de::value::Error::custom(
|
||||
format!("can not parse {:?} to a {}", self.value, $tp)))?;
|
||||
let v = self.value.parse().map_err(|_| {
|
||||
de::value::Error::custom(format!("can not parse {:?} to a {}", self.value, $tp))
|
||||
})?;
|
||||
visitor.$visit_fn(v)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
struct Value<'de> {
|
||||
|
@ -33,6 +33,13 @@ impl ByteString {
|
||||
}
|
||||
|
||||
/// Creates a new `ByteString` from a Bytes.
|
||||
///
|
||||
/// # Safety
|
||||
/// This function is unsafe because it does not check the bytes passed to it
|
||||
/// are valid UTF-8. If this constraint is violated,
|
||||
/// it may cause memory unsafety issues with future users of the `ByteString`,
|
||||
/// as we assume that `ByteString`s are valid UTF-8.
|
||||
/// However, the most likely issue is that the data gets corrupted.
|
||||
pub const unsafe fn from_bytes_unchecked(src: Bytes) -> ByteString {
|
||||
Self(src)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user