enable clippy pedantic everywhere

This commit is contained in:
Toshit Chawda 2024-11-25 13:47:41 -08:00
parent 7efda6c533
commit 19fb49a4cc
No known key found for this signature in database
GPG key ID: 91480ED99E2B3D9D
13 changed files with 75 additions and 58 deletions

View file

@ -12,3 +12,10 @@ opt-level = 3
[patch.crates-io] [patch.crates-io]
fastwebsockets = { git = "https://github.com/r58Playz/fastwebsockets" } fastwebsockets = { git = "https://github.com/r58Playz/fastwebsockets" }
h2 = { git = "https://github.com/r58Playz/h2-wasm" } h2 = { git = "https://github.com/r58Playz/h2-wasm" }
[workspace.lints.clippy]
pedantic = { level = "warn", priority = -1 }
must_use_candidate = "allow"
missing_errors_doc = "allow"
module_name_repetitions = "allow"
struct_excessive_bools = "allow"

View file

@ -3,6 +3,9 @@ name = "epoxy-client"
version = "2.1.15" version = "2.1.15"
edition = "2021" edition = "2021"
[lints]
workspace = true
[lib] [lib]
crate-type = ["cdylib"] crate-type = ["cdylib"]

View file

@ -1,4 +1,5 @@
#![feature(let_chains, impl_trait_in_assoc_type)] #![feature(let_chains, impl_trait_in_assoc_type)]
use std::{error::Error, pin::Pin, str::FromStr, sync::Arc}; use std::{error::Error, pin::Pin, str::FromStr, sync::Arc};
#[cfg(feature = "full")] #[cfg(feature = "full")]
@ -89,7 +90,7 @@ impl TryFrom<EpoxyUrlInput> for Uri {
} else if let Some(value) = value.as_string() { } else if let Some(value) = value.as_string() {
value.try_into().map_err(EpoxyError::from) value.try_into().map_err(EpoxyError::from)
} else { } else {
Err(EpoxyError::InvalidUrl(format!("{:?}", value))) Err(EpoxyError::InvalidUrl(format!("{value:?}")))
} }
} }
} }
@ -176,11 +177,12 @@ pub enum EpoxyError {
} }
impl EpoxyError { impl EpoxyError {
#[expect(clippy::needless_pass_by_value)]
pub fn wisp_transport(value: JsValue) -> Self { pub fn wisp_transport(value: JsValue) -> Self {
if let Some(err) = value.dyn_ref::<js_sys::Error>() { if let Some(err) = value.dyn_ref::<js_sys::Error>() {
Self::WispTransport(err.to_string().into()) Self::WispTransport(err.to_string().into())
} else { } else {
Self::WispTransport(format!("{:?}", value)) Self::WispTransport(format!("{value:?}"))
} }
} }
} }
@ -349,7 +351,7 @@ fn create_wisp_transport(function: Function) -> ProviderWispTransportGenerator {
.map(|x| { .map(|x| {
let pkt = x.map_err(EpoxyError::wisp_transport)?; let pkt = x.map_err(EpoxyError::wisp_transport)?;
let arr: ArrayBuffer = pkt.dyn_into().map_err(|x| { let arr: ArrayBuffer = pkt.dyn_into().map_err(|x| {
EpoxyError::InvalidWispTransportPacket(format!("{:?}", x)) EpoxyError::InvalidWispTransportPacket(format!("{x:?}"))
})?; })?;
Ok::<BytesMut, EpoxyError>(BytesMut::from( Ok::<BytesMut, EpoxyError>(BytesMut::from(
Uint8Array::new(&arr).to_vec().as_slice(), Uint8Array::new(&arr).to_vec().as_slice(),
@ -395,10 +397,10 @@ impl EpoxyClient {
options: EpoxyClientOptions, options: EpoxyClientOptions,
) -> Result<EpoxyClient, EpoxyError> { ) -> Result<EpoxyClient, EpoxyError> {
let stream_provider = if let Some(wisp_url) = transport.as_string() { let stream_provider = if let Some(wisp_url) = transport.as_string() {
let wisp_uri: Uri = wisp_url.clone().try_into()?; let uri: Uri = wisp_url.clone().try_into()?;
if wisp_uri.scheme_str() != Some("wss") && wisp_uri.scheme_str() != Some("ws") { if uri.scheme_str() != Some("wss") && uri.scheme_str() != Some("ws") {
return Err(EpoxyError::InvalidUrlScheme( return Err(EpoxyError::InvalidUrlScheme(
wisp_uri.scheme_str().map(ToString::to_string), uri.scheme_str().map(ToString::to_string),
)); ));
} }
@ -538,18 +540,18 @@ impl EpoxyClient {
None None
}; };
let res = self.client.request(req).await; let resp = self.client.request(req).await;
match res { match resp {
Ok(res) => { Ok(resp) => {
if is_redirect(res.status().as_u16()) if is_redirect(resp.status().as_u16())
&& let Some(mut new_req) = new_req && let Some(mut new_req) = new_req
&& let Some(location) = res.headers().get(LOCATION) && let Some(location) = resp.headers().get(LOCATION)
&& let Ok(redirect_url) = new_req.uri().get_redirect(location) && let Ok(redirect_url) = new_req.uri().get_redirect(location)
{ {
*new_req.uri_mut() = redirect_url; *new_req.uri_mut() = redirect_url;
Ok(EpoxyResponse::Redirect((res, new_req))) Ok(EpoxyResponse::Redirect((resp, new_req)))
} else { } else {
Ok(EpoxyResponse::Success(res)) Ok(EpoxyResponse::Success(resp))
} }
} }
Err(err) => Err(err.into()), Err(err) => Err(err.into()),
@ -570,14 +572,15 @@ impl EpoxyClient {
EpoxyResponse::Redirect((_, req)) => { EpoxyResponse::Redirect((_, req)) => {
redirected = true; redirected = true;
current_url = req.uri().clone(); current_url = req.uri().clone();
current_resp = self.send_req_inner(req, should_redirect).await? current_resp = self.send_req_inner(req, should_redirect).await?;
} }
} }
} }
match current_resp { match current_resp {
EpoxyResponse::Success(resp) => Ok((resp, current_url, redirected)), EpoxyResponse::Redirect((resp, _)) | EpoxyResponse::Success(resp) => {
EpoxyResponse::Redirect((resp, _)) => Ok((resp, current_url, redirected)), Ok((resp, current_url, redirected))
}
} }
} }
@ -753,7 +756,7 @@ impl EpoxyClient {
utils::define_property(&resp, "redirected", redirected.into()); utils::define_property(&resp, "redirected", redirected.into());
let raw_headers = Object::new(); let raw_headers = Object::new();
for (k, v) in response_headers_raw.iter() { for (k, v) in &response_headers_raw {
let k = k.as_str(); let k = k.as_str();
let v: JsValue = v.to_str()?.to_string().into(); let v: JsValue = v.to_str()?.to_string().into();
let jv = object_get(&raw_headers, k); let jv = object_get(&raw_headers, k);

View file

@ -81,9 +81,7 @@ impl StreamProvider {
let mut client_config = if options.disable_certificate_validation { let mut client_config = if options.disable_certificate_validation {
client_config client_config
.dangerous() .dangerous()
.with_custom_certificate_verifier(Arc::new(NoCertificateVerification( .with_custom_certificate_verifier(Arc::new(NoCertificateVerification(provider)))
provider,
)))
} else { } else {
cfg_if! { cfg_if! {
if #[cfg(feature = "full")] { if #[cfg(feature = "full")] {
@ -97,9 +95,9 @@ impl StreamProvider {
}) })
.collect(); .collect();
let pems = pems.map_err(EpoxyError::Pemfile)??; let pems = pems.map_err(EpoxyError::Pemfile)??;
let certstore = RootCertStore::from_iter(pems.into_iter().chain(TLS_SERVER_ROOTS.iter().cloned())); let certstore: RootCertStore = pems.into_iter().chain(TLS_SERVER_ROOTS.iter().cloned()).collect();
} else { } else {
let certstore = RootCertStore::from_iter(TLS_SERVER_ROOTS.iter().cloned()); let certstore: RootCertStore = TLS_SERVER_ROOTS.iter().cloned().collect();
} }
} }
client_config.with_root_certificates(certstore) client_config.with_root_certificates(certstore)
@ -149,7 +147,7 @@ impl StreamProvider {
let current_client = self.current_client.clone(); let current_client = self.current_client.clone();
spawn_local(async move { spawn_local(async move {
match fut.await { match fut.await {
Ok(_) => console_log!("epoxy: wisp multiplexor task ended successfully"), Ok(()) => console_log!("epoxy: wisp multiplexor task ended successfully"),
Err(x) => console_error!( Err(x) => console_error!(
"epoxy: wisp multiplexor task ended with an error: {} {:?}", "epoxy: wisp multiplexor task ended with an error: {} {:?}",
x, x,
@ -220,8 +218,7 @@ impl StreamProvider {
.get_ref() .get_ref()
.1 .1
.alpn_protocol() .alpn_protocol()
.map(|x| x == "h2".as_bytes()) .is_some_and(|x| x == "h2".as_bytes());
.unwrap_or(false);
Ok(IgnoreCloseNotify { Ok(IgnoreCloseNotify {
inner: stream.into(), inner: stream.into(),
h2_negotiated, h2_negotiated,
@ -253,7 +250,9 @@ impl hyper::rt::Read for HyperIo {
cx: &mut std::task::Context<'_>, cx: &mut std::task::Context<'_>,
mut buf: hyper::rt::ReadBufCursor<'_>, mut buf: hyper::rt::ReadBufCursor<'_>,
) -> Poll<Result<(), std::io::Error>> { ) -> Poll<Result<(), std::io::Error>> {
let buf_slice: &mut [u8] = unsafe { std::mem::transmute(buf.as_mut()) }; let buf_slice: &mut [u8] = unsafe {
&mut *(std::ptr::from_mut::<[std::mem::MaybeUninit<u8>]>(buf.as_mut()) as *mut [u8])
};
match self.project().inner.poll_read(cx, buf_slice) { match self.project().inner.poll_read(cx, buf_slice) {
Poll::Ready(bytes_read) => { Poll::Ready(bytes_read) => {
let bytes_read = bytes_read?; let bytes_read = bytes_read?;
@ -327,11 +326,14 @@ impl ConnectSvc for StreamProviderService {
Box::pin(async move { Box::pin(async move {
let scheme = req.scheme_str().ok_or(EpoxyError::InvalidUrlScheme(None))?; let scheme = req.scheme_str().ok_or(EpoxyError::InvalidUrlScheme(None))?;
let host = req.host().ok_or(EpoxyError::NoUrlHost)?.to_string(); let host = req.host().ok_or(EpoxyError::NoUrlHost)?.to_string();
let port = req.port_u16().map(Ok).unwrap_or_else(|| match scheme { let port = req.port_u16().map_or_else(
"https" | "wss" => Ok(443), || match scheme {
"http" | "ws" => Ok(80), "https" | "wss" => Ok(443),
_ => Err(EpoxyError::NoUrlPort), "http" | "ws" => Ok(80),
})?; _ => Err(EpoxyError::NoUrlPort),
},
Ok,
)?;
Ok(HyperIo { Ok(HyperIo {
inner: match scheme { inner: match scheme {
"https" => Either::Left(provider.get_tls_stream(host, port, true).await?), "https" => Either::Left(provider.get_tls_stream(host, port, true).await?),

View file

@ -1,5 +1,5 @@
#![allow(dead_code)] #![allow(dead_code)]
//! hyper_util::rt::tokio::TokioIo //! `hyper_util::rt::tokio::TokioIo`
use std::{ use std::{
pin::Pin, pin::Pin,

View file

@ -92,7 +92,7 @@ extern "C" {
pub async fn convert_body(val: JsValue) -> Result<(Uint8Array, Option<String>), JsValue> { pub async fn convert_body(val: JsValue) -> Result<(Uint8Array, Option<String>), JsValue> {
let req: Array = convert_body_inner(val).await?.unchecked_into(); let req: Array = convert_body_inner(val).await?.unchecked_into();
let content_type: Option<JsString> = object_truthy(req.at(1)).map(|x| x.unchecked_into()); let content_type: Option<JsString> = object_truthy(req.at(1)).map(wasm_bindgen::JsCast::unchecked_into);
Ok((req.at(0).unchecked_into(), content_type.map(Into::into))) Ok((req.at(0).unchecked_into(), content_type.map(Into::into)))
} }
@ -109,13 +109,13 @@ impl StreamingInnerBody {
pub fn from_teed(a: ReadableStream, b: ReadableStream) -> Result<Self, EpoxyError> { pub fn from_teed(a: ReadableStream, b: ReadableStream) -> Result<Self, EpoxyError> {
let reader = a let reader = a
.try_into_stream() .try_into_stream()
.map_err(|x| EpoxyError::StreamingBodyConvertFailed(format!("{:?}", x)))?; .map_err(|x| EpoxyError::StreamingBodyConvertFailed(format!("{x:?}")))?;
let reader = reader let reader = reader
.then(|x| async { .then(|x| async {
Ok::<Bytes, JsValue>(Bytes::from(convert_body(x?).await?.0.to_vec())) Ok::<Bytes, JsValue>(Bytes::from(convert_body(x?).await?.0.to_vec()))
}) })
.map_ok(http_body::Frame::data); .map_ok(http_body::Frame::data);
let reader = reader.map_err(|x| std::io::Error::other(format!("{:?}", x))); let reader = reader.map_err(|x| std::io::Error::other(format!("{x:?}")));
let reader = Box::pin(SendWrapper::new(reader)); let reader = Box::pin(SendWrapper::new(reader));
Ok(Self(reader, SendWrapper::new(b))) Ok(Self(reader, SendWrapper::new(b)))
@ -134,7 +134,7 @@ impl Clone for StreamingInnerBody {
fn clone(&self) -> Self { fn clone(&self) -> Self {
match ReadableStream::from_raw(self.1.as_raw().clone()) match ReadableStream::from_raw(self.1.as_raw().clone())
.try_tee() .try_tee()
.map_err(|x| EpoxyError::StreamingBodyTeeFailed(format!("{:?}", x))) .map_err(|x| EpoxyError::StreamingBodyTeeFailed(format!("{x:?}")))
.and_then(|(a, b)| StreamingInnerBody::from_teed(a, b)) .and_then(|(a, b)| StreamingInnerBody::from_teed(a, b))
{ {
Ok(x) => x, Ok(x) => x,
@ -157,7 +157,7 @@ impl MaybeStreamingBody {
Self::Streaming(x) => { Self::Streaming(x) => {
let (a, b) = ReadableStream::from_raw(x) let (a, b) = ReadableStream::from_raw(x)
.try_tee() .try_tee()
.map_err(|x| EpoxyError::StreamingBodyTeeFailed(format!("{:?}", x)))?; .map_err(|x| EpoxyError::StreamingBodyTeeFailed(format!("{x:?}")))?;
Ok(Either::Left(StreamBody::new( Ok(Either::Left(StreamBody::new(
StreamingInnerBody::from_teed(a, b)?, StreamingInnerBody::from_teed(a, b)?,
@ -172,7 +172,7 @@ pub async fn convert_streaming_body(
val: JsValue, val: JsValue,
) -> Result<(MaybeStreamingBody, Option<String>), JsValue> { ) -> Result<(MaybeStreamingBody, Option<String>), JsValue> {
let req: Array = convert_streaming_body_inner(val).await?.unchecked_into(); let req: Array = convert_streaming_body_inner(val).await?.unchecked_into();
let content_type: Option<JsString> = object_truthy(req.at(2)).map(|x| x.unchecked_into()); let content_type: Option<JsString> = object_truthy(req.at(2)).map(wasm_bindgen::JsCast::unchecked_into);
let body = if req.at(0).is_truthy() { let body = if req.at(0).is_truthy() {
MaybeStreamingBody::Streaming(req.at(1).unchecked_into()) MaybeStreamingBody::Streaming(req.at(1).unchecked_into())

View file

@ -131,7 +131,8 @@ pub fn poll_read_buf<T: AsyncRead + ?Sized, B: BufMut>(
let n = { let n = {
let dst = buf.chunk_mut(); let dst = buf.chunk_mut();
let dst = unsafe { std::mem::transmute::<&mut UninitSlice, &mut [u8]>(dst) }; let dst =
unsafe { &mut *(std::ptr::from_mut::<UninitSlice>(dst) as *mut [u8]) };
ready!(io.poll_read(cx, dst)?) ready!(io.poll_read(cx, dst)?)
}; };
@ -147,9 +148,8 @@ impl<R: AsyncRead> Stream for ReaderStream<R> {
fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> { fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
let mut this = self.as_mut().project(); let mut this = self.as_mut().project();
let reader = match this.reader.as_pin_mut() { let Some(reader) = this.reader.as_pin_mut() else {
Some(r) => r, return Poll::Ready(None);
None => return Poll::Ready(None),
}; };
if this.buf.capacity() == 0 { if this.buf.capacity() == 0 {

View file

@ -26,7 +26,7 @@ fn map_close_notify(x: std::io::Result<usize>) -> std::io::Result<usize> {
Err(x) => { Err(x) => {
// hacky way to find if it's actually a rustls close notify error // hacky way to find if it's actually a rustls close notify error
if x.kind() == ErrorKind::UnexpectedEof if x.kind() == ErrorKind::UnexpectedEof
&& format!("{:?}", x).contains("TLS close_notify") && format!("{x:?}").contains("TLS close_notify")
{ {
Ok(0) Ok(0)
} else { } else {

View file

@ -76,7 +76,7 @@ impl WebSocketRead for WebSocketReader {
} }
let res = futures_util::select! { let res = futures_util::select! {
data = self.read_rx.recv_async() => data.ok(), data = self.read_rx.recv_async() => data.ok(),
_ = self.close_event.listen().fuse() => Some(M::Closed), () = self.close_event.listen().fuse() => Some(M::Closed),
}; };
match res.ok_or(WispError::WsImplSocketClosed)? { match res.ok_or(WispError::WsImplSocketClosed)? {
M::Message(bin) => Ok(Frame::binary(Payload::Bytes(BytesMut::from( M::Message(bin) => Ok(Frame::binary(Payload::Bytes(BytesMut::from(
@ -123,8 +123,7 @@ impl WebSocketWrapper {
let onerror_event = error_event.clone(); let onerror_event = error_event.clone();
let onerror = Closure::wrap(Box::new(move |e| { let onerror = Closure::wrap(Box::new(move |e| {
let _ = onerror_tx.send(WebSocketMessage::Error(WebSocketError::Unknown(format!( let _ = onerror_tx.send(WebSocketMessage::Error(WebSocketError::Unknown(format!(
"{:?}", "{e:?}"
e
)))); ))));
onerror_closed.store(true, Ordering::Release); onerror_closed.store(true, Ordering::Release);
onerror_close.notify(usize::MAX); onerror_close.notify(usize::MAX);
@ -145,7 +144,7 @@ impl WebSocketWrapper {
.into(), .into(),
) )
} }
.map_err(|x| EpoxyError::WebSocketConnectFailed(format!("{:?}", x)))?; .map_err(|x| EpoxyError::WebSocketConnectFailed(format!("{x:?}")))?;
ws.set_binary_type(BinaryType::Arraybuffer); ws.set_binary_type(BinaryType::Arraybuffer);
ws.set_onmessage(Some(onmessage.as_ref().unchecked_ref())); ws.set_onmessage(Some(onmessage.as_ref().unchecked_ref()));
ws.set_onopen(Some(onopen.as_ref().unchecked_ref())); ws.set_onopen(Some(onopen.as_ref().unchecked_ref()));
@ -177,15 +176,15 @@ impl WebSocketWrapper {
return false; return false;
} }
futures_util::select! { futures_util::select! {
_ = self.open_event.listen().fuse() => true, () = self.open_event.listen().fuse() => true,
_ = self.error_event.listen().fuse() => false, () = self.error_event.listen().fuse() => false,
} }
} }
} }
impl WebSocketWrite for WebSocketWrapper { impl WebSocketWrite for WebSocketWrapper {
async fn wisp_write_frame(&mut self, frame: Frame<'_>) -> Result<(), WispError> { async fn wisp_write_frame(&mut self, frame: Frame<'_>) -> Result<(), WispError> {
use wisp_mux::ws::OpCode::*; use wisp_mux::ws::OpCode::{Binary, Close, Text};
if self.closed.load(Ordering::Acquire) { if self.closed.load(Ordering::Acquire) {
return Err(WispError::WsImplSocketClosed); return Err(WispError::WsImplSocketClosed);
} }
@ -193,7 +192,7 @@ impl WebSocketWrite for WebSocketWrapper {
Binary | Text => self Binary | Text => self
.inner .inner
.send_with_u8_array(&frame.payload) .send_with_u8_array(&frame.payload)
.map_err(|x| WebSocketError::SendFailed(format!("{:?}", x)).into()), .map_err(|x| WebSocketError::SendFailed(format!("{x:?}")).into()),
Close => { Close => {
let _ = self.inner.close(); let _ = self.inner.close();
Ok(()) Ok(())
@ -205,7 +204,7 @@ impl WebSocketWrite for WebSocketWrapper {
async fn wisp_close(&mut self) -> Result<(), WispError> { async fn wisp_close(&mut self) -> Result<(), WispError> {
self.inner self.inner
.close() .close()
.map_err(|x| WebSocketError::CloseFailed(format!("{:?}", x)).into()) .map_err(|x| WebSocketError::CloseFailed(format!("{x:?}")).into())
} }
} }

View file

@ -3,6 +3,9 @@ name = "epoxy-server"
version = "2.0.0" version = "2.0.0"
edition = "2021" edition = "2021"
[lints]
workspace = true
[dependencies] [dependencies]
anyhow = "1.0.86" anyhow = "1.0.86"
async-speed-limit = { version = "0.4.2", optional = true } async-speed-limit = { version = "0.4.2", optional = true }

View file

@ -3,6 +3,9 @@ name = "simple-wisp-client"
version = "1.0.0" version = "1.0.0"
edition = "2021" edition = "2021"
[lints]
workspace = true
[dependencies] [dependencies]
atomic-counter = "1.0.1" atomic-counter = "1.0.1"
bytes = "1.7.1" bytes = "1.7.1"

View file

@ -10,6 +10,9 @@ edition = "2021"
keywords = ["websocket", "wisp", "multiplexor", "multiplexing", "stream"] keywords = ["websocket", "wisp", "multiplexor", "multiplexing", "stream"]
categories = ["network-programming", "asynchronous", "web-programming::websocket", "wasm"] categories = ["network-programming", "asynchronous", "web-programming::websocket", "wasm"]
[lints]
workspace = true
[dependencies] [dependencies]
async-trait = "0.1.81" async-trait = "0.1.81"
atomic_enum = "0.3.0" atomic_enum = "0.3.0"

View file

@ -1,11 +1,5 @@
#![cfg_attr(docsrs, feature(doc_cfg))] #![cfg_attr(docsrs, feature(doc_cfg))]
#![warn(clippy::pedantic)]
#![deny(missing_docs, clippy::todo)] #![deny(missing_docs, clippy::todo)]
#![allow(
clippy::must_use_candidate,
clippy::missing_errors_doc,
clippy::module_name_repetitions
)]
//! A library for easily creating [Wisp] clients and servers. //! A library for easily creating [Wisp] clients and servers.
//! //!