refactor: marker traits for non-blocking <Async> vs <runtime::Blocking>

- enforce compile-time errors if you try to block on an async-only runtime
   or await a blocking runtime

 - remove viral HRTB for Streams

 - support UNIX streams
This commit is contained in:
Ryan Leckey 2021-01-10 19:23:04 -08:00
parent cbf280b240
commit 6c8d68e9d0
No known key found for this signature in database
GPG Key ID: F8AA68C235AB08C9
29 changed files with 797 additions and 227 deletions

1
Cargo.lock generated
View File

@ -1105,6 +1105,7 @@ dependencies = [
"bytestring",
"conquer-once",
"crossbeam",
"either",
"futures-core",
"futures-io",
"futures-util",

View File

@ -38,6 +38,7 @@ _mock = ["conquer-once", "parking_lot", "crossbeam"]
[dependencies]
log = "0.4.11"
either = "1.6.1"
actix-rt = { version = "2.0.0-beta.2", optional = true }
_async-std = { version = "1.8", optional = true, package = "async-std" }
futures-util = { version = "0.3", optional = true, features = ["io"] }

View File

@ -2,18 +2,12 @@
//! for **blocking** operations.
//!
use std::io::{Read, Result as IoResult, Write};
use std::net::TcpStream;
mod acquire;
mod close;
mod connect;
mod connection;
mod options;
mod runtime;
#[doc(hidden)]
pub mod io;
pub(crate) mod runtime;
pub use acquire::Acquire;
pub use close::Close;
@ -39,62 +33,3 @@ pub mod prelude {
#[doc(no_inline)]
pub use crate::Database as _;
}
pub(super) mod rt {
/// Uses the `std::net` primitives to implement a blocking runtime for SQLx.
#[derive(Debug)]
pub struct Blocking;
}
impl crate::Runtime for rt::Blocking {
#[doc(hidden)]
type TcpStream = TcpStream;
}
impl Runtime for rt::Blocking {
#[doc(hidden)]
fn connect_tcp(host: &str, port: u16) -> IoResult<Self::TcpStream> {
TcpStream::connect((host, port))
}
}
// 's: stream
impl<'s> crate::io::Stream<'s, rt::Blocking> for TcpStream {
#[doc(hidden)]
#[cfg(feature = "async")]
type ReadFuture = futures_util::future::BoxFuture<'s, IoResult<usize>>;
#[doc(hidden)]
#[cfg(feature = "async")]
type WriteFuture = futures_util::future::BoxFuture<'s, IoResult<usize>>;
#[doc(hidden)]
#[cfg(feature = "async")]
fn read_async(&'s mut self, _buf: &'s mut [u8]) -> Self::ReadFuture {
// UNREACHABLE: [`Blocking`] does not implement the [`Async`] marker
unreachable!()
}
#[doc(hidden)]
#[cfg(feature = "async")]
fn write_async(&'s mut self, _buf: &'s [u8]) -> Self::WriteFuture {
// UNREACHABLE: [`Blocking`] does not implement the [`Async`] marker
unreachable!()
}
}
// 's: stream
impl<'s> io::Stream<'s, rt::Blocking> for TcpStream {
#[doc(hidden)]
fn read(&'s mut self, buf: &'s mut [u8]) -> IoResult<usize> {
Read::read(self, buf)
}
#[doc(hidden)]
fn write(&'s mut self, buf: &'s [u8]) -> IoResult<usize> {
let size = buf.len();
self.write_all(buf)?;
Ok(size)
}
}

View File

@ -1,12 +1,10 @@
use super::{io::Stream, Runtime};
use super::Runtime;
pub trait Close<Rt>: crate::Close<Rt>
where
Rt: Runtime,
{
fn close(self) -> crate::Result<()>
where
for<'s> <Rt as crate::Runtime>::TcpStream: Stream<'s, Rt>;
fn close(self) -> crate::Result<()>;
}
// TODO: impl Close for Pool { ... }

View File

@ -1,4 +1,4 @@
use super::{io::Stream, Runtime};
use super::Runtime;
pub trait Connect<Rt>: crate::Connect<Rt>
where
@ -6,8 +6,7 @@ where
{
fn connect(url: &str) -> crate::Result<Self>
where
Self: Sized,
for<'s> <Rt as crate::Runtime>::TcpStream: Stream<'s, Rt>;
Self: Sized;
}
// TODO: impl Connect for Pool { ... }

View File

@ -1,4 +1,4 @@
use super::{io::Stream, Close, Connect, ConnectOptions, Runtime};
use super::{Close, Connect, ConnectOptions, Runtime};
/// A unique connection (session) with a specific database.
///
@ -15,7 +15,5 @@ where
/// For detailed information, refer to the asynchronous version of
/// this: [`ping()`][crate::Connection::ping].
///
fn ping(&mut self) -> crate::Result<()>
where
for<'s> <Rt as crate::Runtime>::TcpStream: Stream<'s, Rt>;
fn ping(&mut self) -> crate::Result<()>;
}

View File

@ -1,15 +0,0 @@
use std::io;
use crate::Runtime;
// 's: stream
pub trait Stream<'s, Rt>: crate::io::Stream<'s, Rt>
where
Rt: Runtime,
{
#[doc(hidden)]
fn read(&'s mut self, buf: &'s mut [u8]) -> io::Result<usize>;
#[doc(hidden)]
fn write(&'s mut self, buf: &'s [u8]) -> io::Result<usize>;
}

View File

@ -1,4 +1,4 @@
use super::{io::Stream, Connection, Runtime};
use super::{Connection, Runtime};
/// Options which can be used to configure how a SQL connection is opened.
///
@ -18,6 +18,5 @@ where
///
fn connect(&self) -> crate::Result<Self::Connection>
where
Self::Connection: Sized,
for<'s> <Rt as crate::Runtime>::TcpStream: Stream<'s, Rt>;
Self::Connection: Sized;
}

View File

