Skip to content

Commit

Permalink
Merge #572
Browse files Browse the repository at this point in the history
572: GAT-based Device trait. r=Dirbaio a=Dirbaio

The current `'a` lifetime in the `Device` trait is essentially a workaround for lack of GATs.
I'm just experimenting how this would look like, it'll have to wait until GATs are stable to go in.

The main benefit is structs implementing `Device` can now borrow stuff. This wasn't possible
before because the `for<'d> T: Device<'d>` bounds would essentially imply `T: 'static`.

Co-authored-by: Dario Nieuwenhuis <dirbaio@dirbaio.net>
  • Loading branch information
bors[bot] and Dirbaio committed Nov 6, 2022
2 parents 202e9b4 + 13cc7f8 commit f403862
Show file tree
Hide file tree
Showing 24 changed files with 119 additions and 111 deletions.
8 changes: 4 additions & 4 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ jobs:
# Test on stable, MSRV, and nightly.
# Failure is permitted on nightly.
rust:
- stable
- 1.61.0
#- stable # TODO: enable again when "stable" is 1.66 or higher.
- 1.65.0
- nightly

features:
Expand Down Expand Up @@ -64,8 +64,8 @@ jobs:
# Test on stable, MSRV, and nightly.
# Failure is permitted on nightly.
rust:
- stable
- 1.61.0
#- stable # TODO: enable again when "stable" is 1.66 or higher.
- 1.65.0
- nightly

