diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index d53e084e9a..e32d54aeac 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -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 diff --git a/.github/workflows/clippy-fmt.yml b/.github/workflows/clippy-fmt.yml new file mode 100644 index 0000000000..85a4252260 --- /dev/null +++ b/.github/workflows/clippy-fmt.yml @@ -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 diff --git a/.github/workflows/clippy.yml b/.github/workflows/clippy.yml deleted file mode 100644 index 0d895cf202..0000000000 --- a/.github/workflows/clippy.yml +++ /dev/null @@ -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 diff --git a/actix-codec/src/bcodec.rs b/actix-codec/src/bcodec.rs index e67edae1e3..045b20a2ee 100644 --- a/actix-codec/src/bcodec.rs +++ b/actix-codec/src/bcodec.rs @@ -1,4 +1,4 @@ -use bytes::{Bytes, BytesMut, Buf}; +use bytes::{Buf, Bytes, BytesMut}; use std::io; use super::{Decoder, Encoder}; diff --git a/actix-codec/src/framed.rs b/actix-codec/src/framed.rs index cba5dd3c23..bfa5c7b610 100644 --- a/actix-codec/src/framed.rs +++ b/actix-codec/src/framed.rs @@ -271,7 +271,10 @@ impl Framed { } /// Flush write buffer to underlying I/O stream. - pub fn flush(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> + pub fn flush( + mut self: Pin<&mut Self>, + cx: &mut Context<'_>, + ) -> Poll> where T: AsyncWrite, U: Encoder, @@ -304,7 +307,10 @@ impl Framed { } /// Flush write buffer and shutdown underlying I/O stream. - pub fn close(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> + pub fn close( + mut self: Pin<&mut Self>, + cx: &mut Context<'_>, + ) -> Poll> where T: AsyncWrite, U: Encoder, diff --git a/actix-service/benches/and_then.rs b/actix-service/benches/and_then.rs index 0b78a9c0bd..98de007d14 100644 --- a/actix-service/benches/and_then.rs +++ b/actix-service/benches/and_then.rs @@ -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 { - Ok(1) + Ok(1) } async fn svc2(req: usize) -> Result { - Ok(req + 1) + Ok(req + 1) } /* @@ -30,45 +28,44 @@ async fn svc2(req: usize) -> Result { * Cut down version of actix_service::AndThenService based on actix-service::Cell */ +struct AndThenUC(Rc>); -struct AndThenUC(Rc>); - -impl AndThenUC { - fn new(a: A, b: B) -> Self - where - A: Service, - B: Service, - { - Self(Rc::new(UnsafeCell::new((a,b)))) - } +impl AndThenUC { + fn new(a: A, b: B) -> Self + where + A: Service, + B: Service, + { + Self(Rc::new(UnsafeCell::new((a, b)))) + } } -impl Clone for AndThenUC { - fn clone(&self) -> Self { - Self(self.0.clone()) - } +impl Clone for AndThenUC { + fn clone(&self) -> Self { + Self(self.0.clone()) + } } -impl Service for AndThenUC +impl Service for AndThenUC where A: Service, - B: Service + B: Service, { - type Request = A::Request; - type Response = B::Response; - type Error = A::Error; - type Future = AndThenServiceResponse; - - fn poll_ready(&mut self, _: &mut Context<'_>) -> Poll> { - 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())) - } - } + type Request = A::Request; + type Response = B::Response; + type Error = A::Error; + type Future = AndThenServiceResponse; + + fn poll_ready(&mut self, _: &mut Context<'_>) -> Poll> { + 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())), + } + } } #[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(Rc>); - - impl AndThenRC { - fn new(a: A, b: B) -> Self - where - A: Service, - B: Service, - { - Self(Rc::new(RefCell::new((a,b)))) - } - } - - impl Clone for AndThenRC { - fn clone(&self) -> Self { - Self(self.0.clone()) - } - } - - impl Service for AndThenRC - where - A: Service, - B: Service - { - type Request = A::Request; - type Response = B::Response; - type Error = A::Error; - type Future = AndThenServiceResponseRC; - - fn poll_ready(&mut self, _: &mut Context<'_>) -> Poll> { - 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 - where - A: Service, - B: Service, - { - #[pin] - state: StateRC, - } - - #[pin_project::pin_project(project = StateRCProj)] - enum StateRC - where - A: Service, - B: Service, - { - A(#[pin] A::Future, Option>>), - B(#[pin] B::Future), - Empty, - } - - impl Future for AndThenServiceResponseRC - where - A: Service, - B: Service, - { - type Output = Result; - - fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { - 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 +struct AndThenRC(Rc>); + +impl AndThenRC { + fn new(a: A, b: B) -> Self + where + A: Service, + B: Service, + { + Self(Rc::new(RefCell::new((a, b)))) + } +} + +impl Clone for AndThenRC { + fn clone(&self) -> Self { + Self(self.0.clone()) + } +} + +impl Service for AndThenRC +where + A: Service, + B: Service, +{ + type Request = A::Request; + type Response = B::Response; + type Error = A::Error; + type Future = AndThenServiceResponseRC; + + fn poll_ready(&mut self, _: &mut Context<'_>) -> Poll> { + 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 +where + A: Service, + B: Service, +{ + #[pin] + state: StateRC, +} + +#[pin_project::pin_project(project = StateRCProj)] +enum StateRC +where + A: Service, + B: Service, +{ + A(#[pin] A::Future, Option>>), + B(#[pin] B::Future), + Empty, +} + +impl Future for AndThenServiceResponseRC +where + A: Service, + B: Service, +{ + type Output = Result; + + fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + 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(Rc>); - - impl AndThenRCFuture { - fn new(a: A, b: B) -> Self - where - A: Service, - B: Service, - { - Self(Rc::new(RefCell::new((a,b)))) - } - } - - impl Clone for AndThenRCFuture { - fn clone(&self) -> Self { - Self(self.0.clone()) - } - } - - impl Service for AndThenRCFuture - where - A: Service + 'static, - A::Future: 'static, - B: Service + 'static, - B::Future: 'static - { - type Request = A::Request; - type Response = B::Response; - type Error = A::Error; - type Future = BoxFuture; - - fn poll_ready(&mut self, _: &mut Context<'_>) -> Poll> { - 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) - ) - } - } - +struct AndThenRCFuture(Rc>); + +impl AndThenRCFuture { + fn new(a: A, b: B) -> Self + where + A: Service, + B: Service, + { + Self(Rc::new(RefCell::new((a, b)))) + } +} + +impl Clone for AndThenRCFuture { + fn clone(&self) -> Self { + Self(self.0.clone()) + } +} + +impl Service for AndThenRCFuture +where + A: Service + 'static, + A::Future: 'static, + B: Service + 'static, + B::Future: 'static, +{ + type Request = A::Request; + type Response = B::Response; + type Error = A::Error; + type Future = BoxFuture; + + fn poll_ready(&mut self, _: &mut Context<'_>) -> Poll> { + 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); diff --git a/actix-service/benches/unsafecell_vs_refcell.rs b/actix-service/benches/unsafecell_vs_refcell.rs index e8e8b0186a..9746cf9eb5 100644 --- a/actix-service/benches/unsafecell_vs_refcell.rs +++ b/actix-service/benches/unsafecell_vs_refcell.rs @@ -1,73 +1,72 @@ +use actix_service::Service; use criterion::{criterion_main, Criterion}; use futures_util::future::join_all; +use futures_util::future::{ok, Ready}; 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::task::{Context, Poll}; struct SrvUC(Rc>); 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>; - - fn poll_ready(&mut self, _: &mut Context<'_>) -> Poll> { - Poll::Ready(Ok(())) - } - - fn call(&mut self, _: ()) -> Self::Future { - unsafe { *(*self.0).get() = *(*self.0).get() + 1 }; - ok(unsafe { *self.0.get() }) - } + type Request = (); + type Response = usize; + type Error = (); + type Future = Ready>; + + fn poll_ready(&mut self, _: &mut Context<'_>) -> Poll> { + Poll::Ready(Ok(())) + } + + fn call(&mut self, _: ()) -> Self::Future { + unsafe { *(*self.0).get() = *(*self.0).get() + 1 }; + ok(unsafe { *self.0.get() }) + } } struct SrvRC(Rc>); 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>; - - fn poll_ready(&mut self, _: &mut Context<'_>) -> Poll> { - Poll::Ready(Ok(())) - } - - fn call(&mut self, _: ()) -> Self::Future { - let prev = *self.0.borrow(); - *(*self.0).borrow_mut() = prev + 1; - ok(*self.0.borrow()) - } + type Request = (); + type Response = usize; + type Error = (); + type Future = Ready>; + + fn poll_ready(&mut self, _: &mut Context<'_>) -> Poll> { + Poll::Ready(Ok(())) + } + + 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(); diff --git a/actix-service/src/and_then.rs b/actix-service/src/and_then.rs index bf402e8f01..d01168520b 100644 --- a/actix-service/src/and_then.rs +++ b/actix-service/src/and_then.rs @@ -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`") + } } } } diff --git a/actix-service/src/and_then_apply_fn.rs b/actix-service/src/and_then_apply_fn.rs index 105d7ed77c..b62cf5054d 100644 --- a/actix-service/src/and_then_apply_fn.rs +++ b/actix-service/src/and_then_apply_fn.rs @@ -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(()))); diff --git a/actix-service/src/apply_cfg.rs b/actix-service/src/apply_cfg.rs index 1fa4f0eebd..0d984309cb 100644 --- a/actix-service/src/apply_cfg.rs +++ b/actix-service/src/apply_cfg.rs @@ -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}; diff --git a/actix-service/src/then.rs b/actix-service/src/then.rs index 8c7bfa85db..3da46cbbab 100644 --- a/actix-service/src/then.rs +++ b/actix-service/src/then.rs @@ -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`") + } } } } diff --git a/router/src/de.rs b/router/src/de.rs index 3621309b4f..5a45fd5140 100644 --- a/router/src/de.rs +++ b/router/src/de.rs @@ -7,9 +7,13 @@ use crate::ResourcePath; macro_rules! unsupported_type { ($trait_fn:ident, $name:expr) => { fn $trait_fn(self, _: V) -> Result - 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(self, visitor: V) -> Result - 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(self, visitor: V) -> Result - 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> { diff --git a/string/src/lib.rs b/string/src/lib.rs index 7695c6fce4..dd89399b7e 100644 --- a/string/src/lib.rs +++ b/string/src/lib.rs @@ -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) }