@ -1,12 +1,139 @@
use std::io;
use std::io::{self, Read, Write};
use std::net::TcpStream;
#[cfg(unix)]
use std::os::unix::net::UnixStream;
#[cfg(unix)]
use std::path::Path;
/// Describes a set of types and functions used to open and manage
/// resources within SQLx.
///
/// For detailed information, refer to the asynchronous version of
/// this: [`Runtime`][crate::Runtime].
///
pub trait Runtime: crate::Runtime {
/// Opens a TCP connection to a remote host at the specified port.
fn connect_tcp(host: &str, port: u16) -> io::Result<Self::TcpStream>;
#[cfg(feature = "async")]
use futures_util::future::BoxFuture;
use crate::io::Stream as IoStream;
/// Marks a [`Runtime`][crate::Runtime] as being capable of executing blocking operations.
pub trait Runtime: crate::Runtime {}
/// Uses the `std::net` primitives to implement a blocking runtime for SQLx.
#[derive(Debug)]
pub struct Blocking;
impl crate::Runtime for Blocking {
#[doc(hidden)]
type TcpStream = TcpStream;
#[doc(hidden)]
#[cfg(unix)]
type UnixStream = UnixStream;
#[doc(hidden)]
fn connect_tcp(host: &str, port: u16) -> io::Result<Self::TcpStream> {
TcpStream::connect((host, port))
}
#[doc(hidden)]
#[cfg(all(unix, feature = "blocking"))]
fn connect_unix(path: &Path) -> io::Result<Self::UnixStream> {
UnixStream::connect(path)
}
#[doc(hidden)]
#[cfg(feature = "async")]
#[allow(unused_variables)]
fn connect_tcp_async(host: &str, port: u16) -> BoxFuture<'_, io::Result<Self::TcpStream>> {
// UNREACHABLE: where Self: Async
unreachable!()
}
#[doc(hidden)]
#[cfg(all(unix, feature = "async"))]
#[allow(unused_variables)]
fn connect_unix_async(path: &Path) -> BoxFuture<'_, io::Result<Self::UnixStream>> {
// UNREACHABLE: where Self: Async
unreachable!()
}
}
impl Runtime for Blocking {}
// 's: stream
impl<'s> IoStream<'s, Blocking> for TcpStream {
#[doc(hidden)]
#[cfg(feature = "async")]
type ReadFuture = BoxFuture<'s, io::Result<usize>>;
#[doc(hidden)]
#[cfg(feature = "async")]
type WriteFuture = BoxFuture<'s, io::Result<usize>>;
#[inline]
#[doc(hidden)]
fn read(&'s mut self, buf: &'s mut [u8]) -> io::Result<usize> {
Read::read(self, buf)
}
#[inline]
#[doc(hidden)]
fn write(&'s mut self, buf: &'s [u8]) -> io::Result<usize> {
let size = buf.len();
Write::write_all(self, buf)?;
Ok(size)
}
#[doc(hidden)]
#[cfg(feature = "async")]
fn read_async(&'s mut self, _buf: &'s mut [u8]) -> Self::ReadFuture {
// UNREACHABLE: where Self: Async
unreachable!()
}
#[doc(hidden)]
#[cfg(feature = "async")]
fn write_async(&'s mut self, _buf: &'s [u8]) -> Self::WriteFuture {
// UNREACHABLE: where Self: Async
unreachable!()
}
}
// 's: stream
#[cfg(unix)]
impl<'s> IoStream<'s, Blocking> for UnixStream {
#[doc(hidden)]
#[cfg(feature = "async")]
type ReadFuture = BoxFuture<'s, io::Result<usize>>;
#[doc(hidden)]
#[cfg(feature = "async")]
type WriteFuture = BoxFuture<'s, io::Result<usize>>;
#[inline]
#[doc(hidden)]
fn read(&'s mut self, buf: &'s mut [u8]) -> io::Result<usize> {
Read::read(self, buf)
}
#[inline]
#[doc(hidden)]
fn write(&'s mut self, buf: &'s [u8]) -> io::Result<usize> {
let size = buf.len();
Write::write_all(self, buf)?;
Ok(size)
}
#[doc(hidden)]
#[cfg(feature = "async")]
#[allow(unused_variables)]
fn read_async(&'s mut self, _buf: &'s mut [u8]) -> Self::ReadFuture {
// UNREACHABLE: where Self: Async
unreachable!()
}
#[doc(hidden)]
#[cfg(feature = "async")]
#[allow(unused_variables)]
fn write_async(&'s mut self, _buf: &'s [u8]) -> Self::WriteFuture {
// UNREACHABLE: where Self: Async
unreachable!()
}
}

View File

@ -8,8 +8,7 @@ where
#[cfg(feature = "async")]
fn close(self) -> futures_util::future::BoxFuture<'static, crate::Result<()>>
where
Rt: crate::Async,
for<'s> <Rt as Runtime>::TcpStream: crate::io::Stream<'s, Rt>;
Rt: crate::Async;
}
// TODO: impl Close for Pool { ... }

View File

@ -10,8 +10,7 @@ where
fn connect(url: &str) -> futures_util::future::BoxFuture<'_, crate::Result<Self>>
where
Self: Sized,
Rt: crate::Async,
for<'s> <Rt as Runtime>::TcpStream: crate::io::Stream<'s, Rt>;
Rt: crate::Async;
}
// TODO: impl Connect for Pool { ... }

View File

@ -28,6 +28,5 @@ where
#[cfg(feature = "async")]
fn ping(&mut self) -> BoxFuture<'_, crate::Result<()>>
where
Rt: crate::Async,
for<'s> <Rt as Runtime>::TcpStream: crate::io::Stream<'s, Rt>;
Rt: crate::Async;
}

View File

