diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index e1f45ad9f..8de0b1706 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -70,6 +70,12 @@ jobs: features: # These feature sets cannot run tests, so we only check they build. - medium-ip medium-ethernet proto-ipv6 proto-ipv6 proto-igmp proto-dhcpv4 socket-raw socket-udp socket-tcp socket-icmp async + include: + # defmt doesn't support 1.40 + - rust: stable + features: defmt medium-ip medium-ethernet proto-ipv6 proto-ipv6 proto-igmp proto-dhcpv4 socket-raw socket-udp socket-tcp socket-icmp async + - rust: nightly + features: defmt medium-ip medium-ethernet proto-ipv6 proto-ipv6 proto-igmp proto-dhcpv4 socket-raw socket-udp socket-tcp socket-icmp async steps: - uses: actions/checkout@v2 diff --git a/Cargo.toml b/Cargo.toml index dfa99178f..ae471652c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,6 +21,7 @@ byteorder = { version = "1.0", default-features = false } log = { version = "0.4.4", default-features = false, optional = true } libc = { version = "0.2.18", optional = true } bitflags = { version = "1.0", default-features = false } +defmt = { version = "0.2.0", optional = true } [dev-dependencies] env_logger = "0.5" @@ -46,6 +47,13 @@ verbose = [] "socket-tcp" = ["socket"] "socket-icmp" = ["socket"] "async" = [] + +defmt-trace = [] +defmt-debug = [] +defmt-info = [] +defmt-warn = [] +defmt-error = [] + default = [ "std", "log", # needed for `cargo test --no-default-features --features default` :/ "medium-ethernet", "medium-ip", diff --git a/examples/loopback.rs b/examples/loopback.rs index 13d0479b8..7eb6bc3d7 100644 --- a/examples/loopback.rs +++ b/examples/loopback.rs @@ -21,6 +21,7 @@ mod mock { use core::cell::Cell; #[derive(Debug)] + #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct Clock(Cell); impl Clock { @@ -46,6 +47,7 @@ mod mock { // should be AtomicU64 but that's unstable #[derive(Debug, Clone)] + #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct Clock(Arc); impl Clock { diff --git a/fuzz/fuzz_targets/tcp_headers.rs b/fuzz/fuzz_targets/tcp_headers.rs index aec7a2523..86a274dfb 100644 --- a/fuzz/fuzz_targets/tcp_headers.rs +++ b/fuzz/fuzz_targets/tcp_headers.rs @@ -24,6 +24,7 @@ mod mock { // should be AtomicU64 but that's unstable #[derive(Debug, Clone)] + #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct Clock(Arc); impl Clock { diff --git a/src/dhcp/clientv4.rs b/src/dhcp/clientv4.rs index e5029dfe9..33514a509 100644 --- a/src/dhcp/clientv4.rs +++ b/src/dhcp/clientv4.rs @@ -22,6 +22,7 @@ const PARAMETER_REQUEST_LIST: &[u8] = &[ /// IPv4 configuration data returned by `client.poll()` #[derive(Debug)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct Config { pub address: Option, pub router: Option, @@ -29,6 +30,7 @@ pub struct Config { } #[derive(Debug)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] struct RequestState { retry: u16, endpoint_ip: Ipv4Address, @@ -37,12 +39,14 @@ struct RequestState { } #[derive(Debug)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] struct RenewState { endpoint_ip: Ipv4Address, server_identifier: Ipv4Address, } #[derive(Debug)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] enum ClientState { /// Discovering the DHCP server Discovering, diff --git a/src/iface/interface.rs b/src/iface/interface.rs index bdb48d6b8..0299f7174 100644 --- a/src/iface/interface.rs +++ b/src/iface/interface.rs @@ -243,6 +243,7 @@ let iface = InterfaceBuilder::new(device) } #[derive(Debug, PartialEq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg(feature = "medium-ethernet")] enum EthernetPacket<'a> { #[cfg(feature = "proto-ipv4")] @@ -251,6 +252,7 @@ enum EthernetPacket<'a> { } #[derive(Debug, PartialEq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub(crate) enum IpPacket<'a> { #[cfg(feature = "proto-ipv4")] Icmpv4((Ipv4Repr, Icmpv4Repr<'a>)), @@ -591,6 +593,7 @@ impl<'a, DeviceT> Interface<'a, DeviceT> Medium::Ethernet => { inner.process_ethernet(sockets, timestamp, &frame).map_err(|err| { net_debug!("cannot process ingress packet: {}", err); + #[cfg(not(feature = "defmt"))] net_debug!("packet dump follows:\n{}", PrettyPrinter::>::new("", &frame)); err @@ -1844,6 +1847,7 @@ mod test { } #[derive(Debug, PartialEq)] + #[cfg_attr(feature = "defmt", derive(defmt::Format))] struct MockTxToken; impl TxToken for MockTxToken { diff --git a/src/iface/neighbor.rs b/src/iface/neighbor.rs index f251d1cb2..2f08017ce 100644 --- a/src/iface/neighbor.rs +++ b/src/iface/neighbor.rs @@ -11,6 +11,7 @@ use crate::time::{Duration, Instant}; /// A neighbor mapping translates from a protocol address to a hardware address, /// and contains the timestamp past which the mapping should be discarded. #[derive(Debug, Clone, Copy)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct Neighbor { hardware_addr: EthernetAddress, expires_at: Instant, @@ -18,6 +19,7 @@ pub struct Neighbor { /// An answer to a neighbor cache lookup. #[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub(crate) enum Answer { /// The neighbor address is in the cache and not expired. Found(EthernetAddress), diff --git a/src/iface/route.rs b/src/iface/route.rs index 2ddc5fd6c..65e255be3 100644 --- a/src/iface/route.rs +++ b/src/iface/route.rs @@ -11,6 +11,7 @@ use crate::wire::{Ipv6Address, Ipv6Cidr}; /// A prefix of addresses that should be routed via a router #[derive(Debug, Clone, Copy)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct Route { pub via_router: IpAddress, /// `None` means "forever". diff --git a/src/lib.rs b/src/lib.rs index f143055ec..0fda13b5a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -64,6 +64,14 @@ //! feature ever defined, to ensure that, when the representation layer is unable to make sense //! of a packet, it is still logged correctly and in full. //! +//! # Minimum Supported Rust Version (MSRV) +//! +//! This crate is guaranteed to compile on stable Rust 1.40 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 +//! is higher than 1.40. +//! //! [wire]: wire/index.html //! [osi]: https://en.wikipedia.org/wiki/OSI_model //! [berk]: https://en.wikipedia.org/wiki/Berkeley_sockets @@ -97,6 +105,9 @@ compile_error!("You must enable at least one of the following features: proto-ip ))] compile_error!("If you enable the socket feature, you must enable at least one of the following features: socket-raw, socket-udp, socket-tcp, socket-icmp"); +#[cfg(all(feature = "defmt", feature = "log"))] +compile_error!("You must enable at most one of the following features: defmt, log"); + use core::fmt; #[macro_use] @@ -116,6 +127,7 @@ pub mod dhcp; /// The error type for the networking stack. #[derive(Debug, Clone, Copy, PartialEq, Eq)] #[non_exhaustive] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum Error { /// An operation cannot proceed because a buffer is empty or full. Exhausted, diff --git a/src/macros.rs b/src/macros.rs index 0f1cc98ef..63c7ca7e2 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -5,7 +5,13 @@ macro_rules! net_log { (debug, $($arg:expr),*) => { log::debug!($($arg),*); }; } -#[cfg(not(feature = "log"))] +#[cfg(feature = "defmt")] +macro_rules! net_log { + (trace, $($arg:expr),*) => { defmt::trace!($($arg),*); }; + (debug, $($arg:expr),*) => { defmt::debug!($($arg),*); }; +} + +#[cfg(not(any(feature = "log", feature = "defmt")))] #[macro_use] macro_rules! net_log { ($level:ident, $($arg:expr),*) => { $( let _ = $arg; )* } @@ -30,6 +36,7 @@ macro_rules! enum_with_unknown { } ) => { #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)] + #[cfg_attr(feature = "defmt", derive(defmt::Format))] $( #[$enum_attr] )* pub enum $name { $( diff --git a/src/phy/fault_injector.rs b/src/phy/fault_injector.rs index 5f79fec1a..3185f477a 100644 --- a/src/phy/fault_injector.rs +++ b/src/phy/fault_injector.rs @@ -19,6 +19,7 @@ fn xorshift32(state: &mut u32) -> u32 { const MTU: usize = 1536; #[derive(Debug, Default, Clone, Copy)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] struct Config { corrupt_pct: u8, drop_pct: u8, @@ -30,6 +31,7 @@ struct Config { } #[derive(Debug, Clone)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] struct State { rng_seed: u32, refilled_at: Instant, diff --git a/src/phy/fuzz_injector.rs b/src/phy/fuzz_injector.rs index 9f11b1772..5e2023b7a 100644 --- a/src/phy/fuzz_injector.rs +++ b/src/phy/fuzz_injector.rs @@ -18,6 +18,7 @@ pub trait Fuzzer { /// smoltcp, and is not for production use. #[allow(unused)] #[derive(Debug)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct FuzzInjector Device<'a>, FTx: Fuzzer, FRx: Fuzzer> { inner: D, fuzz_tx: FTx, diff --git a/src/phy/mod.rs b/src/phy/mod.rs index b6ae5ff66..c04867772 100644 --- a/src/phy/mod.rs +++ b/src/phy/mod.rs @@ -119,6 +119,7 @@ pub use self::tuntap_interface::TunTapInterface; /// A description of checksum behavior for a particular protocol. #[derive(Debug, Clone, Copy)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum Checksum { /// Verify checksum when receiving and compute checksum when sending. Both, @@ -156,6 +157,7 @@ impl Checksum { /// A description of checksum behavior for every supported protocol. #[derive(Debug, Clone, Default)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[non_exhaustive] pub struct ChecksumCapabilities { pub ipv4: Checksum, @@ -188,6 +190,7 @@ impl ChecksumCapabilities { /// Higher-level protocols may achieve higher throughput or lower latency if they consider /// the bandwidth or packet size limitations. #[derive(Debug, Clone, Default)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[non_exhaustive] pub struct DeviceCapabilities { /// Medium of the device. @@ -229,6 +232,7 @@ pub struct DeviceCapabilities { /// Type of medium of a device. #[derive(Debug, Eq, PartialEq, Copy, Clone)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum Medium { /// Ethernet medium. Devices of this type send and receive Ethernet frames, /// and interfaces using it must do neighbor discovery via ARP or NDISC. diff --git a/src/phy/pcap_writer.rs b/src/phy/pcap_writer.rs index c14118d60..a2226bbd4 100644 --- a/src/phy/pcap_writer.rs +++ b/src/phy/pcap_writer.rs @@ -21,6 +21,7 @@ enum_with_unknown! { /// Packet capture mode. #[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum PcapMode { /// Capture both received and transmitted packets. Both, @@ -118,6 +119,7 @@ impl PcapSink for RefCell { /// [libpcap]: https://wiki.wireshark.org/Development/LibpcapFileFormat /// [sink]: trait.PcapSink.html #[derive(Debug)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct PcapWriter where D: for<'a> Device<'a>, S: PcapSink + Clone, diff --git a/src/socket/icmp.rs b/src/socket/icmp.rs index 4fbb226f0..e5779bddf 100644 --- a/src/socket/icmp.rs +++ b/src/socket/icmp.rs @@ -22,6 +22,7 @@ use crate::wire::{IpAddress, IpEndpoint, IpProtocol, IpRepr}; /// /// [IcmpSocket::bind]: struct.IcmpSocket.html#method.bind #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum Endpoint { Unspecified, Ident(u16), diff --git a/src/socket/meta.rs b/src/socket/meta.rs index b4e9fbb26..fe6873b5f 100644 --- a/src/socket/meta.rs +++ b/src/socket/meta.rs @@ -7,6 +7,7 @@ use crate::time::{Duration, Instant}; /// This enum tracks whether the socket should be polled based on the neighbor it is /// going to send packets to. #[derive(Debug)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] enum NeighborState { /// Socket can be polled immediately. Active, @@ -29,6 +30,7 @@ impl Default for NeighborState { /// This includes things that only external (to the socket, that is) code /// is interested in, but which are more conveniently stored inside the socket itself. #[derive(Debug, Default)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct Meta { /// Handle of this socket within its enclosing `SocketSet`. /// Mainly useful for debug output. diff --git a/src/socket/mod.rs b/src/socket/mod.rs index d7a971bd2..76fe30f5a 100644 --- a/src/socket/mod.rs +++ b/src/socket/mod.rs @@ -61,6 +61,7 @@ pub(crate) use self::ref_::Session as SocketSession; /// Gives an indication on the next time the socket should be polled. #[derive(Debug, PartialOrd, Ord, PartialEq, Eq, Clone, Copy)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub(crate) enum PollAt { /// The socket needs to be polled immidiately. Now, diff --git a/src/socket/set.rs b/src/socket/set.rs index 826776348..686665658 100644 --- a/src/socket/set.rs +++ b/src/socket/set.rs @@ -17,6 +17,7 @@ pub struct Item<'a> { /// A handle, identifying a socket in a set. #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Default, Hash)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct Handle(usize); impl fmt::Display for Handle { diff --git a/src/socket/tcp.rs b/src/socket/tcp.rs index afa5cae0b..987916f85 100644 --- a/src/socket/tcp.rs +++ b/src/socket/tcp.rs @@ -21,6 +21,7 @@ pub type SocketBuffer<'a> = RingBuffer<'a, u8>; /// /// [RFC 793]: https://tools.ietf.org/html/rfc793 #[derive(Debug, PartialEq, Eq, Clone, Copy)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum State { Closed, Listen, @@ -147,6 +148,7 @@ impl RttEstimator { } #[derive(Debug, Clone, Copy, PartialEq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] enum Timer { Idle { keep_alive_at: Option, diff --git a/src/storage/assembler.rs b/src/storage/assembler.rs index 159d93d2f..1eb97bcf8 100644 --- a/src/storage/assembler.rs +++ b/src/storage/assembler.rs @@ -5,6 +5,7 @@ pub struct TooManyHolesError; /// A contiguous chunk of absent data, followed by a contiguous chunk of present data. #[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] struct Contig { hole_size: usize, data_size: usize @@ -80,6 +81,7 @@ const CONTIG_COUNT: usize = 4; /// Currently, up to a hardcoded limit of 4 or 32 holes can be tracked in the buffer. #[derive(Debug)] #[cfg_attr(test, derive(PartialEq, Eq, Clone))] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct Assembler { #[cfg(not(any(feature = "std", feature = "alloc")))] contigs: [Contig; CONTIG_COUNT], diff --git a/src/storage/packet_buffer.rs b/src/storage/packet_buffer.rs index be9866bea..5502de2fe 100644 --- a/src/storage/packet_buffer.rs +++ b/src/storage/packet_buffer.rs @@ -5,6 +5,7 @@ use crate::storage::RingBuffer; /// Size and header of a packet. #[derive(Debug, Clone, Copy)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct PacketMetadata { size: usize, header: Option diff --git a/src/time.rs b/src/time.rs index 719ea8419..0dc1c79e1 100644 --- a/src/time.rs +++ b/src/time.rs @@ -22,6 +22,7 @@ use core::{ops, fmt}; /// * A value less than `0` indicates a time before the starting /// point. #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct Instant { pub millis: i64, } @@ -135,6 +136,7 @@ impl ops::Sub for Instant { /// A relative amount of time. #[derive(Debug, Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct Duration { pub millis: u64, } diff --git a/src/wire/arp.rs b/src/wire/arp.rs index 97fcf3677..3bf394749 100644 --- a/src/wire/arp.rs +++ b/src/wire/arp.rs @@ -22,6 +22,7 @@ enum_with_unknown! { /// A read/write wrapper around an Address Resolution Protocol packet buffer. #[derive(Debug, PartialEq, Clone)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct Packet> { buffer: T } @@ -253,6 +254,7 @@ use crate::wire::{EthernetAddress, Ipv4Address}; /// A high-level representation of an Address Resolution Protocol packet. #[derive(Debug, PartialEq, Eq, Clone, Copy)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[non_exhaustive] pub enum Repr { /// An Ethernet and IPv4 Address Resolution Protocol packet. diff --git a/src/wire/dhcpv4.rs b/src/wire/dhcpv4.rs index 37f6d9404..a9389431b 100644 --- a/src/wire/dhcpv4.rs +++ b/src/wire/dhcpv4.rs @@ -43,6 +43,7 @@ impl MessageType { /// A representation of a single DHCP option. #[derive(Debug, PartialEq, Eq, Clone, Copy)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum DhcpOption<'a> { EndOfList, Pad, @@ -200,6 +201,7 @@ impl<'a> DhcpOption<'a> { /// A read/write wrapper around a Dynamic Host Configuration Protocol packet buffer. #[derive(Debug, PartialEq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct Packet> { buffer: T } @@ -624,6 +626,7 @@ impl<'a, T: AsRef<[u8]> + AsMut<[u8]> + ?Sized> Packet<&'a mut T> { /// /// The `options` field has a variable length. #[derive(Debug, PartialEq, Eq, Clone, Copy)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct Repr<'a> { /// This field is also known as `op` in the RFC. It indicates the type of DHCP message this /// packet represents. diff --git a/src/wire/ethernet.rs b/src/wire/ethernet.rs index 0c425f18b..f53094258 100644 --- a/src/wire/ethernet.rs +++ b/src/wire/ethernet.rs @@ -25,6 +25,7 @@ impl fmt::Display for EtherType { /// A six-octet Ethernet II address. #[derive(Debug, Hash, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Default)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct Address(pub [u8; 6]); impl Address { @@ -78,6 +79,7 @@ impl fmt::Display for Address { /// A read/write wrapper around an Ethernet II frame buffer. #[derive(Debug, Clone)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct Frame> { buffer: T } @@ -246,6 +248,7 @@ impl> PrettyPrint for Frame { /// A high-level representation of an Internet Protocol version 4 packet header. #[derive(Debug, PartialEq, Eq, Clone, Copy)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct Repr { pub src_addr: Address, pub dst_addr: Address, diff --git a/src/wire/icmp.rs b/src/wire/icmp.rs index cf8400c0a..6bbc574cc 100644 --- a/src/wire/icmp.rs +++ b/src/wire/icmp.rs @@ -4,6 +4,7 @@ use crate::wire::icmpv4; use crate::wire::icmpv6; #[derive(Clone, PartialEq, Eq, Debug)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum Repr<'a> { #[cfg(feature = "proto-ipv4")] Ipv4(icmpv4::Repr<'a>), diff --git a/src/wire/icmpv4.rs b/src/wire/icmpv4.rs index 955afb1b0..ddabb3f77 100644 --- a/src/wire/icmpv4.rs +++ b/src/wire/icmpv4.rs @@ -167,6 +167,7 @@ enum_with_unknown! { /// A read/write wrapper around an Internet Control Message Protocol version 4 packet buffer. #[derive(Debug, PartialEq, Clone)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct Packet> { buffer: T } @@ -366,6 +367,7 @@ impl> AsRef<[u8]> for Packet { /// A high-level representation of an Internet Control Message Protocol version 4 packet header. #[derive(Debug, PartialEq, Eq, Clone, Copy)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[non_exhaustive] pub enum Repr<'a> { EchoRequest { diff --git a/src/wire/icmpv6.rs b/src/wire/icmpv6.rs index a347a0311..5ab01db86 100644 --- a/src/wire/icmpv6.rs +++ b/src/wire/icmpv6.rs @@ -191,6 +191,7 @@ impl fmt::Display for TimeExceeded { /// A read/write wrapper around an Internet Control Message Protocol version 6 packet buffer. #[derive(Debug, PartialEq, Clone)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct Packet> { pub(super) buffer: T } @@ -503,6 +504,7 @@ impl> AsRef<[u8]> for Packet { /// A high-level representation of an Internet Control Message Protocol version 6 packet header. #[derive(Debug, PartialEq, Eq, Clone, Copy)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[non_exhaustive] pub enum Repr<'a> { DstUnreachable { diff --git a/src/wire/igmp.rs b/src/wire/igmp.rs index 237f32b05..3c6da88a9 100644 --- a/src/wire/igmp.rs +++ b/src/wire/igmp.rs @@ -23,6 +23,7 @@ enum_with_unknown! { /// A read/write wrapper around an Internet Group Management Protocol v1/v2 packet buffer. #[derive(Debug)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct Packet> { buffer: T, } @@ -171,6 +172,7 @@ impl + AsMut<[u8]>> Packet { /// A high-level representation of an Internet Group Management Protocol v1/v2 header. #[derive(Debug, PartialEq, Eq, Clone)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum Repr { MembershipQuery { max_resp_time: Duration, @@ -188,6 +190,7 @@ pub enum Repr { /// Type of IGMP membership report version #[derive(Debug, PartialEq, Eq, Clone, Copy)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum IgmpVersion { /// IGMPv1 Version1, diff --git a/src/wire/ip.rs b/src/wire/ip.rs index f6f67776e..bdfeee2a2 100644 --- a/src/wire/ip.rs +++ b/src/wire/ip.rs @@ -10,6 +10,7 @@ use crate::wire::{Ipv6Address, Ipv6Cidr, Ipv6Packet, Ipv6Repr}; /// Internet protocol version. #[derive(Debug, Hash, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[non_exhaustive] pub enum Version { Unspecified, @@ -260,6 +261,19 @@ impl fmt::Display for Address { } } +#[cfg(feature = "defmt")] +impl defmt::Format for Address { + fn format(&self, f: defmt::Formatter) { + match self { + &Address::Unspecified => defmt::write!(f, "{:?}", "*"), + #[cfg(feature = "proto-ipv4")] + &Address::Ipv4(addr) => defmt::write!(f, "{:?}", addr), + #[cfg(feature = "proto-ipv6")] + &Address::Ipv6(addr) => defmt::write!(f, "{:?}", addr), + } + } +} + /// A specification of a CIDR block, containing an address and a variable-length /// subnet masking prefix length. #[derive(Debug, Hash, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)] @@ -370,6 +384,18 @@ impl fmt::Display for Cidr { } } +#[cfg(feature = "defmt")] +impl defmt::Format for Cidr { + fn format(&self, f: defmt::Formatter) { + match self { + #[cfg(feature = "proto-ipv4")] + &Cidr::Ipv4(cidr) => defmt::write!(f, "{:?}", cidr), + #[cfg(feature = "proto-ipv6")] + &Cidr::Ipv6(cidr) => defmt::write!(f, "{:?}", cidr), + } + } +} + /// An internet endpoint address. /// /// An endpoint can be constructed from a port, in which case the address is unspecified. @@ -430,6 +456,13 @@ impl fmt::Display for Endpoint { } } +#[cfg(feature = "defmt")] +impl defmt::Format for Endpoint { + fn format(&self, f: defmt::Formatter) { + defmt::write!(f, "{:?}:{=u16}", self.addr, self.port); + } +} + impl From for Endpoint { fn from(port: u16) -> Endpoint { Endpoint { addr: Address::Unspecified, port } @@ -448,6 +481,7 @@ impl> From<(T, u16)> for Endpoint { /// high-level representation for some IP protocol version, or an unspecified representation, /// which permits the `IpAddress::Unspecified` addresses. #[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[non_exhaustive] pub enum Repr { Unspecified { diff --git a/src/wire/ipv4.rs b/src/wire/ipv4.rs index a5369edb6..687b4b9ef 100644 --- a/src/wire/ipv4.rs +++ b/src/wire/ipv4.rs @@ -112,6 +112,13 @@ impl fmt::Display for Address { } } +#[cfg(feature = "defmt")] +impl defmt::Format for Address { + fn format(&self, f: defmt::Formatter) { + defmt::write!(f, "{=u8}.{=u8}.{=u8}.{=u8}", self.0[0], self.0[1], self.0[2], self.0[3]) + } +} + /// A specification of an IPv4 CIDR block, containing an address and a variable-length /// subnet masking prefix length. #[derive(Debug, Hash, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Default)] @@ -227,8 +234,16 @@ impl fmt::Display for Cidr { } } +#[cfg(feature = "defmt")] +impl defmt::Format for Cidr { + fn format(&self, f: defmt::Formatter) { + defmt::write!(f, "{:?}/{=u8}", self.address, self.prefix_len); + } +} + /// A read/write wrapper around an Internet Protocol version 4 packet buffer. #[derive(Debug, PartialEq, Clone)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct Packet> { buffer: T } @@ -552,6 +567,7 @@ impl> AsRef<[u8]> for Packet { /// A high-level representation of an Internet Protocol version 4 packet header. #[derive(Debug, PartialEq, Eq, Clone, Copy)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct Repr { pub src_addr: Address, pub dst_addr: Address, diff --git a/src/wire/ipv6.rs b/src/wire/ipv6.rs index 731d288d7..6f54a0c10 100644 --- a/src/wire/ipv6.rs +++ b/src/wire/ipv6.rs @@ -17,6 +17,7 @@ pub const MIN_MTU: usize = 1280; /// A sixteen-octet IPv6 address. #[derive(Debug, Hash, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Default)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct Address(pub [u8; 16]); impl Address { @@ -267,6 +268,7 @@ impl From for Address { /// A specification of an IPv6 CIDR block, containing an address and a variable-length /// subnet masking prefix length. #[derive(Debug, Hash, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Default)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct Cidr { address: Address, prefix_len: u8, @@ -328,6 +330,7 @@ impl fmt::Display for Cidr { /// A read/write wrapper around an Internet Protocol version 6 packet buffer. #[derive(Debug, PartialEq, Clone)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct Packet> { buffer: T } @@ -593,6 +596,7 @@ impl> AsRef<[u8]> for Packet { /// A high-level representation of an Internet Protocol version 6 packet header. #[derive(Debug, PartialEq, Eq, Clone, Copy)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct Repr { /// IPv6 address of the source node. pub src_addr: Address, diff --git a/src/wire/ipv6fragment.rs b/src/wire/ipv6fragment.rs index 8ef385a72..ffa393617 100644 --- a/src/wire/ipv6fragment.rs +++ b/src/wire/ipv6fragment.rs @@ -7,6 +7,7 @@ pub use super::IpProtocol as Protocol; /// A read/write wrapper around an IPv6 Fragment Header. #[derive(Debug, PartialEq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct Header> { buffer: T } @@ -158,6 +159,7 @@ impl<'a, T: AsRef<[u8]> + ?Sized> fmt::Display for Header<&'a T> { /// A high-level representation of an IPv6 Fragment header. #[derive(Debug, PartialEq, Eq, Clone, Copy)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct Repr { /// The type of header immediately following the Fragment header. pub next_header: Protocol, diff --git a/src/wire/ipv6hopbyhop.rs b/src/wire/ipv6hopbyhop.rs index 6327ceaed..dde76aef4 100644 --- a/src/wire/ipv6hopbyhop.rs +++ b/src/wire/ipv6hopbyhop.rs @@ -6,6 +6,7 @@ pub use super::IpProtocol as Protocol; /// A read/write wrapper around an IPv6 Hop-by-Hop Options Header. #[derive(Debug, PartialEq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct Header> { buffer: T } @@ -157,6 +158,7 @@ impl<'a, T: AsRef<[u8]> + ?Sized> fmt::Display for Header<&'a T> { /// A high-level representation of an IPv6 Hop-by-Hop Options header. #[derive(Debug, PartialEq, Eq, Clone, Copy)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct Repr<'a> { /// The type of header immediately following the Hop-by-Hop Options header. pub next_header: Protocol, diff --git a/src/wire/ipv6option.rs b/src/wire/ipv6option.rs index 023f74ffb..adab8f42b 100644 --- a/src/wire/ipv6option.rs +++ b/src/wire/ipv6option.rs @@ -58,6 +58,7 @@ impl From for FailureType { /// A read/write wrapper around an IPv6 Extension Header Option. #[derive(Debug, PartialEq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct Ipv6Option> { buffer: T } @@ -214,6 +215,7 @@ impl<'a, T: AsRef<[u8]> + ?Sized> fmt::Display for Ipv6Option<&'a T> { /// A high-level representation of an IPv6 Extension Header Option. #[derive(Debug, PartialEq, Eq, Clone, Copy)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[non_exhaustive] pub enum Repr<'a> { Pad1, @@ -278,6 +280,7 @@ impl<'a> Repr<'a> { /// A iterator for IPv6 options. #[derive(Debug)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct Ipv6OptionsIterator<'a> { pos: usize, length: usize, diff --git a/src/wire/ipv6routing.rs b/src/wire/ipv6routing.rs index a76d38efa..a00e44bc7 100644 --- a/src/wire/ipv6routing.rs +++ b/src/wire/ipv6routing.rs @@ -51,6 +51,7 @@ impl fmt::Display for Type { /// A read/write wrapper around an IPv6 Routing Header buffer. #[derive(Debug, PartialEq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct Header> { buffer: T } @@ -389,6 +390,7 @@ impl<'a, T: AsRef<[u8]> + ?Sized> fmt::Display for Header<&'a T> { /// A high-level representation of an IPv6 Routing Header. #[derive(Debug, PartialEq, Eq, Clone, Copy)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[non_exhaustive] pub enum Repr<'a> { Type2 { diff --git a/src/wire/mld.rs b/src/wire/mld.rs index 8fe5e8dc6..eb2a32937 100644 --- a/src/wire/mld.rs +++ b/src/wire/mld.rs @@ -166,6 +166,7 @@ impl + AsMut<[u8]>> Packet { /// A read/write wrapper around an MLDv2 Listener Report Message Address Record. #[derive(Debug, PartialEq, Clone)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct AddressRecord> { buffer: T } @@ -295,6 +296,7 @@ impl + AsMut<[u8]>> AddressRecord { /// A high-level representation of an MLDv2 packet header. #[derive(Debug, PartialEq, Eq, Clone, Copy)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum Repr<'a> { Query { max_resp_code: u16, diff --git a/src/wire/ndisc.rs b/src/wire/ndisc.rs index 775f54816..b31cb1c6b 100644 --- a/src/wire/ndisc.rs +++ b/src/wire/ndisc.rs @@ -10,6 +10,7 @@ use crate::time::Duration; use crate::wire::Ipv6Address; bitflags! { + #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct RouterFlags: u8 { const MANAGED = 0b10000000; const OTHER = 0b01000000; @@ -17,6 +18,7 @@ bitflags! { } bitflags! { + #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct NeighborFlags: u8 { const ROUTER = 0b10000000; const SOLICITED = 0b01000000; @@ -189,6 +191,7 @@ impl + AsMut<[u8]>> Packet { /// A high-level representation of an Neighbor Discovery packet header. #[derive(Debug, PartialEq, Eq, Clone, Copy)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum Repr<'a> { RouterSolicit { lladdr: Option diff --git a/src/wire/ndiscoption.rs b/src/wire/ndiscoption.rs index 6ea9721ed..b0426bdcd 100644 --- a/src/wire/ndiscoption.rs +++ b/src/wire/ndiscoption.rs @@ -36,6 +36,7 @@ impl fmt::Display for Type { } bitflags! { + #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct PrefixInfoFlags: u8 { const ON_LINK = 0b10000000; const ADDRCONF = 0b01000000; @@ -46,6 +47,7 @@ bitflags! { /// /// [NDISC Option]: https://tools.ietf.org/html/rfc4861#section-4.6 #[derive(Debug, PartialEq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct NdiscOption> { buffer: T } @@ -393,6 +395,7 @@ impl<'a, T: AsRef<[u8]> + ?Sized> fmt::Display for NdiscOption<&'a T> { } #[derive(Debug, PartialEq, Eq, Clone, Copy)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct PrefixInformation { pub prefix_len: u8, pub flags: PrefixInfoFlags, @@ -402,6 +405,7 @@ pub struct PrefixInformation { } #[derive(Debug, PartialEq, Eq, Clone, Copy)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct RedirectedHeader<'a> { pub header: Ipv6Repr, pub data: &'a [u8] @@ -409,6 +413,7 @@ pub struct RedirectedHeader<'a> { /// A high-level representation of an NDISC Option. #[derive(Debug, PartialEq, Eq, Clone, Copy)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum Repr<'a> { SourceLinkLayerAddr(EthernetAddress), TargetLinkLayerAddr(EthernetAddress), diff --git a/src/wire/pretty_print.rs b/src/wire/pretty_print.rs index 60a6fe4fb..6d900de7c 100644 --- a/src/wire/pretty_print.rs +++ b/src/wire/pretty_print.rs @@ -34,6 +34,7 @@ use core::marker::PhantomData; /// Indentation state. #[derive(Debug)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct PrettyIndent { prefix: &'static str, level: usize diff --git a/src/wire/tcp.rs b/src/wire/tcp.rs index faa3abcf3..c0fff417b 100644 --- a/src/wire/tcp.rs +++ b/src/wire/tcp.rs @@ -11,6 +11,7 @@ use crate::wire::ip::checksum; /// A sequence number is a monotonically advancing integer modulo 232. /// Sequence numbers do not have a discontiguity when compared pairwise across a signed overflow. #[derive(Debug, PartialEq, Eq, Clone, Copy, Default)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct SeqNumber(pub i32); impl fmt::Display for SeqNumber { @@ -67,6 +68,7 @@ impl cmp::PartialOrd for SeqNumber { /// A read/write wrapper around a Transmission Control Protocol packet buffer. #[derive(Debug, PartialEq, Clone)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct Packet> { buffer: T } @@ -550,6 +552,7 @@ impl> AsRef<[u8]> for Packet { /// A representation of a single TCP option. #[derive(Debug, PartialEq, Eq, Clone, Copy)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum TcpOption<'a> { EndOfList, NoOperation, @@ -702,6 +705,7 @@ impl<'a> TcpOption<'a> { /// The possible control flags of a Transmission Control Protocol packet. #[derive(Debug, PartialEq, Eq, Clone, Copy)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum Control { None, Psh, @@ -731,6 +735,7 @@ impl Control { /// A high-level representation of a Transmission Control Protocol packet. #[derive(Debug, PartialEq, Eq, Clone, Copy)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct Repr<'a> { pub src_port: u16, pub dst_port: u16, diff --git a/src/wire/udp.rs b/src/wire/udp.rs index 1ce43b8e1..f28b149aa 100644 --- a/src/wire/udp.rs +++ b/src/wire/udp.rs @@ -8,6 +8,7 @@ use crate::wire::ip::checksum; /// A read/write wrapper around an User Datagram Protocol packet buffer. #[derive(Debug, PartialEq, Clone)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct Packet> { buffer: T } @@ -199,6 +200,7 @@ impl> AsRef<[u8]> for Packet { /// A high-level representation of an User Datagram Protocol packet. #[derive(Debug, PartialEq, Eq, Clone, Copy)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct Repr<'a> { pub src_port: u16, pub dst_port: u16,