features:
Expand Down
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Remove IpAddress::Unspecified
- When sending packets with a raw socket, the source IP address is sent unmodified (it was previously replaced with the interface's address if it was unspecified).
- Fix enable `defmt/alloc` if `alloc` or `std` is enabled.
- Minimum Supported Rust Version (MSRV) **bumped** from 1.56 to 1.60
- Minimum Supported Rust Version (MSRV) **bumped** from 1.56 to 1.65

## [0.8.1] - 2022-05-12

Expand Down
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
name = "smoltcp"
version = "0.8.1"
edition = "2018"
rust-version = "1.61"
rust-version = "1.65"
authors = ["whitequark <whitequark@whitequark.org>"]
description = "A TCP/IP stack designed for bare-metal, real-time systems without a heap."
documentation = "https://docs.rs/smoltcp/"
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ include complicated compile-time computations, such as macro or type tricks, eve
at cost of performance degradation.

_smoltcp_ does not need heap allocation *at all*, is [extensively documented][docs],
and compiles on stable Rust 1.61 and later.
and compiles on stable Rust 1.65 and later.

_smoltcp_ achieves [~Gbps of throughput](#examplesbenchmarkrs) when tested against
the Linux TCP stack in loopback mode.
Expand Down
8 changes: 2 additions & 6 deletions examples/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,11 +84,7 @@ pub fn parse_options(options: &Options, free: Vec<&str>) -> Matches {
free.join(" ")
);
print!("{}", options.usage(&brief));
process::exit(if matches.free.len() != free.len() {
1
} else {
0
})
process::exit((matches.free.len() != free.len()) as _);
}
matches
}
Expand Down Expand Up @@ -159,7 +155,7 @@ pub fn parse_middleware_options<D>(
loopback: bool,
) -> FaultInjector<Tracer<PcapWriter<D, Box<dyn io::Write>>>>
where
D: for<'a> Device<'a>,
D: Device,
{
let drop_chance = matches
.opt_str("drop-chance")
Expand Down
2 changes: 1 addition & 1 deletion fuzz/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ pub fn parse_middleware_options<D>(
loopback: bool,
) -> FaultInjector<Tracer<PcapWriter<D, Box<dyn Write>>>>
where
D: for<'a> Device<'a>,
D: Device,
{
let drop_chance = matches
.opt_str("drop-chance")
Expand Down
11 changes: 4 additions & 7 deletions src/iface/fragmentation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -364,7 +364,7 @@ impl<'a, K: Eq + Ord + Clone + Copy> PacketAssemblerSet<'a, K> {
/// - Returns [`Error::PacketAssemblerSetKeyNotFound`] when the key was not found in the set.
pub(crate) fn get_packet_assembler_mut(&mut self, key: &K) -> Result<&mut PacketAssembler<'a>> {
if let Some(i) = self.index_buffer.get(key) {
Ok(&mut self.packet_buffer[*i as usize])
Ok(&mut self.packet_buffer[*i])
} else {
Err(Error::PacketAssemblerSetKeyNotFound)
}
Expand All @@ -379,7 +379,7 @@ impl<'a, K: Eq + Ord + Clone + Copy> PacketAssemblerSet<'a, K> {
/// - Returns [`Error::PacketAssemblerIncomplete`] when the fragments assembler was empty or not fully assembled.
pub(crate) fn get_assembled_packet(&mut self, key: &K) -> Result<&[u8]> {
if let Some(i) = self.index_buffer.get(key) {
let p = self.packet_buffer[*i as usize].assemble()?;
let p = self.packet_buffer[*i].assemble()?;
self.index_buffer.remove(key);
Ok(p)
} else {
Expand All @@ -392,10 +392,7 @@ impl<'a, K: Eq + Ord + Clone + Copy> PacketAssemblerSet<'a, K> {
loop {
let mut key = None;
for (k, i) in self.index_buffer.iter() {
if matches!(
self.packet_buffer[*i as usize].assembler,
AssemblerState::NotInit
) {
if matches!(self.packet_buffer[*i].assembler, AssemblerState::NotInit) {
key = Some(*k);
break;
}
Expand All @@ -416,7 +413,7 @@ impl<'a, K: Eq + Ord + Clone + Copy> PacketAssemblerSet<'a, K> {
F: Fn(&mut PacketAssembler<'_>) -> Result<bool>,
{
for (_, i) in &mut self.index_buffer.iter() {
let frag = &mut self.packet_buffer[*i as usize];
let frag = &mut self.packet_buffer[*i];
if f(frag)? {
frag.mark_discarded();
}
Expand Down
2 changes: 1 addition & 1 deletion src/iface/interface/ipv4.rs
Original file line number Diff line number Diff line change
Expand Up @@ -507,7 +507,7 @@ impl<'a> InterfaceInner<'a> {
}

tx_buffer[repr.buffer_len()..][..payload_len].copy_from_slice(
&buffer[*frag_offset as usize + repr.buffer_len() as usize..][..payload_len],
&buffer[*frag_offset as usize + repr.buffer_len()..][..payload_len],
);

// Update the frag offset for the next fragment.
Expand Down
18 changes: 9 additions & 9 deletions src/iface/interface/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -563,7 +563,7 @@ let iface = builder.finalize(&mut device);
/// [neighbor_cache]: #method.neighbor_cache
pub fn finalize<D>(self, device: &mut D) -> Interface<'a>
where
D: for<'d> Device<'d> + ?Sized,
D: Device + ?Sized,
{
let caps = device.capabilities();

Expand Down Expand Up @@ -905,7 +905,7 @@ impl<'a> Interface<'a> {
timestamp: Instant,
) -> Result<bool>
where
D: for<'d> Device<'d> + ?Sized,
D: Device + ?Sized,
{
self.inner.now = timestamp;

Expand Down Expand Up @@ -947,7 +947,7 @@ impl<'a> Interface<'a> {
timestamp: Instant,
) -> Result<bool>
where
D: for<'d> Device<'d> + ?Sized,
D: Device + ?Sized,
{
self.inner.now = timestamp;

Expand Down Expand Up @@ -1047,7 +1047,7 @@ impl<'a> Interface<'a> {
sockets: &mut SocketSet<'_>,
) -> Result<bool>
where
D: for<'d> Device<'d> + ?Sized,
D: Device + ?Sized,
{
self.inner.now = timestamp;

Expand Down Expand Up @@ -1152,7 +1152,7 @@ impl<'a> Interface<'a> {

fn socket_ingress<D>(&mut self, device: &mut D, sockets: &mut SocketSet<'_>) -> bool
where
D: for<'d> Device<'d> + ?Sized,
D: Device + ?Sized,
{
let mut processed_any = false;
let Self {
Expand Down Expand Up @@ -1208,7 +1208,7 @@ impl<'a> Interface<'a> {

fn socket_egress<D>(&mut self, device: &mut D, sockets: &mut SocketSet<'_>) -> bool
where
D: for<'d> Device<'d> + ?Sized,
D: Device + ?Sized,
{
let Self {
inner,
Expand Down Expand Up @@ -1318,7 +1318,7 @@ impl<'a> Interface<'a> {
#[cfg(feature = "proto-igmp")]
fn igmp_egress<D>(&mut self, device: &mut D) -> Result<bool>
where
D: for<'d> Device<'d> + ?Sized,
D: Device + ?Sized,
{
match self.inner.igmp_report_state {
IgmpReportState::ToSpecificQuery {
Expand Down Expand Up @@ -1384,7 +1384,7 @@ impl<'a> Interface<'a> {
#[cfg(feature = "proto-ipv4-fragmentation")]
fn ipv4_egress<D>(&mut self, device: &mut D) -> Result<bool>
where
D: for<'d> Device<'d> + ?Sized,
D: Device + ?Sized,
{
// Reset the buffer when we transmitted everything.
if self.out_packets.ipv4_out_packet.finished() {
Expand Down Expand Up @@ -1422,7 +1422,7 @@ impl<'a> Interface<'a> {
#[cfg(feature = "proto-sixlowpan-fragmentation")]
fn sixlowpan_egress<D>(&mut self, device: &mut D) -> Result<bool>
where
D: for<'d> Device<'d> + ?Sized,
D: Device + ?Sized,
{
// Reset the buffer when we transmitted everything.
if self.out_packets.sixlowpan_out_packet.finished() {
Expand Down
2 changes: 1 addition & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@
//!
//! # Minimum Supported Rust Version (MSRV)
//!
//! This crate is guaranteed to compile on stable Rust 1.61 and up with any valid set of features.
//! This crate is guaranteed to compile on stable Rust 1.65 and up with any valid set of features.
//! It *might* compile on older versions but that may change in any new patch release.
//!
//! The exception is when using the `defmt` feature, in which case `defmt`'s MSRV applies, which
Expand Down
21 changes: 11 additions & 10 deletions src/phy/fault_injector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,13 +94,13 @@ impl State {
/// adverse network conditions (such as random packet loss or corruption), or software
/// or hardware limitations (such as a limited number or size of usable network buffers).
#[derive(Debug)]
pub struct FaultInjector<D: for<'a> Device<'a>> {
pub struct FaultInjector<D: Device> {
inner: D,
state: RefCell<State>,
config: Config,
}

impl<D: for<'a> Device<'a>> FaultInjector<D> {
impl<D: Device> FaultInjector<D> {
/// Create a fault injector device, using the given random number generator seed.
pub fn new(inner: D, seed: u32) -> FaultInjector<D> {
let state = State {
Expand Down Expand Up @@ -195,12 +195,13 @@ impl<D: for<'a> Device<'a>> FaultInjector<D> {
}
}

impl<'a, D> Device<'a> for FaultInjector<D>
where
D: for<'b> Device<'b>,
{
type RxToken = RxToken<'a, <D as Device<'a>>::RxToken>;
type TxToken = TxToken<'a, <D as Device<'a>>::TxToken>;
impl<D: Device> Device for FaultInjector<D> {
type RxToken<'a> = RxToken<'a, D::RxToken<'a>>
where
Self: 'a;
type TxToken<'a> = TxToken<'a, D::TxToken<'a>>
where
Self: 'a;

fn capabilities(&self) -> DeviceCapabilities {
let mut caps = self.inner.capabilities();
Expand All @@ -210,7 +211,7 @@ where
caps
}

fn receive(&'a mut self) -> Option<(Self::RxToken, Self::TxToken)> {
fn receive(&mut self) -> Option<(Self::RxToken<'_>, Self::TxToken<'_>)> {
let &mut Self {
ref mut inner,
ref state,
Expand All @@ -233,7 +234,7 @@ where
})
}

fn transmit(&'a mut self) -> Option<Self::TxToken> {
fn transmit(&mut self) -> Option<Self::TxToken<'_>> {
let &mut Self {
ref mut inner,
ref state,
Expand Down
23 changes: 13 additions & 10 deletions src/phy/fuzz_injector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,14 @@ pub trait Fuzzer {
#[allow(unused)]
#[derive(Debug)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct FuzzInjector<D: for<'a> Device<'a>, FTx: Fuzzer, FRx: Fuzzer> {
pub struct FuzzInjector<D: Device, FTx: Fuzzer, FRx: Fuzzer> {
inner: D,
fuzz_tx: FTx,
fuzz_rx: FRx,
}

#[allow(unused)]
impl<D: for<'a> Device<'a>, FTx: Fuzzer, FRx: Fuzzer> FuzzInjector<D, FTx, FRx> {
impl<D: Device, FTx: Fuzzer, FRx: Fuzzer> FuzzInjector<D, FTx, FRx> {
/// Create a fuzz injector device.
pub fn new(inner: D, fuzz_tx: FTx, fuzz_rx: FRx) -> FuzzInjector<D, FTx, FRx> {
FuzzInjector {
Expand All @@ -42,14 +42,17 @@ impl<D: for<'a> Device<'a>, FTx: Fuzzer, FRx: Fuzzer> FuzzInjector<D, FTx, FRx>
}
}

impl<'a, D, FTx, FRx> Device<'a> for FuzzInjector<D, FTx, FRx>
impl<D: Device, FTx, FRx> Device for FuzzInjector<D, FTx, FRx>
where
D: for<'b> Device<'b>,
FTx: Fuzzer + 'a,
FRx: Fuzzer + 'a,
FTx: Fuzzer,
FRx: Fuzzer,
{
type RxToken = RxToken<'a, <D as Device<'a>>::RxToken, FRx>;
type TxToken = TxToken<'a, <D as Device<'a>>::TxToken, FTx>;
type RxToken<'a> = RxToken<'a, D::RxToken<'a>, FRx>
where
Self: 'a;
type TxToken<'a> = TxToken<'a, D::TxToken<'a>, FTx>
where
Self: 'a;

fn capabilities(&self) -> DeviceCapabilities {
let mut caps = self.inner.capabilities();
Expand All @@ -59,7 +62,7 @@ where
caps
}

fn receive(&'a mut self) -> Option<(Self::RxToken, Self::TxToken)> {
fn receive(&mut self) -> Option<(Self::RxToken<'_>, Self::TxToken<'_>)> {
let &mut Self {
ref mut inner,
ref fuzz_rx,
Expand All @@ -78,7 +81,7 @@ where
})
}

fn transmit(&'a mut self) -> Option<Self::TxToken> {
fn transmit(&mut self) -> Option<Self::TxToken<'_>> {
let &mut Self {
ref mut inner,
fuzz_rx: _,
Expand Down
10 changes: 5 additions & 5 deletions src/phy/loopback.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,9 @@ impl Loopback {
}
}

impl<'a> Device<'a> for Loopback {
type RxToken = RxToken;
type TxToken = TxToken<'a>;
impl Device for Loopback {
type RxToken<'a> = RxToken;
type TxToken<'a> = TxToken<'a>;

fn capabilities(&self) -> DeviceCapabilities {
DeviceCapabilities {
Expand All @@ -41,7 +41,7 @@ impl<'a> Device<'a> for Loopback {
}
}

fn receive(&'a mut self) -> Option<(Self::RxToken, Self::TxToken)> {
fn receive(&mut self) -> Option<(Self::RxToken<'_>, Self::TxToken<'_>)> {
self.queue.pop_front().map(move |buffer| {
let rx = RxToken { buffer };
let tx = TxToken {
Expand All @@ -51,7 +51,7 @@ impl<'a> Device<'a> for Loopback {
})
}

fn transmit(&'a mut self) -> Option<Self::TxToken> {
fn transmit(&mut self) -> Option<Self::TxToken<'_>> {
Some(TxToken {
queue: &mut self.queue,
})
Expand Down
Loading

0 comments on commit f403862

Please sign in to comment.