@ -2,6 +2,8 @@ use std::marker::PhantomData;
use bytes::{Bytes, BytesMut};
use super::Stream;
/// Wraps a stream and buffers input and output to and from it.
///
/// It can be excessively inefficient to work directly with a `Read` or `Write`. For example,
@ -47,7 +49,7 @@ impl<Rt, S> BufStream<Rt, S> {
}
pub fn consume(&mut self, n: usize) {
let _ = self.take(n);
let _rem = self.take(n);
}
pub fn reserve(&mut self, additional: usize) {
@ -119,7 +121,7 @@ macro_rules! read {
}
#[cfg(feature = "async")]
impl<Rt: crate::Runtime, S: for<'s> crate::io::Stream<'s, Rt>> BufStream<Rt, S> {
impl<Rt: crate::Async, S: for<'s> Stream<'s, Rt>> BufStream<Rt, S> {
pub async fn flush_async(&mut self) -> crate::Result<()> {
// write as much as we can each time and move the cursor as we write from the buffer
// if _this_ future drops, offset will have a record of how much of the wbuf has
@ -141,7 +143,7 @@ impl<Rt: crate::Runtime, S: for<'s> crate::io::Stream<'s, Rt>> BufStream<Rt, S>
}
#[cfg(feature = "blocking")]
impl<Rt: crate::Runtime, S: for<'s> crate::blocking::io::Stream<'s, Rt>> BufStream<Rt, S> {
impl<Rt: crate::blocking::Runtime, S: for<'s> Stream<'s, Rt>> BufStream<Rt, S> {
pub fn flush(&mut self) -> crate::Result<()> {
self.stream.write(&self.wbuf)?;
self.wbuf.clear();

View File

@ -1,18 +1,74 @@
#[cfg(feature = "async")]
use std::future::Future;
use std::io;
use crate::Runtime;
// 's: stream
pub trait Stream<'s, Rt: Runtime>: Send + Sync + Unpin {
pub trait Stream<'s, Rt>: Send + Sync + Unpin
where
Rt: Runtime,
{
#[cfg(feature = "async")]
type ReadFuture: 's + std::future::Future<Output = std::io::Result<usize>> + Send;
type ReadFuture: 's + Future<Output = io::Result<usize>> + Send;
#[cfg(feature = "async")]
type WriteFuture: 's + std::future::Future<Output = std::io::Result<usize>> + Send;
type WriteFuture: 's + Future<Output = io::Result<usize>> + Send;
#[cfg(feature = "async")]
#[doc(hidden)]
fn read_async(&'s mut self, buf: &'s mut [u8]) -> Self::ReadFuture;
fn read_async(&'s mut self, buf: &'s mut [u8]) -> Self::ReadFuture
where
Rt: crate::Async;
#[cfg(feature = "async")]
#[doc(hidden)]
fn write_async(&'s mut self, buf: &'s [u8]) -> Self::WriteFuture;
fn write_async(&'s mut self, buf: &'s [u8]) -> Self::WriteFuture
where
Rt: crate::Async;
#[cfg(feature = "blocking")]
#[doc(hidden)]
fn read(&'s mut self, buf: &'s mut [u8]) -> io::Result<usize>
where
Rt: crate::blocking::Runtime;
#[cfg(feature = "blocking")]
#[doc(hidden)]
fn write(&'s mut self, buf: &'s [u8]) -> io::Result<usize>
where
Rt: crate::blocking::Runtime;
}
#[cfg(not(any(
feature = "async-std",
feature = "actix",
feature = "tokio",
feature = "blocking"
)))]
impl<'s, Rt> Stream<'s, Rt> for ()
where
Rt: Runtime,
{
#[cfg(feature = "async")]
type ReadFuture = futures_util::future::BoxFuture<'s, io::Result<usize>>;
#[cfg(feature = "async")]
type WriteFuture = futures_util::future::BoxFuture<'s, io::Result<usize>>;
#[cfg(feature = "async")]
#[doc(hidden)]
#[allow(unused_variables)]
fn read_async(&'s mut self, buf: &'s mut [u8]) -> Self::ReadFuture {
// UNREACHABLE: where Self: Async
unreachable!()
}
#[cfg(feature = "async")]
#[doc(hidden)]
#[allow(unused_variables)]
fn write_async(&'s mut self, buf: &'s [u8]) -> Self::WriteFuture {
// UNREACHABLE: where Self: Async
unreachable!()
}
}

View File

@ -2,6 +2,7 @@
//! database driver (`sqlx-postgres`, `sqlx-mysql`, etc.).
//!
#![cfg_attr(doc_cfg, feature(doc_cfg))]
#![cfg_attr(not(any(feature = "async", feature = "blocking")), allow(unused))]
#![deny(unsafe_code)]
#![warn(rust_2018_idioms)]
#![warn(future_incompatible)]
@ -30,6 +31,9 @@ mod runtime;
#[doc(hidden)]
pub mod io;
#[doc(hidden)]
pub mod net;
#[doc(hidden)]
#[cfg(feature = "_mock")]
pub mod mock;
@ -39,7 +43,7 @@ pub mod blocking;
pub use acquire::Acquire;
#[cfg(feature = "blocking")]
pub use blocking::rt::Blocking;
pub use blocking::runtime::Blocking;
pub use close::Close;
pub use connect::Connect;
pub use connection::Connection;
@ -56,6 +60,10 @@ pub use runtime::Tokio;
pub use runtime::{Async, DefaultRuntime, Runtime};
/// Convenience re-export of common traits for non-blocking operations.
#[cfg(any(
any(feature = "async-std", feature = "tokio", feature = "actix"),
not(feature = "blocking")
))]
pub mod prelude {
#[doc(no_inline)]
pub use super::Acquire as _;

View File

@ -1,18 +1,18 @@
use std::collections::HashMap;
use std::io;
#[cfg(feature = "async")]
use std::pin::Pin;
#[cfg(unix)]
use std::path::Path;
use std::sync::atomic::AtomicU16;
use std::sync::atomic::Ordering;
use bytes::BytesMut;
use conquer_once::Lazy;
use crossbeam::channel;
#[cfg(feature = "async")]
use futures_util::future::{self, BoxFuture};
use parking_lot::RwLock;
#[cfg(feature = "blocking")]
use crate::blocking;
use crate::{io::Stream, Runtime};
use crate::{io::Stream as IoStream, Runtime};
#[derive(Debug)]
pub struct Mock;
@ -32,23 +32,39 @@ static MOCK_STREAMS: Lazy<RwLock<HashMap<u16, MockStream>>> = Lazy::new(RwLock::
impl Runtime for Mock {
type TcpStream = MockStream;
}
#[cfg(feature = "async")]
impl crate::Async for Mock {
fn connect_tcp_async(
_host: &str,
port: u16,
) -> futures_util::future::BoxFuture<'_, io::Result<Self::TcpStream>> {
Box::pin(futures_util::future::ready(Self::get_stream(port)))
}
}
#[cfg(unix)]
type UnixStream = MockStream;
#[cfg(feature = "blocking")]
impl crate::blocking::Runtime for Mock {
#[doc(hidden)]
#[cfg(feature = "blocking")]
fn connect_tcp(_host: &str, port: u16) -> io::Result<Self::TcpStream> {
Self::get_stream(port)
}
#[doc(hidden)]
#[cfg(all(unix, feature = "blocking"))]
fn connect_unix(_path: &Path) -> io::Result<Self::UnixStream> {
Err(io::Error::new(
io::ErrorKind::Other,
"Unix streams are not supported in the Mock runtime",
))
}
#[doc(hidden)]
#[cfg(feature = "async")]
fn connect_tcp_async(_host: &str, port: u16) -> BoxFuture<'_, io::Result<Self::TcpStream>> {
Box::pin(future::ready(Self::get_stream(port)))
}
#[doc(hidden)]
#[cfg(all(unix, feature = "async"))]
fn connect_unix_async(_path: &Path) -> BoxFuture<'_, io::Result<Self::UnixStream>> {
Box::pin(future::err(io::Error::new(
io::ErrorKind::Other,
"Unix streams are not supported in the Mock runtime",
)))
}
}
impl Mock {
@ -82,12 +98,12 @@ impl MockStream {
}
}
impl<'s> Stream<'s, Mock> for MockStream {
impl<'s> IoStream<'s, Mock> for MockStream {
#[cfg(feature = "async")]
type ReadFuture = Pin<Box<dyn std::future::Future<Output = io::Result<usize>> + 's + Send>>;
type ReadFuture = BoxFuture<'s, io::Result<usize>>;
#[cfg(feature = "async")]
type WriteFuture = Pin<Box<dyn std::future::Future<Output = io::Result<usize>> + 's + Send>>;
type WriteFuture = BoxFuture<'s, io::Result<usize>>;
#[cfg(feature = "async")]
fn read_async(&'s mut self, mut buf: &'s mut [u8]) -> Self::ReadFuture {
@ -100,7 +116,7 @@ impl<'s> Stream<'s, Mock> for MockStream {
let written = buf.write(&self.rbuf)?;
// remove the bytes that we were able to write
let _ = self.rbuf.split_to(written);
let _rem = self.rbuf.split_to(written);
// return how many bytes we wrote
return Ok(written);
@ -124,15 +140,13 @@ impl<'s> Stream<'s, Mock> for MockStream {
#[cfg(feature = "async")]
fn write_async(&'s mut self, buf: &'s [u8]) -> Self::WriteFuture {
// send it all, right away
let _ = self.write.send(buf.to_vec());
let _res = self.write.send(buf.to_vec());
// that was easy
Box::pin(futures_util::future::ok(buf.len()))
Box::pin(future::ok(buf.len()))
}
}
#[cfg(feature = "blocking")]
impl<'s> blocking::io::Stream<'s, Mock> for MockStream {
#[cfg(feature = "blocking")]
fn read(&'s mut self, mut buf: &'s mut [u8]) -> io::Result<usize> {
use io::Write;
@ -142,7 +156,7 @@ impl<'s> blocking::io::Stream<'s, Mock> for MockStream {
let written = buf.write(&self.rbuf)?;
// remove the bytes that we were able to write
let _ = self.rbuf.split_to(written);
let _rem = self.rbuf.split_to(written);
// return how many bytes we wrote
return Ok(written);
@ -157,9 +171,10 @@ impl<'s> blocking::io::Stream<'s, Mock> for MockStream {
}
}
#[cfg(feature = "blocking")]
fn write(&'s mut self, buf: &'s [u8]) -> io::Result<usize> {
// send it all, right away
let _ = self.write.send(buf.to_vec());
let _res = self.write.send(buf.to_vec());
// that was easy
Ok(buf.len())

3
sqlx-core/src/net.rs Normal file
View File

@ -0,0 +1,3 @@
mod stream;
pub use stream::Stream;

196
sqlx-core/src/net/stream.rs Normal file
View File

@ -0,0 +1,196 @@
use std::io;
use std::path::PathBuf;
use either::Either;
#[cfg(feature = "async")]
use futures_util::future::{self, FutureExt};
use crate::io::Stream as IoStream;
use crate::Runtime;
#[derive(Debug)]
pub enum Stream<Rt>
where
Rt: Runtime,
{
Tcp(Rt::TcpStream),
#[cfg(unix)]
Unix(Rt::UnixStream),
}
impl<Rt> Stream<Rt>
where
Rt: Runtime,
{
#[cfg(feature = "async")]
pub async fn connect_async(address: Either<&(String, u16), &PathBuf>) -> io::Result<Self>
where
Rt: crate::Async,
{
match address {
Either::Left((host, port)) => Rt::connect_tcp_async(host, *port).await.map(Self::Tcp),
#[cfg(unix)]
Either::Right(socket) => Rt::connect_unix_async(socket).await.map(Self::Unix),
#[cfg(not(unix))]
Either(_socket) => Err(io::Error::new(
io::ErrorKind::Other,
"Unix streams are not supported outside Unix platforms",
)),
}
}
#[cfg(feature = "blocking")]
pub fn connect(address: Either<&(String, u16), &PathBuf>) -> io::Result<Self>
where
Rt: crate::blocking::Runtime,
{
match address {
Either::Left((host, port)) => Rt::connect_tcp(host, *port).map(Self::Tcp),
#[cfg(unix)]
Either::Right(socket) => Rt::connect_unix(socket).map(Self::Unix),
#[cfg(not(unix))]
Either(_socket) => Err(io::Error::new(
io::ErrorKind::Other,
"Unix streams are not supported outside Unix platforms",
)),
}
}
}
#[cfg(unix)]
impl<'s, Rt> IoStream<'s, Rt> for Stream<Rt>
where
Rt: Runtime,
{
#[doc(hidden)]
#[cfg(feature = "async")]
type ReadFuture = future::Either<
<Rt::TcpStream as IoStream<'s, Rt>>::ReadFuture,
<Rt::UnixStream as IoStream<'s, Rt>>::ReadFuture,
>;
#[doc(hidden)]
#[cfg(feature = "async")]
type WriteFuture = future::Either<
<Rt::TcpStream as IoStream<'s, Rt>>::WriteFuture,
<Rt::UnixStream as IoStream<'s, Rt>>::WriteFuture,
>;
#[inline]
#[doc(hidden)]
#[cfg(feature = "async")]
fn read_async(&'s mut self, buf: &'s mut [u8]) -> Self::ReadFuture
where
Rt: crate::Async,
{
match self {
Self::Tcp(stream) => stream.read_async(buf).left_future(),
Self::Unix(stream) => stream.read_async(buf).right_future(),
}
}
#[inline]
#[doc(hidden)]
#[cfg(feature = "async")]
fn write_async(&'s mut self, buf: &'s [u8]) -> Self::WriteFuture
where
Rt: crate::Async,
{
match self {
Self::Tcp(stream) => stream.write_async(buf).left_future(),
Self::Unix(stream) => stream.write_async(buf).right_future(),
}
}
#[inline]
#[doc(hidden)]
#[cfg(feature = "blocking")]
fn read(&'s mut self, buf: &'s mut [u8]) -> io::Result<usize>
where
Rt: crate::blocking::Runtime,
{
match self {
Self::Tcp(stream) => stream.read(buf),
Self::Unix(stream) => stream.read(buf),
}
}
#[inline]
#[doc(hidden)]
#[cfg(feature = "blocking")]
fn write(&'s mut self, buf: &'s [u8]) -> io::Result<usize>
where
Rt: crate::blocking::Runtime,
{
match self {
Self::Tcp(stream) => stream.write(buf),
Self::Unix(stream) => stream.write(buf),
}
}
}
#[cfg(not(unix))]
impl<'s, Rt> IoStream<'s, Rt> for Stream<Rt>
where
Rt: Runtime,
{
#[doc(hidden)]
#[cfg(feature = "async")]
type ReadFuture = <Rt::TcpStream as IoStream<'s, Rt>>::ReadFuture;
#[doc(hidden)]
#[cfg(feature = "async")]
type WriteFuture = <Rt::TcpStream as IoStream<'s, Rt>>::WriteFuture;
#[inline]
#[doc(hidden)]
#[cfg(feature = "async")]
fn read_async(&'s mut self, buf: &'s mut [u8]) -> Self::ReadFuture
where
Rt: crate::Async,
{
match self {
Self::Tcp(stream) => stream.read_async(buf),
}
}
#[inline]
#[doc(hidden)]
#[cfg(feature = "async")]
fn write_async(&'s mut self, buf: &'s [u8]) -> Self::WriteFuture
where
Rt: crate::Async,
{
match self {
Self::Tcp(stream) => stream.write_async(buf),
}
}
#[inline]
#[doc(hidden)]
#[cfg(feature = "blocking")]
fn read(&'s mut self, buf: &'s mut [u8]) -> io::Result<usize>
where
Rt: crate::blocking::Runtime,
{
match self {
Self::Tcp(stream) => stream.read(buf),
}
}
#[inline]
#[doc(hidden)]
#[cfg(feature = "blocking")]
fn write(&'s mut self, buf: &'s [u8]) -> io::Result<usize>
where
Rt: crate::blocking::Runtime,
{
match self {
Self::Tcp(stream) => stream.write(buf),
}
}
}

View File

@ -17,6 +17,5 @@ where
fn connect(&self) -> futures_util::future::BoxFuture<'_, crate::Result<Self::Connection>>
where
Self::Connection: Sized,
Rt: crate::Async,
for<'s> Rt::TcpStream: crate::io::Stream<'s, Rt>;
Rt: crate::Async;
}

View File

@ -1,4 +1,13 @@
use crate::io::Stream;
use std::io;
#[cfg(unix)]
use std::path::Path;
#[cfg(feature = "async")]
use futures_util::future::BoxFuture;
#[cfg(feature = "blocking")]
use crate::blocking;
use crate::io::Stream as IoStream;
#[cfg(feature = "async-std")]
#[path = "runtime/async_std.rs"]
@ -43,28 +52,41 @@ pub use tokio_::Tokio;
///
pub trait Runtime: 'static + Send + Sync + Sized {
#[doc(hidden)]
type TcpStream: 'static + Send + Sync;
type TcpStream: for<'s> IoStream<'s, Self>;
#[doc(hidden)]
#[cfg(unix)]
type UnixStream: for<'s> IoStream<'s, Self>;
#[doc(hidden)]
#[cfg(feature = "blocking")]
fn connect_tcp(host: &str, port: u16) -> io::Result<Self::TcpStream>
where
Self: blocking::Runtime;
#[doc(hidden)]
#[cfg(all(unix, feature = "blocking"))]
fn connect_unix(path: &Path) -> io::Result<Self::UnixStream>
where
Self: blocking::Runtime;
#[doc(hidden)]
#[cfg(feature = "async")]
fn connect_tcp_async(host: &str, port: u16) -> BoxFuture<'_, io::Result<Self::TcpStream>>
where
Self: Async;
#[doc(hidden)]
#[cfg(all(unix, feature = "async"))]
fn connect_unix_async(path: &Path) -> BoxFuture<'_, io::Result<Self::UnixStream>>
where
Self: Async;
}
/// Marks a [`Runtime`] as being capable of handling asynchronous execution.
// Provided so that attempting to use the asynchronous methods with the
// Blocking runtime will error at compile-time as opposed to runtime.
pub trait Async: Runtime
where
// NOTE: This requires a **pervasive** bound for everything that needs
// to bound on <Runtime>. Remove if you can think of something else that
// allows us to both allow polymorphic read/write on streams across
// runtimes _and_ not depend on <BoxFuture>. When GATs are stabilized,
// we should be able to switch to that and remove this HRTB.
Self::TcpStream: for<'s> Stream<'s, Self>,
{
#[cfg(feature = "async")]
#[doc(hidden)]
fn connect_tcp_async(
host: &str,
port: u16,
) -> futures_util::future::BoxFuture<'_, std::io::Result<Self::TcpStream>>;
}
pub trait Async: Runtime {}
// when no runtime is available
// we implement `()` for it to allow the lib to still compile
@ -75,7 +97,28 @@ where
feature = "blocking"
)))]
impl Runtime for () {
#[doc(hidden)]
type TcpStream = ();
#[doc(hidden)]
#[cfg(unix)]
type UnixStream = ();
#[doc(hidden)]
#[cfg(feature = "async")]
#[allow(unused_variables)]
fn connect_tcp_async(host: &str, port: u16) -> BoxFuture<'_, io::Result<Self::TcpStream>> {
// UNREACHABLE: where Self: Async
unreachable!()
}
#[doc(hidden)]
#[cfg(all(unix, feature = "async"))]
#[allow(unused_variables)]
fn connect_unix_async(path: &Path) -> BoxFuture<'_, io::Result<Self::UnixStream>> {
// UNREACHABLE: where Self: blocking::Runtime
unreachable!()
}
}
// pick a default runtime

