Skip to content

Commit 98fb223

Browse files
committed
UDP: use async-fn-in-trait instead of associated types that are Future
This removes the lifetimes from the Connect associated types; leaving them would cause errors (possibly related to [12681]), but I think that stacks whose sockets are not 'static can work around this by implementing the stack traits on a &'short stack instead. [12681]: rust-lang/rust#102681
1 parent 01a61fd commit 98fb223

File tree

2 files changed

+20
-60
lines changed

2 files changed

+20
-60
lines changed

embedded-nal-async/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
//! # embedded-nal-async - An async Network Abstraction Layer for Embedded Systems
22
33
#![no_std]
4+
#![feature(async_fn_in_trait)]
45
#![deny(missing_docs)]
56
#![deny(unsafe_code)]
67

embedded-nal-async/src/stack/udp.rs

Lines changed: 19 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
//! Implementing `UniquelyBound` and `MultiplyBound` with the same type is expected to be a
1515
//! common choice.
1616
17-
use core::future::Future;
1817
use no_std_net::SocketAddr;
1918

2019
/// This trait is implemented by UDP sockets.
@@ -32,11 +31,7 @@ pub trait ConnectedUdp {
3231
type Error: embedded_io::Error;
3332

3433
/// Send the provided data to the connected peer
35-
fn send<'a>(&'a mut self, data: &'a [u8]) -> Self::SendFuture<'a>;
36-
/// Return type of the [`.send()`] method
37-
type SendFuture<'a>: Future<Output = Result<(), Self::Error>>
38-
where
39-
Self: 'a;
34+
async fn send<'a>(&mut self, data: &[u8]) -> Result<(), Self::Error>;
4035

4136
/// Receive a datagram into the provided buffer.
4237
///
@@ -49,20 +44,16 @@ pub trait ConnectedUdp {
4944
/// This deviates from the sync/nb equivalent trait in that it describes the overflow behavior
5045
/// (a possibility not considered there). The name deviates from the original `receive()` to
5146
/// make room for a version that is more zero-copy friendly.
52-
fn receive_into<'a>(&'a mut self, buffer: &'a mut [u8]) -> Self::ReceiveIntoFuture<'a>;
53-
/// Return type of the [`.receive_into()`] method
54-
type ReceiveIntoFuture<'a>: Future<Output = Result<usize, Self::Error>>
55-
where
56-
Self: 'a;
47+
async fn receive_into(&mut self, buffer: &mut [u8]) -> Result<usize, Self::Error>;
5748

5849
// WIP to allow zero-copy operation
5950
// The plain receive is simple and can be provided -- implementations that don't populate
6051
// receive calls from scatter-gather can just return a slice of the raw data instead, and rely
6152
// on the socket still being exclusively owned. receive_oned is harder as providing it requires
6253
// alloc.
6354
//
64-
// fn receive(&mut self, buffer: &mut [u8]) -> impl Future<Output = Result<impl AsRef<u8> + '_, Self::Error>>;
65-
// fn receive_owned(&mut self) -> impl Future<Output = Result<impl AsRef<u8> + 'static, Self::Error>>;
55+
// async fn receive(&mut self, buffer: &mut [u8]) -> utput = Result<impl AsRef<u8> + '_, Self::Error>;
56+
// async fn receive_owned(&mut self) -> Result<impl AsRef<u8> + 'static, Self::Error>;
6657
}
6758

6859
/// This trait is implemented by UDP sockets.
@@ -101,16 +92,12 @@ pub trait UnconnectedUdp {
10192
/// receive time; these should be equal. This allows implementations of the trait to use a
10293
/// single kind of socket for both sockets bound to a single and sockets bound to multiple
10394
/// addresses.
104-
fn send<'a>(
105-
&'a mut self,
95+
async fn send(
96+
&mut self,
10697
local: SocketAddr,
10798
remote: SocketAddr,
108-
data: &'a [u8],
109-
) -> Self::SendFuture<'a>;
110-
/// Return type of the [`.send()`] method
111-
type SendFuture<'a>: Future<Output = Result<(), Self::Error>>
112-
where
113-
Self: 'a;
99+
data: &[u8],
100+
) -> Result<(), Self::Error>;
114101

115102
/// Receive a datagram into the provided buffer.
116103
///
@@ -120,12 +107,7 @@ pub trait UnconnectedUdp {
120107
///
121108
/// The local and remote address are given, in that order, in the result along with the number
122109
/// of bytes.
123-
fn receive_into<'a>(&'a mut self, buffer: &'a mut [u8]) -> Self::ReceiveIntoFuture<'a>;
124-
/// Return type of the [`.receive_into()`] method
125-
type ReceiveIntoFuture<'a>: Future<
126-
Output = Result<(usize, SocketAddr, SocketAddr), Self::Error>,
127-
> where
128-
Self: 'a;
110+
async fn receive_into(& mut self, buffer: & mut [u8]) -> Result<(usize, SocketAddr, SocketAddr), Self::Error>;
129111
}
130112

131113
/// This trait is implemented by UDP/IP stacks. The trait allows the underlying driver to
@@ -138,17 +120,11 @@ pub trait UdpStack {
138120
type Error: embedded_io::Error;
139121

140122
/// Eventual socket return type of the [`.connect()`] method
141-
type Connected<'m>: ConnectedUdp
142-
where
143-
Self: 'm;
123+
type Connected: ConnectedUdp;
144124
/// Eventual socket return type of the [`.bind_single()`] method
145-
type UniquelyBound<'m>: UnconnectedUdp
146-
where
147-
Self: 'm;
125+
type UniquelyBound: UnconnectedUdp;
148126
/// Eventual return type of the [`.bind_multiple()`] method
149-
type MultiplyBound<'m>: UnconnectedUdp
150-
where
151-
Self: 'm;
127+
type MultiplyBound: UnconnectedUdp;
152128

153129
/// Create a socket that has a fixed remote address.
154130
///
@@ -157,34 +133,25 @@ pub trait UdpStack {
157133
/// While asynchronous traits implemented through GAT can not have provided default methods,
158134
/// implementers are encouraged to use the hidden `.connect_default()` method if all they would
159135
/// do is delegating to [`.connect_from`] with a suitable unspecified local address.
160-
fn connect(&self, remote: SocketAddr) -> Self::ConnectFuture<'_>;
161-
/// Future return type of the [`.connect()`] method
162-
type ConnectFuture<'a>: Future<Output = Result<(SocketAddr, Self::Connected<'a>), Self::Error>>
163-
where
164-
Self: 'a;
136+
async fn connect(&self, remote: SocketAddr) -> Result<(SocketAddr, Self::Connected), Self::Error>;
165137

166138
/// Create a socket that has a fixed remote address.
167139
///
168140
/// The local address is given explicitly, but may be partially unspecified; it is fixed by the
169141
/// network stack at connection time. The full local address is returned along with the
170142
/// connected socket, primarily for debugging purposes.
171-
fn connect_from(&self, local: SocketAddr, remote: SocketAddr) -> Self::ConnectFromFuture<'_>;
172-
/// Future return type of the [`.connect_from()`] method
173-
type ConnectFromFuture<'a>: Future<
174-
Output = Result<(SocketAddr, Self::Connected<'a>), Self::Error>,
175-
> where
176-
Self: 'a;
143+
async fn connect_from(&self, local: SocketAddr, remote: SocketAddr) -> Result<(SocketAddr, Self::Connected), Self::Error>;
177144

178145
/// Helper that implements [`connect()`] using [`connect_from()`].
179146
#[doc(hidden)]
180-
fn connect_default(&self, remote: SocketAddr) -> Self::ConnectFromFuture<'_> {
147+
async fn connect_default(&self, remote: SocketAddr) -> Result<(SocketAddr, Self::Connected), Self::Error> {
181148
use no_std_net::{Ipv4Addr, Ipv6Addr, SocketAddr::*, SocketAddrV4, SocketAddrV6};
182149

183150
let local = match remote {
184151
V4(_) => V4(SocketAddrV4::new(Ipv4Addr::UNSPECIFIED, 0)),
185152
V6(_) => V6(SocketAddrV6::new(Ipv6Addr::UNSPECIFIED, 0, 0, 0)),
186153
};
187-
self.connect_from(local, remote)
154+
self.connect_from(local, remote).await
188155
}
189156

190157
/// Create a socket that has a fixed local address.
@@ -195,12 +162,7 @@ pub trait UdpStack {
195162
///
196163
/// The full local address is returned along with the bound socket; it may then be passed on to
197164
/// other protocols for advertising purposes.
198-
fn bind_single(&self, local: SocketAddr) -> Self::BindSingleFuture<'_>;
199-
/// Future return type of the [`.bind_single()`] method
200-
type BindSingleFuture<'a>: Future<
201-
Output = Result<(SocketAddr, Self::UniquelyBound<'a>), Self::Error>,
202-
> where
203-
Self: 'a;
165+
async fn bind_single(&self, local: SocketAddr) -> Result<(SocketAddr, Self::UniquelyBound), Self::Error>;
204166

205167
/// Create a socket that has no single fixed local address.
206168
///
@@ -224,9 +186,6 @@ pub trait UdpStack {
224186
/// * There is currently no hybrid binding that allows emulating what POSIX systems do when
225187
/// binding to `[::]:0`, that is, picking some available port but then still leaving the
226188
/// interface and IP address unspecified.
227-
fn bind_multiple(&self, local: SocketAddr) -> Self::BindMultipleFuture<'_>;
228-
/// Future return type of the [`.bind_multiple()`] method
229-
type BindMultipleFuture<'a>: Future<Output = Result<Self::MultiplyBound<'a>, Self::Error>>
230-
where
231-
Self: 'a;
189+
async fn bind_multiple(&self, local: SocketAddr) -> Result<Self::MultiplyBound, Self::Error>;
190+
232191
}

0 commit comments

Comments
 (0)