View File

@ -1,6 +1,10 @@
use std::io;
#[cfg(unix)]
use std::path::Path;
use actix_rt::net::TcpStream;
#[cfg(unix)]
use actix_rt::net::UnixStream;
use async_compat::Compat;
use futures_util::io::{Read, Write};
use futures_util::{future::BoxFuture, AsyncReadExt, AsyncWriteExt, FutureExt, TryFutureExt};
@ -17,20 +21,44 @@ use crate::{io::Stream, Async, Runtime};
#[derive(Debug)]
pub struct Actix;
// NOTE: Compat<_> is used for IO streams to avoid requiring a Box per read/write call
// https://github.com/tokio-rs/tokio/issues/2723
impl Runtime for Actix {
// NOTE: Compat<_> is used to avoid requiring a Box per read/write call
// https://github.com/tokio-rs/tokio/issues/2723
#[doc(hidden)]
type TcpStream = Compat<TcpStream>;
}
impl Async for Actix {
#[doc(hidden)]
#[cfg(unix)]
type UnixStream = Compat<UnixStream>;
#[doc(hidden)]
#[cfg(feature = "blocking")]
fn connect_tcp(_host: &str, _port: u16) -> io::Result<Self::TcpStream> {
// UNREACHABLE: where Self: blocking::Runtime
unreachable!()
}
#[doc(hidden)]
#[cfg(all(unix, feature = "blocking"))]
fn connect_unix(_path: &Path) -> io::Result<Self::UnixStream> {
// UNREACHABLE: where Self: blocking::Runtime
unreachable!()
}
#[doc(hidden)]
fn connect_tcp_async(host: &str, port: u16) -> BoxFuture<'_, io::Result<Self::TcpStream>> {
TcpStream::connect((host, port)).map_ok(Compat::new).boxed()
}
#[doc(hidden)]
#[cfg(unix)]
fn connect_unix_async(path: &Path) -> BoxFuture<'_, io::Result<Self::UnixStream>> {
UnixStream::connect(path).map_ok(Compat::new).boxed()
}
}
impl Async for Actix {}
// 's: stream
impl<'s> Stream<'s, Actix> for Compat<TcpStream> {
#[doc(hidden)]
@ -42,12 +70,66 @@ impl<'s> Stream<'s, Actix> for Compat<TcpStream> {
#[inline]
#[doc(hidden)]
fn read_async(&'s mut self, buf: &'s mut [u8]) -> Self::ReadFuture {
self.read(buf)
AsyncReadExt::read(self, buf)
}
#[inline]
#[doc(hidden)]
fn write_async(&'s mut self, buf: &'s [u8]) -> Self::WriteFuture {
self.write(buf)
AsyncWriteExt::write(self, buf)
}
#[inline]
#[doc(hidden)]
#[cfg(feature = "blocking")]
fn read(&'s mut self, _buf: &'s mut [u8]) -> io::Result<usize> {
// UNREACHABLE: where Self: blocking::Runtime
unreachable!()
}
#[inline]
#[doc(hidden)]
#[cfg(feature = "blocking")]
fn write(&'s mut self, _buf: &'s [u8]) -> io::Result<usize> {
// UNREACHABLE: where Self: blocking::Runtime
unreachable!()
}
}
// 's: stream
#[cfg(unix)]
impl<'s> Stream<'s, Actix> for Compat<UnixStream> {
#[doc(hidden)]
type ReadFuture = Read<'s, Self>;
#[doc(hidden)]
type WriteFuture = Write<'s, Self>;
#[inline]
#[doc(hidden)]
fn read_async(&'s mut self, buf: &'s mut [u8]) -> Self::ReadFuture {
AsyncReadExt::read(self, buf)
}
#[inline]
#[doc(hidden)]
fn write_async(&'s mut self, buf: &'s [u8]) -> Self::WriteFuture {
AsyncWriteExt::write(self, buf)
}
#[inline]
#[doc(hidden)]
#[cfg(feature = "blocking")]
fn read(&'s mut self, _buf: &'s mut [u8]) -> io::Result<usize> {
// UNREACHABLE: where Self: blocking::Runtime
unreachable!()
}
#[inline]
#[doc(hidden)]
#[cfg(feature = "blocking")]
fn write(&'s mut self, _buf: &'s [u8]) -> io::Result<usize> {
// UNREACHABLE: where Self: blocking::Runtime
unreachable!()
}
}

View File

@ -1,4 +1,10 @@
use std::io;
#[cfg(unix)]
use std::path::Path;
use _async_std::net::TcpStream;
#[cfg(unix)]
use _async_std::os::unix::net::UnixStream;
#[cfg(feature = "blocking")]
use _async_std::task;
use futures_util::io::{Read, Write};
@ -21,23 +27,42 @@ pub struct AsyncStd;
impl Runtime for AsyncStd {
#[doc(hidden)]
type TcpStream = TcpStream;
}
impl Async for AsyncStd {
#[doc(hidden)]
fn connect_tcp_async(host: &str, port: u16) -> BoxFuture<'_, std::io::Result<Self::TcpStream>> {
TcpStream::connect((host, port)).boxed()
}
}
#[cfg(unix)]
type UnixStream = UnixStream;
#[cfg(feature = "blocking")]
impl blocking::Runtime for AsyncStd {
#[doc(hidden)]
fn connect_tcp(host: &str, port: u16) -> std::io::Result<Self::TcpStream> {
#[cfg(feature = "blocking")]
fn connect_tcp(host: &str, port: u16) -> io::Result<Self::TcpStream> {
task::block_on(Self::connect_tcp_async(host, port))
}
#[doc(hidden)]
#[cfg(all(unix, feature = "blocking"))]
fn connect_unix(path: &Path) -> io::Result<Self::UnixStream> {
task::block_on(Self::connect_unix_async(path))
}
#[doc(hidden)]
fn connect_tcp_async(host: &str, port: u16) -> BoxFuture<'_, io::Result<Self::TcpStream>> {
TcpStream::connect((host, port)).boxed()
}
#[doc(hidden)]
#[cfg(unix)]
fn connect_unix_async(path: &Path) -> BoxFuture<'_, io::Result<Self::UnixStream>> {
UnixStream::connect(path).boxed()
}
}
impl Async for AsyncStd {}
// blocking operations provided by trivially wrapping async counterparts
// with `task::block_on`
#[cfg(feature = "blocking")]
impl blocking::Runtime for AsyncStd {}
// 's: stream
impl<'s> Stream<'s, AsyncStd> for TcpStream {
#[doc(hidden)]
@ -49,26 +74,62 @@ impl<'s> Stream<'s, AsyncStd> for TcpStream {
#[inline]
#[doc(hidden)]
fn read_async(&'s mut self, buf: &'s mut [u8]) -> Self::ReadFuture {
self.read(buf)
AsyncReadExt::read(self, buf)
}
#[inline]
#[doc(hidden)]
fn write_async(&'s mut self, buf: &'s [u8]) -> Self::WriteFuture {
self.write(buf)
AsyncWriteExt::write(self, buf)
}
#[inline]
#[doc(hidden)]
#[cfg(feature = "blocking")]
fn read(&'s mut self, buf: &'s mut [u8]) -> io::Result<usize> {
task::block_on(self.read_async(buf))
}
#[inline]
#[doc(hidden)]
#[cfg(feature = "blocking")]
fn write(&'s mut self, buf: &'s [u8]) -> io::Result<usize> {
task::block_on(self.write_async(buf))
}
}
// 's: stream
#[cfg(feature = "blocking")]
impl<'s> blocking::io::Stream<'s, AsyncStd> for TcpStream {
#[cfg(unix)]
impl<'s> Stream<'s, AsyncStd> for UnixStream {
#[doc(hidden)]
fn read(&'s mut self, buf: &'s mut [u8]) -> std::io::Result<usize> {
_async_std::task::block_on(self.read_async(buf))
}
type ReadFuture = Read<'s, Self>;
#[doc(hidden)]
fn write(&'s mut self, buf: &'s [u8]) -> std::io::Result<usize> {
_async_std::task::block_on(self.write_async(buf))
type WriteFuture = Write<'s, Self>;
#[inline]
#[doc(hidden)]
fn read_async(&'s mut self, buf: &'s mut [u8]) -> Self::ReadFuture {
AsyncReadExt::read(self, buf)
}
#[inline]
#[doc(hidden)]
fn write_async(&'s mut self, buf: &'s [u8]) -> Self::WriteFuture {
AsyncWriteExt::write(self, buf)
}
#[inline]
#[doc(hidden)]
#[cfg(feature = "blocking")]
fn read(&'s mut self, buf: &'s mut [u8]) -> io::Result<usize> {
task::block_on(self.read_async(buf))
}
#[inline]
#[doc(hidden)]
#[cfg(feature = "blocking")]
fn write(&'s mut self, buf: &'s [u8]) -> io::Result<usize> {
task::block_on(self.write_async(buf))
}
}

View File

@ -1,6 +1,10 @@
use std::io;
#[cfg(unix)]
use std::path::Path;
use _tokio::net::TcpStream;
#[cfg(unix)]
use _tokio::net::UnixStream;
use async_compat::Compat;
use futures_util::io::{Read, Write};
use futures_util::{future::BoxFuture, AsyncReadExt, AsyncWriteExt, FutureExt, TryFutureExt};
@ -15,20 +19,44 @@ use crate::{io::Stream, Async, Runtime};
#[derive(Debug)]
pub struct Tokio;
// NOTE: Compat<_> is used for IO streams to avoid requiring a Box per read/write call
// https://github.com/tokio-rs/tokio/issues/2723
impl Runtime for Tokio {
// NOTE: Compat<_> is used to avoid requiring a Box per read/write call
// https://github.com/tokio-rs/tokio/issues/2723
#[doc(hidden)]
type TcpStream = Compat<TcpStream>;
}
impl Async for Tokio {
#[doc(hidden)]
#[cfg(unix)]
type UnixStream = Compat<UnixStream>;
#[doc(hidden)]
#[cfg(feature = "blocking")]
fn connect_tcp(_host: &str, _port: u16) -> io::Result<Self::TcpStream> {
// UNREACHABLE: where Self: blocking::Runtime
unreachable!()
}
#[doc(hidden)]
#[cfg(all(unix, feature = "blocking"))]
fn connect_unix(_path: &Path) -> io::Result<Self::UnixStream> {
// UNREACHABLE: where Self: blocking::Runtime
unreachable!()
}
#[doc(hidden)]
fn connect_tcp_async(host: &str, port: u16) -> BoxFuture<'_, io::Result<Self::TcpStream>> {
TcpStream::connect((host, port)).map_ok(Compat::new).boxed()
}
#[doc(hidden)]
#[cfg(unix)]
fn connect_unix_async(path: &Path) -> BoxFuture<'_, io::Result<Self::UnixStream>> {
UnixStream::connect(path).map_ok(Compat::new).boxed()
}
}
impl Async for Tokio {}
// 's: stream
impl<'s> Stream<'s, Tokio> for Compat<TcpStream> {
#[doc(hidden)]
@ -40,12 +68,66 @@ impl<'s> Stream<'s, Tokio> for Compat<TcpStream> {
#[inline]
#[doc(hidden)]
fn read_async(&'s mut self, buf: &'s mut [u8]) -> Self::ReadFuture {
self.read(buf)
AsyncReadExt::read(self, buf)
}
#[inline]
#[doc(hidden)]
fn write_async(&'s mut self, buf: &'s [u8]) -> Self::WriteFuture {
self.write(buf)
AsyncWriteExt::write(self, buf)
}
#[inline]
#[doc(hidden)]
#[cfg(feature = "blocking")]
fn read(&'s mut self, _buf: &'s mut [u8]) -> io::Result<usize> {
// UNREACHABLE: where Self: blocking::Runtime
unreachable!()
}
#[inline]
#[doc(hidden)]
#[cfg(feature = "blocking")]
fn write(&'s mut self, _buf: &'s [u8]) -> io::Result<usize> {
// UNREACHABLE: where Self: blocking::Runtime
unreachable!()
}
}
// 's: stream
#[cfg(unix)]
impl<'s> Stream<'s, Tokio> for Compat<UnixStream> {
#[doc(hidden)]
type ReadFuture = Read<'s, Self>;
#[doc(hidden)]
type WriteFuture = Write<'s, Self>;
#[inline]
#[doc(hidden)]
fn read_async(&'s mut self, buf: &'s mut [u8]) -> Self::ReadFuture {
AsyncReadExt::read(self, buf)
}
#[inline]
#[doc(hidden)]
fn write_async(&'s mut self, buf: &'s [u8]) -> Self::WriteFuture {
AsyncWriteExt::write(self, buf)
}
#[inline]
#[doc(hidden)]
#[cfg(feature = "blocking")]
fn read(&'s mut self, _buf: &'s mut [u8]) -> io::Result<usize> {
// UNREACHABLE: where Self: blocking::Runtime
unreachable!()
}
#[inline]
#[doc(hidden)]
#[cfg(feature = "blocking")]
fn write(&'s mut self, _buf: &'s [u8]) -> io::Result<usize> {
// UNREACHABLE: where Self: blocking::Runtime
unreachable!()
}
}

View File

@ -1,6 +1,7 @@
use std::fmt::{self, Debug, Formatter};
use sqlx_core::io::BufStream;
use sqlx_core::net::Stream as NetStream;
use sqlx_core::{Close, Connect, Connection, DefaultRuntime, Runtime};
use crate::protocol::Capabilities;
@ -16,7 +17,7 @@ pub struct MySqlConnection<Rt = DefaultRuntime>
where
Rt: Runtime,
{
stream: BufStream<Rt, Rt::TcpStream>,
stream: BufStream<Rt, NetStream<Rt>>,
connection_id: u32,
// the capability flags are used by the client and server to indicate which
@ -32,7 +33,7 @@ impl<Rt> MySqlConnection<Rt>
where
Rt: Runtime,
{
pub(crate) fn new(stream: Rt::TcpStream) -> Self {
pub(crate) fn new(stream: NetStream<Rt>) -> Self {
Self {
stream: BufStream::with_capacity(stream, 4096, 1024),
connection_id: 0,
@ -73,7 +74,6 @@ where
fn ping(&mut self) -> futures_util::future::BoxFuture<'_, sqlx_core::Result<()>>
where
Rt: sqlx_core::Async,
for<'s> Rt::TcpStream: sqlx_core::io::Stream<'s, Rt>,
{
Box::pin(self.ping_async())
}
@ -87,7 +87,6 @@ impl<Rt: Runtime> Connect<Rt> for MySqlConnection<Rt> {
where
Self: Sized,
Rt: sqlx_core::Async,
for<'s> <Rt as Runtime>::TcpStream: sqlx_core::io::Stream<'s, Rt>,
{
use sqlx_core::ConnectOptions;
@ -101,7 +100,6 @@ impl<Rt: Runtime> Close<Rt> for MySqlConnection<Rt> {
fn close(self) -> futures_util::future::BoxFuture<'static, sqlx_core::Result<()>>
where
Rt: sqlx_core::Async,
for<'s> <Rt as Runtime>::TcpStream: sqlx_core::io::Stream<'s, Rt>,
{
Box::pin(self.close_async())
}
@ -112,10 +110,7 @@ impl<Rt> sqlx_core::blocking::Connection<Rt> for MySqlConnection<Rt>
where
Rt: sqlx_core::blocking::Runtime,
{
fn ping(&mut self) -> sqlx_core::Result<()>
where
for<'s> <Rt as Runtime>::TcpStream: sqlx_core::blocking::io::Stream<'s, Rt>,
{
fn ping(&mut self) -> sqlx_core::Result<()> {
self.ping()
}
}
@ -128,7 +123,6 @@ where
fn connect(url: &str) -> sqlx_core::Result<Self>
where
Self: Sized,
for<'s> <Rt as Runtime>::TcpStream: sqlx_core::blocking::io::Stream<'s, Rt>,
{
Self::connect(&url.parse::<MySqlConnectOptions<Rt>>()?)
}
@ -139,10 +133,7 @@ impl<Rt> sqlx_core::blocking::Close<Rt> for MySqlConnection<Rt>
where
Rt: sqlx_core::blocking::Runtime,
{
fn close(self) -> sqlx_core::Result<()>
where
for<'s> <Rt as Runtime>::TcpStream: sqlx_core::blocking::io::Stream<'s, Rt>,
{
fn close(self) -> sqlx_core::Result<()> {
self.close()
}
}

View File

@ -10,7 +10,6 @@ where
pub(crate) async fn close_async(mut self) -> Result<()>
where
Rt: sqlx_core::Async,
for<'s> <Rt as Runtime>::TcpStream: sqlx_core::io::Stream<'s, Rt>,
{
self.write_packet(&Quit)?;
self.stream.flush_async().await?;
@ -22,7 +21,6 @@ where
pub(crate) fn close(mut self) -> Result<()>
where
Rt: sqlx_core::blocking::Runtime,
for<'s> <Rt as Runtime>::TcpStream: sqlx_core::blocking::io::Stream<'s, Rt>,
{
self.write_packet(&Quit)?;
self.stream.flush()?;

View File

@ -11,6 +11,7 @@
//!
//! https://dev.mysql.com/doc/internals/en/connection-phase.html
//!
use sqlx_core::net::Stream as NetStream;
use sqlx_core::Result;
use crate::protocol::{Auth, AuthResponse, Handshake, HandshakeResponse};
@ -18,11 +19,11 @@ use crate::{MySqlConnectOptions, MySqlConnection};
macro_rules! connect {
(@blocking @tcp $options:ident) => {
Rt::connect_tcp($options.get_host(), $options.get_port())?;
NetStream::connect($options.address.as_ref())?;
};
(@tcp $options:ident) => {
Rt::connect_tcp_async($options.get_host(), $options.get_port()).await?;
NetStream::connect_async($options.address.as_ref()).await?;
};
(@blocking @packet $self:ident) => {
@ -132,10 +133,7 @@ impl<Rt> MySqlConnection<Rt>
where
Rt: sqlx_core::blocking::Runtime,
{
pub(crate) fn connect(options: &MySqlConnectOptions<Rt>) -> Result<Self>
where
for<'s> Rt::TcpStream: sqlx_core::blocking::io::Stream<'s, Rt>,
{
pub(crate) fn connect(options: &MySqlConnectOptions<Rt>) -> Result<Self> {
connect!(@blocking options)
}
}

View File

@ -14,7 +14,6 @@ where
pub(crate) async fn ping_async(&mut self) -> Result<()>
where
Rt: sqlx_core::Async,
for<'s> Rt::TcpStream: sqlx_core::io::Stream<'s, Rt>,
{
self.write_packet(&Ping)?;
@ -26,7 +25,7 @@ where
#[cfg(feature = "blocking")]
pub(crate) fn ping(&mut self) -> Result<()>
where
for<'s> Rt::TcpStream: sqlx_core::blocking::io::Stream<'s, Rt>,
Rt: sqlx_core::blocking::Runtime,
{
self.write_packet(&Ping)?;

View File

@ -134,7 +134,6 @@ where
where
T: Deserialize<'de, Capabilities>,
Rt: sqlx_core::Async,
for<'s> Rt::TcpStream: sqlx_core::io::Stream<'s, Rt>,
{
read_packet!(self)
}
@ -148,7 +147,7 @@ where
pub(super) fn read_packet<'de, T>(&'de mut self) -> Result<T>
where
T: Deserialize<'de, Capabilities>,
for<'s> Rt::TcpStream: sqlx_core::blocking::io::Stream<'s, Rt>,
Rt: sqlx_core::blocking::Runtime,
{
read_packet!(@blocking self)
}

View File

@ -32,7 +32,7 @@ where
Rt: Runtime,
{
runtime: PhantomData<Rt>,
address: Either<(String, u16), PathBuf>,
pub(crate) address: Either<(String, u16), PathBuf>,
username: Option<String>,
password: Option<String>,
database: Option<String>,
@ -144,7 +144,6 @@ where
where
Self::Connection: Sized,
Rt: sqlx_core::Async,
for<'s> Rt::TcpStream: sqlx_core::io::Stream<'s, Rt>,
{
Box::pin(MySqlConnection::connect_async(self))
}
@ -158,7 +157,6 @@ where
fn connect(&self) -> sqlx_core::Result<Self::Connection>
where
Self::Connection: Sized,
for<'s> Rt::TcpStream: sqlx_core::blocking::io::Stream<'s, Rt>,
{
<MySqlConnection<Rt>>::connect(self)
}