Browse Source

Merge pull request #506 from qiujiangkun/fix_clippy

Various clippy fix
Dario Nieuwenhuis 3 years ago
parent
commit
f8b0e56a6d
67 changed files with 6605 additions and 4302 deletions
  1. 43 35
      benches/bench.rs
  2. 33 25
      examples/benchmark.rs
  3. 30 24
      examples/client.rs
  4. 13 10
      examples/dhcp_client.rs
  5. 34 23
      examples/httpclient.rs
  6. 27 21
      examples/loopback.rs
  7. 32 24
      examples/multicast.rs
  8. 126 61
      examples/ping.rs
  9. 59 45
      examples/server.rs
  10. 13 8
      examples/tcpdump.rs
  11. 126 52
      examples/utils.rs
  12. 389 264
      src/iface/interface.rs
  13. 4 4
      src/iface/mod.rs
  14. 152 51
      src/iface/neighbor.rs
  15. 116 46
      src/iface/route.rs
  16. 20 17
      src/lib.rs
  17. 0 1
      src/macros.rs
  18. 216 130
      src/parsers.rs
  19. 86 49
      src/phy/fault_injector.rs
  20. 32 17
      src/phy/fuzz_injector.rs
  21. 9 5
      src/phy/loopback.rs
  22. 36 18
      src/phy/mod.rs
  23. 61 39
      src/phy/pcap_writer.rs
  24. 19 17
      src/phy/raw_socket.rs
  25. 1 1
      src/phy/sys/bpf.rs
  26. 6 6
      src/phy/sys/linux.rs
  27. 73 30
      src/phy/sys/mod.rs
  28. 49 25
      src/phy/sys/raw_socket.rs
  29. 34 14
      src/phy/sys/tuntap_interface.rs
  30. 93 38
      src/phy/tracer.rs
  31. 17 15
      src/phy/tuntap_interface.rs
  32. 91 52
      src/socket/dhcpv4.rs
  33. 346 173
      src/socket/icmp.rs
  34. 35 23
      src/socket/meta.rs
  35. 35 36
      src/socket/mod.rs
  36. 205 119
      src/socket/raw.rs
  37. 7 3
      src/socket/ref_.rs
  38. 47 37
      src/socket/set.rs
  39. 401 236
      src/socket/tcp.rs
  40. 246 114
      src/socket/udp.rs
  41. 1 1
      src/socket/waker.rs
  42. 46 28
      src/storage/assembler.rs
  43. 2 2
      src/storage/mod.rs
  44. 69 40
      src/storage/packet_buffer.rs
  45. 91 43
      src/storage/ring_buffer.rs
  46. 48 23
      src/time.rs
  47. 83 63
      src/wire/arp.rs
  48. 185 121
      src/wire/dhcpv4.rs
  49. 75 63
      src/wire/ethernet.rs
  50. 140 119
      src/wire/icmpv4.rs
  51. 276 255
      src/wire/icmpv6.rs
  52. 43 38
      src/wire/igmp.rs
  53. 318 241
      src/wire/ip.rs
  54. 310 184
      src/wire/ipv4.rs
  55. 295 192
      src/wire/ipv6.rs
  56. 56 25
      src/wire/ipv6fragment.rs
  57. 86 46
      src/wire/ipv6hopbyhop.rs
  58. 105 78
      src/wire/ipv6option.rs
  59. 129 96
      src/wire/ipv6routing.rs
  60. 123 123
      src/wire/mld.rs
  61. 73 98
      src/wire/mod.rs
  62. 129 81
      src/wire/ndisc.rs
  63. 121 116
      src/wire/ndiscoption.rs
  64. 12 9
      src/wire/pretty_print.rs
  65. 313 235
      src/wire/tcp.rs
  66. 86 55
      src/wire/udp.rs
  67. 28 19
      utils/packet2pcap.rs

+ 43 - 35
benches/bench.rs

@@ -1,22 +1,24 @@
 #![feature(test)]
 
 mod wire {
-    use test;
-    #[cfg(feature = "proto-ipv6")]
-    use smoltcp::wire::{Ipv6Address, Ipv6Repr, Ipv6Packet};
-    #[cfg(feature = "proto-ipv4")]
-    use smoltcp::wire::{Ipv4Address, Ipv4Repr, Ipv4Packet};
-    use smoltcp::phy::{ChecksumCapabilities};
+    use smoltcp::phy::ChecksumCapabilities;
     use smoltcp::wire::{IpAddress, IpProtocol};
-    use smoltcp::wire::{TcpRepr, TcpPacket, TcpSeqNumber, TcpControl};
-    use smoltcp::wire::{UdpRepr, UdpPacket};
+    #[cfg(feature = "proto-ipv4")]
+    use smoltcp::wire::{Ipv4Address, Ipv4Packet, Ipv4Repr};
+    #[cfg(feature = "proto-ipv6")]
+    use smoltcp::wire::{Ipv6Address, Ipv6Packet, Ipv6Repr};
+    use smoltcp::wire::{TcpControl, TcpPacket, TcpRepr, TcpSeqNumber};
+    use smoltcp::wire::{UdpPacket, UdpRepr};
+    use test;
 
     #[cfg(feature = "proto-ipv6")]
-    const SRC_ADDR: IpAddress = IpAddress::Ipv6(Ipv6Address([0xfe, 0x80, 0, 0, 0, 0, 0, 0,
-                                                             0, 0, 0, 0, 0, 0, 0, 1]));
+    const SRC_ADDR: IpAddress = IpAddress::Ipv6(Ipv6Address([
+        0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
+    ]));
     #[cfg(feature = "proto-ipv6")]
-    const DST_ADDR: IpAddress = IpAddress::Ipv6(Ipv6Address([0xfe, 0x80, 0, 0, 0, 0, 0, 0,
-                                                             0, 0, 0, 0, 0, 0, 0, 2]));
+    const DST_ADDR: IpAddress = IpAddress::Ipv6(Ipv6Address([
+        0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2,
+    ]));
 
     #[cfg(all(not(feature = "proto-ipv6"), feature = "proto-ipv4"))]
     const SRC_ADDR: IpAddress = IpAddress::Ipv4(Ipv4Address([192, 168, 1, 1]));
@@ -26,42 +28,50 @@ mod wire {
     #[bench]
     #[cfg(any(feature = "proto-ipv6", feature = "proto-ipv4"))]
     fn bench_emit_tcp(b: &mut test::Bencher) {
-        static PAYLOAD_BYTES: [u8; 400] =
-            [0x2a; 400];
+        static PAYLOAD_BYTES: [u8; 400] = [0x2a; 400];
         let repr = TcpRepr {
-            src_port:     48896,
-            dst_port:     80,
-            seq_number:   TcpSeqNumber(0x01234567),
-            ack_number:   None,
-            window_len:   0x0123,
-            control:      TcpControl::Syn,
+            src_port: 48896,
+            dst_port: 80,
+            seq_number: TcpSeqNumber(0x01234567),
+            ack_number: None,
+            window_len: 0x0123,
+            control: TcpControl::Syn,
             max_seg_size: None,
             window_scale: None,
-            payload:      &PAYLOAD_BYTES
+            payload: &PAYLOAD_BYTES,
         };
         let mut bytes = vec![0xa5; repr.buffer_len()];
 
         b.iter(|| {
             let mut packet = TcpPacket::new(&mut bytes);
-            repr.emit(&mut packet, &SRC_ADDR, &DST_ADDR, &ChecksumCapabilities::default());
+            repr.emit(
+                &mut packet,
+                &SRC_ADDR,
+                &DST_ADDR,
+                &ChecksumCapabilities::default(),
+            );
         });
     }
 
     #[bench]
     #[cfg(any(feature = "proto-ipv6", feature = "proto-ipv4"))]
     fn bench_emit_udp(b: &mut test::Bencher) {
-        static PAYLOAD_BYTES: [u8; 400] =
-            [0x2a; 400];
+        static PAYLOAD_BYTES: [u8; 400] = [0x2a; 400];
         let repr = UdpRepr {
             src_port: 48896,
             dst_port: 80,
-            payload:  &PAYLOAD_BYTES
+            payload: &PAYLOAD_BYTES,
         };
         let mut bytes = vec![0xa5; repr.buffer_len()];
 
         b.iter(|| {
             let mut packet = UdpPacket::new(&mut bytes);
-            repr.emit(&mut packet, &SRC_ADDR, &DST_ADDR, &ChecksumCapabilities::default());
+            repr.emit(
+                &mut packet,
+                &SRC_ADDR,
+                &DST_ADDR,
+                &ChecksumCapabilities::default(),
+            );
         });
     }
 
@@ -69,11 +79,11 @@ mod wire {
     #[cfg(feature = "proto-ipv4")]
     fn bench_emit_ipv4(b: &mut test::Bencher) {
         let repr = Ipv4Repr {
-            src_addr:    Ipv4Address([192, 168, 1, 1]),
-            dst_addr:    Ipv4Address([192, 168, 1, 2]),
-            protocol:    IpProtocol::Tcp,
+            src_addr: Ipv4Address([192, 168, 1, 1]),
+            dst_addr: Ipv4Address([192, 168, 1, 2]),
+            protocol: IpProtocol::Tcp,
             payload_len: 100,
-            hop_limit:   64
+            hop_limit: 64,
         };
         let mut bytes = vec![0xa5; repr.buffer_len()];
 
@@ -87,13 +97,11 @@ mod wire {
     #[cfg(feature = "proto-ipv6")]
     fn bench_emit_ipv6(b: &mut test::Bencher) {
         let repr = Ipv6Repr {
-            src_addr:    Ipv6Address([0xfe, 0x80, 0, 0, 0, 0, 0, 0,
-                                      0, 0, 0, 0, 0, 0, 0, 1]),
-            dst_addr:    Ipv6Address([0xfe, 0x80, 0, 0, 0, 0, 0, 0,
-                                      0, 0, 0, 0, 0, 0, 0, 2]),
+            src_addr: Ipv6Address([0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]),
+            dst_addr: Ipv6Address([0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2]),
             next_header: IpProtocol::Tcp,
             payload_len: 100,
-            hop_limit:   64
+            hop_limit: 64,
         };
         let mut bytes = vec![0xa5; repr.buffer_len()];
 

+ 33 - 25
examples/benchmark.rs

@@ -2,28 +2,34 @@
 
 mod utils;
 
+use log::debug;
 use std::cmp;
 use std::collections::BTreeMap;
-use std::sync::atomic::{Ordering, AtomicBool};
-use std::thread;
 use std::io::{Read, Write};
 use std::net::TcpStream;
 use std::os::unix::io::AsRawFd;
-use log::debug;
+use std::sync::atomic::{AtomicBool, Ordering};
+use std::thread;
 
-use smoltcp::phy::{Device, Medium, wait as phy_wait};
-use smoltcp::wire::{EthernetAddress, IpAddress, IpCidr};
-use smoltcp::iface::{NeighborCache, InterfaceBuilder};
+use smoltcp::iface::{InterfaceBuilder, NeighborCache};
+use smoltcp::phy::{wait as phy_wait, Device, Medium};
 use smoltcp::socket::SocketSet;
 use smoltcp::socket::{TcpSocket, TcpSocketBuffer};
 use smoltcp::time::{Duration, Instant};
+use smoltcp::wire::{EthernetAddress, IpAddress, IpCidr};
 
 const AMOUNT: usize = 1_000_000_000;
 
-enum Client { Reader, Writer }
+enum Client {
+    Reader,
+    Writer,
+}
 
 fn client(kind: Client) {
-    let port = match kind { Client::Reader => 1234, Client::Writer => 1235 };
+    let port = match kind {
+        Client::Reader => 1234,
+        Client::Writer => 1235,
+    };
     let mut stream = TcpStream::connect(("192.168.69.1", port)).unwrap();
     let mut buffer = vec![0; 1_000_000];
 
@@ -42,7 +48,7 @@ fn client(kind: Client) {
                 // print!("(P:{})", result);
                 processed += result
             }
-            Err(err) => panic!("cannot process: {}", err)
+            Err(err) => panic!("cannot process: {}", err),
         }
     }
 
@@ -69,11 +75,11 @@ fn main() {
     let mut matches = utils::parse_options(&opts, free);
     let device = utils::parse_tuntap_options(&mut matches);
     let fd = device.as_raw_fd();
-    let device = utils::parse_middleware_options(&mut matches, device, /*loopback=*/false);
+    let device = utils::parse_middleware_options(&mut matches, device, /*loopback=*/ false);
     let mode = match matches.free[0].as_ref() {
         "reader" => Client::Reader,
         "writer" => Client::Writer,
-        _ => panic!("invalid mode")
+        _ => panic!("invalid mode"),
     };
 
     thread::spawn(move || client(mode));
@@ -91,8 +97,7 @@ fn main() {
     let ethernet_addr = EthernetAddress([0x02, 0x00, 0x00, 0x00, 0x00, 0x01]);
     let ip_addrs = [IpCidr::new(IpAddress::v4(192, 168, 69, 1), 24)];
     let medium = device.capabilities().medium;
-    let mut builder = InterfaceBuilder::new(device)
-            .ip_addrs(ip_addrs);
+    let mut builder = InterfaceBuilder::new(device).ip_addrs(ip_addrs);
     if medium == Medium::Ethernet {
         builder = builder
             .ethernet_addr(ethernet_addr)
@@ -109,13 +114,12 @@ fn main() {
     while !CLIENT_DONE.load(Ordering::SeqCst) {
         let timestamp = Instant::now();
         match iface.poll(&mut sockets, timestamp) {
-            Ok(_) => {},
+            Ok(_) => {}
             Err(e) => {
-                debug!("poll error: {}",e);
+                debug!("poll error: {}", e);
             }
         }
 
-
         // tcp:1234: emit data
         {
             let mut socket = sockets.get::<TcpSocket>(tcp1_handle);
@@ -125,10 +129,12 @@ fn main() {
 
             if socket.can_send() {
                 if processed < AMOUNT {
-                    let length = socket.send(|buffer| {
-                        let length = cmp::min(buffer.len(), AMOUNT - processed);
-                        (length, length)
-                    }).unwrap();
+                    let length = socket
+                        .send(|buffer| {
+                            let length = cmp::min(buffer.len(), AMOUNT - processed);
+                            (length, length)
+                        })
+                        .unwrap();
                     processed += length;
                 }
             }
@@ -143,10 +149,12 @@ fn main() {
 
             if socket.can_recv() {
                 if processed < AMOUNT {
-                    let length = socket.recv(|buffer| {
-                        let length = cmp::min(buffer.len(), AMOUNT - processed);
-                        (length, length)
-                    }).unwrap();
+                    let length = socket
+                        .recv(|buffer| {
+                            let length = cmp::min(buffer.len(), AMOUNT - processed);
+                            (length, length)
+                        })
+                        .unwrap();
                     processed += length;
                 }
             }
@@ -155,7 +163,7 @@ fn main() {
         match iface.poll_at(&sockets, timestamp) {
             Some(poll_at) if timestamp < poll_at => {
                 phy_wait(fd, Some(poll_at - timestamp)).expect("wait error");
-            },
+            }
             Some(_) => (),
             None => {
                 phy_wait(fd, default_timeout).expect("wait error");

+ 30 - 24
examples/client.rs

@@ -1,15 +1,15 @@
 mod utils;
 
-use std::str::{self, FromStr};
+use log::debug;
 use std::collections::BTreeMap;
 use std::os::unix::io::AsRawFd;
-use log::debug;
+use std::str::{self, FromStr};
 
-use smoltcp::phy::{Device, Medium, wait as phy_wait};
-use smoltcp::wire::{EthernetAddress, Ipv4Address, IpAddress, IpCidr};
-use smoltcp::iface::{NeighborCache, InterfaceBuilder, Routes};
+use smoltcp::iface::{InterfaceBuilder, NeighborCache, Routes};
+use smoltcp::phy::{wait as phy_wait, Device, Medium};
 use smoltcp::socket::{SocketSet, TcpSocket, TcpSocketBuffer};
 use smoltcp::time::Instant;
+use smoltcp::wire::{EthernetAddress, IpAddress, IpCidr, Ipv4Address};
 
 fn main() {
     utils::setup_logging("");
@@ -24,7 +24,7 @@ fn main() {
     let device = utils::parse_tuntap_options(&mut matches);
 
     let fd = device.as_raw_fd();
-    let device = utils::parse_middleware_options(&mut matches, device, /*loopback=*/false);
+    let device = utils::parse_middleware_options(&mut matches, device, /*loopback=*/ false);
     let address = IpAddress::from_str(&matches.free[0]).expect("invalid address format");
     let port = u16::from_str(&matches.free[1]).expect("invalid port format");
 
@@ -40,11 +40,11 @@ fn main() {
     let mut routes_storage = [None; 1];
     let mut routes = Routes::new(&mut routes_storage[..]);
     routes.add_default_ipv4_route(default_v4_gw).unwrap();
-    
+
     let medium = device.capabilities().medium;
     let mut builder = InterfaceBuilder::new(device)
-            .ip_addrs(ip_addrs)
-            .routes(routes);
+        .ip_addrs(ip_addrs)
+        .routes(routes);
     if medium == Medium::Ethernet {
         builder = builder
             .ethernet_addr(ethernet_addr)
@@ -64,7 +64,7 @@ fn main() {
     loop {
         let timestamp = Instant::now();
         match iface.poll(&mut sockets, timestamp) {
-            Ok(_) => {},
+            Ok(_) => {}
             Err(e) => {
                 debug!("poll error: {}", e);
             }
@@ -76,25 +76,31 @@ fn main() {
                 debug!("connected");
             } else if !socket.is_active() && tcp_active {
                 debug!("disconnected");
-                break
+                break;
             }
             tcp_active = socket.is_active();
 
             if socket.may_recv() {
-                let data = socket.recv(|data| {
-                    let mut data = data.to_owned();
-                    if !data.is_empty() {
-                        debug!("recv data: {:?}",
-                               str::from_utf8(data.as_ref()).unwrap_or("(invalid utf8)"));
-                        data = data.split(|&b| b == b'\n').collect::<Vec<_>>().concat();
-                        data.reverse();
-                        data.extend(b"\n");
-                    }
-                    (data.len(), data)
-                }).unwrap();
+                let data = socket
+                    .recv(|data| {
+                        let mut data = data.to_owned();
+                        if !data.is_empty() {
+                            debug!(
+                                "recv data: {:?}",
+                                str::from_utf8(data.as_ref()).unwrap_or("(invalid utf8)")
+                            );
+                            data = data.split(|&b| b == b'\n').collect::<Vec<_>>().concat();
+                            data.reverse();
+                            data.extend(b"\n");
+                        }
+                        (data.len(), data)
+                    })
+                    .unwrap();
                 if socket.can_send() && !data.is_empty() {
-                    debug!("send data: {:?}",
-                           str::from_utf8(data.as_ref()).unwrap_or("(invalid utf8)"));
+                    debug!(
+                        "send data: {:?}",
+                        str::from_utf8(data.as_ref()).unwrap_or("(invalid utf8)")
+                    );
                     socket.send_slice(&data[..]).unwrap();
                 }
             } else if socket.may_send() {

+ 13 - 10
examples/dhcp_client.rs

@@ -1,15 +1,18 @@
 #![allow(clippy::option_map_unit_fn)]
 mod utils;
 
+use log::*;
 use std::collections::BTreeMap;
 use std::os::unix::io::AsRawFd;
-use log::*;
 
-use smoltcp::{phy::{Device, Medium, wait as phy_wait}, time::Duration};
-use smoltcp::wire::{EthernetAddress, Ipv4Address, IpCidr, Ipv4Cidr};
-use smoltcp::iface::{NeighborCache, InterfaceBuilder, Interface, Routes};
-use smoltcp::socket::{SocketSet, Dhcpv4Socket, Dhcpv4Event};
+use smoltcp::iface::{Interface, InterfaceBuilder, NeighborCache, Routes};
+use smoltcp::socket::{Dhcpv4Event, Dhcpv4Socket, SocketSet};
 use smoltcp::time::Instant;
+use smoltcp::wire::{EthernetAddress, IpCidr, Ipv4Address, Ipv4Cidr};
+use smoltcp::{
+    phy::{wait as phy_wait, Device, Medium},
+    time::Duration,
+};
 
 fn main() {
     #[cfg(feature = "log")]
@@ -22,7 +25,7 @@ fn main() {
     let mut matches = utils::parse_options(&opts, free);
     let device = utils::parse_tuntap_options(&mut matches);
     let fd = device.as_raw_fd();
-    let device = utils::parse_middleware_options(&mut matches, device, /*loopback=*/false);
+    let device = utils::parse_middleware_options(&mut matches, device, /*loopback=*/ false);
 
     let neighbor_cache = NeighborCache::new(BTreeMap::new());
     let ethernet_addr = EthernetAddress([0x02, 0x00, 0x00, 0x00, 0x00, 0x01]);
@@ -32,8 +35,8 @@ fn main() {
 
     let medium = device.capabilities().medium;
     let mut builder = InterfaceBuilder::new(device)
-            .ip_addrs(ip_addrs)
-            .routes(routes);
+        .ip_addrs(ip_addrs)
+        .routes(routes);
     if medium == Medium::Ethernet {
         builder = builder
             .ethernet_addr(ethernet_addr)
@@ -92,11 +95,11 @@ fn main() {
 }
 
 fn set_ipv4_addr<DeviceT>(iface: &mut Interface<'_, DeviceT>, cidr: Ipv4Cidr)
-    where DeviceT: for<'d> Device<'d>
+where
+    DeviceT: for<'d> Device<'d>,
 {
     iface.update_ip_addrs(|addrs| {
         let dest = addrs.iter_mut().next().unwrap();
         *dest = IpCidr::Ipv4(cidr);
     });
 }
-

+ 34 - 23
examples/httpclient.rs

@@ -1,16 +1,16 @@
 mod utils;
 
-use std::str::{self, FromStr};
+use log::debug;
 use std::collections::BTreeMap;
 use std::os::unix::io::AsRawFd;
+use std::str::{self, FromStr};
 use url::Url;
-use log::debug;
 
-use smoltcp::phy::{Device, Medium, wait as phy_wait};
-use smoltcp::wire::{EthernetAddress, Ipv4Address, Ipv6Address, IpAddress, IpCidr};
-use smoltcp::iface::{NeighborCache, InterfaceBuilder, Routes};
+use smoltcp::iface::{InterfaceBuilder, NeighborCache, Routes};
+use smoltcp::phy::{wait as phy_wait, Device, Medium};
 use smoltcp::socket::{SocketSet, TcpSocket, TcpSocketBuffer};
 use smoltcp::time::Instant;
+use smoltcp::wire::{EthernetAddress, IpAddress, IpCidr, Ipv4Address, Ipv6Address};
 
 fn main() {
     utils::setup_logging("");
@@ -24,11 +24,10 @@ fn main() {
     let mut matches = utils::parse_options(&opts, free);
     let device = utils::parse_tuntap_options(&mut matches);
     let fd = device.as_raw_fd();
-    let device = utils::parse_middleware_options(&mut matches, device, /*loopback=*/false);
+    let device = utils::parse_middleware_options(&mut matches, device, /*loopback=*/ false);
     let address = IpAddress::from_str(&matches.free[0]).expect("invalid address format");
     let url = Url::parse(&matches.free[1]).expect("invalid url format");
 
-
     let neighbor_cache = NeighborCache::new(BTreeMap::new());
 
     let tcp_rx_buffer = TcpSocketBuffer::new(vec![0; 1024]);
@@ -36,9 +35,11 @@ fn main() {
     let tcp_socket = TcpSocket::new(tcp_rx_buffer, tcp_tx_buffer);
 
     let ethernet_addr = EthernetAddress([0x02, 0x00, 0x00, 0x00, 0x00, 0x02]);
-    let ip_addrs = [IpCidr::new(IpAddress::v4(192, 168, 69, 1), 24),
-                    IpCidr::new(IpAddress::v6(0xfdaa, 0, 0, 0, 0, 0, 0, 1), 64),
-                    IpCidr::new(IpAddress::v6(0xfe80, 0, 0, 0, 0, 0, 0, 1), 64)];
+    let ip_addrs = [
+        IpCidr::new(IpAddress::v4(192, 168, 69, 1), 24),
+        IpCidr::new(IpAddress::v6(0xfdaa, 0, 0, 0, 0, 0, 0, 1), 64),
+        IpCidr::new(IpAddress::v6(0xfe80, 0, 0, 0, 0, 0, 0, 1), 64),
+    ];
     let default_v4_gw = Ipv4Address::new(192, 168, 69, 100);
     let default_v6_gw = Ipv6Address::new(0xfe80, 0, 0, 0, 0, 0, 0, 0x100);
     let mut routes_storage = [None; 2];
@@ -48,8 +49,8 @@ fn main() {
 
     let medium = device.capabilities().medium;
     let mut builder = InterfaceBuilder::new(device)
-            .ip_addrs(ip_addrs)
-            .routes(routes);
+        .ip_addrs(ip_addrs)
+        .routes(routes);
     if medium == Medium::Ethernet {
         builder = builder
             .ethernet_addr(ethernet_addr)
@@ -60,15 +61,19 @@ fn main() {
     let mut sockets = SocketSet::new(vec![]);
     let tcp_handle = sockets.add(tcp_socket);
 
-    enum State { Connect, Request, Response }
+    enum State {
+        Connect,
+        Request,
+        Response,
+    }
     let mut state = State::Connect;
 
     loop {
         let timestamp = Instant::now();
         match iface.poll(&mut sockets, timestamp) {
-            Ok(_) => {},
+            Ok(_) => {}
             Err(e) => {
-                debug!("poll error: {}",e);
+                debug!("poll error: {}", e);
             }
         }
 
@@ -79,7 +84,9 @@ fn main() {
                 State::Connect if !socket.is_active() => {
                     debug!("connecting");
                     let local_port = 49152 + rand::random::<u16>() % 16384;
-                    socket.connect((address, url.port().unwrap_or(80)), local_port).unwrap();
+                    socket
+                        .connect((address, url.port().unwrap_or(80)), local_port)
+                        .unwrap();
                     State::Request
                 }
                 State::Request if socket.may_send() => {
@@ -88,22 +95,26 @@ fn main() {
                     socket.send_slice(http_get.as_ref()).expect("cannot send");
                     let http_host = "Host: ".to_owned() + url.host_str().unwrap() + "\r\n";
                     socket.send_slice(http_host.as_ref()).expect("cannot send");
-                    socket.send_slice(b"Connection: close\r\n").expect("cannot send");
+                    socket
+                        .send_slice(b"Connection: close\r\n")
+                        .expect("cannot send");
                     socket.send_slice(b"\r\n").expect("cannot send");
                     State::Response
                 }
                 State::Response if socket.can_recv() => {
-                    socket.recv(|data| {
-                        println!("{}", str::from_utf8(data).unwrap_or("(invalid utf8)"));
-                        (data.len(), ())
-                    }).unwrap();
+                    socket
+                        .recv(|data| {
+                            println!("{}", str::from_utf8(data).unwrap_or("(invalid utf8)"));
+                            (data.len(), ())
+                        })
+                        .unwrap();
                     State::Response
                 }
                 State::Response if !socket.may_recv() => {
                     debug!("received complete response");
-                    break
+                    break;
                 }
-                _ => state
+                _ => state,
             }
         }
 

+ 27 - 21
examples/loopback.rs

@@ -7,18 +7,18 @@
 mod utils;
 
 use core::str;
-use log::{info, debug, error};
+use log::{debug, error, info};
 
+use smoltcp::iface::{InterfaceBuilder, NeighborCache};
 use smoltcp::phy::{Loopback, Medium};
-use smoltcp::wire::{EthernetAddress, IpAddress, IpCidr};
-use smoltcp::iface::{NeighborCache, InterfaceBuilder};
 use smoltcp::socket::{SocketSet, TcpSocket, TcpSocketBuffer};
 use smoltcp::time::{Duration, Instant};
+use smoltcp::wire::{EthernetAddress, IpAddress, IpCidr};
 
 #[cfg(not(feature = "std"))]
 mod mock {
-    use smoltcp::time::{Duration, Instant};
     use core::cell::Cell;
+    use smoltcp::time::{Duration, Instant};
 
     #[derive(Debug)]
     #[cfg_attr(feature = "defmt", derive(defmt::Format))]
@@ -41,9 +41,9 @@ mod mock {
 
 #[cfg(feature = "std")]
 mod mock {
+    use smoltcp::time::{Duration, Instant};
+    use std::sync::atomic::{AtomicUsize, Ordering};
     use std::sync::Arc;
-    use std::sync::atomic::{Ordering, AtomicUsize};
-	use smoltcp::time::{Duration, Instant};
 
     // should be AtomicU64 but that's unstable
     #[derive(Debug, Clone)]
@@ -56,7 +56,8 @@ mod mock {
         }
 
         pub fn advance(&self, duration: Duration) {
-            self.0.fetch_add(duration.total_millis() as usize, Ordering::SeqCst);
+            self.0
+                .fetch_add(duration.total_millis() as usize, Ordering::SeqCst);
         }
 
         pub fn elapsed(&self) -> Instant {
@@ -78,7 +79,7 @@ fn main() {
         utils::add_middleware_options(&mut opts, &mut free);
 
         let mut matches = utils::parse_options(&opts, free);
-        utils::parse_middleware_options(&mut matches, device, /*loopback=*/true)
+        utils::parse_middleware_options(&mut matches, device, /*loopback=*/ true)
     };
 
     let mut neighbor_cache_entries = [None; 8];
@@ -86,10 +87,10 @@ fn main() {
 
     let mut ip_addrs = [IpCidr::new(IpAddress::v4(127, 0, 0, 1), 8)];
     let mut iface = InterfaceBuilder::new(device)
-            .ethernet_addr(EthernetAddress::default())
-            .neighbor_cache(neighbor_cache)
-            .ip_addrs(ip_addrs)
-            .finalize();
+        .ethernet_addr(EthernetAddress::default())
+        .neighbor_cache(neighbor_cache)
+        .ip_addrs(ip_addrs)
+        .finalize();
 
     let server_socket = {
         // It is not strictly necessary to use a `static mut` and unsafe code here, but
@@ -116,12 +117,12 @@ fn main() {
     let server_handle = socket_set.add(server_socket);
     let client_handle = socket_set.add(client_socket);
 
-    let mut did_listen  = false;
+    let mut did_listen = false;
     let mut did_connect = false;
     let mut done = false;
     while !done && clock.elapsed() < Instant::from_millis(10_000) {
         match iface.poll(&mut socket_set, clock.elapsed()) {
-            Ok(_) => {},
+            Ok(_) => {}
             Err(e) => {
                 debug!("poll error: {}", e);
             }
@@ -138,9 +139,10 @@ fn main() {
             }
 
             if socket.can_recv() {
-                debug!("got {:?}", socket.recv(|buffer| {
-                    (buffer.len(), str::from_utf8(buffer).unwrap())
-                }));
+                debug!(
+                    "got {:?}",
+                    socket.recv(|buffer| { (buffer.len(), str::from_utf8(buffer).unwrap()) })
+                );
                 socket.close();
                 done = true;
             }
@@ -151,8 +153,12 @@ fn main() {
             if !socket.is_open() {
                 if !did_connect {
                     debug!("connecting");
-                    socket.connect((IpAddress::v4(127, 0, 0, 1), 1234),
-                                   (IpAddress::Unspecified, 65000)).unwrap();
+                    socket
+                        .connect(
+                            (IpAddress::v4(127, 0, 0, 1), 1234),
+                            (IpAddress::Unspecified, 65000),
+                        )
+                        .unwrap();
                     did_connect = true;
                 }
             }
@@ -169,8 +175,8 @@ fn main() {
             Some(delay) => {
                 debug!("sleeping for {} ms", delay);
                 clock.advance(delay)
-            },
-            None => clock.advance(Duration::from_millis(1))
+            }
+            None => clock.advance(Duration::from_millis(1)),
         }
     }
 

+ 32 - 24
examples/multicast.rs

@@ -1,17 +1,20 @@
 mod utils;
 
+use log::debug;
 use std::collections::BTreeMap;
 use std::os::unix::io::AsRawFd;
-use log::debug;
 
+use smoltcp::iface::{InterfaceBuilder, NeighborCache};
 use smoltcp::phy::wait as phy_wait;
-use smoltcp::wire::{EthernetAddress, IpVersion, IpProtocol, IpAddress, IpCidr, Ipv4Address,
-                    Ipv4Packet, IgmpPacket, IgmpRepr};
-use smoltcp::iface::{NeighborCache, InterfaceBuilder};
-use smoltcp::socket::{SocketSet,
-                      RawSocket, RawSocketBuffer, RawPacketMetadata,
-                      UdpSocket, UdpSocketBuffer, UdpPacketMetadata};
+use smoltcp::socket::{
+    RawPacketMetadata, RawSocket, RawSocketBuffer, SocketSet, UdpPacketMetadata, UdpSocket,
+    UdpSocketBuffer,
+};
 use smoltcp::time::Instant;
+use smoltcp::wire::{
+    EthernetAddress, IgmpPacket, IgmpRepr, IpAddress, IpCidr, IpProtocol, IpVersion, Ipv4Address,
+    Ipv4Packet,
+};
 
 const MDNS_PORT: u16 = 5353;
 const MDNS_GROUP: [u8; 4] = [224, 0, 0, 251];
@@ -26,10 +29,7 @@ fn main() {
     let mut matches = utils::parse_options(&opts, free);
     let device = utils::parse_tuntap_options(&mut matches);
     let fd = device.as_raw_fd();
-    let device = utils::parse_middleware_options(&mut matches,
-                                                 device,
-                                                 /*loopback=*/
-                                                 false);
+    let device = utils::parse_middleware_options(&mut matches, device, /*loopback=*/ false);
     let neighbor_cache = NeighborCache::new(BTreeMap::new());
 
     let local_addr = Ipv4Address::new(192, 168, 69, 2);
@@ -38,15 +38,17 @@ fn main() {
     let ip_addr = IpCidr::new(IpAddress::from(local_addr), 24);
     let mut ipv4_multicast_storage = [None; 1];
     let mut iface = InterfaceBuilder::new(device)
-            .ethernet_addr(ethernet_addr)
-            .neighbor_cache(neighbor_cache)
-            .ip_addrs([ip_addr])
-            .ipv4_multicast_groups(&mut ipv4_multicast_storage[..])
-            .finalize();
+        .ethernet_addr(ethernet_addr)
+        .neighbor_cache(neighbor_cache)
+        .ip_addrs([ip_addr])
+        .ipv4_multicast_groups(&mut ipv4_multicast_storage[..])
+        .finalize();
 
     let now = Instant::now();
     // Join a multicast group to receive mDNS traffic
-    iface.join_multicast_group(Ipv4Address::from_bytes(&MDNS_GROUP), now).unwrap();
+    iface
+        .join_multicast_group(Ipv4Address::from_bytes(&MDNS_GROUP), now)
+        .unwrap();
 
     let mut sockets = SocketSet::new(vec![]);
 
@@ -55,8 +57,10 @@ fn main() {
     // Will not send IGMP
     let raw_tx_buffer = RawSocketBuffer::new(vec![], vec![]);
     let raw_socket = RawSocket::new(
-        IpVersion::Ipv4, IpProtocol::Igmp,
-        raw_rx_buffer, raw_tx_buffer
+        IpVersion::Ipv4,
+        IpProtocol::Igmp,
+        raw_rx_buffer,
+        raw_tx_buffer,
     );
     let raw_handle = sockets.add(raw_socket);
 
@@ -70,9 +74,9 @@ fn main() {
     loop {
         let timestamp = Instant::now();
         match iface.poll(&mut sockets, timestamp) {
-            Ok(_) => {},
+            Ok(_) => {}
             Err(e) => {
-                debug!("poll error: {}",e);
+                debug!("poll error: {}", e);
             }
         }
 
@@ -82,7 +86,8 @@ fn main() {
             if socket.can_recv() {
                 // For display purposes only - normally we wouldn't process incoming IGMP packets
                 // in the application layer
-                socket.recv()
+                socket
+                    .recv()
                     .and_then(Ipv4Packet::new_checked)
                     .and_then(|ipv4_packet| IgmpPacket::new_checked(ipv4_packet.payload()))
                     .and_then(|igmp_packet| IgmpRepr::parse(&igmp_packet))
@@ -97,8 +102,11 @@ fn main() {
             }
 
             if socket.can_recv() {
-                socket.recv()
-                    .map(|(data, sender)| println!("mDNS traffic: {} UDP bytes from {}", data.len(), sender))
+                socket
+                    .recv()
+                    .map(|(data, sender)| {
+                        println!("mDNS traffic: {} UDP bytes from {}", data.len(), sender)
+                    })
                     .unwrap_or_else(|e| println!("Recv UDP error: {:?}", e));
             }
         }

+ 126 - 61
examples/ping.rs

@@ -1,21 +1,25 @@
 mod utils;
 
-use std::str::FromStr;
-use std::collections::BTreeMap;
+use byteorder::{ByteOrder, NetworkEndian};
+use log::debug;
 use std::cmp;
-use std::os::unix::io::AsRawFd;
+use std::collections::BTreeMap;
 use std::collections::HashMap;
-use log::debug;
-use byteorder::{ByteOrder, NetworkEndian};
+use std::os::unix::io::AsRawFd;
+use std::str::FromStr;
 
-use smoltcp::{phy::Medium, time::{Duration, Instant}};
-use smoltcp::phy::Device;
+use smoltcp::iface::{InterfaceBuilder, NeighborCache, Routes};
 use smoltcp::phy::wait as phy_wait;
-use smoltcp::wire::{EthernetAddress, IpAddress, IpCidr,
-                    Ipv6Address, Icmpv6Repr, Icmpv6Packet,
-                    Ipv4Address, Icmpv4Repr, Icmpv4Packet};
-use smoltcp::iface::{NeighborCache, InterfaceBuilder, Routes};
-use smoltcp::socket::{SocketSet, IcmpSocket, IcmpSocketBuffer, IcmpPacketMetadata, IcmpEndpoint};
+use smoltcp::phy::Device;
+use smoltcp::socket::{IcmpEndpoint, IcmpPacketMetadata, IcmpSocket, IcmpSocketBuffer, SocketSet};
+use smoltcp::wire::{
+    EthernetAddress, Icmpv4Packet, Icmpv4Repr, Icmpv6Packet, Icmpv6Repr, IpAddress, IpCidr,
+    Ipv4Address, Ipv6Address,
+};
+use smoltcp::{
+    phy::Medium,
+    time::{Duration, Instant},
+};
 
 macro_rules! send_icmp_ping {
     ( $repr_type:ident, $packet_type:ident, $ident:expr, $seq_no:expr,
@@ -26,13 +30,11 @@ macro_rules! send_icmp_ping {
             data: &$echo_payload,
         };
 
-        let icmp_payload = $socket
-            .send(icmp_repr.buffer_len(), $remote_addr)
-            .unwrap();
+        let icmp_payload = $socket.send(icmp_repr.buffer_len(), $remote_addr).unwrap();
 
         let icmp_packet = $packet_type::new_unchecked(icmp_payload);
         (icmp_repr, icmp_packet)
-    }}
+    }};
 }
 
 macro_rules! get_icmp_pong {
@@ -41,14 +43,18 @@ macro_rules! get_icmp_pong {
         if let $repr_type::EchoReply { seq_no, data, .. } = $repr {
             if let Some(_) = $waiting_queue.get(&seq_no) {
                 let packet_timestamp_ms = NetworkEndian::read_i64(data);
-                println!("{} bytes from {}: icmp_seq={}, time={}ms",
-                         data.len(), $remote_addr, seq_no,
-                         $timestamp.total_millis() - packet_timestamp_ms);
+                println!(
+                    "{} bytes from {}: icmp_seq={}, time={}ms",
+                    data.len(),
+                    $remote_addr,
+                    seq_no,
+                    $timestamp.total_millis() - packet_timestamp_ms
+                );
                 $waiting_queue.remove(&seq_no);
                 $received += 1;
             }
         }
-    }}
+    }};
 }
 
 fn main() {
@@ -57,26 +63,45 @@ fn main() {
     let (mut opts, mut free) = utils::create_options();
     utils::add_tuntap_options(&mut opts, &mut free);
     utils::add_middleware_options(&mut opts, &mut free);
-    opts.optopt("c", "count", "Amount of echo request packets to send (default: 4)", "COUNT");
-    opts.optopt("i", "interval",
-                "Interval between successive packets sent (seconds) (default: 1)", "INTERVAL");
-    opts.optopt("", "timeout",
-                "Maximum wait duration for an echo response packet (seconds) (default: 5)",
-                "TIMEOUT");
+    opts.optopt(
+        "c",
+        "count",
+        "Amount of echo request packets to send (default: 4)",
+        "COUNT",
+    );
+    opts.optopt(
+        "i",
+        "interval",
+        "Interval between successive packets sent (seconds) (default: 1)",
+        "INTERVAL",
+    );
+    opts.optopt(
+        "",
+        "timeout",
+        "Maximum wait duration for an echo response packet (seconds) (default: 5)",
+        "TIMEOUT",
+    );
     free.push("ADDRESS");
 
     let mut matches = utils::parse_options(&opts, free);
     let device = utils::parse_tuntap_options(&mut matches);
     let fd = device.as_raw_fd();
-    let device = utils::parse_middleware_options(&mut matches, device, /*loopback=*/false);
+    let device = utils::parse_middleware_options(&mut matches, device, /*loopback=*/ false);
     let device_caps = device.capabilities();
-    let address  = IpAddress::from_str(&matches.free[0]).expect("invalid address format");
-    let count    = matches.opt_str("count").map(|s| usize::from_str(&s).unwrap()).unwrap_or(4);
-    let interval = matches.opt_str("interval")
+    let address = IpAddress::from_str(&matches.free[0]).expect("invalid address format");
+    let count = matches
+        .opt_str("count")
+        .map(|s| usize::from_str(&s).unwrap())
+        .unwrap_or(4);
+    let interval = matches
+        .opt_str("interval")
         .map(|s| Duration::from_secs(u64::from_str(&s).unwrap()))
         .unwrap_or_else(|| Duration::from_secs(1));
-    let timeout  = Duration::from_secs(
-        matches.opt_str("timeout").map(|s| u64::from_str(&s).unwrap()).unwrap_or(5)
+    let timeout = Duration::from_secs(
+        matches
+            .opt_str("timeout")
+            .map(|s| u64::from_str(&s).unwrap())
+            .unwrap_or(5),
     );
 
     let neighbor_cache = NeighborCache::new(BTreeMap::new());
@@ -89,9 +114,11 @@ fn main() {
 
     let ethernet_addr = EthernetAddress([0x02, 0x00, 0x00, 0x00, 0x00, 0x02]);
     let src_ipv6 = IpAddress::v6(0xfdaa, 0, 0, 0, 0, 0, 0, 1);
-    let ip_addrs = [IpCidr::new(IpAddress::v4(192, 168, 69, 1), 24),
-                    IpCidr::new(src_ipv6, 64),
-                    IpCidr::new(IpAddress::v6(0xfe80, 0, 0, 0, 0, 0, 0, 1), 64)];
+    let ip_addrs = [
+        IpCidr::new(IpAddress::v4(192, 168, 69, 1), 24),
+        IpCidr::new(src_ipv6, 64),
+        IpCidr::new(IpAddress::v6(0xfe80, 0, 0, 0, 0, 0, 0, 1), 64),
+    ];
     let default_v4_gw = Ipv4Address::new(192, 168, 69, 100);
     let default_v6_gw = Ipv6Address::new(0xfe80, 0, 0, 0, 0, 0, 0, 0x100);
     let mut routes_storage = [None; 2];
@@ -101,8 +128,8 @@ fn main() {
 
     let medium = device.capabilities().medium;
     let mut builder = InterfaceBuilder::new(device)
-            .ip_addrs(ip_addrs)
-            .routes(routes);
+        .ip_addrs(ip_addrs)
+        .routes(routes);
     if medium == Medium::Ethernet {
         builder = builder
             .ethernet_addr(ethernet_addr)
@@ -123,7 +150,7 @@ fn main() {
     loop {
         let timestamp = Instant::now();
         match iface.poll(&mut sockets, timestamp) {
-            Ok(_) => {},
+            Ok(_) => {}
             Err(e) => {
                 debug!("poll error: {}", e);
             }
@@ -137,25 +164,40 @@ fn main() {
                 send_at = timestamp;
             }
 
-            if socket.can_send() && seq_no < count as u16 &&
-                    send_at <= timestamp {
+            if socket.can_send() && seq_no < count as u16 && send_at <= timestamp {
                 NetworkEndian::write_i64(&mut echo_payload, timestamp.total_millis());
 
                 match remote_addr {
                     IpAddress::Ipv4(_) => {
                         let (icmp_repr, mut icmp_packet) = send_icmp_ping!(
-                                Icmpv4Repr, Icmpv4Packet, ident, seq_no,
-                                echo_payload, socket, remote_addr);
+                            Icmpv4Repr,
+                            Icmpv4Packet,
+                            ident,
+                            seq_no,
+                            echo_payload,
+                            socket,
+                            remote_addr
+                        );
                         icmp_repr.emit(&mut icmp_packet, &device_caps.checksum);
-                    },
+                    }
                     IpAddress::Ipv6(_) => {
                         let (icmp_repr, mut icmp_packet) = send_icmp_ping!(
-                                Icmpv6Repr, Icmpv6Packet, ident, seq_no,
-                                echo_payload, socket, remote_addr);
-                        icmp_repr.emit(&src_ipv6, &remote_addr,
-                                       &mut icmp_packet, &device_caps.checksum);
-                    },
-                    _ => unimplemented!()
+                            Icmpv6Repr,
+                            Icmpv6Packet,
+                            ident,
+                            seq_no,
+                            echo_payload,
+                            socket,
+                            remote_addr
+                        );
+                        icmp_repr.emit(
+                            &src_ipv6,
+                            &remote_addr,
+                            &mut icmp_packet,
+                            &device_caps.checksum,
+                        );
+                    }
+                    _ => unimplemented!(),
                 }
 
                 waiting_queue.insert(seq_no, timestamp);
@@ -171,17 +213,36 @@ fn main() {
                         let icmp_packet = Icmpv4Packet::new_checked(&payload).unwrap();
                         let icmp_repr =
                             Icmpv4Repr::parse(&icmp_packet, &device_caps.checksum).unwrap();
-                        get_icmp_pong!(Icmpv4Repr, icmp_repr, payload,
-                                waiting_queue, remote_addr, timestamp, received);
+                        get_icmp_pong!(
+                            Icmpv4Repr,
+                            icmp_repr,
+                            payload,
+                            waiting_queue,
+                            remote_addr,
+                            timestamp,
+                            received
+                        );
                     }
                     IpAddress::Ipv6(_) => {
                         let icmp_packet = Icmpv6Packet::new_checked(&payload).unwrap();
-                        let icmp_repr = Icmpv6Repr::parse(&remote_addr, &src_ipv6,
-                                &icmp_packet, &device_caps.checksum).unwrap();
-                        get_icmp_pong!(Icmpv6Repr, icmp_repr, payload,
-                                waiting_queue, remote_addr, timestamp, received);
-                    },
-                    _ => unimplemented!()
+                        let icmp_repr = Icmpv6Repr::parse(
+                            &remote_addr,
+                            &src_ipv6,
+                            &icmp_packet,
+                            &device_caps.checksum,
+                        )
+                        .unwrap();
+                        get_icmp_pong!(
+                            Icmpv6Repr,
+                            icmp_repr,
+                            payload,
+                            waiting_queue,
+                            remote_addr,
+                            timestamp,
+                            received
+                        );
+                    }
+                    _ => unimplemented!(),
                 }
             }
 
@@ -195,7 +256,7 @@ fn main() {
             });
 
             if seq_no == count as u16 && waiting_queue.is_empty() {
-                break
+                break;
             }
         }
 
@@ -204,7 +265,7 @@ fn main() {
             Some(poll_at) if timestamp < poll_at => {
                 let resume_at = cmp::min(poll_at, send_at);
                 phy_wait(fd, Some(resume_at - timestamp)).expect("wait error");
-            },
+            }
             Some(_) => (),
             None => {
                 phy_wait(fd, Some(send_at - timestamp)).expect("wait error");
@@ -213,6 +274,10 @@ fn main() {
     }
 
     println!("--- {} ping statistics ---", remote_addr);
-    println!("{} packets transmitted, {} received, {:.0}% packet loss",
-             seq_no, received, 100.0 * (seq_no - received) as f64 / seq_no as f64);
+    println!(
+        "{} packets transmitted, {} received, {:.0}% packet loss",
+        seq_no,
+        received,
+        100.0 * (seq_no - received) as f64 / seq_no as f64
+    );
 }

+ 59 - 45
examples/server.rs

@@ -1,18 +1,18 @@
 mod utils;
 
-use std::str;
+use log::debug;
 use std::collections::BTreeMap;
 use std::fmt::Write;
 use std::os::unix::io::AsRawFd;
-use log::debug;
+use std::str;
 
-use smoltcp::phy::{Device, Medium, wait as phy_wait};
-use smoltcp::wire::{EthernetAddress, IpAddress, IpCidr};
-use smoltcp::iface::{NeighborCache, InterfaceBuilder};
+use smoltcp::iface::{InterfaceBuilder, NeighborCache};
+use smoltcp::phy::{wait as phy_wait, Device, Medium};
 use smoltcp::socket::SocketSet;
-use smoltcp::socket::{UdpSocket, UdpSocketBuffer, UdpPacketMetadata};
 use smoltcp::socket::{TcpSocket, TcpSocketBuffer};
+use smoltcp::socket::{UdpPacketMetadata, UdpSocket, UdpSocketBuffer};
 use smoltcp::time::{Duration, Instant};
+use smoltcp::wire::{EthernetAddress, IpAddress, IpCidr};
 
 fn main() {
     utils::setup_logging("");
@@ -24,7 +24,7 @@ fn main() {
     let mut matches = utils::parse_options(&opts, free);
     let device = utils::parse_tuntap_options(&mut matches);
     let fd = device.as_raw_fd();
-    let device = utils::parse_middleware_options(&mut matches, device, /*loopback=*/false);
+    let device = utils::parse_middleware_options(&mut matches, device, /*loopback=*/ false);
 
     let neighbor_cache = NeighborCache::new(BTreeMap::new());
 
@@ -52,12 +52,11 @@ fn main() {
     let ip_addrs = [
         IpCidr::new(IpAddress::v4(192, 168, 69, 1), 24),
         IpCidr::new(IpAddress::v6(0xfdaa, 0, 0, 0, 0, 0, 0, 1), 64),
-        IpCidr::new(IpAddress::v6(0xfe80, 0, 0, 0, 0, 0, 0, 1), 64)
+        IpCidr::new(IpAddress::v6(0xfe80, 0, 0, 0, 0, 0, 0, 1), 64),
     ];
 
     let medium = device.capabilities().medium;
-    let mut builder = InterfaceBuilder::new(device)
-            .ip_addrs(ip_addrs);
+    let mut builder = InterfaceBuilder::new(device).ip_addrs(ip_addrs);
     if medium == Medium::Ethernet {
         builder = builder
             .ethernet_addr(ethernet_addr)
@@ -66,7 +65,7 @@ fn main() {
     let mut iface = builder.finalize();
 
     let mut sockets = SocketSet::new(vec![]);
-    let udp_handle  = sockets.add(udp_socket);
+    let udp_handle = sockets.add(udp_socket);
     let tcp1_handle = sockets.add(tcp1_socket);
     let tcp2_handle = sockets.add(tcp2_socket);
     let tcp3_handle = sockets.add(tcp3_socket);
@@ -76,7 +75,7 @@ fn main() {
     loop {
         let timestamp = Instant::now();
         match iface.poll(&mut sockets, timestamp) {
-            Ok(_) => {},
+            Ok(_) => {}
             Err(e) => {
                 debug!("poll error: {}", e);
             }
@@ -91,16 +90,21 @@ fn main() {
 
             let client = match socket.recv() {
                 Ok((data, endpoint)) => {
-                    debug!("udp:6969 recv data: {:?} from {}",
-                           str::from_utf8(data).unwrap(), endpoint);
+                    debug!(
+                        "udp:6969 recv data: {:?} from {}",
+                        str::from_utf8(data).unwrap(),
+                        endpoint
+                    );
                     Some(endpoint)
                 }
-                Err(_) => None
+                Err(_) => None,
             };
             if let Some(endpoint) = client {
                 let data = b"hello\n";
-                debug!("udp:6969 send data: {:?}",
-                       str::from_utf8(data.as_ref()).unwrap());
+                debug!(
+                    "udp:6969 send data: {:?}",
+                    str::from_utf8(data.as_ref()).unwrap()
+                );
                 socket.send_slice(data, endpoint).unwrap();
             }
         }
@@ -135,21 +139,27 @@ fn main() {
             tcp_6970_active = socket.is_active();
 
             if socket.may_recv() {
-                let data = socket.recv(|buffer| {
-                    let recvd_len = buffer.len();
-                    let mut data = buffer.to_owned();
-                    if !data.is_empty() {
-                        debug!("tcp:6970 recv data: {:?}",
-                               str::from_utf8(data.as_ref()).unwrap_or("(invalid utf8)"));
-                        data = data.split(|&b| b == b'\n').collect::<Vec<_>>().concat();
-                        data.reverse();
-                        data.extend(b"\n");
-                    }
-                    (recvd_len, data)
-                }).unwrap();
+                let data = socket
+                    .recv(|buffer| {
+                        let recvd_len = buffer.len();
+                        let mut data = buffer.to_owned();
+                        if !data.is_empty() {
+                            debug!(
+                                "tcp:6970 recv data: {:?}",
+                                str::from_utf8(data.as_ref()).unwrap_or("(invalid utf8)")
+                            );
+                            data = data.split(|&b| b == b'\n').collect::<Vec<_>>().concat();
+                            data.reverse();
+                            data.extend(b"\n");
+                        }
+                        (recvd_len, data)
+                    })
+                    .unwrap();
                 if socket.can_send() && !data.is_empty() {
-                    debug!("tcp:6970 send data: {:?}",
-                           str::from_utf8(data.as_ref()).unwrap_or("(invalid utf8)"));
+                    debug!(
+                        "tcp:6970 send data: {:?}",
+                        str::from_utf8(data.as_ref()).unwrap_or("(invalid utf8)")
+                    );
                     socket.send_slice(&data[..]).unwrap();
                 }
             } else if socket.may_send() {
@@ -168,12 +178,14 @@ fn main() {
             }
 
             if socket.may_recv() {
-                socket.recv(|buffer| {
-                    if !buffer.is_empty() {
-                        debug!("tcp:6971 recv {:?} octets", buffer.len());
-                    }
-                    (buffer.len(), ())
-                }).unwrap();
+                socket
+                    .recv(|buffer| {
+                        if !buffer.is_empty() {
+                            debug!("tcp:6971 recv {:?} octets", buffer.len());
+                        }
+                        (buffer.len(), ())
+                    })
+                    .unwrap();
             } else if socket.may_send() {
                 socket.close();
             }
@@ -187,15 +199,17 @@ fn main() {
             }
 
             if socket.may_send() {
-                socket.send(|data| {
-                    if !data.is_empty() {
-                        debug!("tcp:6972 send {:?} octets", data.len());
-                        for (i, b) in data.iter_mut().enumerate() {
-                            *b = (i % 256) as u8;
+                socket
+                    .send(|data| {
+                        if !data.is_empty() {
+                            debug!("tcp:6972 send {:?} octets", data.len());
+                            for (i, b) in data.iter_mut().enumerate() {
+                                *b = (i % 256) as u8;
+                            }
                         }
-                    }
-                    (data.len(), ())
-                }).unwrap();
+                        (data.len(), ())
+                    })
+                    .unwrap();
             }
         }
 

+ 13 - 8
examples/tcpdump.rs

@@ -1,9 +1,9 @@
-use std::env;
-use std::os::unix::io::AsRawFd;
 use smoltcp::phy::wait as phy_wait;
-use smoltcp::phy::{Device, RxToken, RawSocket};
-use smoltcp::wire::{PrettyPrinter, EthernetFrame};
+use smoltcp::phy::{Device, RawSocket, RxToken};
 use smoltcp::time::Instant;
+use smoltcp::wire::{EthernetFrame, PrettyPrinter};
+use std::env;
+use std::os::unix::io::AsRawFd;
 
 fn main() {
     let ifname = env::args().nth(1).unwrap();
@@ -11,9 +11,14 @@ fn main() {
     loop {
         phy_wait(socket.as_raw_fd(), None).unwrap();
         let (rx_token, _) = socket.receive().unwrap();
-        rx_token.consume(Instant::now(), |buffer| {
-            println!("{}", PrettyPrinter::<EthernetFrame<&[u8]>>::new("", &buffer));
-            Ok(())
-        }).unwrap();
+        rx_token
+            .consume(Instant::now(), |buffer| {
+                println!(
+                    "{}",
+                    PrettyPrinter::<EthernetFrame<&[u8]>>::new("", &buffer)
+                );
+                Ok(())
+            })
+            .unwrap();
     }
 }

+ 126 - 52
examples/utils.rs

@@ -1,43 +1,59 @@
 #![allow(dead_code)]
 
+#[cfg(feature = "log")]
+use env_logger::Builder;
+use getopts::{Matches, Options};
+#[cfg(feature = "log")]
+use log::{trace, Level, LevelFilter};
 use std::cell::RefCell;
-use std::str::{self, FromStr};
-use std::rc::Rc;
-use std::io::{self, Write};
-use std::fs::File;
-use std::time::{SystemTime, UNIX_EPOCH};
 use std::env;
+use std::fs::File;
+use std::io::{self, Write};
 use std::process;
-#[cfg(feature = "log")]
-use log::{Level, LevelFilter, trace};
-#[cfg(feature = "log")]
-use env_logger::Builder;
-use getopts::{Options, Matches};
+use std::rc::Rc;
+use std::str::{self, FromStr};
+use std::time::{SystemTime, UNIX_EPOCH};
 
-use smoltcp::phy::{Device, Tracer, FaultInjector, Medium};
+use smoltcp::phy::RawSocket;
 #[cfg(feature = "phy-tuntap_interface")]
 use smoltcp::phy::TunTapInterface;
-use smoltcp::phy::{PcapWriter, PcapSink, PcapMode};
-use smoltcp::phy::RawSocket;
+use smoltcp::phy::{Device, FaultInjector, Medium, Tracer};
+use smoltcp::phy::{PcapMode, PcapSink, PcapWriter};
 use smoltcp::time::{Duration, Instant};
 
 #[cfg(feature = "log")]
 pub fn setup_logging_with_clock<F>(filter: &str, since_startup: F)
-        where F: Fn() -> Instant + Send + Sync + 'static {
+where
+    F: Fn() -> Instant + Send + Sync + 'static,
+{
     Builder::new()
         .format(move |buf, record| {
             let elapsed = since_startup();
             let timestamp = format!("[{}]", elapsed);
             if record.target().starts_with("smoltcp::") {
-                writeln!(buf, "\x1b[0m{} ({}): {}\x1b[0m", timestamp,
-                         record.target().replace("smoltcp::", ""), record.args())
+                writeln!(
+                    buf,
+                    "\x1b[0m{} ({}): {}\x1b[0m",
+                    timestamp,
+                    record.target().replace("smoltcp::", ""),
+                    record.args()
+                )
             } else if record.level() == Level::Trace {
                 let message = format!("{}", record.args());
-                writeln!(buf, "\x1b[37m{} {}\x1b[0m", timestamp,
-                         message.replace("\n", "\n             "))
+                writeln!(
+                    buf,
+                    "\x1b[37m{} {}\x1b[0m",
+                    timestamp,
+                    message.replace("\n", "\n             ")
+                )
             } else {
-                writeln!(buf, "\x1b[32m{} ({}): {}\x1b[0m", timestamp,
-                         record.target(), record.args())
+                writeln!(
+                    buf,
+                    "\x1b[32m{} ({}): {}\x1b[0m",
+                    timestamp,
+                    record.target(),
+                    record.args()
+                )
             }
         })
         .filter(None, LevelFilter::Trace)
@@ -48,9 +64,7 @@ pub fn setup_logging_with_clock<F>(filter: &str, since_startup: F)
 
 #[cfg(feature = "log")]
 pub fn setup_logging(filter: &str) {
-    setup_logging_with_clock(filter, move  || {
-        Instant::now()
-    })
+    setup_logging_with_clock(filter, Instant::now)
 }
 
 pub fn create_options() -> (Options, Vec<&'static str>) {
@@ -67,10 +81,17 @@ pub fn parse_options(options: &Options, free: Vec<&str>) -> Matches {
         }
         Ok(matches) => {
             if matches.opt_present("h") || matches.free.len() != free.len() {
-                let brief = format!("Usage: {} [OPTION]... {}",
-                                    env::args().next().unwrap(), free.join(" "));
+                let brief = format!(
+                    "Usage: {} [OPTION]... {}",
+                    env::args().next().unwrap(),
+                    free.join(" ")
+                );
                 print!("{}", options.usage(&brief));
-                process::exit(if matches.free.len() != free.len() { 1 } else { 0 })
+                process::exit(if matches.free.len() != free.len() {
+                    1
+                } else {
+                    0
+                })
             }
             matches
         }
@@ -86,7 +107,7 @@ pub fn add_tuntap_options(opts: &mut Options, _free: &mut Vec<&str>) {
 pub fn parse_tuntap_options(matches: &mut Matches) -> TunTapInterface {
     let tun = matches.opt_str("tun");
     let tap = matches.opt_str("tap");
-    match(tun,tap) {
+    match (tun, tap) {
         (Some(tun), None) => TunTapInterface::new(&tun, Medium::Ip).unwrap(),
         (None, Some(tap)) => TunTapInterface::new(&tap, Medium::Ethernet).unwrap(),
         _ => panic!("You must specify exactly one of --tun or --tap"),
@@ -100,32 +121,78 @@ pub fn parse_raw_socket_options(matches: &mut Matches) -> RawSocket {
 
 pub fn add_middleware_options(opts: &mut Options, _free: &mut Vec<&str>) {
     opts.optopt("", "pcap", "Write a packet capture file", "FILE");
-    opts.optopt("", "drop-chance", "Chance of dropping a packet (%)", "CHANCE");
-    opts.optopt("", "corrupt-chance", "Chance of corrupting a packet (%)", "CHANCE");
-    opts.optopt("", "size-limit", "Drop packets larger than given size (octets)", "SIZE");
-    opts.optopt("", "tx-rate-limit", "Drop packets after transmit rate exceeds given limit \
-                                      (packets per interval)", "RATE");
-    opts.optopt("", "rx-rate-limit", "Drop packets after transmit rate exceeds given limit \
-                                      (packets per interval)", "RATE");
-    opts.optopt("", "shaping-interval", "Sets the interval for rate limiting (ms)", "RATE");
+    opts.optopt(
+        "",
+        "drop-chance",
+        "Chance of dropping a packet (%)",
+        "CHANCE",
+    );
+    opts.optopt(
+        "",
+        "corrupt-chance",
+        "Chance of corrupting a packet (%)",
+        "CHANCE",
+    );
+    opts.optopt(
+        "",
+        "size-limit",
+        "Drop packets larger than given size (octets)",
+        "SIZE",
+    );
+    opts.optopt(
+        "",
+        "tx-rate-limit",
+        "Drop packets after transmit rate exceeds given limit \
+                                      (packets per interval)",
+        "RATE",
+    );
+    opts.optopt(
+        "",
+        "rx-rate-limit",
+        "Drop packets after transmit rate exceeds given limit \
+                                      (packets per interval)",
+        "RATE",
+    );
+    opts.optopt(
+        "",
+        "shaping-interval",
+        "Sets the interval for rate limiting (ms)",
+        "RATE",
+    );
 }
 
-pub fn parse_middleware_options<D>(matches: &mut Matches, device: D, loopback: bool)
-        -> FaultInjector<Tracer<PcapWriter<D, Rc<dyn PcapSink>>>>
-    where D: for<'a> Device<'a>
+pub fn parse_middleware_options<D>(
+    matches: &mut Matches,
+    device: D,
+    loopback: bool,
+) -> FaultInjector<Tracer<PcapWriter<D, Rc<dyn PcapSink>>>>
+where
+    D: for<'a> Device<'a>,
 {
-    let drop_chance      = matches.opt_str("drop-chance").map(|s| u8::from_str(&s).unwrap())
-                                  .unwrap_or(0);
-    let corrupt_chance   = matches.opt_str("corrupt-chance").map(|s| u8::from_str(&s).unwrap())
-                                  .unwrap_or(0);
-    let size_limit       = matches.opt_str("size-limit").map(|s| usize::from_str(&s).unwrap())
-                                  .unwrap_or(0);
-    let tx_rate_limit    = matches.opt_str("tx-rate-limit").map(|s| u64::from_str(&s).unwrap())
-                                  .unwrap_or(0);
-    let rx_rate_limit    = matches.opt_str("rx-rate-limit").map(|s| u64::from_str(&s).unwrap())
-                                  .unwrap_or(0);
-    let shaping_interval = matches.opt_str("shaping-interval").map(|s| u64::from_str(&s).unwrap())
-                                  .unwrap_or(0);
+    let drop_chance = matches
+        .opt_str("drop-chance")
+        .map(|s| u8::from_str(&s).unwrap())
+        .unwrap_or(0);
+    let corrupt_chance = matches
+        .opt_str("corrupt-chance")
+        .map(|s| u8::from_str(&s).unwrap())
+        .unwrap_or(0);
+    let size_limit = matches
+        .opt_str("size-limit")
+        .map(|s| usize::from_str(&s).unwrap())
+        .unwrap_or(0);
+    let tx_rate_limit = matches
+        .opt_str("tx-rate-limit")
+        .map(|s| u64::from_str(&s).unwrap())
+        .unwrap_or(0);
+    let rx_rate_limit = matches
+        .opt_str("rx-rate-limit")
+        .map(|s| u64::from_str(&s).unwrap())
+        .unwrap_or(0);
+    let shaping_interval = matches
+        .opt_str("shaping-interval")
+        .map(|s| u64::from_str(&s).unwrap())
+        .unwrap_or(0);
 
     let pcap_writer: Box<dyn io::Write>;
     if let Some(pcap_filename) = matches.opt_str("pcap") {
@@ -134,12 +201,19 @@ pub fn parse_middleware_options<D>(matches: &mut Matches, device: D, loopback: b
         pcap_writer = Box::new(io::sink())
     }
 
-    let seed = SystemTime::now().duration_since(UNIX_EPOCH).unwrap().subsec_nanos();
+    let seed = SystemTime::now()
+        .duration_since(UNIX_EPOCH)
+        .unwrap()
+        .subsec_nanos();
 
     let device = PcapWriter::new(
         device,
         Rc::new(RefCell::new(pcap_writer)) as Rc<dyn PcapSink>,
-        if loopback { PcapMode::TxOnly } else { PcapMode::Both },
+        if loopback {
+            PcapMode::TxOnly
+        } else {
+            PcapMode::Both
+        },
     );
 
     let device = Tracer::new(device, |_timestamp, _printer| {

File diff suppressed because it is too large
+ 389 - 264
src/iface/interface.rs


+ 4 - 4
src/iface/mod.rs

@@ -4,18 +4,18 @@ The `iface` module deals with the *network interfaces*. It filters incoming fram
 provides lookup and caching of hardware addresses, and handles management packets.
 */
 
+#[cfg(any(feature = "medium-ethernet", feature = "medium-ip"))]
+mod interface;
 #[cfg(feature = "medium-ethernet")]
 mod neighbor;
 mod route;
-#[cfg(any(feature = "medium-ethernet", feature = "medium-ip"))]
-mod interface;
 
-#[cfg(feature = "medium-ethernet")]
-pub use self::neighbor::Neighbor as Neighbor;
 #[cfg(feature = "medium-ethernet")]
 pub(crate) use self::neighbor::Answer as NeighborAnswer;
 #[cfg(feature = "medium-ethernet")]
 pub use self::neighbor::Cache as NeighborCache;
+#[cfg(feature = "medium-ethernet")]
+pub use self::neighbor::Neighbor;
 pub use self::route::{Route, Routes};
 
 #[cfg(any(feature = "medium-ethernet", feature = "medium-ip"))]

+ 152 - 51
src/iface/neighbor.rs

@@ -3,8 +3,8 @@
 
 use managed::ManagedMap;
 
-use crate::wire::{EthernetAddress, IpAddress};
 use crate::time::{Duration, Instant};
+use crate::wire::{EthernetAddress, IpAddress};
 
 /// A cached neighbor.
 ///
@@ -14,7 +14,7 @@ use crate::time::{Duration, Instant};
 #[cfg_attr(feature = "defmt", derive(defmt::Format))]
 pub struct Neighbor {
     hardware_addr: EthernetAddress,
-    expires_at:    Instant,
+    expires_at: Instant,
 }
 
 /// An answer to a neighbor cache lookup.
@@ -27,7 +27,7 @@ pub(crate) enum Answer {
     NotFound,
     /// The neighbor address is not in the cache, or has expired,
     /// and a lookup has been made recently.
-    RateLimited
+    RateLimited,
 }
 
 impl Answer {
@@ -61,10 +61,9 @@ impl Answer {
 /// ```
 #[derive(Debug)]
 pub struct Cache<'a> {
-    storage:      ManagedMap<'a, IpAddress, Neighbor>,
+    storage: ManagedMap<'a, IpAddress, Neighbor>,
     silent_until: Instant,
-    gc_threshold: usize
-
+    gc_threshold: usize,
 }
 
 impl<'a> Cache<'a> {
@@ -82,21 +81,32 @@ impl<'a> Cache<'a> {
     /// # Panics
     /// This function panics if `storage.len() == 0`.
     pub fn new<T>(storage: T) -> Cache<'a>
-            where T: Into<ManagedMap<'a, IpAddress, Neighbor>> {
-
+    where
+        T: Into<ManagedMap<'a, IpAddress, Neighbor>>,
+    {
         Cache::new_with_limit(storage, Cache::GC_THRESHOLD)
     }
 
     pub fn new_with_limit<T>(storage: T, gc_threshold: usize) -> Cache<'a>
-            where T: Into<ManagedMap<'a, IpAddress, Neighbor>> {
+    where
+        T: Into<ManagedMap<'a, IpAddress, Neighbor>>,
+    {
         let mut storage = storage.into();
         storage.clear();
 
-        Cache { storage, gc_threshold, silent_until: Instant::from_millis(0) }
+        Cache {
+            storage,
+            gc_threshold,
+            silent_until: Instant::from_millis(0),
+        }
     }
 
-    pub fn fill(&mut self, protocol_addr: IpAddress, hardware_addr: EthernetAddress,
-                timestamp: Instant) {
+    pub fn fill(
+        &mut self,
+        protocol_addr: IpAddress,
+        hardware_addr: EthernetAddress,
+        timestamp: Instant,
+    ) {
         debug_assert!(protocol_addr.is_unicast());
         debug_assert!(hardware_addr.is_unicast());
 
@@ -104,11 +114,12 @@ impl<'a> Cache<'a> {
         let current_storage_size = self.storage.len();
 
         match self.storage {
-            ManagedMap::Borrowed(_) =>  (),
+            ManagedMap::Borrowed(_) => (),
             #[cfg(any(feature = "std", feature = "alloc"))]
             ManagedMap::Owned(ref mut map) => {
                 if current_storage_size >= self.gc_threshold {
-                    let new_btree_map = map.iter_mut()
+                    let new_btree_map = map
+                        .iter_mut()
                         .map(|(key, value)| (*key, *value))
                         .filter(|(_, v)| timestamp < v.expires_at)
                         .collect();
@@ -118,13 +129,18 @@ impl<'a> Cache<'a> {
             }
         };
         let neighbor = Neighbor {
-            expires_at: timestamp + Self::ENTRY_LIFETIME, hardware_addr
+            expires_at: timestamp + Self::ENTRY_LIFETIME,
+            hardware_addr,
         };
         match self.storage.insert(protocol_addr, neighbor) {
             Ok(Some(old_neighbor)) => {
                 if old_neighbor.hardware_addr != hardware_addr {
-                    net_trace!("replaced {} => {} (was {})",
-                               protocol_addr, hardware_addr, old_neighbor.hardware_addr);
+                    net_trace!(
+                        "replaced {} => {} (was {})",
+                        protocol_addr,
+                        hardware_addr,
+                        old_neighbor.hardware_addr
+                    );
                 }
             }
             Ok(None) => {
@@ -147,21 +163,23 @@ impl<'a> Cache<'a> {
                     }
                     // Owned maps can extend themselves.
                     #[cfg(any(feature = "std", feature = "alloc"))]
-                    ManagedMap::Owned(_) => unreachable!()
+                    ManagedMap::Owned(_) => unreachable!(),
                 };
 
-                let _old_neighbor =
-                    self.storage.remove(&old_protocol_addr).unwrap();
+                let _old_neighbor = self.storage.remove(&old_protocol_addr).unwrap();
                 match self.storage.insert(protocol_addr, neighbor) {
                     Ok(None) => {
-                        net_trace!("filled {} => {} (evicted {} => {})",
-                                   protocol_addr, hardware_addr,
-                                   old_protocol_addr, _old_neighbor.hardware_addr);
+                        net_trace!(
+                            "filled {} => {} (evicted {} => {})",
+                            protocol_addr,
+                            hardware_addr,
+                            old_protocol_addr,
+                            _old_neighbor.hardware_addr
+                        );
                     }
                     // We've covered everything else above.
-                    _ => unreachable!()
+                    _ => unreachable!(),
                 }
-
             }
         }
     }
@@ -171,10 +189,13 @@ impl<'a> Cache<'a> {
             return Answer::Found(EthernetAddress::BROADCAST);
         }
 
-        if let Some(&Neighbor { expires_at, hardware_addr }) =
-                self.storage.get(protocol_addr) {
+        if let Some(&Neighbor {
+            expires_at,
+            hardware_addr,
+        }) = self.storage.get(protocol_addr)
+        {
             if timestamp < expires_at {
-                return Answer::Found(hardware_addr)
+                return Answer::Found(hardware_addr);
             }
         }
 
@@ -193,9 +214,8 @@ impl<'a> Cache<'a> {
 #[cfg(test)]
 mod test {
     use super::*;
-    use std::collections::BTreeMap;
     use crate::wire::ip::test::{MOCK_IP_ADDR_1, MOCK_IP_ADDR_2, MOCK_IP_ADDR_3, MOCK_IP_ADDR_4};
-
+    use std::collections::BTreeMap;
 
     const HADDR_A: EthernetAddress = EthernetAddress([0, 0, 0, 0, 0, 1]);
     const HADDR_B: EthernetAddress = EthernetAddress([0, 0, 0, 0, 0, 2]);
@@ -207,17 +227,47 @@ mod test {
         let mut cache_storage = [Default::default(); 3];
         let mut cache = Cache::new(&mut cache_storage[..]);
 
-        assert_eq!(cache.lookup(&MOCK_IP_ADDR_1, Instant::from_millis(0)).found(), false);
-        assert_eq!(cache.lookup(&MOCK_IP_ADDR_2, Instant::from_millis(0)).found(), false);
+        assert_eq!(
+            cache
+                .lookup(&MOCK_IP_ADDR_1, Instant::from_millis(0))
+                .found(),
+            false
+        );
+        assert_eq!(
+            cache
+                .lookup(&MOCK_IP_ADDR_2, Instant::from_millis(0))
+                .found(),
+            false
+        );
 
         cache.fill(MOCK_IP_ADDR_1, HADDR_A, Instant::from_millis(0));
-        assert_eq!(cache.lookup(&MOCK_IP_ADDR_1, Instant::from_millis(0)), Answer::Found(HADDR_A));
-        assert_eq!(cache.lookup(&MOCK_IP_ADDR_2, Instant::from_millis(0)).found(), false);
-        assert_eq!(cache.lookup(&MOCK_IP_ADDR_1, Instant::from_millis(0) + Cache::ENTRY_LIFETIME * 2).found(),
-                   false);
+        assert_eq!(
+            cache.lookup(&MOCK_IP_ADDR_1, Instant::from_millis(0)),
+            Answer::Found(HADDR_A)
+        );
+        assert_eq!(
+            cache
+                .lookup(&MOCK_IP_ADDR_2, Instant::from_millis(0))
+                .found(),
+            false
+        );
+        assert_eq!(
+            cache
+                .lookup(
+                    &MOCK_IP_ADDR_1,
+                    Instant::from_millis(0) + Cache::ENTRY_LIFETIME * 2
+                )
+                .found(),
+            false
+        );
 
         cache.fill(MOCK_IP_ADDR_1, HADDR_A, Instant::from_millis(0));
-        assert_eq!(cache.lookup(&MOCK_IP_ADDR_2, Instant::from_millis(0)).found(), false);
+        assert_eq!(
+            cache
+                .lookup(&MOCK_IP_ADDR_2, Instant::from_millis(0))
+                .found(),
+            false
+        );
     }
 
     #[test]
@@ -226,9 +276,19 @@ mod test {
         let mut cache = Cache::new(&mut cache_storage[..]);
 
         cache.fill(MOCK_IP_ADDR_1, HADDR_A, Instant::from_millis(0));
-        assert_eq!(cache.lookup(&MOCK_IP_ADDR_1, Instant::from_millis(0)), Answer::Found(HADDR_A));
-        assert_eq!(cache.lookup(&MOCK_IP_ADDR_1, Instant::from_millis(0) + Cache::ENTRY_LIFETIME * 2).found(),
-                   false);
+        assert_eq!(
+            cache.lookup(&MOCK_IP_ADDR_1, Instant::from_millis(0)),
+            Answer::Found(HADDR_A)
+        );
+        assert_eq!(
+            cache
+                .lookup(
+                    &MOCK_IP_ADDR_1,
+                    Instant::from_millis(0) + Cache::ENTRY_LIFETIME * 2
+                )
+                .found(),
+            false
+        );
     }
 
     #[test]
@@ -237,9 +297,15 @@ mod test {
         let mut cache = Cache::new(&mut cache_storage[..]);
 
         cache.fill(MOCK_IP_ADDR_1, HADDR_A, Instant::from_millis(0));
-        assert_eq!(cache.lookup(&MOCK_IP_ADDR_1, Instant::from_millis(0)), Answer::Found(HADDR_A));
+        assert_eq!(
+            cache.lookup(&MOCK_IP_ADDR_1, Instant::from_millis(0)),
+            Answer::Found(HADDR_A)
+        );
         cache.fill(MOCK_IP_ADDR_1, HADDR_B, Instant::from_millis(0));
-        assert_eq!(cache.lookup(&MOCK_IP_ADDR_1, Instant::from_millis(0)), Answer::Found(HADDR_B));
+        assert_eq!(
+            cache.lookup(&MOCK_IP_ADDR_1, Instant::from_millis(0)),
+            Answer::Found(HADDR_B)
+        );
     }
 
     #[test]
@@ -249,10 +315,20 @@ mod test {
         cache.fill(MOCK_IP_ADDR_2, HADDR_B, Instant::from_millis(50));
         // Adding third item after the expiration of the previous
         // two should garbage collect
-        cache.fill(MOCK_IP_ADDR_3, HADDR_C, Instant::from_millis(50) + Cache::ENTRY_LIFETIME * 2);
+        cache.fill(
+            MOCK_IP_ADDR_3,
+            HADDR_C,
+            Instant::from_millis(50) + Cache::ENTRY_LIFETIME * 2,
+        );
 
         assert_eq!(cache.storage.len(), 1);
-        assert_eq!(cache.lookup(&MOCK_IP_ADDR_3, Instant::from_millis(50) + Cache::ENTRY_LIFETIME * 2), Answer::Found(HADDR_C));
+        assert_eq!(
+            cache.lookup(
+                &MOCK_IP_ADDR_3,
+                Instant::from_millis(50) + Cache::ENTRY_LIFETIME * 2
+            ),
+            Answer::Found(HADDR_C)
+        );
     }
 
     #[test]
@@ -263,12 +339,28 @@ mod test {
         cache.fill(MOCK_IP_ADDR_1, HADDR_A, Instant::from_millis(100));
         cache.fill(MOCK_IP_ADDR_2, HADDR_B, Instant::from_millis(50));
         cache.fill(MOCK_IP_ADDR_3, HADDR_C, Instant::from_millis(200));
-        assert_eq!(cache.lookup(&MOCK_IP_ADDR_2, Instant::from_millis(1000)), Answer::Found(HADDR_B));
-        assert_eq!(cache.lookup(&MOCK_IP_ADDR_4, Instant::from_millis(1000)).found(), false);
+        assert_eq!(
+            cache.lookup(&MOCK_IP_ADDR_2, Instant::from_millis(1000)),
+            Answer::Found(HADDR_B)
+        );
+        assert_eq!(
+            cache
+                .lookup(&MOCK_IP_ADDR_4, Instant::from_millis(1000))
+                .found(),
+            false
+        );
 
         cache.fill(MOCK_IP_ADDR_4, HADDR_D, Instant::from_millis(300));
-        assert_eq!(cache.lookup(&MOCK_IP_ADDR_2, Instant::from_millis(1000)).found(), false);
-        assert_eq!(cache.lookup(&MOCK_IP_ADDR_4, Instant::from_millis(1000)), Answer::Found(HADDR_D));
+        assert_eq!(
+            cache
+                .lookup(&MOCK_IP_ADDR_2, Instant::from_millis(1000))
+                .found(),
+            false
+        );
+        assert_eq!(
+            cache.lookup(&MOCK_IP_ADDR_4, Instant::from_millis(1000)),
+            Answer::Found(HADDR_D)
+        );
     }
 
     #[test]
@@ -276,10 +368,19 @@ mod test {
         let mut cache_storage = [Default::default(); 3];
         let mut cache = Cache::new(&mut cache_storage[..]);
 
-        assert_eq!(cache.lookup(&MOCK_IP_ADDR_1, Instant::from_millis(0)), Answer::NotFound);
+        assert_eq!(
+            cache.lookup(&MOCK_IP_ADDR_1, Instant::from_millis(0)),
+            Answer::NotFound
+        );
 
         cache.limit_rate(Instant::from_millis(0));
-        assert_eq!(cache.lookup(&MOCK_IP_ADDR_1, Instant::from_millis(100)), Answer::RateLimited);
-        assert_eq!(cache.lookup(&MOCK_IP_ADDR_1, Instant::from_millis(2000)), Answer::NotFound);
+        assert_eq!(
+            cache.lookup(&MOCK_IP_ADDR_1, Instant::from_millis(100)),
+            Answer::RateLimited
+        );
+        assert_eq!(
+            cache.lookup(&MOCK_IP_ADDR_1, Instant::from_millis(2000)),
+            Answer::NotFound
+        );
     }
 }

+ 116 - 46
src/iface/route.rs

@@ -1,13 +1,13 @@
-use managed::ManagedMap;
 use crate::time::Instant;
 use core::ops::Bound;
+use managed::ManagedMap;
 
-use crate::{Error, Result};
-use crate::wire::{IpCidr, IpAddress};
+use crate::wire::{IpAddress, IpCidr};
 #[cfg(feature = "proto-ipv4")]
 use crate::wire::{Ipv4Address, Ipv4Cidr};
 #[cfg(feature = "proto-ipv6")]
 use crate::wire::{Ipv6Address, Ipv6Cidr};
+use crate::{Error, Result};
 
 /// A prefix of addresses that should be routed via a router
 #[derive(Debug, Clone, Copy)]
@@ -70,7 +70,9 @@ impl<'a> Routes<'a> {
     /// Creates a routing tables. The backing storage is **not** cleared
     /// upon creation.
     pub fn new<T>(storage: T) -> Routes<'a>
-            where T: Into<ManagedMap<'a, IpCidr, Route>> {
+    where
+        T: Into<ManagedMap<'a, IpCidr, Route>>,
+    {
         let storage = storage.into();
         Routes { storage }
     }
@@ -89,7 +91,7 @@ impl<'a> Routes<'a> {
         let route = Route::new_ipv4_gateway(gateway);
         match self.storage.insert(cidr, route) {
             Ok(route) => Ok(route),
-            Err((_cidr, _route)) => Err(Error::Exhausted)
+            Err((_cidr, _route)) => Err(Error::Exhausted),
         }
     }
 
@@ -102,7 +104,7 @@ impl<'a> Routes<'a> {
         let route = Route::new_ipv6_gateway(gateway);
         match self.storage.insert(cidr, route) {
             Ok(route) => Ok(route),
-            Err((_cidr, _route)) => Err(Error::Exhausted)
+            Err((_cidr, _route)) => Err(Error::Exhausted),
         }
     }
 
@@ -124,8 +126,7 @@ impl<'a> Routes<'a> {
         self.storage.remove(&cidr)
     }
 
-    pub(crate) fn lookup(&self, addr: &IpAddress, timestamp: Instant) ->
-            Option<IpAddress> {
+    pub(crate) fn lookup(&self, addr: &IpAddress, timestamp: Instant) -> Option<IpAddress> {
         assert!(addr.is_unicast());
 
         let cidr = match addr {
@@ -133,10 +134,14 @@ impl<'a> Routes<'a> {
             IpAddress::Ipv4(addr) => IpCidr::Ipv4(Ipv4Cidr::new(*addr, 32)),
             #[cfg(feature = "proto-ipv6")]
             IpAddress::Ipv6(addr) => IpCidr::Ipv6(Ipv6Cidr::new(*addr, 128)),
-            _ => unimplemented!()
+            _ => unimplemented!(),
         };
 
-        for (prefix, route) in self.storage.range((Bound::Unbounded::<IpCidr>, Bound::Included(cidr))).rev() {
+        for (prefix, route) in self
+            .storage
+            .range((Bound::Unbounded::<IpCidr>, Bound::Included(cidr)))
+            .rev()
+        {
             // TODO: do something with route.preferred_until
             if let Some(expires_at) = route.expires_at {
                 if timestamp > expires_at {
@@ -159,24 +164,28 @@ mod test {
     #[cfg(feature = "proto-ipv6")]
     mod mock {
         use super::super::*;
-        pub const ADDR_1A: Ipv6Address = Ipv6Address(
-                [0xfe, 0x80, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 1]);
-        pub const ADDR_1B: Ipv6Address = Ipv6Address(
-                [0xfe, 0x80, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 13]);
-        pub const ADDR_1C: Ipv6Address = Ipv6Address(
-                [0xfe, 0x80, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 42]);
+        pub const ADDR_1A: Ipv6Address =
+            Ipv6Address([0xfe, 0x80, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 1]);
+        pub const ADDR_1B: Ipv6Address =
+            Ipv6Address([0xfe, 0x80, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 13]);
+        pub const ADDR_1C: Ipv6Address =
+            Ipv6Address([0xfe, 0x80, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 42]);
         pub fn cidr_1() -> Ipv6Cidr {
-            Ipv6Cidr::new(Ipv6Address(
-                    [0xfe, 0x80, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0]), 64)
+            Ipv6Cidr::new(
+                Ipv6Address([0xfe, 0x80, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0]),
+                64,
+            )
         }
 
-        pub const ADDR_2A: Ipv6Address = Ipv6Address(
-                [0xfe, 0x80, 0, 0, 0, 0, 51, 100, 0, 0, 0, 0, 0, 0, 0, 1]);
-        pub const ADDR_2B: Ipv6Address = Ipv6Address(
-                [0xfe, 0x80, 0, 0, 0, 0, 51, 100, 0, 0, 0, 0, 0, 0, 0, 21]);
+        pub const ADDR_2A: Ipv6Address =
+            Ipv6Address([0xfe, 0x80, 0, 0, 0, 0, 51, 100, 0, 0, 0, 0, 0, 0, 0, 1]);
+        pub const ADDR_2B: Ipv6Address =
+            Ipv6Address([0xfe, 0x80, 0, 0, 0, 0, 51, 100, 0, 0, 0, 0, 0, 0, 0, 21]);
         pub fn cidr_2() -> Ipv6Cidr {
-            Ipv6Cidr::new(Ipv6Address(
-                    [0xfe, 0x80, 0, 0, 0, 0, 51, 100, 0, 0, 0, 0, 0, 0, 0, 0]), 64)
+            Ipv6Cidr::new(
+                Ipv6Address([0xfe, 0x80, 0, 0, 0, 0, 51, 100, 0, 0, 0, 0, 0, 0, 0, 0]),
+                64,
+            )
         }
     }
 
@@ -204,25 +213,56 @@ mod test {
         let mut routes_storage = [None, None, None];
         let mut routes = Routes::new(&mut routes_storage[..]);
 
-        assert_eq!(routes.lookup(&ADDR_1A.into(), Instant::from_millis(0)), None);
-        assert_eq!(routes.lookup(&ADDR_1B.into(), Instant::from_millis(0)), None);
-        assert_eq!(routes.lookup(&ADDR_1C.into(), Instant::from_millis(0)), None);
-        assert_eq!(routes.lookup(&ADDR_2A.into(), Instant::from_millis(0)), None);
-        assert_eq!(routes.lookup(&ADDR_2B.into(), Instant::from_millis(0)), None);
+        assert_eq!(
+            routes.lookup(&ADDR_1A.into(), Instant::from_millis(0)),
+            None
+        );
+        assert_eq!(
+            routes.lookup(&ADDR_1B.into(), Instant::from_millis(0)),
+            None
+        );
+        assert_eq!(
+            routes.lookup(&ADDR_1C.into(), Instant::from_millis(0)),
+            None
+        );
+        assert_eq!(
+            routes.lookup(&ADDR_2A.into(), Instant::from_millis(0)),
+            None
+        );
+        assert_eq!(
+            routes.lookup(&ADDR_2B.into(), Instant::from_millis(0)),
+            None
+        );
 
         let route = Route {
             via_router: ADDR_1A.into(),
-            preferred_until: None, expires_at: None,
+            preferred_until: None,
+            expires_at: None,
         };
         routes.update(|storage| {
             storage.insert(cidr_1().into(), route).unwrap();
         });
 
-        assert_eq!(routes.lookup(&ADDR_1A.into(), Instant::from_millis(0)), Some(ADDR_1A.into()));
-        assert_eq!(routes.lookup(&ADDR_1B.into(), Instant::from_millis(0)), Some(ADDR_1A.into()));
-        assert_eq!(routes.lookup(&ADDR_1C.into(), Instant::from_millis(0)), Some(ADDR_1A.into()));
-        assert_eq!(routes.lookup(&ADDR_2A.into(), Instant::from_millis(0)), None);
-        assert_eq!(routes.lookup(&ADDR_2B.into(), Instant::from_millis(0)), None);
+        assert_eq!(
+            routes.lookup(&ADDR_1A.into(), Instant::from_millis(0)),
+            Some(ADDR_1A.into())
+        );
+        assert_eq!(
+            routes.lookup(&ADDR_1B.into(), Instant::from_millis(0)),
+            Some(ADDR_1A.into())
+        );
+        assert_eq!(
+            routes.lookup(&ADDR_1C.into(), Instant::from_millis(0)),
+            Some(ADDR_1A.into())
+        );
+        assert_eq!(
+            routes.lookup(&ADDR_2A.into(), Instant::from_millis(0)),
+            None
+        );
+        assert_eq!(
+            routes.lookup(&ADDR_2B.into(), Instant::from_millis(0)),
+            None
+        );
 
         let route2 = Route {
             via_router: ADDR_2A.into(),
@@ -233,16 +273,46 @@ mod test {
             storage.insert(cidr_2().into(), route2).unwrap();
         });
 
-        assert_eq!(routes.lookup(&ADDR_1A.into(), Instant::from_millis(0)), Some(ADDR_1A.into()));
-        assert_eq!(routes.lookup(&ADDR_1B.into(), Instant::from_millis(0)), Some(ADDR_1A.into()));
-        assert_eq!(routes.lookup(&ADDR_1C.into(), Instant::from_millis(0)), Some(ADDR_1A.into()));
-        assert_eq!(routes.lookup(&ADDR_2A.into(), Instant::from_millis(0)), Some(ADDR_2A.into()));
-        assert_eq!(routes.lookup(&ADDR_2B.into(), Instant::from_millis(0)), Some(ADDR_2A.into()));
-
-        assert_eq!(routes.lookup(&ADDR_1A.into(), Instant::from_millis(10)), Some(ADDR_1A.into()));
-        assert_eq!(routes.lookup(&ADDR_1B.into(), Instant::from_millis(10)), Some(ADDR_1A.into()));
-        assert_eq!(routes.lookup(&ADDR_1C.into(), Instant::from_millis(10)), Some(ADDR_1A.into()));
-        assert_eq!(routes.lookup(&ADDR_2A.into(), Instant::from_millis(10)), Some(ADDR_2A.into()));
-        assert_eq!(routes.lookup(&ADDR_2B.into(), Instant::from_millis(10)), Some(ADDR_2A.into()));
+        assert_eq!(
+            routes.lookup(&ADDR_1A.into(), Instant::from_millis(0)),
+            Some(ADDR_1A.into())
+        );
+        assert_eq!(
+            routes.lookup(&ADDR_1B.into(), Instant::from_millis(0)),
+            Some(ADDR_1A.into())
+        );
+        assert_eq!(
+            routes.lookup(&ADDR_1C.into(), Instant::from_millis(0)),
+            Some(ADDR_1A.into())
+        );
+        assert_eq!(
+            routes.lookup(&ADDR_2A.into(), Instant::from_millis(0)),
+            Some(ADDR_2A.into())
+        );
+        assert_eq!(
+            routes.lookup(&ADDR_2B.into(), Instant::from_millis(0)),
+            Some(ADDR_2A.into())
+        );
+
+        assert_eq!(
+            routes.lookup(&ADDR_1A.into(), Instant::from_millis(10)),
+            Some(ADDR_1A.into())
+        );
+        assert_eq!(
+            routes.lookup(&ADDR_1B.into(), Instant::from_millis(10)),
+            Some(ADDR_1A.into())
+        );
+        assert_eq!(
+            routes.lookup(&ADDR_1C.into(), Instant::from_millis(10)),
+            Some(ADDR_1A.into())
+        );
+        assert_eq!(
+            routes.lookup(&ADDR_2A.into(), Instant::from_millis(10)),
+            Some(ADDR_2A.into())
+        );
+        assert_eq!(
+            routes.lookup(&ADDR_2B.into(), Instant::from_millis(10)),
+            Some(ADDR_2A.into())
+        );
     }
 }

+ 20 - 17
src/lib.rs

@@ -1,6 +1,12 @@
 #![cfg_attr(not(any(test, feature = "std")), no_std)]
 #![deny(unsafe_code)]
-#![cfg_attr(all(any(feature = "proto-ipv4", feature = "proto-ipv6"), feature = "medium-ethernet"), deny(unused))]
+#![cfg_attr(
+    all(
+        any(feature = "proto-ipv4", feature = "proto-ipv6"),
+        feature = "medium-ethernet"
+    ),
+    deny(unused)
+)]
 
 //! The _smoltcp_ library is built in a layered structure, with the layers corresponding
 //! to the levels of API abstraction. Only the highest layers would be used by a typical
@@ -107,10 +113,7 @@ compile_error!("If you enable the socket feature, you must enable at least one o
 
 #[cfg(all(
     feature = "socket",
-    not(any(
-        feature = "medium-ethernet",
-        feature = "medium-ip",
-    ))
+    not(any(feature = "medium-ethernet", feature = "medium-ip",))
 ))]
 compile_error!("If you enable the socket feature, you must enable at least one of the following features: medium-ip, medium-ethernet");
 
@@ -123,13 +126,13 @@ use core::fmt;
 mod macros;
 mod parsers;
 
-pub mod storage;
-pub mod phy;
-pub mod wire;
 pub mod iface;
+pub mod phy;
 #[cfg(feature = "socket")]
 pub mod socket;
+pub mod storage;
 pub mod time;
+pub mod wire;
 
 /// The error type for the networking stack.
 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
@@ -178,16 +181,16 @@ pub type Result<T> = core::result::Result<T, Error>;
 impl fmt::Display for Error {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match *self {
-            Error::Exhausted     => write!(f, "buffer space exhausted"),
-            Error::Illegal       => write!(f, "illegal operation"),
+            Error::Exhausted => write!(f, "buffer space exhausted"),
+            Error::Illegal => write!(f, "illegal operation"),
             Error::Unaddressable => write!(f, "unaddressable destination"),
-            Error::Finished      => write!(f, "operation finished"),
-            Error::Truncated     => write!(f, "truncated packet"),
-            Error::Checksum      => write!(f, "checksum error"),
-            Error::Unrecognized  => write!(f, "unrecognized packet"),
-            Error::Fragmented    => write!(f, "fragmented packet"),
-            Error::Malformed     => write!(f, "malformed packet"),
-            Error::Dropped       => write!(f, "dropped by socket"),
+            Error::Finished => write!(f, "operation finished"),
+            Error::Truncated => write!(f, "truncated packet"),
+            Error::Checksum => write!(f, "checksum error"),
+            Error::Unrecognized => write!(f, "unrecognized packet"),
+            Error::Fragmented => write!(f, "fragmented packet"),
+            Error::Malformed => write!(f, "malformed packet"),
+            Error::Dropped => write!(f, "dropped by socket"),
         }
     }
 }

+ 0 - 1
src/macros.rs

@@ -1,4 +1,3 @@
-
 #[cfg(feature = "log")]
 macro_rules! net_log {
     (trace, $($arg:expr),*) => { log::trace!($($arg),*); };

+ 216 - 130
src/parsers.rs

@@ -1,7 +1,10 @@
-#![cfg_attr(not(all(feature = "proto-ipv6", feature = "proto-ipv4")), allow(dead_code))]
+#![cfg_attr(
+    not(all(feature = "proto-ipv6", feature = "proto-ipv4")),
+    allow(dead_code)
+)]
 
-use core::str::FromStr;
 use core::result;
+use core::str::FromStr;
 
 #[cfg(feature = "medium-ethernet")]
 use crate::wire::EthernetAddress;
@@ -15,14 +18,14 @@ type Result<T> = result::Result<T, ()>;
 
 struct Parser<'a> {
     data: &'a [u8],
-    pos:  usize
+    pos: usize,
 }
 
 impl<'a> Parser<'a> {
     fn new(data: &'a str) -> Parser<'a> {
         Parser {
             data: data.as_bytes(),
-            pos:  0
+            pos: 0,
         }
     }
 
@@ -40,12 +43,14 @@ impl<'a> Parser<'a> {
                 self.pos += 1;
                 Ok(chr)
             }
-            None => Err(())
+            None => Err(()),
         }
     }
 
     fn try_do<F, T>(&mut self, f: F) -> Option<T>
-            where F: FnOnce(&mut Parser<'a>) -> Result<T> {
+    where
+        F: FnOnce(&mut Parser<'a>) -> Result<T>,
+    {
         let pos = self.pos;
         match f(self) {
             Ok(res) => Some(res),
@@ -65,7 +70,9 @@ impl<'a> Parser<'a> {
     }
 
     fn until_eof<F, T>(&mut self, f: F) -> Result<T>
-            where F: FnOnce(&mut Parser<'a>) -> Result<T> {
+    where
+        F: FnOnce(&mut Parser<'a>) -> Result<T>,
+    {
         let res = f(self)?;
         self.accept_eof()?;
         Ok(res)
@@ -99,8 +106,7 @@ impl<'a> Parser<'a> {
         }
     }
 
-    fn accept_number(&mut self, max_digits: usize, max_value: u32,
-                     hex: bool) -> Result<u32> {
+    fn accept_number(&mut self, max_digits: usize, max_value: u32, hex: bool) -> Result<u32> {
         let mut value = self.accept_digit(hex)? as u32;
         for _ in 1..max_digits {
             match self.try_do(|p| p.accept_digit(hex)) {
@@ -108,7 +114,7 @@ impl<'a> Parser<'a> {
                     value *= if hex { 16 } else { 10 };
                     value += digit as u32;
                 }
-                None => break
+                None => break,
             }
         }
         if value < max_value {
@@ -133,10 +139,10 @@ impl<'a> Parser<'a> {
     #[cfg(feature = "medium-ethernet")]
     fn accept_mac(&mut self) -> Result<EthernetAddress> {
         if let Some(mac) = self.try_do(|p| p.accept_mac_joined_with(b'-')) {
-            return Ok(mac)
+            return Ok(mac);
         }
         if let Some(mac) = self.try_do(|p| p.accept_mac_joined_with(b':')) {
-            return Ok(mac)
+            return Ok(mac);
         }
         Err(())
     }
@@ -154,9 +160,13 @@ impl<'a> Parser<'a> {
     }
 
     #[cfg(feature = "proto-ipv6")]
-    fn accept_ipv6_part(&mut self, (head, tail): (&mut [u16; 8], &mut [u16; 6]),
-                        (head_idx, tail_idx): (&mut usize, &mut usize),
-                        mut use_tail: bool, is_cidr: bool) -> Result<()> {
+    fn accept_ipv6_part(
+        &mut self,
+        (head, tail): (&mut [u16; 8], &mut [u16; 6]),
+        (head_idx, tail_idx): (&mut usize, &mut usize),
+        mut use_tail: bool,
+        is_cidr: bool,
+    ) -> Result<()> {
         let double_colon = match self.try_do(|p| p.accept_str(b"::")) {
             Some(_) if !use_tail && *head_idx < 7 => {
                 // Found a double colon. Start filling out the
@@ -164,7 +174,7 @@ impl<'a> Parser<'a> {
                 // this is the last character we can parse.
                 use_tail = true;
                 true
-            },
+            }
             Some(_) => {
                 // This is a bad address. Only one double colon is
                 // allowed and an address is only 128 bits.
@@ -193,21 +203,20 @@ impl<'a> Parser<'a> {
                     });
                 }
                 Ok(())
-            },
+            }
             Some(part) if *tail_idx < 6 => {
                 // Valid u16 to be added to the address
                 tail[*tail_idx] = part as u16;
                 *tail_idx += 1;
 
-                if *tail_idx == 1 && tail[0] == 0xffff
-                        && head[0..8] == [0, 0, 0, 0, 0, 0, 0, 0] {
+                if *tail_idx == 1 && tail[0] == 0xffff && head[0..8] == [0, 0, 0, 0, 0, 0, 0, 0] {
                     self.try_do(|p| {
                         p.accept_char(b':')?;
                         p.accept_ipv4_mapped_ipv6_part(tail, tail_idx)
                     });
                 }
                 Ok(())
-            },
+            }
             Some(_) => {
                 // Tail or head section is too long
                 Err(())
@@ -259,7 +268,12 @@ impl<'a> Parser<'a> {
         let (mut addr, mut tail) = ([0u16; 8], [0u16; 6]);
         let (mut head_idx, mut tail_idx) = (0, 0);
 
-        self.accept_ipv6_part((&mut addr, &mut tail), (&mut head_idx, &mut tail_idx), false, is_cidr)?;
+        self.accept_ipv6_part(
+            (&mut addr, &mut tail),
+            (&mut head_idx, &mut tail_idx),
+            false,
+            is_cidr,
+        )?;
 
         // We need to copy the tail portion (the portion following the "::") to the
         // end of the address.
@@ -290,14 +304,14 @@ impl<'a> Parser<'a> {
         #[allow(clippy::single_match)]
         match self.try_do(|p| p.accept_ipv4()) {
             Some(ipv4) => return Ok(IpAddress::Ipv4(ipv4)),
-            None => ()
+            None => (),
         }
 
         #[cfg(feature = "proto-ipv6")]
         #[allow(clippy::single_match)]
         match self.try_do(|p| p.accept_ipv6(false)) {
             Some(ipv6) => return Ok(IpAddress::Ipv6(ipv6)),
-            None => ()
+            None => (),
         }
 
         Err(())
@@ -314,7 +328,10 @@ impl<'a> Parser<'a> {
             self.accept_number(5, 65535, false)?
         };
 
-        Ok(IpEndpoint { addr: IpAddress::Ipv4(ip), port: port as u16 })
+        Ok(IpEndpoint {
+            addr: IpAddress::Ipv4(ip),
+            port: port as u16,
+        })
     }
 
     #[cfg(feature = "proto-ipv6")]
@@ -326,10 +343,16 @@ impl<'a> Parser<'a> {
             self.accept_char(b':')?;
             let port = self.accept_number(5, 65535, false)?;
 
-            Ok(IpEndpoint { addr: IpAddress::Ipv6(ip), port: port as u16 })
+            Ok(IpEndpoint {
+                addr: IpAddress::Ipv6(ip),
+                port: port as u16,
+            })
         } else {
             let ip = self.accept_ipv6(false)?;
-            Ok(IpEndpoint { addr: IpAddress::Ipv6(ip), port: 0 })
+            Ok(IpEndpoint {
+                addr: IpAddress::Ipv6(ip),
+                port: 0,
+            })
         }
     }
 
@@ -338,14 +361,14 @@ impl<'a> Parser<'a> {
         #[allow(clippy::single_match)]
         match self.try_do(|p| p.accept_ipv4_endpoint()) {
             Some(ipv4) => return Ok(ipv4),
-            None => ()
+            None => (),
         }
 
         #[cfg(feature = "proto-ipv6")]
         #[allow(clippy::single_match)]
         match self.try_do(|p| p.accept_ipv6_endpoint()) {
             Some(ipv6) => return Ok(ipv6),
-            None => ()
+            None => (),
         }
 
         Err(())
@@ -431,14 +454,14 @@ impl FromStr for IpCidr {
         #[allow(clippy::single_match)]
         match Ipv4Cidr::from_str(s) {
             Ok(cidr) => return Ok(IpCidr::Ipv4(cidr)),
-            Err(_) => ()
+            Err(_) => (),
         }
 
         #[cfg(feature = "proto-ipv6")]
         #[allow(clippy::single_match)]
         match Ipv6Cidr::from_str(s) {
             Ok(cidr) => return Ok(IpCidr::Ipv6(cidr)),
-            Err(_) => ()
+            Err(_) => (),
         }
 
         Err(())
@@ -449,7 +472,7 @@ impl FromStr for IpEndpoint {
     type Err = ();
 
     fn from_str(s: &str) -> Result<IpEndpoint> {
-        Parser::new(s).until_eof(|p| Ok(p.accept_ip_endpoint()?))
+        Parser::new(s).until_eof(|p| p.accept_ip_endpoint())
     }
 }
 
@@ -465,29 +488,40 @@ mod test {
 
                 if let Ok(cidr) = cidr {
                     assert_eq!($from_str(&format!("{}", cidr)), Ok(cidr));
-                    assert_eq!(IpCidr::from_str(&format!("{}", cidr)),
-                               Ok($variant(cidr)));
+                    assert_eq!(IpCidr::from_str(&format!("{}", cidr)), Ok($variant(cidr)));
                 }
             }
-        }
+        };
     }
 
     #[test]
     #[cfg(all(feature = "proto-ipv4", feature = "medium-ethernet"))]
     fn test_mac() {
         assert_eq!(EthernetAddress::from_str(""), Err(()));
-        assert_eq!(EthernetAddress::from_str("02:00:00:00:00:00"),
-                   Ok(EthernetAddress([0x02, 0x00, 0x00, 0x00, 0x00, 0x00])));
-        assert_eq!(EthernetAddress::from_str("01:23:45:67:89:ab"),
-                   Ok(EthernetAddress([0x01, 0x23, 0x45, 0x67, 0x89, 0xab])));
-        assert_eq!(EthernetAddress::from_str("cd:ef:10:00:00:00"),
-                   Ok(EthernetAddress([0xcd, 0xef, 0x10, 0x00, 0x00, 0x00])));
-        assert_eq!(EthernetAddress::from_str("00:00:00:ab:cd:ef"),
-                   Ok(EthernetAddress([0x00, 0x00, 0x00, 0xab, 0xcd, 0xef])));
-        assert_eq!(EthernetAddress::from_str("00-00-00-ab-cd-ef"),
-                   Ok(EthernetAddress([0x00, 0x00, 0x00, 0xab, 0xcd, 0xef])));
-        assert_eq!(EthernetAddress::from_str("AB-CD-EF-00-00-00"),
-                   Ok(EthernetAddress([0xab, 0xcd, 0xef, 0x00, 0x00, 0x00])));
+        assert_eq!(
+            EthernetAddress::from_str("02:00:00:00:00:00"),
+            Ok(EthernetAddress([0x02, 0x00, 0x00, 0x00, 0x00, 0x00]))
+        );
+        assert_eq!(
+            EthernetAddress::from_str("01:23:45:67:89:ab"),
+            Ok(EthernetAddress([0x01, 0x23, 0x45, 0x67, 0x89, 0xab]))
+        );
+        assert_eq!(
+            EthernetAddress::from_str("cd:ef:10:00:00:00"),
+            Ok(EthernetAddress([0xcd, 0xef, 0x10, 0x00, 0x00, 0x00]))
+        );
+        assert_eq!(
+            EthernetAddress::from_str("00:00:00:ab:cd:ef"),
+            Ok(EthernetAddress([0x00, 0x00, 0x00, 0xab, 0xcd, 0xef]))
+        );
+        assert_eq!(
+            EthernetAddress::from_str("00-00-00-ab-cd-ef"),
+            Ok(EthernetAddress([0x00, 0x00, 0x00, 0xab, 0xcd, 0xef]))
+        );
+        assert_eq!(
+            EthernetAddress::from_str("AB-CD-EF-00-00-00"),
+            Ok(EthernetAddress([0xab, 0xcd, 0xef, 0x00, 0x00, 0x00]))
+        );
         assert_eq!(EthernetAddress::from_str("100:00:00:00:00:00"), Err(()));
         assert_eq!(EthernetAddress::from_str("002:00:00:00:00:00"), Err(()));
         assert_eq!(EthernetAddress::from_str("02:00:00:00:00:000"), Err(()));
@@ -498,10 +532,14 @@ mod test {
     #[cfg(feature = "proto-ipv4")]
     fn test_ipv4() {
         assert_eq!(Ipv4Address::from_str(""), Err(()));
-        assert_eq!(Ipv4Address::from_str("1.2.3.4"),
-                   Ok(Ipv4Address([1, 2, 3, 4])));
-        assert_eq!(Ipv4Address::from_str("001.2.3.4"),
-                   Ok(Ipv4Address([1, 2, 3, 4])));
+        assert_eq!(
+            Ipv4Address::from_str("1.2.3.4"),
+            Ok(Ipv4Address([1, 2, 3, 4]))
+        );
+        assert_eq!(
+            Ipv4Address::from_str("001.2.3.4"),
+            Ok(Ipv4Address([1, 2, 3, 4]))
+        );
         assert_eq!(Ipv4Address::from_str("0001.2.3.4"), Err(()));
         assert_eq!(Ipv4Address::from_str("999.2.3.4"), Err(()));
         assert_eq!(Ipv4Address::from_str("1.2.3.4.5"), Err(()));
@@ -515,73 +553,87 @@ mod test {
     fn test_ipv6() {
         // Obviously not valid
         assert_eq!(Ipv6Address::from_str(""), Err(()));
-        assert_eq!(Ipv6Address::from_str("fe80:0:0:0:0:0:0:1"),
-                   Ok(Ipv6Address::new(0xfe80, 0, 0, 0, 0, 0, 0, 1)));
-        assert_eq!(Ipv6Address::from_str("::1"),
-                   Ok(Ipv6Address::LOOPBACK));
-        assert_eq!(Ipv6Address::from_str("::"),
-                   Ok(Ipv6Address::UNSPECIFIED));
-        assert_eq!(Ipv6Address::from_str("fe80::1"),
-                   Ok(Ipv6Address::new(0xfe80, 0, 0, 0, 0, 0, 0, 1)));
-        assert_eq!(Ipv6Address::from_str("1234:5678::"),
-                   Ok(Ipv6Address::new(0x1234, 0x5678, 0, 0, 0, 0, 0, 0)));
-        assert_eq!(Ipv6Address::from_str("1234:5678::8765:4321"),
-                   Ok(Ipv6Address::new(0x1234, 0x5678, 0, 0, 0, 0, 0x8765, 0x4321)));
+        assert_eq!(
+            Ipv6Address::from_str("fe80:0:0:0:0:0:0:1"),
+            Ok(Ipv6Address::new(0xfe80, 0, 0, 0, 0, 0, 0, 1))
+        );
+        assert_eq!(Ipv6Address::from_str("::1"), Ok(Ipv6Address::LOOPBACK));
+        assert_eq!(Ipv6Address::from_str("::"), Ok(Ipv6Address::UNSPECIFIED));
+        assert_eq!(
+            Ipv6Address::from_str("fe80::1"),
+            Ok(Ipv6Address::new(0xfe80, 0, 0, 0, 0, 0, 0, 1))
+        );
+        assert_eq!(
+            Ipv6Address::from_str("1234:5678::"),
+            Ok(Ipv6Address::new(0x1234, 0x5678, 0, 0, 0, 0, 0, 0))
+        );
+        assert_eq!(
+            Ipv6Address::from_str("1234:5678::8765:4321"),
+            Ok(Ipv6Address::new(0x1234, 0x5678, 0, 0, 0, 0, 0x8765, 0x4321))
+        );
         // Two double colons in address
-        assert_eq!(Ipv6Address::from_str("1234:5678::1::1"),
-                   Err(()));
-        assert_eq!(Ipv6Address::from_str("4444:333:22:1::4"),
-                   Ok(Ipv6Address::new(0x4444, 0x0333, 0x0022, 0x0001, 0, 0, 0, 4)));
-        assert_eq!(Ipv6Address::from_str("1:1:1:1:1:1::"),
-                   Ok(Ipv6Address::new(1, 1, 1, 1, 1, 1, 0, 0)));
-        assert_eq!(Ipv6Address::from_str("::1:1:1:1:1:1"),
-                   Ok(Ipv6Address::new(0, 0, 1, 1, 1, 1, 1, 1)));
-        assert_eq!(Ipv6Address::from_str("::1:1:1:1:1:1:1"),
-                   Err(()));
+        assert_eq!(Ipv6Address::from_str("1234:5678::1::1"), Err(()));
+        assert_eq!(
+            Ipv6Address::from_str("4444:333:22:1::4"),
+            Ok(Ipv6Address::new(0x4444, 0x0333, 0x0022, 0x0001, 0, 0, 0, 4))
+        );
+        assert_eq!(
+            Ipv6Address::from_str("1:1:1:1:1:1::"),
+            Ok(Ipv6Address::new(1, 1, 1, 1, 1, 1, 0, 0))
+        );
+        assert_eq!(
+            Ipv6Address::from_str("::1:1:1:1:1:1"),
+            Ok(Ipv6Address::new(0, 0, 1, 1, 1, 1, 1, 1))
+        );
+        assert_eq!(Ipv6Address::from_str("::1:1:1:1:1:1:1"), Err(()));
         // Double colon appears too late indicating an address that is too long
-        assert_eq!(Ipv6Address::from_str("1:1:1:1:1:1:1::"),
-                   Err(()));
+        assert_eq!(Ipv6Address::from_str("1:1:1:1:1:1:1::"), Err(()));
         // Section after double colon is too long for a valid address
-        assert_eq!(Ipv6Address::from_str("::1:1:1:1:1:1:1"),
-                   Err(()));
+        assert_eq!(Ipv6Address::from_str("::1:1:1:1:1:1:1"), Err(()));
         // Obviously too long
-        assert_eq!(Ipv6Address::from_str("1:1:1:1:1:1:1:1:1"),
-                   Err(()));
+        assert_eq!(Ipv6Address::from_str("1:1:1:1:1:1:1:1:1"), Err(()));
         // Address is too short
-        assert_eq!(Ipv6Address::from_str("1:1:1:1:1:1:1"),
-                   Err(()));
+        assert_eq!(Ipv6Address::from_str("1:1:1:1:1:1:1"), Err(()));
         // Long number
-        assert_eq!(Ipv6Address::from_str("::000001"),
-                   Err(()));
+        assert_eq!(Ipv6Address::from_str("::000001"), Err(()));
         // IPv4-Mapped address
-        assert_eq!(Ipv6Address::from_str("::ffff:192.168.1.1"),
-                   Ok(Ipv6Address([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, 192, 168, 1, 1])));
-        assert_eq!(Ipv6Address::from_str("0:0:0:0:0:ffff:192.168.1.1"),
-                   Ok(Ipv6Address([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, 192, 168, 1, 1])));
-        assert_eq!(Ipv6Address::from_str("0::ffff:192.168.1.1"),
-                   Ok(Ipv6Address([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, 192, 168, 1, 1])));
+        assert_eq!(
+            Ipv6Address::from_str("::ffff:192.168.1.1"),
+            Ok(Ipv6Address([
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, 192, 168, 1, 1
+            ]))
+        );
+        assert_eq!(
+            Ipv6Address::from_str("0:0:0:0:0:ffff:192.168.1.1"),
+            Ok(Ipv6Address([
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, 192, 168, 1, 1
+            ]))
+        );
+        assert_eq!(
+            Ipv6Address::from_str("0::ffff:192.168.1.1"),
+            Ok(Ipv6Address([
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, 192, 168, 1, 1
+            ]))
+        );
         // Only ffff is allowed in position 6 when IPv4 mapped
-        assert_eq!(Ipv6Address::from_str("0:0:0:0:0:eeee:192.168.1.1"),
-                   Err(()));
+        assert_eq!(Ipv6Address::from_str("0:0:0:0:0:eeee:192.168.1.1"), Err(()));
         // Positions 1-5 must be 0 when IPv4 mapped
-        assert_eq!(Ipv6Address::from_str("0:0:0:0:1:ffff:192.168.1.1"),
-                   Err(()));
-        assert_eq!(Ipv6Address::from_str("1::ffff:192.168.1.1"),
-                   Err(()));
+        assert_eq!(Ipv6Address::from_str("0:0:0:0:1:ffff:192.168.1.1"), Err(()));
+        assert_eq!(Ipv6Address::from_str("1::ffff:192.168.1.1"), Err(()));
         // Out of range ipv4 octet
-        assert_eq!(Ipv6Address::from_str("0:0:0:0:0:ffff:256.168.1.1"),
-                   Err(()));
+        assert_eq!(Ipv6Address::from_str("0:0:0:0:0:ffff:256.168.1.1"), Err(()));
         // Invalid hex in ipv4 octet
-        assert_eq!(Ipv6Address::from_str("0:0:0:0:0:ffff:c0.168.1.1"),
-                   Err(()));
+        assert_eq!(Ipv6Address::from_str("0:0:0:0:0:ffff:c0.168.1.1"), Err(()));
     }
 
     #[test]
     #[cfg(feature = "proto-ipv4")]
     fn test_ip_ipv4() {
         assert_eq!(IpAddress::from_str(""), Err(()));
-        assert_eq!(IpAddress::from_str("1.2.3.4"),
-                   Ok(IpAddress::Ipv4(Ipv4Address([1, 2, 3, 4]))));
+        assert_eq!(
+            IpAddress::from_str("1.2.3.4"),
+            Ok(IpAddress::Ipv4(Ipv4Address([1, 2, 3, 4])))
+        );
         assert_eq!(IpAddress::from_str("x"), Err(()));
     }
 
@@ -589,8 +641,12 @@ mod test {
     #[cfg(feature = "proto-ipv6")]
     fn test_ip_ipv6() {
         assert_eq!(IpAddress::from_str(""), Err(()));
-        assert_eq!(IpAddress::from_str("fe80::1"),
-                   Ok(IpAddress::Ipv6(Ipv6Address::new(0xfe80, 0, 0, 0, 0, 0, 0, 1))));
+        assert_eq!(
+            IpAddress::from_str("fe80::1"),
+            Ok(IpAddress::Ipv6(Ipv6Address::new(
+                0xfe80, 0, 0, 0, 0, 0, 0, 1
+            )))
+        );
         assert_eq!(IpAddress::from_str("x"), Err(()));
     }
 
@@ -598,14 +654,22 @@ mod test {
     #[cfg(feature = "proto-ipv4")]
     fn test_cidr_ipv4() {
         let tests = [
-            ("127.0.0.1/8",
-             Ok(Ipv4Cidr::new(Ipv4Address([127, 0, 0, 1]), 8u8))),
-            ("192.168.1.1/24",
-             Ok(Ipv4Cidr::new(Ipv4Address([192, 168, 1, 1]), 24u8))),
-            ("8.8.8.8/32",
-             Ok(Ipv4Cidr::new(Ipv4Address([8, 8, 8, 8]), 32u8))),
-            ("8.8.8.8/0",
-             Ok(Ipv4Cidr::new(Ipv4Address([8, 8, 8, 8]), 0u8))),
+            (
+                "127.0.0.1/8",
+                Ok(Ipv4Cidr::new(Ipv4Address([127, 0, 0, 1]), 8u8)),
+            ),
+            (
+                "192.168.1.1/24",
+                Ok(Ipv4Cidr::new(Ipv4Address([192, 168, 1, 1]), 24u8)),
+            ),
+            (
+                "8.8.8.8/32",
+                Ok(Ipv4Cidr::new(Ipv4Address([8, 8, 8, 8]), 32u8)),
+            ),
+            (
+                "8.8.8.8/0",
+                Ok(Ipv4Cidr::new(Ipv4Address([8, 8, 8, 8]), 0u8)),
+            ),
             ("", Err(())),
             ("1", Err(())),
             ("127.0.0.1", Err(())),
@@ -622,22 +686,32 @@ mod test {
     #[cfg(feature = "proto-ipv6")]
     fn test_cidr_ipv6() {
         let tests = [
-            ("fe80::1/64",
-             Ok(Ipv6Cidr::new(Ipv6Address::new(0xfe80, 0, 0, 0, 0, 0, 0, 1), 64u8))),
-            ("fe80::/64",
-             Ok(Ipv6Cidr::new(Ipv6Address::new(0xfe80, 0, 0, 0, 0, 0, 0, 0), 64u8))),
-            ("::1/128",
-             Ok(Ipv6Cidr::new(Ipv6Address::LOOPBACK, 128u8))),
-            ("::/128",
-             Ok(Ipv6Cidr::new(Ipv6Address::UNSPECIFIED, 128u8))),
-            ("fe80:0:0:0:0:0:0:1/64",
-             Ok(Ipv6Cidr::new(Ipv6Address::new(0xfe80, 0, 0, 0, 0, 0, 0, 1), 64u8))),
-            ("fe80:0:0:0:0:0:0:1|64",
-             Err(())),
-            ("fe80::|64",
-             Err(())),
-            ("fe80::1::/64",
-             Err(()))
+            (
+                "fe80::1/64",
+                Ok(Ipv6Cidr::new(
+                    Ipv6Address::new(0xfe80, 0, 0, 0, 0, 0, 0, 1),
+                    64u8,
+                )),
+            ),
+            (
+                "fe80::/64",
+                Ok(Ipv6Cidr::new(
+                    Ipv6Address::new(0xfe80, 0, 0, 0, 0, 0, 0, 0),
+                    64u8,
+                )),
+            ),
+            ("::1/128", Ok(Ipv6Cidr::new(Ipv6Address::LOOPBACK, 128u8))),
+            ("::/128", Ok(Ipv6Cidr::new(Ipv6Address::UNSPECIFIED, 128u8))),
+            (
+                "fe80:0:0:0:0:0:0:1/64",
+                Ok(Ipv6Cidr::new(
+                    Ipv6Address::new(0xfe80, 0, 0, 0, 0, 0, 0, 1),
+                    64u8,
+                )),
+            ),
+            ("fe80:0:0:0:0:0:0:1|64", Err(())),
+            ("fe80::|64", Err(())),
+            ("fe80::1::/64", Err(())),
         ];
         check_cidr_test_array!(tests, Ipv6Cidr::from_str, IpCidr::Ipv6);
     }
@@ -649,11 +723,17 @@ mod test {
         assert_eq!(IpEndpoint::from_str("x"), Err(()));
         assert_eq!(
             IpEndpoint::from_str("127.0.0.1"),
-            Ok(IpEndpoint { addr: IpAddress::v4(127, 0, 0, 1), port: 0 })
+            Ok(IpEndpoint {
+                addr: IpAddress::v4(127, 0, 0, 1),
+                port: 0
+            })
         );
         assert_eq!(
             IpEndpoint::from_str("127.0.0.1:12345"),
-            Ok(IpEndpoint { addr: IpAddress::v4(127, 0, 0, 1), port: 12345 })
+            Ok(IpEndpoint {
+                addr: IpAddress::v4(127, 0, 0, 1),
+                port: 12345
+            })
         );
     }
 
@@ -664,11 +744,17 @@ mod test {
         assert_eq!(IpEndpoint::from_str("x"), Err(()));
         assert_eq!(
             IpEndpoint::from_str("fe80::1"),
-            Ok(IpEndpoint { addr: IpAddress::v6(0xfe80, 0, 0, 0, 0, 0, 0, 1), port: 0 })
+            Ok(IpEndpoint {
+                addr: IpAddress::v6(0xfe80, 0, 0, 0, 0, 0, 0, 1),
+                port: 0
+            })
         );
         assert_eq!(
             IpEndpoint::from_str("[fe80::1]:12345"),
-            Ok(IpEndpoint { addr: IpAddress::v6(0xfe80, 0, 0, 0, 0, 0, 0, 1), port: 12345 })
+            Ok(IpEndpoint {
+                addr: IpAddress::v6(0xfe80, 0, 0, 0, 0, 0, 0, 1),
+                port: 12345
+            })
         );
     }
 }

+ 86 - 49
src/phy/fault_injector.rs

@@ -1,8 +1,8 @@
 use core::cell::RefCell;
 
-use crate::{Error, Result};
-use crate::phy::{self, DeviceCapabilities, Device};
+use crate::phy::{self, Device, DeviceCapabilities};
 use crate::time::{Duration, Instant};
+use crate::{Error, Result};
 
 // We use our own RNG to stay compatible with #![no_std].
 // The use of the RNG below has a slight bias, but it doesn't matter.
@@ -22,21 +22,21 @@ const MTU: usize = 1536;
 #[cfg_attr(feature = "defmt", derive(defmt::Format))]
 struct Config {
     corrupt_pct: u8,
-    drop_pct:    u8,
+    drop_pct: u8,
     reorder_pct: u8,
-    max_size:    usize,
+    max_size: usize,
     max_tx_rate: u64,
     max_rx_rate: u64,
-    interval:    Duration,
+    interval: Duration,
 }
 
 #[derive(Debug, Clone)]
 #[cfg_attr(feature = "defmt", derive(defmt::Format))]
 struct State {
-    rng_seed:    u32,
+    rng_seed: u32,
     refilled_at: Instant,
-    tx_bucket:   u64,
-    rx_bucket:   u64,
+    tx_bucket: u64,
+    rx_bucket: u64,
 }
 
 impl State {
@@ -48,7 +48,7 @@ impl State {
         let buffer = buffer.as_mut();
         // We introduce a single bitflip, as the most likely, and the hardest to detect, error.
         let index = (xorshift32(&mut self.rng_seed) as usize) % buffer.len();
-        let bit   = 1 << (xorshift32(&mut self.rng_seed) % 8) as u8;
+        let bit = 1 << (xorshift32(&mut self.rng_seed) % 8) as u8;
         buffer[index] ^= bit;
     }
 
@@ -61,7 +61,9 @@ impl State {
     }
 
     fn maybe_transmit(&mut self, config: &Config, timestamp: Instant) -> bool {
-        if config.max_tx_rate == 0 { return true }
+        if config.max_tx_rate == 0 {
+            return true;
+        }
 
         self.refill(config, timestamp);
         if self.tx_bucket > 0 {
@@ -73,7 +75,9 @@ impl State {
     }
 
     fn maybe_receive(&mut self, config: &Config, timestamp: Instant) -> bool {
-        if config.max_rx_rate == 0 { return true }
+        if config.max_rx_rate == 0 {
+            return true;
+        }
 
         self.refill(config, timestamp);
         if self.rx_bucket > 0 {
@@ -92,22 +96,22 @@ impl State {
 /// or hardware limitations (such as a limited number or size of usable network buffers).
 #[derive(Debug)]
 pub struct FaultInjector<D: for<'a> Device<'a>> {
-    inner:      D,
-    state:      RefCell<State>,
-    config:     Config,
+    inner: D,
+    state: RefCell<State>,
+    config: Config,
 }
 
 impl<D: for<'a> Device<'a>> 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 {
-            rng_seed:    seed,
+            rng_seed: seed,
             refilled_at: Instant::from_millis(0),
-            tx_bucket:   0,
-            rx_bucket:   0,
+            tx_bucket: 0,
+            rx_bucket: 0,
         };
         FaultInjector {
-            inner: inner,
+            inner,
             state: RefCell::new(state),
             config: Config::default(),
         }
@@ -153,7 +157,9 @@ impl<D: for<'a> Device<'a>> FaultInjector<D> {
     /// # Panics
     /// This function panics if the probability is not between 0% and 100%.
     pub fn set_corrupt_chance(&mut self, pct: u8) {
-        if pct > 100 { panic!("percentage out of range") }
+        if pct > 100 {
+            panic!("percentage out of range")
+        }
         self.config.corrupt_pct = pct
     }
 
@@ -162,7 +168,9 @@ impl<D: for<'a> Device<'a>> FaultInjector<D> {
     /// # Panics
     /// This function panics if the probability is not between 0% and 100%.
     pub fn set_drop_chance(&mut self, pct: u8) {
-        if pct > 100 { panic!("percentage out of range") }
+        if pct > 100 {
+            panic!("percentage out of range")
+        }
         self.config.drop_pct = pct
     }
 
@@ -189,7 +197,8 @@ impl<D: for<'a> Device<'a>> FaultInjector<D> {
 }
 
 impl<'a, D> Device<'a> for FaultInjector<D>
-    where D: for<'b> Device<'b>,
+where
+    D: for<'b> Device<'b>,
 {
     type RxToken = RxToken<'a, <D as Device<'a>>::RxToken>;
     type TxToken = TxToken<'a, <D as Device<'a>>::TxToken>;
@@ -203,60 +212,78 @@ impl<'a, D> Device<'a> for FaultInjector<D>
     }
 
     fn receive(&'a mut self) -> Option<(Self::RxToken, Self::TxToken)> {
-        let &mut Self { ref mut inner, ref state, config } = self;
+        let &mut Self {
+            ref mut inner,
+            ref state,
+            config,
+        } = self;
         inner.receive().map(|(rx_token, tx_token)| {
             let rx = RxToken {
-                state:   &state,
-                config:  config,
-                token:   rx_token,
+                state,
+                config,
+                token: rx_token,
                 corrupt: [0; MTU],
             };
             let tx = TxToken {
-                state:   &state,
-                config:  config,
-                token:   tx_token,
-                junk:    [0; MTU],
+                state,
+                config,
+                token: tx_token,
+                junk: [0; MTU],
             };
             (rx, tx)
         })
     }
 
     fn transmit(&'a mut self) -> Option<Self::TxToken> {
-        let &mut Self { ref mut inner, ref state, config } = self;
+        let &mut Self {
+            ref mut inner,
+            ref state,
+            config,
+        } = self;
         inner.transmit().map(|token| TxToken {
-            state:  &state,
-            config: config,
-            token: token,
-            junk:   [0; MTU],
+            state,
+            config,
+            token,
+            junk: [0; MTU],
         })
     }
 }
 
 #[doc(hidden)]
 pub struct RxToken<'a, Rx: phy::RxToken> {
-    state:   &'a RefCell<State>,
-    config:  Config,
-    token:   Rx,
+    state: &'a RefCell<State>,
+    config: Config,
+    token: Rx,
     corrupt: [u8; MTU],
 }
 
 impl<'a, Rx: phy::RxToken> phy::RxToken for RxToken<'a, Rx> {
     fn consume<R, F>(self, timestamp: Instant, f: F) -> Result<R>
-        where F: FnOnce(&mut [u8]) -> Result<R>
+    where
+        F: FnOnce(&mut [u8]) -> Result<R>,
     {
         if self.state.borrow_mut().maybe(self.config.drop_pct) {
             net_trace!("rx: randomly dropping a packet");
-            return Err(Error::Exhausted)
+            return Err(Error::Exhausted);
         }
-        if !self.state.borrow_mut().maybe_receive(&self.config, timestamp) {
+        if !self
+            .state
+            .borrow_mut()
+            .maybe_receive(&self.config, timestamp)
+        {
             net_trace!("rx: dropping a packet because of rate limiting");
-            return Err(Error::Exhausted)
+            return Err(Error::Exhausted);
         }
-        let Self { token, config, state, mut corrupt } = self;
+        let Self {
+            token,
+            config,
+            state,
+            mut corrupt,
+        } = self;
         token.consume(timestamp, |buffer| {
             if config.max_size > 0 && buffer.as_ref().len() > config.max_size {
                 net_trace!("rx: dropping a packet that is too large");
-                return Err(Error::Exhausted)
+                return Err(Error::Exhausted);
             }
             if state.borrow_mut().maybe(config.corrupt_pct) {
                 net_trace!("rx: randomly corrupting a packet");
@@ -273,15 +300,16 @@ impl<'a, Rx: phy::RxToken> phy::RxToken for RxToken<'a, Rx> {
 
 #[doc(hidden)]
 pub struct TxToken<'a, Tx: phy::TxToken> {
-    state:  &'a RefCell<State>,
+    state: &'a RefCell<State>,
     config: Config,
-    token:  Tx,
-    junk:   [u8; MTU],
+    token: Tx,
+    junk: [u8; MTU],
 }
 
 impl<'a, Tx: phy::TxToken> phy::TxToken for TxToken<'a, Tx> {
     fn consume<R, F>(mut self, timestamp: Instant, len: usize, f: F) -> Result<R>
-        where F: FnOnce(&mut [u8]) -> Result<R>
+    where
+        F: FnOnce(&mut [u8]) -> Result<R>,
     {
         let drop = if self.state.borrow_mut().maybe(self.config.drop_pct) {
             net_trace!("tx: randomly dropping a packet");
@@ -289,7 +317,11 @@ impl<'a, Tx: phy::TxToken> phy::TxToken for TxToken<'a, Tx> {
         } else if self.config.max_size > 0 && len > self.config.max_size {
             net_trace!("tx: dropping a packet that is too large");
             true
-        } else if !self.state.borrow_mut().maybe_transmit(&self.config, timestamp) {
+        } else if !self
+            .state
+            .borrow_mut()
+            .maybe_transmit(&self.config, timestamp)
+        {
             net_trace!("tx: dropping a packet because of rate limiting");
             true
         } else {
@@ -300,7 +332,12 @@ impl<'a, Tx: phy::TxToken> phy::TxToken for TxToken<'a, Tx> {
             return f(&mut self.junk[..len]);
         }
 
-        let Self { token, state, config, .. } = self;
+        let Self {
+            token,
+            state,
+            config,
+            ..
+        } = self;
         token.consume(timestamp, len, |mut buf| {
             if state.borrow_mut().maybe(config.corrupt_pct) {
                 net_trace!("tx: corrupting a packet");

+ 32 - 17
src/phy/fuzz_injector.rs

@@ -1,6 +1,6 @@
-use crate::Result;
-use crate::phy::{self, DeviceCapabilities, Device};
+use crate::phy::{self, Device, DeviceCapabilities};
 use crate::time::Instant;
+use crate::Result;
 
 // This could be fixed once associated consts are stable.
 const MTU: usize = 1536;
@@ -20,7 +20,7 @@ pub trait Fuzzer {
 #[derive(Debug)]
 #[cfg_attr(feature = "defmt", derive(defmt::Format))]
 pub struct FuzzInjector<D: for<'a> Device<'a>, FTx: Fuzzer, FRx: Fuzzer> {
-    inner:   D,
+    inner: D,
     fuzz_tx: FTx,
     fuzz_rx: FRx,
 }
@@ -29,7 +29,11 @@ pub struct FuzzInjector<D: for<'a> Device<'a>, FTx: Fuzzer, FRx: Fuzzer> {
 impl<D: for<'a> Device<'a>, 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 { inner, fuzz_tx, fuzz_rx }
+        FuzzInjector {
+            inner,
+            fuzz_tx,
+            fuzz_rx,
+        }
     }
 
     /// Return the underlying device, consuming the fuzz injector.
@@ -39,9 +43,10 @@ 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>
-    where D: for<'b> Device<'b>,
-          FTx: Fuzzer + 'a,
-          FRx: Fuzzer + 'a
+where
+    D: for<'b> Device<'b>,
+    FTx: Fuzzer + 'a,
+    FRx: Fuzzer + 'a,
 {
     type RxToken = RxToken<'a, <D as Device<'a>>::RxToken, FRx>;
     type TxToken = TxToken<'a, <D as Device<'a>>::TxToken, FTx>;
@@ -55,38 +60,47 @@ impl<'a, D, FTx, FRx> Device<'a> for FuzzInjector<D, FTx, FRx>
     }
 
     fn receive(&'a mut self) -> Option<(Self::RxToken, Self::TxToken)> {
-        let &mut Self { ref mut inner, ref fuzz_rx, ref fuzz_tx } = self;
+        let &mut Self {
+            ref mut inner,
+            ref fuzz_rx,
+            ref fuzz_tx,
+        } = self;
         inner.receive().map(|(rx_token, tx_token)| {
             let rx = RxToken {
                 fuzzer: fuzz_rx,
-                token:   rx_token,
+                token: rx_token,
             };
             let tx = TxToken {
                 fuzzer: fuzz_tx,
-                token:   tx_token,
+                token: tx_token,
             };
             (rx, tx)
         })
     }
 
     fn transmit(&'a mut self) -> Option<Self::TxToken> {
-        let &mut Self { ref mut inner, fuzz_rx: _, ref fuzz_tx } = self;
+        let &mut Self {
+            ref mut inner,
+            fuzz_rx: _,
+            ref fuzz_tx,
+        } = self;
         inner.transmit().map(|token| TxToken {
             fuzzer: fuzz_tx,
-            token:   token,
+            token: token,
         })
     }
 }
 
 #[doc(hidden)]
-pub struct RxToken<'a, Rx: phy::RxToken, F: Fuzzer + 'a>{
+pub struct RxToken<'a, Rx: phy::RxToken, F: Fuzzer + 'a> {
     fuzzer: &'a F,
-    token:  Rx,
+    token: Rx,
 }
 
 impl<'a, Rx: phy::RxToken, FRx: Fuzzer> phy::RxToken for RxToken<'a, Rx, FRx> {
     fn consume<R, F>(self, timestamp: Instant, f: F) -> Result<R>
-        where F: FnOnce(&mut [u8]) -> Result<R>
+    where
+        F: FnOnce(&mut [u8]) -> Result<R>,
     {
         let Self { fuzzer, token } = self;
         token.consume(timestamp, |buffer| {
@@ -99,12 +113,13 @@ impl<'a, Rx: phy::RxToken, FRx: Fuzzer> phy::RxToken for RxToken<'a, Rx, FRx> {
 #[doc(hidden)]
 pub struct TxToken<'a, Tx: phy::TxToken, F: Fuzzer + 'a> {
     fuzzer: &'a F,
-    token:  Tx,
+    token: Tx,
 }
 
 impl<'a, Tx: phy::TxToken, FTx: Fuzzer> phy::TxToken for TxToken<'a, Tx, FTx> {
     fn consume<R, F>(self, timestamp: Instant, len: usize, f: F) -> Result<R>
-        where F: FnOnce(&mut [u8]) -> Result<R>
+    where
+        F: FnOnce(&mut [u8]) -> Result<R>,
     {
         let Self { fuzzer, token } = self;
         token.consume(timestamp, len, |mut buf| {

+ 9 - 5
src/phy/loopback.rs

@@ -1,12 +1,12 @@
-use alloc::vec::Vec;
 #[cfg(not(feature = "rust-1_28"))]
 use alloc::collections::VecDeque;
+use alloc::vec::Vec;
 #[cfg(feature = "rust-1_28")]
 use alloc::VecDeque;
 
-use crate::Result;
 use crate::phy::{self, Device, DeviceCapabilities, Medium};
 use crate::time::Instant;
+use crate::Result;
 
 /// A loopback device.
 #[derive(Debug)]
@@ -44,7 +44,9 @@ impl<'a> Device<'a> for Loopback {
     fn receive(&'a mut self) -> Option<(Self::RxToken, Self::TxToken)> {
         self.queue.pop_front().map(move |buffer| {
             let rx = RxToken { buffer };
-            let tx = TxToken { queue: &mut self.queue };
+            let tx = TxToken {
+                queue: &mut self.queue,
+            };
             (rx, tx)
         })
     }
@@ -63,7 +65,8 @@ pub struct RxToken {
 
 impl phy::RxToken for RxToken {
     fn consume<R, F>(mut self, _timestamp: Instant, f: F) -> Result<R>
-        where F: FnOnce(&mut [u8]) -> Result<R>
+    where
+        F: FnOnce(&mut [u8]) -> Result<R>,
     {
         f(&mut self.buffer)
     }
@@ -76,7 +79,8 @@ pub struct TxToken<'a> {
 
 impl<'a> phy::TxToken for TxToken<'a> {
     fn consume<R, F>(self, _timestamp: Instant, len: usize, f: F) -> Result<R>
-        where F: FnOnce(&mut [u8]) -> Result<R>
+    where
+        F: FnOnce(&mut [u8]) -> Result<R>,
     {
         let mut buffer = Vec::new();
         buffer.resize(len, 0);

+ 36 - 18
src/phy/mod.rs

@@ -11,7 +11,9 @@ and implementations of it:
     [TunTapInterface](struct.TunTapInterface.html), to transmit and receive frames
     on the host OS.
 */
-#![cfg_attr(feature = "medium-ethernet", doc = r##"
+#![cfg_attr(
+    feature = "medium-ethernet",
+    doc = r##"
 # Examples
 
 An implementation of the [Device](trait.Device.html) trait for a simple hardware
@@ -84,37 +86,50 @@ impl<'a> phy::TxToken for StmPhyTxToken<'a> {
     }
 }
 ```
-"##)]
+"##
+)]
 
-use crate::Result;
 use crate::time::Instant;
+use crate::Result;
 
-#[cfg(all(any(feature = "phy-raw_socket", feature = "phy-tuntap_interface"), unix))]
+#[cfg(all(
+    any(feature = "phy-raw_socket", feature = "phy-tuntap_interface"),
+    unix
+))]
 mod sys;
 
-mod tracer;
 mod fault_injector;
 mod fuzz_injector;
-mod pcap_writer;
 #[cfg(any(feature = "std", feature = "alloc"))]
 mod loopback;
+mod pcap_writer;
 #[cfg(all(feature = "phy-raw_socket", unix))]
 mod raw_socket;
-#[cfg(all(feature = "phy-tuntap_interface", any(target_os = "linux", target_os = "android")))]
+mod tracer;
+#[cfg(all(
+    feature = "phy-tuntap_interface",
+    any(target_os = "linux", target_os = "android")
+))]
 mod tuntap_interface;
 
-#[cfg(all(any(feature = "phy-raw_socket", feature = "phy-tuntap_interface"), unix))]
+#[cfg(all(
+    any(feature = "phy-raw_socket", feature = "phy-tuntap_interface"),
+    unix
+))]
 pub use self::sys::wait;
 
-pub use self::tracer::Tracer;
 pub use self::fault_injector::FaultInjector;
-pub use self::fuzz_injector::{Fuzzer, FuzzInjector};
-pub use self::pcap_writer::{PcapLinkType, PcapMode, PcapSink, PcapWriter};
+pub use self::fuzz_injector::{FuzzInjector, Fuzzer};
 #[cfg(any(feature = "std", feature = "alloc"))]
 pub use self::loopback::Loopback;
+pub use self::pcap_writer::{PcapLinkType, PcapMode, PcapSink, PcapWriter};
 #[cfg(all(feature = "phy-raw_socket", unix))]
 pub use self::raw_socket::RawSocket;
-#[cfg(all(feature = "phy-tuntap_interface", any(target_os = "linux", target_os = "android")))]
+pub use self::tracer::Tracer;
+#[cfg(all(
+    feature = "phy-tuntap_interface",
+    any(target_os = "linux", target_os = "android")
+))]
 pub use self::tuntap_interface::TunTapInterface;
 
 /// A description of checksum behavior for a particular protocol.
@@ -142,7 +157,7 @@ impl Checksum {
     pub fn rx(&self) -> bool {
         match *self {
             Checksum::Both | Checksum::Rx => true,
-            _ => false
+            _ => false,
         }
     }
 
@@ -150,7 +165,7 @@ impl Checksum {
     pub fn tx(&self) -> bool {
         match *self {
             Checksum::Both | Checksum::Tx => true,
-            _ => false
+            _ => false,
         }
     }
 }
@@ -234,7 +249,9 @@ impl DeviceCapabilities {
     pub fn ip_mtu(&self) -> usize {
         match self.medium {
             #[cfg(feature = "medium-ethernet")]
-            Medium::Ethernet => self.max_transmission_unit - crate::wire::EthernetFrame::<&[u8]>::header_len(),
+            Medium::Ethernet => {
+                self.max_transmission_unit - crate::wire::EthernetFrame::<&[u8]>::header_len()
+            }
             #[cfg(feature = "medium-ip")]
             Medium::Ip => self.max_transmission_unit,
         }
@@ -260,7 +277,6 @@ pub enum Medium {
     Ip,
 }
 
-
 impl Default for Medium {
     fn default() -> Medium {
         #[cfg(feature = "medium-ethernet")]
@@ -306,7 +322,8 @@ pub trait RxToken {
     /// The timestamp must be a number of milliseconds, monotonically increasing since an
     /// arbitrary moment in time, such as system startup.
     fn consume<R, F>(self, timestamp: Instant, f: F) -> Result<R>
-        where F: FnOnce(&mut [u8]) -> Result<R>;
+    where
+        F: FnOnce(&mut [u8]) -> Result<R>;
 }
 
 /// A token to transmit a single network packet.
@@ -321,5 +338,6 @@ pub trait TxToken {
     /// The timestamp must be a number of milliseconds, monotonically increasing since an
     /// arbitrary moment in time, such as system startup.
     fn consume<R, F>(self, timestamp: Instant, len: usize, f: F) -> Result<R>
-        where F: FnOnce(&mut [u8]) -> Result<R>;
+    where
+        F: FnOnce(&mut [u8]) -> Result<R>;
 }

+ 61 - 39
src/phy/pcap_writer.rs

@@ -1,13 +1,13 @@
+use byteorder::{ByteOrder, NativeEndian};
+use phy::Medium;
 #[cfg(feature = "std")]
 use std::cell::RefCell;
 #[cfg(feature = "std")]
 use std::io::Write;
-use byteorder::{ByteOrder, NativeEndian};
-use phy::Medium;
 
-use crate::Result;
-use crate::phy::{self, DeviceCapabilities, Device};
+use crate::phy::{self, Device, DeviceCapabilities};
 use crate::time::Instant;
+use crate::Result;
 
 enum_with_unknown! {
     /// Captured packet header type.
@@ -28,7 +28,7 @@ pub enum PcapMode {
     /// Capture only received packets.
     RxOnly,
     /// Capture only transmitted packets.
-    TxOnly
+    TxOnly,
 }
 
 /// A packet capture sink.
@@ -54,12 +54,12 @@ pub trait PcapSink {
     ///
     /// This method may be overridden e.g. if special synchronization is necessary.
     fn global_header(&self, link_type: PcapLinkType) {
-        self.write_u32(0xa1b2c3d4);       // magic number
-        self.write_u16(2);                // major version
-        self.write_u16(4);                // minor version
-        self.write_u32(0);                // timezone (= UTC)
-        self.write_u32(0);                // accuracy (not used)
-        self.write_u32(65535);            // maximum packet length
+        self.write_u32(0xa1b2c3d4); // magic number
+        self.write_u16(2); // major version
+        self.write_u16(4); // minor version
+        self.write_u32(0); // timezone (= UTC)
+        self.write_u32(0); // accuracy (not used)
+        self.write_u32(65535); // maximum packet length
         self.write_u32(link_type.into()); // link-layer header type
     }
 
@@ -72,10 +72,10 @@ pub trait PcapSink {
     fn packet_header(&self, timestamp: Instant, length: usize) {
         assert!(length <= 65535);
 
-        self.write_u32(timestamp.secs() as u32);   // timestamp seconds
-        self.write_u32(timestamp.millis() as u32);   // timestamp microseconds
-        self.write_u32(length  as u32);   // captured length
-        self.write_u32(length  as u32);   // original length
+        self.write_u32(timestamp.secs() as u32); // timestamp seconds
+        self.write_u32(timestamp.millis() as u32); // timestamp microseconds
+        self.write_u32(length as u32); // captured length
+        self.write_u32(length as u32); // original length
     }
 
     /// Write the libpcap packet header followed by packet data into the sink.
@@ -121,12 +121,13 @@ impl<T: Write> PcapSink for RefCell<T> {
 #[derive(Debug)]
 #[cfg_attr(feature = "defmt", derive(defmt::Format))]
 pub struct PcapWriter<D, S>
-    where D: for<'a> Device<'a>,
-          S: PcapSink + Clone,
+where
+    D: for<'a> Device<'a>,
+    S: PcapSink + Clone,
 {
     lower: D,
-    sink:  S,
-    mode:  PcapMode,
+    sink: S,
+    mode: PcapMode,
 }
 
 impl<D: for<'a> Device<'a>, S: PcapSink + Clone> PcapWriter<D, S> {
@@ -145,27 +146,49 @@ impl<D: for<'a> Device<'a>, S: PcapSink + Clone> PcapWriter<D, S> {
 }
 
 impl<'a, D, S> Device<'a> for PcapWriter<D, S>
-    where D: for<'b> Device<'b>,
-          S: PcapSink + Clone + 'a,
+where
+    D: for<'b> Device<'b>,
+    S: PcapSink + Clone + 'a,
 {
     type RxToken = RxToken<<D as Device<'a>>::RxToken, S>;
     type TxToken = TxToken<<D as Device<'a>>::TxToken, S>;
 
-    fn capabilities(&self) -> DeviceCapabilities { self.lower.capabilities() }
+    fn capabilities(&self) -> DeviceCapabilities {
+        self.lower.capabilities()
+    }
 
     fn receive(&'a mut self) -> Option<(Self::RxToken, Self::TxToken)> {
-        let &mut Self { ref mut lower, ref sink, mode, .. } = self;
+        let &mut Self {
+            ref mut lower,
+            ref sink,
+            mode,
+            ..
+        } = self;
         lower.receive().map(|(rx_token, tx_token)| {
-            let rx = RxToken { token: rx_token, sink: sink.clone(), mode };
-            let tx = TxToken { token: tx_token, sink: sink.clone(), mode };
+            let rx = RxToken {
+                token: rx_token,
+                sink: sink.clone(),
+                mode,
+            };
+            let tx = TxToken {
+                token: tx_token,
+                sink: sink.clone(),
+                mode,
+            };
             (rx, tx)
         })
     }
 
     fn transmit(&'a mut self) -> Option<Self::TxToken> {
-        let &mut Self { ref mut lower, ref sink, mode } = self;
-        lower.transmit().map(|token| {
-            TxToken { token, sink: sink.clone(), mode }
+        let &mut Self {
+            ref mut lower,
+            ref sink,
+            mode,
+        } = self;
+        lower.transmit().map(|token| TxToken {
+            token,
+            sink: sink.clone(),
+            mode,
         })
     }
 }
@@ -173,8 +196,8 @@ impl<'a, D, S> Device<'a> for PcapWriter<D, S>
 #[doc(hidden)]
 pub struct RxToken<Rx: phy::RxToken, S: PcapSink> {
     token: Rx,
-    sink:  S,
-    mode:  PcapMode,
+    sink: S,
+    mode: PcapMode,
 }
 
 impl<Rx: phy::RxToken, S: PcapSink> phy::RxToken for RxToken<Rx, S> {
@@ -182,9 +205,8 @@ impl<Rx: phy::RxToken, S: PcapSink> phy::RxToken for RxToken<Rx, S> {
         let Self { token, sink, mode } = self;
         token.consume(timestamp, |buffer| {
             match mode {
-                PcapMode::Both | PcapMode::RxOnly =>
-                    sink.packet(timestamp, buffer.as_ref()),
-                PcapMode::TxOnly => ()
+                PcapMode::Both | PcapMode::RxOnly => sink.packet(timestamp, buffer.as_ref()),
+                PcapMode::TxOnly => (),
             }
             f(buffer)
         })
@@ -194,21 +216,21 @@ impl<Rx: phy::RxToken, S: PcapSink> phy::RxToken for RxToken<Rx, S> {
 #[doc(hidden)]
 pub struct TxToken<Tx: phy::TxToken, S: PcapSink> {
     token: Tx,
-    sink:  S,
-    mode:  PcapMode
+    sink: S,
+    mode: PcapMode,
 }
 
 impl<Tx: phy::TxToken, S: PcapSink> phy::TxToken for TxToken<Tx, S> {
     fn consume<R, F>(self, timestamp: Instant, len: usize, f: F) -> Result<R>
-        where F: FnOnce(&mut [u8]) -> Result<R>
+    where
+        F: FnOnce(&mut [u8]) -> Result<R>,
     {
         let Self { token, sink, mode } = self;
         token.consume(timestamp, len, |buffer| {
             let result = f(buffer);
             match mode {
-                PcapMode::Both | PcapMode::TxOnly =>
-                    sink.packet(timestamp, &buffer),
-                PcapMode::RxOnly => ()
+                PcapMode::Both | PcapMode::TxOnly => sink.packet(timestamp, buffer),
+                PcapMode::RxOnly => (),
             };
             result
         })

+ 19 - 17
src/phy/raw_socket.rs

@@ -1,18 +1,18 @@
 use std::cell::RefCell;
-use std::vec::Vec;
-use std::rc::Rc;
 use std::io;
-use std::os::unix::io::{RawFd, AsRawFd};
+use std::os::unix::io::{AsRawFd, RawFd};
+use std::rc::Rc;
+use std::vec::Vec;
 
-use crate::Result;
-use crate::phy::{self, sys, DeviceCapabilities, Device, Medium};
+use crate::phy::{self, sys, Device, DeviceCapabilities, Medium};
 use crate::time::Instant;
+use crate::Result;
 
 /// A socket that captures or transmits the complete frame.
 #[derive(Debug)]
 pub struct RawSocket {
-    lower:  Rc<RefCell<sys::RawSocketDesc>>,
-    mtu:    usize
+    lower: Rc<RefCell<sys::RawSocketDesc>>,
+    mtu: usize,
 }
 
 impl AsRawFd for RawSocket {
@@ -32,7 +32,7 @@ impl RawSocket {
         let mtu = lower.interface_mtu()?;
         Ok(RawSocket {
             lower: Rc::new(RefCell::new(lower)),
-            mtu:   mtu
+            mtu: mtu,
         })
     }
 }
@@ -56,13 +56,13 @@ impl<'a> Device<'a> for RawSocket {
             Ok(size) => {
                 buffer.resize(size, 0);
                 let rx = RxToken { buffer };
-                let tx = TxToken { lower: self.lower.clone() };
+                let tx = TxToken {
+                    lower: self.lower.clone(),
+                };
                 Some((rx, tx))
             }
-            Err(ref err) if err.kind() == io::ErrorKind::WouldBlock => {
-                None
-            }
-            Err(err) => panic!("{}", err)
+            Err(ref err) if err.kind() == io::ErrorKind::WouldBlock => None,
+            Err(err) => panic!("{}", err),
         }
     }
 
@@ -75,12 +75,13 @@ impl<'a> Device<'a> for RawSocket {
 
 #[doc(hidden)]
 pub struct RxToken {
-    buffer: Vec<u8>
+    buffer: Vec<u8>,
 }
 
 impl phy::RxToken for RxToken {
     fn consume<R, F>(mut self, _timestamp: Instant, f: F) -> Result<R>
-        where F: FnOnce(&mut [u8]) -> Result<R>
+    where
+        F: FnOnce(&mut [u8]) -> Result<R>,
     {
         f(&mut self.buffer[..])
     }
@@ -88,12 +89,13 @@ impl phy::RxToken for RxToken {
 
 #[doc(hidden)]
 pub struct TxToken {
-    lower:  Rc<RefCell<sys::RawSocketDesc>>,
+    lower: Rc<RefCell<sys::RawSocketDesc>>,
 }
 
 impl phy::TxToken for TxToken {
     fn consume<R, F>(self, _timestamp: Instant, len: usize, f: F) -> Result<R>
-        where F: FnOnce(&mut [u8]) -> Result<R>
+    where
+        F: FnOnce(&mut [u8]) -> Result<R>,
     {
         let mut lower = self.lower.borrow_mut();
         let mut buffer = vec![0; len];

+ 1 - 1
src/phy/sys/bpf.rs

@@ -4,8 +4,8 @@ use std::os::unix::io::{AsRawFd, RawFd};
 
 use libc;
 
-use crate::wire::ETHERNET_HEADER_LEN;
 use super::{ifreq, ifreq_for};
+use crate::wire::ETHERNET_HEADER_LEN;
 
 /// set interface
 #[cfg(any(target_os = "macos", target_os = "openbsd"))]

+ 6 - 6
src/phy/sys/linux.rs

@@ -1,10 +1,10 @@
 #![allow(unused)]
 
-pub const SIOCGIFMTU:   libc::c_ulong = 0x8921;
+pub const SIOCGIFMTU: libc::c_ulong = 0x8921;
 pub const SIOCGIFINDEX: libc::c_ulong = 0x8933;
-pub const ETH_P_ALL:    libc::c_short = 0x0003;
+pub const ETH_P_ALL: libc::c_short = 0x0003;
 
-pub const TUNSETIFF:    libc::c_ulong = 0x400454CA;
-pub const IFF_TUN:      libc::c_int   = 0x0001;
-pub const IFF_TAP:      libc::c_int   = 0x0002;
-pub const IFF_NO_PI:    libc::c_int   = 0x1000;
+pub const TUNSETIFF: libc::c_ulong = 0x400454CA;
+pub const IFF_TUN: libc::c_int = 0x0001;
+pub const IFF_TAP: libc::c_int = 0x0002;
+pub const IFF_NO_PI: libc::c_int = 0x1000;

+ 73 - 30
src/phy/sys/mod.rs

@@ -1,25 +1,45 @@
 #![allow(unsafe_code)]
 
-use std::{mem, ptr, io};
-use std::os::unix::io::RawFd;
 use crate::time::Duration;
+use std::os::unix::io::RawFd;
+use std::{io, mem, ptr};
 
 #[cfg(any(target_os = "linux", target_os = "android"))]
 #[path = "linux.rs"]
 mod imp;
 
-#[cfg(all(feature = "phy-raw_socket", any(target_os = "linux", target_os = "android")))]
-pub mod raw_socket;
-#[cfg(all(feature = "phy-raw_socket", not(any(target_os = "linux", target_os = "android")), unix))]
+#[cfg(all(
+    feature = "phy-raw_socket",
+    not(any(target_os = "linux", target_os = "android")),
+    unix
+))]
 pub mod bpf;
-#[cfg(all(feature = "phy-tuntap_interface", any(target_os = "linux", target_os = "android")))]
+#[cfg(all(
+    feature = "phy-raw_socket",
+    any(target_os = "linux", target_os = "android")
+))]
+pub mod raw_socket;
+#[cfg(all(
+    feature = "phy-tuntap_interface",
+    any(target_os = "linux", target_os = "android")
+))]
 pub mod tuntap_interface;
 
-#[cfg(all(feature = "phy-raw_socket", any(target_os = "linux", target_os = "android")))]
-pub use self::raw_socket::RawSocketDesc;
-#[cfg(all(feature = "phy-raw_socket", not(any(target_os = "linux", target_os = "android")), unix))]
+#[cfg(all(
+    feature = "phy-raw_socket",
+    not(any(target_os = "linux", target_os = "android")),
+    unix
+))]
 pub use self::bpf::BpfDevice as RawSocketDesc;
-#[cfg(all(feature = "phy-tuntap_interface", any(target_os = "linux", target_os = "android")))]
+#[cfg(all(
+    feature = "phy-raw_socket",
+    any(target_os = "linux", target_os = "android")
+))]
+pub use self::raw_socket::RawSocketDesc;
+#[cfg(all(
+    feature = "phy-tuntap_interface",
+    any(target_os = "linux", target_os = "android")
+))]
 pub use self::tuntap_interface::TunTapInterfaceDesc;
 
 /// Wait until given file descriptor becomes readable, but no longer than given timeout.
@@ -44,35 +64,51 @@ pub fn wait(fd: RawFd, duration: Option<Duration>) -> io::Result<()> {
             exceptfds.assume_init()
         };
 
-        let mut timeout = libc::timeval { tv_sec: 0, tv_usec: 0 };
-        let timeout_ptr =
-            if let Some(duration) = duration {
-                timeout.tv_sec = duration.secs() as libc::time_t;
-                timeout.tv_usec = (duration.millis() * 1_000) as libc::suseconds_t;
-                &mut timeout as *mut _
-            } else {
-                ptr::null_mut()
-            };
+        let mut timeout = libc::timeval {
+            tv_sec: 0,
+            tv_usec: 0,
+        };
+        let timeout_ptr = if let Some(duration) = duration {
+            timeout.tv_sec = duration.secs() as libc::time_t;
+            timeout.tv_usec = (duration.millis() * 1_000) as libc::suseconds_t;
+            &mut timeout as *mut _
+        } else {
+            ptr::null_mut()
+        };
 
-        let res = libc::select(fd + 1, &mut readfds, &mut writefds, &mut exceptfds, timeout_ptr);
-        if res == -1 { return Err(io::Error::last_os_error()) }
+        let res = libc::select(
+            fd + 1,
+            &mut readfds,
+            &mut writefds,
+            &mut exceptfds,
+            timeout_ptr,
+        );
+        if res == -1 {
+            return Err(io::Error::last_os_error());
+        }
         Ok(())
     }
 }
 
-#[cfg(all(any(feature = "phy-tuntap_interface", feature = "phy-raw_socket"), unix))]
+#[cfg(all(
+    any(feature = "phy-tuntap_interface", feature = "phy-raw_socket"),
+    unix
+))]
 #[repr(C)]
 #[derive(Debug)]
 struct ifreq {
     ifr_name: [libc::c_char; libc::IF_NAMESIZE],
-    ifr_data: libc::c_int /* ifr_ifindex or ifr_mtu */
+    ifr_data: libc::c_int, /* ifr_ifindex or ifr_mtu */
 }
 
-#[cfg(all(any(feature = "phy-tuntap_interface", feature = "phy-raw_socket"), unix))]
+#[cfg(all(
+    any(feature = "phy-tuntap_interface", feature = "phy-raw_socket"),
+    unix
+))]
 fn ifreq_for(name: &str) -> ifreq {
     let mut ifreq = ifreq {
         ifr_name: [0; libc::IF_NAMESIZE],
-        ifr_data: 0
+        ifr_data: 0,
     };
     for (i, byte) in name.as_bytes().iter().enumerate() {
         ifreq.ifr_name[i] = *byte as libc::c_char
@@ -80,13 +116,20 @@ fn ifreq_for(name: &str) -> ifreq {
     ifreq
 }
 
-#[cfg(all(any(target_os = "linux", target_os = "android"),
-          any(feature = "phy-tuntap_interface", feature = "phy-raw_socket")))]
-fn ifreq_ioctl(lower: libc::c_int, ifreq: &mut ifreq,
-               cmd: libc::c_ulong) -> io::Result<libc::c_int> {
+#[cfg(all(
+    any(target_os = "linux", target_os = "android"),
+    any(feature = "phy-tuntap_interface", feature = "phy-raw_socket")
+))]
+fn ifreq_ioctl(
+    lower: libc::c_int,
+    ifreq: &mut ifreq,
+    cmd: libc::c_ulong,
+) -> io::Result<libc::c_int> {
     unsafe {
         let res = libc::ioctl(lower, cmd as _, ifreq as *mut ifreq);
-        if res == -1 { return Err(io::Error::last_os_error()) }
+        if res == -1 {
+            return Err(io::Error::last_os_error());
+        }
     }
 
     Ok(ifreq.ifr_data)

+ 49 - 25
src/phy/sys/raw_socket.rs

@@ -1,12 +1,12 @@
-use std::{mem, io};
-use std::os::unix::io::{RawFd, AsRawFd};
 use super::*;
 use crate::wire::EthernetFrame;
+use std::os::unix::io::{AsRawFd, RawFd};
+use std::{io, mem};
 
 #[derive(Debug)]
 pub struct RawSocketDesc {
     lower: libc::c_int,
-    ifreq: ifreq
+    ifreq: ifreq,
 }
 
 impl AsRawFd for RawSocketDesc {
@@ -18,41 +18,51 @@ impl AsRawFd for RawSocketDesc {
 impl RawSocketDesc {
     pub fn new(name: &str) -> io::Result<RawSocketDesc> {
         let lower = unsafe {
-            let lower = libc::socket(libc::AF_PACKET, libc::SOCK_RAW | libc::SOCK_NONBLOCK,
-                                     imp::ETH_P_ALL.to_be() as i32);
-            if lower == -1 { return Err(io::Error::last_os_error()) }
+            let lower = libc::socket(
+                libc::AF_PACKET,
+                libc::SOCK_RAW | libc::SOCK_NONBLOCK,
+                imp::ETH_P_ALL.to_be() as i32,
+            );
+            if lower == -1 {
+                return Err(io::Error::last_os_error());
+            }
             lower
         };
 
         Ok(RawSocketDesc {
             lower: lower,
-            ifreq: ifreq_for(name)
+            ifreq: ifreq_for(name),
         })
     }
 
     pub fn interface_mtu(&mut self) -> io::Result<usize> {
         // SIOCGIFMTU returns the IP MTU (typically 1500 bytes.)
         // smoltcp counts the entire Ethernet packet in the MTU, so add the Ethernet header size to it.
-        let ip_mtu = ifreq_ioctl(self.lower, &mut self.ifreq, imp::SIOCGIFMTU).map(|mtu| mtu as usize)?;
+        let ip_mtu =
+            ifreq_ioctl(self.lower, &mut self.ifreq, imp::SIOCGIFMTU).map(|mtu| mtu as usize)?;
         Ok(ip_mtu + EthernetFrame::<&[u8]>::header_len())
     }
 
     pub fn bind_interface(&mut self) -> io::Result<()> {
         let sockaddr = libc::sockaddr_ll {
-            sll_family:   libc::AF_PACKET as u16,
+            sll_family: libc::AF_PACKET as u16,
             sll_protocol: imp::ETH_P_ALL.to_be() as u16,
-            sll_ifindex:  ifreq_ioctl(self.lower, &mut self.ifreq, imp::SIOCGIFINDEX)?,
-            sll_hatype:   1,
-            sll_pkttype:  0,
-            sll_halen:    6,
-            sll_addr:     [0; 8]
+            sll_ifindex: ifreq_ioctl(self.lower, &mut self.ifreq, imp::SIOCGIFINDEX)?,
+            sll_hatype: 1,
+            sll_pkttype: 0,
+            sll_halen: 6,
+            sll_addr: [0; 8],
         };
 
         unsafe {
-            let res = libc::bind(self.lower,
-                                 &sockaddr as *const libc::sockaddr_ll as *const libc::sockaddr,
-                                 mem::size_of::<libc::sockaddr_ll>() as u32);
-            if res == -1 { return Err(io::Error::last_os_error()) }
+            let res = libc::bind(
+                self.lower,
+                &sockaddr as *const libc::sockaddr_ll as *const libc::sockaddr,
+                mem::size_of::<libc::sockaddr_ll>() as u32,
+            );
+            if res == -1 {
+                return Err(io::Error::last_os_error());
+            }
         }
 
         Ok(())
@@ -60,18 +70,30 @@ impl RawSocketDesc {
 
     pub fn recv(&mut self, buffer: &mut [u8]) -> io::Result<usize> {
         unsafe {
-            let len = libc::recv(self.lower, buffer.as_mut_ptr() as *mut libc::c_void,
-                                 buffer.len(), 0);
-            if len == -1 { return Err(io::Error::last_os_error()) }
+            let len = libc::recv(
+                self.lower,
+                buffer.as_mut_ptr() as *mut libc::c_void,
+                buffer.len(),
+                0,
+            );
+            if len == -1 {
+                return Err(io::Error::last_os_error());
+            }
             Ok(len as usize)
         }
     }
 
     pub fn send(&mut self, buffer: &[u8]) -> io::Result<usize> {
         unsafe {
-            let len = libc::send(self.lower, buffer.as_ptr() as *const libc::c_void,
-                                 buffer.len(), 0);
-            if len == -1 { Err(io::Error::last_os_error()).unwrap() }
+            let len = libc::send(
+                self.lower,
+                buffer.as_ptr() as *const libc::c_void,
+                buffer.len(),
+                0,
+            );
+            if len == -1 {
+                Err(io::Error::last_os_error()).unwrap()
+            }
             Ok(len as usize)
         }
     }
@@ -79,6 +101,8 @@ impl RawSocketDesc {
 
 impl Drop for RawSocketDesc {
     fn drop(&mut self) {
-        unsafe { libc::close(self.lower); }
+        unsafe {
+            libc::close(self.lower);
+        }
     }
 }

+ 34 - 14
src/phy/sys/tuntap_interface.rs

@@ -1,7 +1,7 @@
-use std::io;
-use std::os::unix::io::{RawFd, AsRawFd};
 use super::*;
 use crate::{phy::Medium, wire::EthernetFrame};
+use std::io;
+use std::os::unix::io::{AsRawFd, RawFd};
 
 #[derive(Debug)]
 pub struct TunTapInterfaceDesc {
@@ -19,9 +19,13 @@ impl AsRawFd for TunTapInterfaceDesc {
 impl TunTapInterfaceDesc {
     pub fn new(name: &str, medium: Medium) -> io::Result<TunTapInterfaceDesc> {
         let lower = unsafe {
-            let lower = libc::open("/dev/net/tun\0".as_ptr() as *const libc::c_char,
-                                   libc::O_RDWR | libc::O_NONBLOCK);
-            if lower == -1 { return Err(io::Error::last_os_error()) }
+            let lower = libc::open(
+                "/dev/net/tun\0".as_ptr() as *const libc::c_char,
+                libc::O_RDWR | libc::O_NONBLOCK,
+            );
+            if lower == -1 {
+                return Err(io::Error::last_os_error());
+            }
             lower
         };
 
@@ -46,13 +50,17 @@ impl TunTapInterfaceDesc {
     pub fn interface_mtu(&mut self) -> io::Result<usize> {
         let lower = unsafe {
             let lower = libc::socket(libc::AF_INET, libc::SOCK_DGRAM, libc::IPPROTO_IP);
-            if lower == -1 { return Err(io::Error::last_os_error()) }
+            if lower == -1 {
+                return Err(io::Error::last_os_error());
+            }
             lower
         };
 
         let ip_mtu = ifreq_ioctl(lower, &mut self.ifreq, imp::SIOCGIFMTU).map(|mtu| mtu as usize);
 
-        unsafe { libc::close(lower); }
+        unsafe {
+            libc::close(lower);
+        }
 
         // Propagate error after close, to ensure we always close.
         let ip_mtu = ip_mtu?;
@@ -71,18 +79,28 @@ impl TunTapInterfaceDesc {
 
     pub fn recv(&mut self, buffer: &mut [u8]) -> io::Result<usize> {
         unsafe {
-            let len = libc::read(self.lower, buffer.as_mut_ptr() as *mut libc::c_void,
-                                 buffer.len());
-            if len == -1 { return Err(io::Error::last_os_error()) }
+            let len = libc::read(
+                self.lower,
+                buffer.as_mut_ptr() as *mut libc::c_void,
+                buffer.len(),
+            );
+            if len == -1 {
+                return Err(io::Error::last_os_error());
+            }
             Ok(len as usize)
         }
     }
 
     pub fn send(&mut self, buffer: &[u8]) -> io::Result<usize> {
         unsafe {
-            let len = libc::write(self.lower, buffer.as_ptr() as *const libc::c_void,
-                                  buffer.len());
-            if len == -1 { Err(io::Error::last_os_error()).unwrap() }
+            let len = libc::write(
+                self.lower,
+                buffer.as_ptr() as *const libc::c_void,
+                buffer.len(),
+            );
+            if len == -1 {
+                Err(io::Error::last_os_error()).unwrap()
+            }
             Ok(len as usize)
         }
     }
@@ -90,6 +108,8 @@ impl TunTapInterfaceDesc {
 
 impl Drop for TunTapInterfaceDesc {
     fn drop(&mut self) {
-        unsafe { libc::close(self.lower); }
+        unsafe {
+            libc::close(self.lower);
+        }
     }
 }

+ 93 - 38
src/phy/tracer.rs

@@ -1,8 +1,11 @@
 use core::fmt;
 
-use crate::{Result, wire::pretty_print::{PrettyIndent, PrettyPrint}};
-use crate::phy::{self, DeviceCapabilities, Device, Medium};
+use crate::phy::{self, Device, DeviceCapabilities, Medium};
 use crate::time::Instant;
+use crate::{
+    wire::pretty_print::{PrettyIndent, PrettyPrint},
+    Result,
+};
 
 /// A tracer device.
 ///
@@ -10,7 +13,7 @@ use crate::time::Instant;
 /// using the provided writer function, and then passes them to another
 /// device.
 pub struct Tracer<D: for<'a> Device<'a>> {
-    inner:  D,
+    inner: D,
     writer: fn(Instant, Packet),
 }
 
@@ -42,50 +45,78 @@ impl<D: for<'a> Device<'a>> Tracer<D> {
 }
 
 impl<'a, D> Device<'a> for Tracer<D>
-    where D: for<'b> Device<'b>,
+where
+    D: for<'b> Device<'b>,
 {
     type RxToken = RxToken<<D as Device<'a>>::RxToken>;
     type TxToken = TxToken<<D as Device<'a>>::TxToken>;
 
-    fn capabilities(&self) -> DeviceCapabilities { self.inner.capabilities() }
+    fn capabilities(&self) -> DeviceCapabilities {
+        self.inner.capabilities()
+    }
 
     fn receive(&'a mut self) -> Option<(Self::RxToken, Self::TxToken)> {
-        let &mut Self { ref mut inner, writer, .. } = self;
+        let &mut Self {
+            ref mut inner,
+            writer,
+            ..
+        } = self;
         let medium = inner.capabilities().medium;
         inner.receive().map(|(rx_token, tx_token)| {
-            let rx = RxToken { token: rx_token, writer, medium };
-            let tx = TxToken { token: tx_token, writer, medium };
+            let rx = RxToken {
+                token: rx_token,
+                writer,
+                medium,
+            };
+            let tx = TxToken {
+                token: tx_token,
+                writer,
+                medium,
+            };
             (rx, tx)
         })
     }
 
     fn transmit(&'a mut self) -> Option<Self::TxToken> {
-        let &mut Self { ref mut inner, writer } = self;
+        let &mut Self {
+            ref mut inner,
+            writer,
+        } = self;
         let medium = inner.capabilities().medium;
-        inner.transmit().map(|tx_token| {
-            TxToken { token: tx_token, medium, writer }
+        inner.transmit().map(|tx_token| TxToken {
+            token: tx_token,
+            medium,
+            writer,
         })
     }
 }
 
 #[doc(hidden)]
 pub struct RxToken<Rx: phy::RxToken> {
-    token:     Rx,
-    writer:    fn(Instant, Packet),
-    medium:    Medium,
+    token: Rx,
+    writer: fn(Instant, Packet),
+    medium: Medium,
 }
 
 impl<Rx: phy::RxToken> phy::RxToken for RxToken<Rx> {
     fn consume<R, F>(self, timestamp: Instant, f: F) -> Result<R>
-        where F: FnOnce(&mut [u8]) -> Result<R>
+    where
+        F: FnOnce(&mut [u8]) -> Result<R>,
     {
-        let Self { token, writer, medium } = self;
+        let Self {
+            token,
+            writer,
+            medium,
+        } = self;
         token.consume(timestamp, |buffer| {
-            writer(timestamp, Packet{
-                buffer,
-                medium,
-                prefix: "<- ",
-            });
+            writer(
+                timestamp,
+                Packet {
+                    buffer,
+                    medium,
+                    prefix: "<- ",
+                },
+            );
             f(buffer)
         })
     }
@@ -93,23 +124,31 @@ impl<Rx: phy::RxToken> phy::RxToken for RxToken<Rx> {
 
 #[doc(hidden)]
 pub struct TxToken<Tx: phy::TxToken> {
-    token:     Tx,
-    writer:    fn(Instant, Packet),
-    medium:    Medium,
+    token: Tx,
+    writer: fn(Instant, Packet),
+    medium: Medium,
 }
 
 impl<Tx: phy::TxToken> phy::TxToken for TxToken<Tx> {
     fn consume<R, F>(self, timestamp: Instant, len: usize, f: F) -> Result<R>
-        where F: FnOnce(&mut [u8]) -> Result<R>
+    where
+        F: FnOnce(&mut [u8]) -> Result<R>,
     {
-        let Self { token, writer, medium } = self;
+        let Self {
+            token,
+            writer,
+            medium,
+        } = self;
         token.consume(timestamp, len, |buffer| {
             let result = f(buffer);
-            writer(timestamp, Packet{
-                buffer,
-                medium,
-                prefix: "-> ",
-            });
+            writer(
+                timestamp,
+                Packet {
+                    buffer,
+                    medium,
+                    prefix: "-> ",
+                },
+            );
             result
         })
     }
@@ -126,15 +165,31 @@ impl<'a> fmt::Display for Packet<'a> {
         let mut indent = PrettyIndent::new(self.prefix);
         match self.medium {
             #[cfg(feature = "medium-ethernet")]
-            Medium::Ethernet => crate::wire::EthernetFrame::<&'static [u8]>::pretty_print(&self.buffer, f, &mut indent),
+            Medium::Ethernet => crate::wire::EthernetFrame::<&'static [u8]>::pretty_print(
+                &self.buffer,
+                f,
+                &mut indent,
+            ),
             #[cfg(feature = "medium-ip")]
-            Medium::Ip => match crate::wire::IpVersion::of_packet(&self.buffer) {
+            Medium::Ip => match crate::wire::IpVersion::of_packet(self.buffer) {
                 #[cfg(feature = "proto-ipv4")]
-                Ok(crate::wire::IpVersion::Ipv4) => crate::wire::Ipv4Packet::<&'static [u8]>::pretty_print(&self.buffer, f, &mut indent),
+                Ok(crate::wire::IpVersion::Ipv4) => {
+                    crate::wire::Ipv4Packet::<&'static [u8]>::pretty_print(
+                        &self.buffer,
+                        f,
+                        &mut indent,
+                    )
+                }
                 #[cfg(feature = "proto-ipv6")]
-                Ok(crate::wire::IpVersion::Ipv6) => crate::wire::Ipv6Packet::<&'static [u8]>::pretty_print(&self.buffer, f, &mut indent),
-                _ => f.write_str("unrecognized IP version")
-            }
+                Ok(crate::wire::IpVersion::Ipv6) => {
+                    crate::wire::Ipv6Packet::<&'static [u8]>::pretty_print(
+                        &self.buffer,
+                        f,
+                        &mut indent,
+                    )
+                }
+                _ => f.write_str("unrecognized IP version"),
+            },
         }
     }
-}
+}

+ 17 - 15
src/phy/tuntap_interface.rs

@@ -1,18 +1,18 @@
 use std::cell::RefCell;
-use std::vec::Vec;
-use std::rc::Rc;
 use std::io;
-use std::os::unix::io::{RawFd, AsRawFd};
+use std::os::unix::io::{AsRawFd, RawFd};
+use std::rc::Rc;
+use std::vec::Vec;
 
-use crate::Result;
-use crate::phy::{self, sys, DeviceCapabilities, Device, Medium};
+use crate::phy::{self, sys, Device, DeviceCapabilities, Medium};
 use crate::time::Instant;
+use crate::Result;
 
 /// A virtual TUN (IP) or TAP (Ethernet) interface.
 #[derive(Debug)]
 pub struct TunTapInterface {
-    lower:  Rc<RefCell<sys::TunTapInterfaceDesc>>,
-    mtu:    usize,
+    lower: Rc<RefCell<sys::TunTapInterfaceDesc>>,
+    mtu: usize,
     medium: Medium,
 }
 
@@ -59,13 +59,13 @@ impl<'a> Device<'a> for TunTapInterface {
             Ok(size) => {
                 buffer.resize(size, 0);
                 let rx = RxToken { buffer };
-                let tx = TxToken { lower: self.lower.clone() };
+                let tx = TxToken {
+                    lower: self.lower.clone(),
+                };
                 Some((rx, tx))
             }
-            Err(ref err) if err.kind() == io::ErrorKind::WouldBlock => {
-                None
-            }
-            Err(err) => panic!("{}", err)
+            Err(ref err) if err.kind() == io::ErrorKind::WouldBlock => None,
+            Err(err) => panic!("{}", err),
         }
     }
 
@@ -78,12 +78,13 @@ impl<'a> Device<'a> for TunTapInterface {
 
 #[doc(hidden)]
 pub struct RxToken {
-    buffer: Vec<u8>
+    buffer: Vec<u8>,
 }
 
 impl phy::RxToken for RxToken {
     fn consume<R, F>(mut self, _timestamp: Instant, f: F) -> Result<R>
-        where F: FnOnce(&mut [u8]) -> Result<R>
+    where
+        F: FnOnce(&mut [u8]) -> Result<R>,
     {
         f(&mut self.buffer[..])
     }
@@ -96,7 +97,8 @@ pub struct TxToken {
 
 impl phy::TxToken for TxToken {
     fn consume<R, F>(self, _timestamp: Instant, len: usize, f: F) -> Result<R>
-        where F: FnOnce(&mut [u8]) -> Result<R>
+    where
+        F: FnOnce(&mut [u8]) -> Result<R>,
     {
         let mut lower = self.lower.borrow_mut();
         let mut buffer = vec![0; len];

+ 91 - 52
src/socket/dhcpv4.rs

@@ -1,12 +1,12 @@
-use crate::{Error, Result};
-use crate::wire::{IpProtocol, IpAddress,
-           Ipv4Cidr, Ipv4Address, Ipv4Repr,
-           UdpRepr, UDP_HEADER_LEN,
-           DhcpPacket, DhcpRepr, DhcpMessageType, DHCP_CLIENT_PORT, DHCP_SERVER_PORT, DHCP_MAX_DNS_SERVER_COUNT};
-use crate::wire::dhcpv4::{field as dhcpv4_field};
-use crate::socket::{SocketMeta, Context};
-use crate::time::{Instant, Duration};
 use crate::socket::SocketHandle;
+use crate::socket::{Context, SocketMeta};
+use crate::time::{Duration, Instant};
+use crate::wire::dhcpv4::field as dhcpv4_field;
+use crate::wire::{
+    DhcpMessageType, DhcpPacket, DhcpRepr, IpAddress, IpProtocol, Ipv4Address, Ipv4Cidr, Ipv4Repr,
+    UdpRepr, DHCP_CLIENT_PORT, DHCP_MAX_DNS_SERVER_COUNT, DHCP_SERVER_PORT, UDP_HEADER_LEN,
+};
+use crate::{Error, Result};
 
 use super::{PollAt, Socket};
 
@@ -31,7 +31,7 @@ const PARAMETER_REQUEST_LIST: &[u8] = &[
 #[derive(Debug, Eq, PartialEq)]
 #[cfg_attr(feature = "defmt", derive(defmt::Format))]
 pub struct Config {
-    /// IP address 
+    /// IP address
     pub address: Ipv4Cidr,
     /// Router address, also known as default gateway. Does not necessarily
     /// match the DHCP server's address.
@@ -133,7 +133,7 @@ impl Dhcpv4Socket {
     pub fn new() -> Self {
         Dhcpv4Socket {
             meta: SocketMeta::default(),
-            state: ClientState::Discovering(DiscoverState{
+            state: ClientState::Discovering(DiscoverState {
                 retry_at: Instant::from_millis(0),
             }),
             config_changed: true,
@@ -159,7 +159,13 @@ impl Dhcpv4Socket {
         PollAt::Time(t)
     }
 
-    pub(crate) fn process(&mut self, cx: &Context, ip_repr: &Ipv4Repr, repr: &UdpRepr, payload: &[u8]) -> Result<()> {
+    pub(crate) fn process(
+        &mut self,
+        cx: &Context,
+        ip_repr: &Ipv4Repr,
+        repr: &UdpRepr,
+        payload: &[u8],
+    ) -> Result<()> {
         let src_ip = ip_repr.src_addr;
 
         // This is enforced in interface.rs.
@@ -179,25 +185,37 @@ impl Dhcpv4Socket {
                 return Ok(());
             }
         };
-        if dhcp_repr.client_hardware_address != cx.ethernet_address.unwrap() { return Ok(()) }
-        if dhcp_repr.transaction_id != self.transaction_id { return Ok(()) }
+        if dhcp_repr.client_hardware_address != cx.ethernet_address.unwrap() {
+            return Ok(());
+        }
+        if dhcp_repr.transaction_id != self.transaction_id {
+            return Ok(());
+        }
         let server_identifier = match dhcp_repr.server_identifier {
             Some(server_identifier) => server_identifier,
             None => {
-                net_debug!("DHCP ignoring {:?} because missing server_identifier", dhcp_repr.message_type);
+                net_debug!(
+                    "DHCP ignoring {:?} because missing server_identifier",
+                    dhcp_repr.message_type
+                );
                 return Ok(());
             }
         };
 
-        net_debug!("DHCP recv {:?} from {} ({})", dhcp_repr.message_type, src_ip, server_identifier);
-        
-        match (&mut self.state, dhcp_repr.message_type){
+        net_debug!(
+            "DHCP recv {:?} from {} ({})",
+            dhcp_repr.message_type,
+            src_ip,
+            server_identifier
+        );
+
+        match (&mut self.state, dhcp_repr.message_type) {
             (ClientState::Discovering(_state), DhcpMessageType::Offer) => {
                 if !dhcp_repr.your_ip.is_unicast() {
                     net_debug!("DHCP ignoring OFFER because your_ip is not unicast");
-                    return Ok(())
+                    return Ok(());
                 }
-                
+
                 self.state = ClientState::Requesting(RequestState {
                     retry_at: cx.now,
                     retry: 0,
@@ -205,13 +223,15 @@ impl Dhcpv4Socket {
                         address: src_ip,
                         identifier: server_identifier,
                     },
-                    requested_ip: dhcp_repr.your_ip // use the offered ip
+                    requested_ip: dhcp_repr.your_ip, // use the offered ip
                 });
             }
             (ClientState::Requesting(state), DhcpMessageType::Ack) => {
-                if let Some((config, renew_at, expires_at)) = Self::parse_ack(cx.now, &dhcp_repr, self.max_lease_duration) {
+                if let Some((config, renew_at, expires_at)) =
+                    Self::parse_ack(cx.now, &dhcp_repr, self.max_lease_duration)
+                {
                     self.config_changed = true;
-                    self.state = ClientState::Renewing(RenewState{
+                    self.state = ClientState::Renewing(RenewState {
                         server: state.server,
                         config,
                         renew_at,
@@ -223,7 +243,9 @@ impl Dhcpv4Socket {
                 self.reset();
             }
             (ClientState::Renewing(state), DhcpMessageType::Ack) => {
-                if let Some((config, renew_at, expires_at)) = Self::parse_ack(cx.now, &dhcp_repr, self.max_lease_duration) {
+                if let Some((config, renew_at, expires_at)) =
+                    Self::parse_ack(cx.now, &dhcp_repr, self.max_lease_duration)
+                {
                     state.renew_at = renew_at;
                     state.expires_at = expires_at;
                     if state.config != config {
@@ -236,19 +258,26 @@ impl Dhcpv4Socket {
                 self.reset();
             }
             _ => {
-                net_debug!("DHCP ignoring {:?}: unexpected in current state", dhcp_repr.message_type);
+                net_debug!(
+                    "DHCP ignoring {:?}: unexpected in current state",
+                    dhcp_repr.message_type
+                );
             }
         }
 
         Ok(())
     }
 
-    fn parse_ack(now: Instant, dhcp_repr: &DhcpRepr, max_lease_duration: Option<Duration>) -> Option<(Config, Instant, Instant)> {
+    fn parse_ack(
+        now: Instant,
+        dhcp_repr: &DhcpRepr,
+        max_lease_duration: Option<Duration>,
+    ) -> Option<(Config, Instant, Instant)> {
         let subnet_mask = match dhcp_repr.subnet_mask {
             Some(subnet_mask) => subnet_mask,
             None => {
                 net_debug!("DHCP ignoring ACK because missing subnet_mask");
-                return None
+                return None;
             }
         };
 
@@ -256,16 +285,19 @@ impl Dhcpv4Socket {
             Some(prefix_len) => prefix_len,
             None => {
                 net_debug!("DHCP ignoring ACK because subnet_mask is not a valid mask");
-                return None
+                return None;
             }
         };
 
         if !dhcp_repr.your_ip.is_unicast() {
             net_debug!("DHCP ignoring ACK because your_ip is not unicast");
-            return None
+            return None;
         }
 
-        let mut lease_duration = dhcp_repr.lease_duration.map(|d| Duration::from_secs(d as _)).unwrap_or(DEFAULT_LEASE_DURATION);
+        let mut lease_duration = dhcp_repr
+            .lease_duration
+            .map(|d| Duration::from_secs(d as _))
+            .unwrap_or(DEFAULT_LEASE_DURATION);
         if let Some(max_lease_duration) = max_lease_duration {
             lease_duration = lease_duration.min(max_lease_duration);
         }
@@ -275,20 +307,18 @@ impl Dhcpv4Socket {
         let mut dns_servers = [None; DHCP_MAX_DNS_SERVER_COUNT];
         if let Some(received) = dhcp_repr.dns_servers {
             let mut i = 0;
-            for addr in received.iter() {
-                if let Some(addr) = addr{
-                    if addr.is_unicast() {
-                        // This can never be out-of-bounds since both arrays have length DHCP_MAX_DNS_SERVER_COUNT
-                        dns_servers[i] = Some(*addr);
-                        i += 1;
-                    }
+            for addr in received.iter().flatten() {
+                if addr.is_unicast() {
+                    // This can never be out-of-bounds since both arrays have length DHCP_MAX_DNS_SERVER_COUNT
+                    dns_servers[i] = Some(*addr);
+                    i += 1;
                 }
             }
         }
-        let config = Config{
+        let config = Config {
             address: Ipv4Cidr::new(dhcp_repr.your_ip, prefix_len),
             router: dhcp_repr.router,
-            dns_servers: dns_servers
+            dns_servers: dns_servers,
         };
 
         // RFC 2131 indicates clients should renew a lease halfway through its expiration.
@@ -299,9 +329,10 @@ impl Dhcpv4Socket {
     }
 
     pub(crate) fn dispatch<F>(&mut self, cx: &Context, emit: F) -> Result<()>
-            where F: FnOnce((Ipv4Repr, UdpRepr, DhcpRepr)) -> Result<()> {
-
-        // note: Dhcpv4Socket is only usable in ethernet mediums, so the 
+    where
+        F: FnOnce((Ipv4Repr, UdpRepr, DhcpRepr)) -> Result<()>,
+    {
+        // note: Dhcpv4Socket is only usable in ethernet mediums, so the
         // unwrap can never fail.
         let ethernet_addr = cx.ethernet_address.unwrap();
 
@@ -337,7 +368,7 @@ impl Dhcpv4Socket {
             src_port: DHCP_CLIENT_PORT,
             dst_port: DHCP_SERVER_PORT,
         };
-    
+
         let mut ipv4_repr = Ipv4Repr {
             src_addr: Ipv4Address::UNSPECIFIED,
             dst_addr: Ipv4Address::BROADCAST,
@@ -349,11 +380,15 @@ impl Dhcpv4Socket {
         match &mut self.state {
             ClientState::Discovering(state) => {
                 if cx.now < state.retry_at {
-                    return Err(Error::Exhausted)
+                    return Err(Error::Exhausted);
                 }
 
                 // send packet
-                net_debug!("DHCP send DISCOVER to {}: {:?}", ipv4_repr.dst_addr, dhcp_repr);
+                net_debug!(
+                    "DHCP send DISCOVER to {}: {:?}",
+                    ipv4_repr.dst_addr,
+                    dhcp_repr
+                );
                 ipv4_repr.payload_len = udp_repr.header_len() + dhcp_repr.buffer_len();
                 emit((ipv4_repr, udp_repr, dhcp_repr))?;
 
@@ -364,14 +399,14 @@ impl Dhcpv4Socket {
             }
             ClientState::Requesting(state) => {
                 if cx.now < state.retry_at {
-                    return Err(Error::Exhausted)
+                    return Err(Error::Exhausted);
                 }
 
                 if state.retry >= REQUEST_RETRIES {
                     net_debug!("DHCP request retries exceeded, restarting discovery");
                     self.reset();
                     // return Ok so we get polled again
-                    return Ok(())
+                    return Ok(());
                 }
 
                 dhcp_repr.message_type = DhcpMessageType::Request;
@@ -379,7 +414,11 @@ impl Dhcpv4Socket {
                 dhcp_repr.requested_ip = Some(state.requested_ip);
                 dhcp_repr.server_identifier = Some(state.server.identifier);
 
-                net_debug!("DHCP send request to {}: {:?}", ipv4_repr.dst_addr, dhcp_repr);
+                net_debug!(
+                    "DHCP send request to {}: {:?}",
+                    ipv4_repr.dst_addr,
+                    dhcp_repr
+                );
                 ipv4_repr.payload_len = udp_repr.header_len() + dhcp_repr.buffer_len();
                 emit((ipv4_repr, udp_repr, dhcp_repr))?;
 
@@ -395,11 +434,11 @@ impl Dhcpv4Socket {
                     net_debug!("DHCP lease expired");
                     self.reset();
                     // return Ok so we get polled again
-                    return Ok(())
+                    return Ok(());
                 }
-    
+
                 if cx.now < state.renew_at {
-                    return Err(Error::Exhausted)
+                    return Err(Error::Exhausted);
                 }
 
                 ipv4_repr.src_addr = state.config.address.address();
@@ -411,7 +450,7 @@ impl Dhcpv4Socket {
                 net_debug!("DHCP send renew to {}: {:?}", ipv4_repr.dst_addr, dhcp_repr);
                 ipv4_repr.payload_len = udp_repr.header_len() + dhcp_repr.buffer_len();
                 emit((ipv4_repr, udp_repr, dhcp_repr))?;
-        
+
                 // In both RENEWING and REBINDING states, if the client receives no
                 // response to its DHCPREQUEST message, the client SHOULD wait one-half
                 // of the remaining time until T2 (in RENEWING state) and one-half of
@@ -440,7 +479,7 @@ impl Dhcpv4Socket {
         if let ClientState::Renewing(_) = &self.state {
             self.config_changed = true;
         }
-        self.state = ClientState::Discovering(DiscoverState{
+        self.state = ClientState::Discovering(DiscoverState {
             retry_at: Instant::from_millis(0),
         });
     }

+ 346 - 173
src/socket/icmp.rs

@@ -2,20 +2,20 @@ use core::cmp;
 #[cfg(feature = "async")]
 use core::task::Waker;
 
-use crate::{Error, Result};
 use crate::phy::ChecksumCapabilities;
-use crate::socket::{Socket, SocketMeta, SocketHandle, PollAt, Context};
-use crate::storage::{PacketBuffer, PacketMetadata};
 #[cfg(feature = "async")]
 use crate::socket::WakerRegistration;
+use crate::socket::{Context, PollAt, Socket, SocketHandle, SocketMeta};
+use crate::storage::{PacketBuffer, PacketMetadata};
+use crate::{Error, Result};
 
+use crate::wire::IcmpRepr;
 #[cfg(feature = "proto-ipv4")]
-use crate::wire::{Ipv4Address, Ipv4Repr, Icmpv4Packet, Icmpv4Repr};
+use crate::wire::{Icmpv4Packet, Icmpv4Repr, Ipv4Address, Ipv4Repr};
 #[cfg(feature = "proto-ipv6")]
-use crate::wire::{Ipv6Address, Ipv6Repr, Icmpv6Packet, Icmpv6Repr};
-use crate::wire::IcmpRepr;
-use crate::wire::{UdpPacket, UdpRepr};
+use crate::wire::{Icmpv6Packet, Icmpv6Repr, Ipv6Address, Ipv6Repr};
 use crate::wire::{IpAddress, IpEndpoint, IpProtocol, IpRepr};
+use crate::wire::{UdpPacket, UdpRepr};
 
 /// Type of endpoint to bind the ICMP socket to. See [IcmpSocket::bind] for
 /// more details.
@@ -26,7 +26,7 @@ use crate::wire::{IpAddress, IpEndpoint, IpProtocol, IpRepr};
 pub enum Endpoint {
     Unspecified,
     Ident(u16),
-    Udp(IpEndpoint)
+    Udp(IpEndpoint),
 }
 
 impl Endpoint {
@@ -34,13 +34,15 @@ impl Endpoint {
         match *self {
             Endpoint::Ident(_) => true,
             Endpoint::Udp(endpoint) => endpoint.port != 0,
-            Endpoint::Unspecified => false
+            Endpoint::Unspecified => false,
         }
     }
 }
 
 impl Default for Endpoint {
-    fn default() -> Endpoint { Endpoint::Unspecified }
+    fn default() -> Endpoint {
+        Endpoint::Unspecified
+    }
 }
 
 /// An ICMP packet metadata.
@@ -64,7 +66,7 @@ pub struct IcmpSocket<'a> {
     rx_buffer: IcmpSocketBuffer<'a>,
     tx_buffer: IcmpSocketBuffer<'a>,
     /// The endpoint this socket is communicating with
-    endpoint:  Endpoint,
+    endpoint: Endpoint,
     /// The time-to-live (IPv4) or hop limit (IPv6) value used in outgoing packets.
     hop_limit: Option<u8>,
     #[cfg(feature = "async")]
@@ -75,13 +77,12 @@ pub struct IcmpSocket<'a> {
 
 impl<'a> IcmpSocket<'a> {
     /// Create an ICMP socket with the given buffers.
-    pub fn new(rx_buffer: IcmpSocketBuffer<'a>,
-               tx_buffer: IcmpSocketBuffer<'a>) -> IcmpSocket<'a> {
+    pub fn new(rx_buffer: IcmpSocketBuffer<'a>, tx_buffer: IcmpSocketBuffer<'a>) -> IcmpSocket<'a> {
         IcmpSocket {
-            meta:      SocketMeta::default(),
+            meta: SocketMeta::default(),
             rx_buffer: rx_buffer,
             tx_buffer: tx_buffer,
-            endpoint:  Endpoint::default(),
+            endpoint: Endpoint::default(),
             hop_limit: None,
             #[cfg(feature = "async")]
             rx_waker: WakerRegistration::new(),
@@ -219,7 +220,9 @@ impl<'a> IcmpSocket<'a> {
             return Err(Error::Unaddressable);
         }
 
-        if self.is_open() { return Err(Error::Illegal) }
+        if self.is_open() {
+            return Err(Error::Illegal);
+        }
 
         self.endpoint = endpoint;
 
@@ -282,13 +285,17 @@ impl<'a> IcmpSocket<'a> {
     /// size, and `Err(Error::Unaddressable)` if the remote address is unspecified.
     pub fn send(&mut self, size: usize, endpoint: IpAddress) -> Result<&mut [u8]> {
         if endpoint.is_unspecified() {
-            return Err(Error::Unaddressable)
+            return Err(Error::Unaddressable);
         }
 
         let packet_buf = self.tx_buffer.enqueue(size, endpoint)?;
 
-        net_trace!("{}:{}: buffer to send {} octets",
-                   self.meta.handle, endpoint, size);
+        net_trace!(
+            "{}:{}: buffer to send {} octets",
+            self.meta.handle,
+            endpoint,
+            size
+        );
         Ok(packet_buf)
     }
 
@@ -308,8 +315,12 @@ impl<'a> IcmpSocket<'a> {
     pub fn recv(&mut self) -> Result<(&[u8], IpAddress)> {
         let (endpoint, packet_buf) = self.rx_buffer.dequeue()?;
 
-        net_trace!("{}:{}: receive {} buffered octets",
-                   self.meta.handle, endpoint, packet_buf.len());
+        net_trace!(
+            "{}:{}: receive {} buffered octets",
+            self.meta.handle,
+            endpoint,
+            packet_buf.len()
+        );
         Ok((packet_buf, endpoint))
     }
 
@@ -332,19 +343,33 @@ impl<'a> IcmpSocket<'a> {
             // accept Destination Unreachable messages with the data containing
             // a UDP packet send from the local port we are bound to.
             #[cfg(feature = "proto-ipv4")]
-            (&Endpoint::Udp(endpoint), &IcmpRepr::Ipv4(Icmpv4Repr::DstUnreachable { data, .. }))
-                    if endpoint.addr.is_unspecified() || endpoint.addr == ip_repr.dst_addr() => {
+            (
+                &Endpoint::Udp(endpoint),
+                &IcmpRepr::Ipv4(Icmpv4Repr::DstUnreachable { data, .. }),
+            ) if endpoint.addr.is_unspecified() || endpoint.addr == ip_repr.dst_addr() => {
                 let packet = UdpPacket::new_unchecked(data);
-                match UdpRepr::parse(&packet, &ip_repr.src_addr(), &ip_repr.dst_addr(), &cx.caps.checksum) {
+                match UdpRepr::parse(
+                    &packet,
+                    &ip_repr.src_addr(),
+                    &ip_repr.dst_addr(),
+                    &cx.caps.checksum,
+                ) {
                     Ok(repr) => endpoint.port == repr.src_port,
                     Err(_) => false,
                 }
             }
             #[cfg(feature = "proto-ipv6")]
-            (&Endpoint::Udp(endpoint), &IcmpRepr::Ipv6(Icmpv6Repr::DstUnreachable { data, .. }))
-                    if endpoint.addr.is_unspecified() || endpoint.addr == ip_repr.dst_addr() => {
+            (
+                &Endpoint::Udp(endpoint),
+                &IcmpRepr::Ipv6(Icmpv6Repr::DstUnreachable { data, .. }),
+            ) if endpoint.addr.is_unspecified() || endpoint.addr == ip_repr.dst_addr() => {
                 let packet = UdpPacket::new_unchecked(data);
-                match UdpRepr::parse(&packet, &ip_repr.src_addr(), &ip_repr.dst_addr(), &cx.caps.checksum) {
+                match UdpRepr::parse(
+                    &packet,
+                    &ip_repr.src_addr(),
+                    &ip_repr.dst_addr(),
+                    &cx.caps.checksum,
+                ) {
                     Ok(repr) => endpoint.port == repr.src_port,
                     Err(_) => false,
                 }
@@ -353,44 +378,70 @@ impl<'a> IcmpSocket<'a> {
             // Echo Request/Reply with the identifier field matching the endpoint
             // port.
             #[cfg(feature = "proto-ipv4")]
-            (&Endpoint::Ident(bound_ident),
-             &IcmpRepr::Ipv4(Icmpv4Repr::EchoRequest { ident, .. })) |
-            (&Endpoint::Ident(bound_ident),
-             &IcmpRepr::Ipv4(Icmpv4Repr::EchoReply { ident, .. })) =>
-                ident == bound_ident,
+            (
+                &Endpoint::Ident(bound_ident),
+                &IcmpRepr::Ipv4(Icmpv4Repr::EchoRequest { ident, .. }),
+            )
+            | (
+                &Endpoint::Ident(bound_ident),
+                &IcmpRepr::Ipv4(Icmpv4Repr::EchoReply { ident, .. }),
+            ) => ident == bound_ident,
             #[cfg(feature = "proto-ipv6")]
-            (&Endpoint::Ident(bound_ident),
-             &IcmpRepr::Ipv6(Icmpv6Repr::EchoRequest { ident, .. })) |
-            (&Endpoint::Ident(bound_ident),
-             &IcmpRepr::Ipv6(Icmpv6Repr::EchoReply { ident, .. })) =>
-                ident == bound_ident,
+            (
+                &Endpoint::Ident(bound_ident),
+                &IcmpRepr::Ipv6(Icmpv6Repr::EchoRequest { ident, .. }),
+            )
+            | (
+                &Endpoint::Ident(bound_ident),
+                &IcmpRepr::Ipv6(Icmpv6Repr::EchoReply { ident, .. }),
+            ) => ident == bound_ident,
             _ => false,
         }
     }
 
-    pub(crate) fn process(&mut self, _cx: &Context, ip_repr: &IpRepr, icmp_repr: &IcmpRepr) -> Result<()> {
+    pub(crate) fn process(
+        &mut self,
+        _cx: &Context,
+        ip_repr: &IpRepr,
+        icmp_repr: &IcmpRepr,
+    ) -> Result<()> {
         match *icmp_repr {
             #[cfg(feature = "proto-ipv4")]
             IcmpRepr::Ipv4(ref icmp_repr) => {
-                let packet_buf = self.rx_buffer.enqueue(icmp_repr.buffer_len(),
-                                                        ip_repr.src_addr())?;
-                icmp_repr.emit(&mut Icmpv4Packet::new_unchecked(packet_buf),
-                               &ChecksumCapabilities::default());
-
-                net_trace!("{}:{}: receiving {} octets",
-                           self.meta.handle, icmp_repr.buffer_len(), packet_buf.len());
-            },
+                let packet_buf = self
+                    .rx_buffer
+                    .enqueue(icmp_repr.buffer_len(), ip_repr.src_addr())?;
+                icmp_repr.emit(
+                    &mut Icmpv4Packet::new_unchecked(packet_buf),
+                    &ChecksumCapabilities::default(),
+                );
+
+                net_trace!(
+                    "{}:{}: receiving {} octets",
+                    self.meta.handle,
+                    icmp_repr.buffer_len(),
+                    packet_buf.len()
+                );
+            }
             #[cfg(feature = "proto-ipv6")]
             IcmpRepr::Ipv6(ref icmp_repr) => {
-                let packet_buf = self.rx_buffer.enqueue(icmp_repr.buffer_len(),
-                                                        ip_repr.src_addr())?;
-                icmp_repr.emit(&ip_repr.src_addr(), &ip_repr.dst_addr(),
-                               &mut Icmpv6Packet::new_unchecked(packet_buf),
-                               &ChecksumCapabilities::default());
-
-                net_trace!("{}:{}: receiving {} octets",
-                           self.meta.handle, icmp_repr.buffer_len(), packet_buf.len());
-            },
+                let packet_buf = self
+                    .rx_buffer
+                    .enqueue(icmp_repr.buffer_len(), ip_repr.src_addr())?;
+                icmp_repr.emit(
+                    &ip_repr.src_addr(),
+                    &ip_repr.dst_addr(),
+                    &mut Icmpv6Packet::new_unchecked(packet_buf),
+                    &ChecksumCapabilities::default(),
+                );
+
+                net_trace!(
+                    "{}:{}: receiving {} octets",
+                    self.meta.handle,
+                    icmp_repr.buffer_len(),
+                    packet_buf.len()
+                );
+            }
         }
 
         #[cfg(feature = "async")]
@@ -400,42 +451,52 @@ impl<'a> IcmpSocket<'a> {
     }
 
     pub(crate) fn dispatch<F>(&mut self, _cx: &Context, emit: F) -> Result<()>
-        where F: FnOnce((IpRepr, IcmpRepr)) -> Result<()>
+    where
+        F: FnOnce((IpRepr, IcmpRepr)) -> Result<()>,
     {
-        let handle    = self.meta.handle;
+        let handle = self.meta.handle;
         let hop_limit = self.hop_limit.unwrap_or(64);
         self.tx_buffer.dequeue_with(|remote_endpoint, packet_buf| {
-            net_trace!("{}:{}: sending {} octets",
-                       handle, remote_endpoint, packet_buf.len());
+            net_trace!(
+                "{}:{}: sending {} octets",
+                handle,
+                remote_endpoint,
+                packet_buf.len()
+            );
             match *remote_endpoint {
                 #[cfg(feature = "proto-ipv4")]
                 IpAddress::Ipv4(ipv4_addr) => {
                     let packet = Icmpv4Packet::new_unchecked(&*packet_buf);
                     let repr = Icmpv4Repr::parse(&packet, &ChecksumCapabilities::ignored())?;
                     let ip_repr = IpRepr::Ipv4(Ipv4Repr {
-                        src_addr:    Ipv4Address::default(),
-                        dst_addr:    ipv4_addr,
-                        protocol:    IpProtocol::Icmp,
+                        src_addr: Ipv4Address::default(),
+                        dst_addr: ipv4_addr,
+                        protocol: IpProtocol::Icmp,
                         payload_len: repr.buffer_len(),
-                        hop_limit:   hop_limit,
+                        hop_limit: hop_limit,
                     });
                     emit((ip_repr, IcmpRepr::Ipv4(repr)))
-                },
+                }
                 #[cfg(feature = "proto-ipv6")]
                 IpAddress::Ipv6(ipv6_addr) => {
                     let packet = Icmpv6Packet::new_unchecked(&*packet_buf);
                     let src_addr = Ipv6Address::default();
-                    let repr = Icmpv6Repr::parse(&src_addr.into(), &ipv6_addr.into(), &packet, &ChecksumCapabilities::ignored())?;
+                    let repr = Icmpv6Repr::parse(
+                        &src_addr.into(),
+                        &ipv6_addr.into(),
+                        &packet,
+                        &ChecksumCapabilities::ignored(),
+                    )?;
                     let ip_repr = IpRepr::Ipv6(Ipv6Repr {
-                        src_addr:    src_addr,
-                        dst_addr:    ipv6_addr,
+                        src_addr: src_addr,
+                        dst_addr: ipv6_addr,
                         next_header: IpProtocol::Icmpv6,
                         payload_len: repr.buffer_len(),
-                        hop_limit:   hop_limit,
+                        hop_limit: hop_limit,
                     });
                     emit((ip_repr, IcmpRepr::Ipv6(repr)))
-                },
-                _ => Err(Error::Unaddressable)
+                }
+                _ => Err(Error::Unaddressable),
             }
         })?;
 
@@ -462,20 +523,25 @@ impl<'a> Into<Socket<'a>> for IcmpSocket<'a> {
 
 #[cfg(test)]
 mod tests_common {
+    pub use super::*;
     pub use crate::phy::DeviceCapabilities;
     pub use crate::wire::IpAddress;
-    pub use super::*;
 
     pub fn buffer(packets: usize) -> IcmpSocketBuffer<'static> {
-        IcmpSocketBuffer::new(vec![IcmpPacketMetadata::EMPTY; packets], vec![0; 66 * packets])
+        IcmpSocketBuffer::new(
+            vec![IcmpPacketMetadata::EMPTY; packets],
+            vec![0; 66 * packets],
+        )
     }
 
-    pub fn socket(rx_buffer: IcmpSocketBuffer<'static>,
-              tx_buffer: IcmpSocketBuffer<'static>) -> IcmpSocket<'static> {
+    pub fn socket(
+        rx_buffer: IcmpSocketBuffer<'static>,
+        tx_buffer: IcmpSocketBuffer<'static>,
+    ) -> IcmpSocket<'static> {
         IcmpSocket::new(rx_buffer, tx_buffer)
     }
 
-    pub const LOCAL_PORT:  u16         = 53;
+    pub const LOCAL_PORT: u16 = 53;
 
     pub static UDP_REPR: UdpRepr = UdpRepr {
         src_port: 53,
@@ -492,13 +558,16 @@ mod test_ipv4 {
     use crate::wire::Icmpv4DstUnreachable;
 
     const REMOTE_IPV4: Ipv4Address = Ipv4Address([0x7f, 0x00, 0x00, 0x02]);
-    const LOCAL_IPV4:  Ipv4Address = Ipv4Address([0x7f, 0x00, 0x00, 0x01]);
-    const LOCAL_END_V4: IpEndpoint = IpEndpoint { addr: IpAddress::Ipv4(LOCAL_IPV4), port: LOCAL_PORT };
+    const LOCAL_IPV4: Ipv4Address = Ipv4Address([0x7f, 0x00, 0x00, 0x01]);
+    const LOCAL_END_V4: IpEndpoint = IpEndpoint {
+        addr: IpAddress::Ipv4(LOCAL_IPV4),
+        port: LOCAL_PORT,
+    };
 
     static ECHOV4_REPR: Icmpv4Repr = Icmpv4Repr::EchoRequest {
-            ident:  0x1234,
-            seq_no: 0x5678,
-            data:   &[0xff; 16]
+        ident: 0x1234,
+        seq_no: 0x5678,
+        data: &[0xff; 16],
     };
 
     static LOCAL_IPV4_REPR: IpRepr = IpRepr::Ipv4(Ipv4Repr {
@@ -506,7 +575,7 @@ mod test_ipv4 {
         dst_addr: REMOTE_IPV4,
         protocol: IpProtocol::Icmp,
         payload_len: 24,
-        hop_limit: 0x40
+        hop_limit: 0x40,
     });
 
     static REMOTE_IPV4_REPR: IpRepr = IpRepr::Ipv4(Ipv4Repr {
@@ -514,14 +583,16 @@ mod test_ipv4 {
         dst_addr: LOCAL_IPV4,
         protocol: IpProtocol::Icmp,
         payload_len: 24,
-        hop_limit: 0x40
+        hop_limit: 0x40,
     });
 
     #[test]
     fn test_send_unaddressable() {
         let mut socket = socket(buffer(0), buffer(1));
-        assert_eq!(socket.send_slice(b"abcdef", IpAddress::default()),
-                   Err(Error::Unaddressable));
+        assert_eq!(
+            socket.send_slice(b"abcdef", IpAddress::default()),
+            Err(Error::Unaddressable)
+        );
         assert_eq!(socket.send_slice(b"abcdef", REMOTE_IPV4.into()), Ok(()));
     }
 
@@ -530,34 +601,51 @@ mod test_ipv4 {
         let mut socket = socket(buffer(0), buffer(1));
         let checksum = ChecksumCapabilities::default();
 
-        assert_eq!(socket.dispatch(&Context::DUMMY, |_| unreachable!()),
-                   Err(Error::Exhausted));
+        assert_eq!(
+            socket.dispatch(&Context::DUMMY, |_| unreachable!()),
+            Err(Error::Exhausted)
+        );
 
         // This buffer is too long
-        assert_eq!(socket.send_slice(&[0xff; 67], REMOTE_IPV4.into()), Err(Error::Truncated));
+        assert_eq!(
+            socket.send_slice(&[0xff; 67], REMOTE_IPV4.into()),
+            Err(Error::Truncated)
+        );
         assert!(socket.can_send());
 
         let mut bytes = [0xff; 24];
         let mut packet = Icmpv4Packet::new_unchecked(&mut bytes);
         ECHOV4_REPR.emit(&mut packet, &checksum);
 
-        assert_eq!(socket.send_slice(&packet.into_inner()[..], REMOTE_IPV4.into()), Ok(()));
-        assert_eq!(socket.send_slice(b"123456", REMOTE_IPV4.into()), Err(Error::Exhausted));
+        assert_eq!(
+            socket.send_slice(&packet.into_inner()[..], REMOTE_IPV4.into()),
+            Ok(())
+        );
+        assert_eq!(
+            socket.send_slice(b"123456", REMOTE_IPV4.into()),
+            Err(Error::Exhausted)
+        );
         assert!(!socket.can_send());
 
-        assert_eq!(socket.dispatch(&Context::DUMMY, |(ip_repr, icmp_repr)| {
-            assert_eq!(ip_repr, LOCAL_IPV4_REPR);
-            assert_eq!(icmp_repr, ECHOV4_REPR.into());
+        assert_eq!(
+            socket.dispatch(&Context::DUMMY, |(ip_repr, icmp_repr)| {
+                assert_eq!(ip_repr, LOCAL_IPV4_REPR);
+                assert_eq!(icmp_repr, ECHOV4_REPR.into());
+                Err(Error::Unaddressable)
+            }),
             Err(Error::Unaddressable)
-        }), Err(Error::Unaddressable));
+        );
         // buffer is not taken off of the tx queue due to the error
         assert!(!socket.can_send());
 
-        assert_eq!(socket.dispatch(&Context::DUMMY, |(ip_repr, icmp_repr)| {
-            assert_eq!(ip_repr, LOCAL_IPV4_REPR);
-            assert_eq!(icmp_repr, ECHOV4_REPR.into());
+        assert_eq!(
+            socket.dispatch(&Context::DUMMY, |(ip_repr, icmp_repr)| {
+                assert_eq!(ip_repr, LOCAL_IPV4_REPR);
+                assert_eq!(icmp_repr, ECHOV4_REPR.into());
+                Ok(())
+            }),
             Ok(())
-        }), Ok(()));
+        );
         // buffer is taken off of the queue this time
         assert!(socket.can_send());
     }
@@ -573,17 +661,26 @@ mod test_ipv4 {
 
         s.set_hop_limit(Some(0x2a));
 
-        assert_eq!(s.send_slice(&packet.into_inner()[..], REMOTE_IPV4.into()), Ok(()));
-        assert_eq!(s.dispatch(&Context::DUMMY, |(ip_repr, _)| {
-            assert_eq!(ip_repr, IpRepr::Ipv4(Ipv4Repr {
-                src_addr: Ipv4Address::UNSPECIFIED,
-                dst_addr: REMOTE_IPV4,
-                protocol: IpProtocol::Icmp,
-                payload_len: ECHOV4_REPR.buffer_len(),
-                hop_limit: 0x2a,
-            }));
+        assert_eq!(
+            s.send_slice(&packet.into_inner()[..], REMOTE_IPV4.into()),
+            Ok(())
+        );
+        assert_eq!(
+            s.dispatch(&Context::DUMMY, |(ip_repr, _)| {
+                assert_eq!(
+                    ip_repr,
+                    IpRepr::Ipv4(Ipv4Repr {
+                        src_addr: Ipv4Address::UNSPECIFIED,
+                        dst_addr: REMOTE_IPV4,
+                        protocol: IpProtocol::Icmp,
+                        payload_len: ECHOV4_REPR.buffer_len(),
+                        hop_limit: 0x2a,
+                    })
+                );
+                Ok(())
+            }),
             Ok(())
-        }), Ok(()));
+        );
     }
 
     #[test]
@@ -602,13 +699,17 @@ mod test_ipv4 {
         let data = &packet.into_inner()[..];
 
         assert!(socket.accepts(&Context::DUMMY, &REMOTE_IPV4_REPR, &ECHOV4_REPR.into()));
-        assert_eq!(socket.process(&Context::DUMMY, &REMOTE_IPV4_REPR, &ECHOV4_REPR.into()),
-                   Ok(()));
+        assert_eq!(
+            socket.process(&Context::DUMMY, &REMOTE_IPV4_REPR, &ECHOV4_REPR.into()),
+            Ok(())
+        );
         assert!(socket.can_recv());
 
         assert!(socket.accepts(&Context::DUMMY, &REMOTE_IPV4_REPR, &ECHOV4_REPR.into()));
-        assert_eq!(socket.process(&Context::DUMMY, &REMOTE_IPV4_REPR, &ECHOV4_REPR.into()),
-                   Err(Error::Exhausted));
+        assert_eq!(
+            socket.process(&Context::DUMMY, &REMOTE_IPV4_REPR, &ECHOV4_REPR.into()),
+            Err(Error::Exhausted)
+        );
 
         assert_eq!(socket.recv(), Ok((&data[..], REMOTE_IPV4.into())));
         assert!(!socket.can_recv());
@@ -623,9 +724,9 @@ mod test_ipv4 {
         let mut bytes = [0xff; 20];
         let mut packet = Icmpv4Packet::new_unchecked(&mut bytes);
         let icmp_repr = Icmpv4Repr::EchoRequest {
-            ident:  0x4321,
+            ident: 0x4321,
             seq_no: 0x5678,
-            data:   &[0xff; 16]
+            data: &[0xff; 16],
         };
         icmp_repr.emit(&mut packet, &checksum);
 
@@ -649,7 +750,8 @@ mod test_ipv4 {
             &LOCAL_IPV4.into(),
             UDP_PAYLOAD.len(),
             |buf| buf.copy_from_slice(UDP_PAYLOAD),
-            &checksum);
+            &checksum,
+        );
 
         let data = &packet.into_inner()[..];
 
@@ -660,16 +762,16 @@ mod test_ipv4 {
                 dst_addr: REMOTE_IPV4,
                 protocol: IpProtocol::Icmp,
                 payload_len: 12,
-                hop_limit: 0x40
+                hop_limit: 0x40,
             },
-            data: data
+            data: data,
         };
         let ip_repr = IpRepr::Unspecified {
             src_addr: REMOTE_IPV4.into(),
             dst_addr: LOCAL_IPV4.into(),
             protocol: IpProtocol::Icmp,
             payload_len: icmp_repr.buffer_len(),
-            hop_limit: 0x40
+            hop_limit: 0x40,
         };
 
         assert!(!socket.can_recv());
@@ -677,14 +779,19 @@ mod test_ipv4 {
         // Ensure we can accept ICMP error response to the bound
         // UDP port
         assert!(socket.accepts(&Context::DUMMY, &ip_repr, &icmp_repr.into()));
-        assert_eq!(socket.process(&Context::DUMMY, &ip_repr, &icmp_repr.into()),
-                   Ok(()));
+        assert_eq!(
+            socket.process(&Context::DUMMY, &ip_repr, &icmp_repr.into()),
+            Ok(())
+        );
         assert!(socket.can_recv());
 
         let mut bytes = [0x00; 46];
         let mut packet = Icmpv4Packet::new_unchecked(&mut bytes[..]);
         icmp_repr.emit(&mut packet, &checksum);
-        assert_eq!(socket.recv(), Ok((&packet.into_inner()[..], REMOTE_IPV4.into())));
+        assert_eq!(
+            socket.recv(),
+            Ok((&packet.into_inner()[..], REMOTE_IPV4.into()))
+        );
         assert!(!socket.can_recv());
     }
 }
@@ -695,15 +802,18 @@ mod test_ipv6 {
 
     use crate::wire::Icmpv6DstUnreachable;
 
-    const REMOTE_IPV6: Ipv6Address = Ipv6Address([0xfe, 0x80, 0, 0, 0, 0, 0, 0,
-                                                  0, 0, 0, 0, 0, 0, 0, 1]);
-    const LOCAL_IPV6:  Ipv6Address = Ipv6Address([0xfe, 0x80, 0, 0, 0, 0, 0, 0,
-                                                  0, 0, 0, 0, 0, 0, 0, 2]);
-    const LOCAL_END_V6: IpEndpoint = IpEndpoint { addr: IpAddress::Ipv6(LOCAL_IPV6), port: LOCAL_PORT };
+    const REMOTE_IPV6: Ipv6Address =
+        Ipv6Address([0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]);
+    const LOCAL_IPV6: Ipv6Address =
+        Ipv6Address([0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2]);
+    const LOCAL_END_V6: IpEndpoint = IpEndpoint {
+        addr: IpAddress::Ipv6(LOCAL_IPV6),
+        port: LOCAL_PORT,
+    };
     static ECHOV6_REPR: Icmpv6Repr = Icmpv6Repr::EchoRequest {
-            ident:  0x1234,
-            seq_no: 0x5678,
-            data:   &[0xff; 16]
+        ident: 0x1234,
+        seq_no: 0x5678,
+        data: &[0xff; 16],
     };
 
     static LOCAL_IPV6_REPR: IpRepr = IpRepr::Ipv6(Ipv6Repr {
@@ -711,7 +821,7 @@ mod test_ipv6 {
         dst_addr: REMOTE_IPV6,
         next_header: IpProtocol::Icmpv6,
         payload_len: 24,
-        hop_limit: 0x40
+        hop_limit: 0x40,
     });
 
     static REMOTE_IPV6_REPR: IpRepr = IpRepr::Ipv6(Ipv6Repr {
@@ -719,14 +829,16 @@ mod test_ipv6 {
         dst_addr: LOCAL_IPV6,
         next_header: IpProtocol::Icmpv6,
         payload_len: 24,
-        hop_limit: 0x40
+        hop_limit: 0x40,
     });
 
     #[test]
     fn test_send_unaddressable() {
         let mut socket = socket(buffer(0), buffer(1));
-        assert_eq!(socket.send_slice(b"abcdef", IpAddress::default()),
-                   Err(Error::Unaddressable));
+        assert_eq!(
+            socket.send_slice(b"abcdef", IpAddress::default()),
+            Err(Error::Unaddressable)
+        );
         assert_eq!(socket.send_slice(b"abcdef", REMOTE_IPV6.into()), Ok(()));
     }
 
@@ -735,34 +847,56 @@ mod test_ipv6 {
         let mut socket = socket(buffer(0), buffer(1));
         let checksum = ChecksumCapabilities::default();
 
-        assert_eq!(socket.dispatch(&Context::DUMMY, |_| unreachable!()),
-                   Err(Error::Exhausted));
+        assert_eq!(
+            socket.dispatch(&Context::DUMMY, |_| unreachable!()),
+            Err(Error::Exhausted)
+        );
 
         // This buffer is too long
-        assert_eq!(socket.send_slice(&[0xff; 67], REMOTE_IPV6.into()), Err(Error::Truncated));
+        assert_eq!(
+            socket.send_slice(&[0xff; 67], REMOTE_IPV6.into()),
+            Err(Error::Truncated)
+        );
         assert!(socket.can_send());
 
         let mut bytes = vec![0xff; 24];
         let mut packet = Icmpv6Packet::new_unchecked(&mut bytes);
-        ECHOV6_REPR.emit(&LOCAL_IPV6.into(), &REMOTE_IPV6.into(), &mut packet, &checksum);
+        ECHOV6_REPR.emit(
+            &LOCAL_IPV6.into(),
+            &REMOTE_IPV6.into(),
+            &mut packet,
+            &checksum,
+        );
 
-        assert_eq!(socket.send_slice(&packet.into_inner()[..], REMOTE_IPV6.into()), Ok(()));
-        assert_eq!(socket.send_slice(b"123456", REMOTE_IPV6.into()), Err(Error::Exhausted));
+        assert_eq!(
+            socket.send_slice(&packet.into_inner()[..], REMOTE_IPV6.into()),
+            Ok(())
+        );
+        assert_eq!(
+            socket.send_slice(b"123456", REMOTE_IPV6.into()),
+            Err(Error::Exhausted)
+        );
         assert!(!socket.can_send());
 
-        assert_eq!(socket.dispatch(&Context::DUMMY, |(ip_repr, icmp_repr)| {
-            assert_eq!(ip_repr, LOCAL_IPV6_REPR);
-            assert_eq!(icmp_repr, ECHOV6_REPR.into());
+        assert_eq!(
+            socket.dispatch(&Context::DUMMY, |(ip_repr, icmp_repr)| {
+                assert_eq!(ip_repr, LOCAL_IPV6_REPR);
+                assert_eq!(icmp_repr, ECHOV6_REPR.into());
+                Err(Error::Unaddressable)
+            }),
             Err(Error::Unaddressable)
-        }), Err(Error::Unaddressable));
+        );
         // buffer is not taken off of the tx queue due to the error
         assert!(!socket.can_send());
 
-        assert_eq!(socket.dispatch(&Context::DUMMY, |(ip_repr, icmp_repr)| {
-            assert_eq!(ip_repr, LOCAL_IPV6_REPR);
-            assert_eq!(icmp_repr, ECHOV6_REPR.into());
+        assert_eq!(
+            socket.dispatch(&Context::DUMMY, |(ip_repr, icmp_repr)| {
+                assert_eq!(ip_repr, LOCAL_IPV6_REPR);
+                assert_eq!(icmp_repr, ECHOV6_REPR.into());
+                Ok(())
+            }),
             Ok(())
-        }), Ok(()));
+        );
         // buffer is taken off of the queue this time
         assert!(socket.can_send());
     }
@@ -774,21 +908,35 @@ mod test_ipv6 {
 
         let mut bytes = vec![0xff; 24];
         let mut packet = Icmpv6Packet::new_unchecked(&mut bytes);
-        ECHOV6_REPR.emit(&LOCAL_IPV6.into(), &REMOTE_IPV6.into(), &mut packet, &checksum);
+        ECHOV6_REPR.emit(
+            &LOCAL_IPV6.into(),
+            &REMOTE_IPV6.into(),
+            &mut packet,
+            &checksum,
+        );
 
         s.set_hop_limit(Some(0x2a));
 
-        assert_eq!(s.send_slice(&packet.into_inner()[..], REMOTE_IPV6.into()), Ok(()));
-        assert_eq!(s.dispatch(&Context::DUMMY, |(ip_repr, _)| {
-            assert_eq!(ip_repr, IpRepr::Ipv6(Ipv6Repr {
-                src_addr: Ipv6Address::UNSPECIFIED,
-                dst_addr: REMOTE_IPV6,
-                next_header: IpProtocol::Icmpv6,
-                payload_len: ECHOV6_REPR.buffer_len(),
-                hop_limit: 0x2a,
-            }));
+        assert_eq!(
+            s.send_slice(&packet.into_inner()[..], REMOTE_IPV6.into()),
             Ok(())
-        }), Ok(()));
+        );
+        assert_eq!(
+            s.dispatch(&Context::DUMMY, |(ip_repr, _)| {
+                assert_eq!(
+                    ip_repr,
+                    IpRepr::Ipv6(Ipv6Repr {
+                        src_addr: Ipv6Address::UNSPECIFIED,
+                        dst_addr: REMOTE_IPV6,
+                        next_header: IpProtocol::Icmpv6,
+                        payload_len: ECHOV6_REPR.buffer_len(),
+                        hop_limit: 0x2a,
+                    })
+                );
+                Ok(())
+            }),
+            Ok(())
+        );
     }
 
     #[test]
@@ -803,17 +951,26 @@ mod test_ipv6 {
 
         let mut bytes = [0xff; 24];
         let mut packet = Icmpv6Packet::new_unchecked(&mut bytes);
-        ECHOV6_REPR.emit(&LOCAL_IPV6.into(), &REMOTE_IPV6.into(), &mut packet, &checksum);
+        ECHOV6_REPR.emit(
+            &LOCAL_IPV6.into(),
+            &REMOTE_IPV6.into(),
+            &mut packet,
+            &checksum,
+        );
         let data = &packet.into_inner()[..];
 
         assert!(socket.accepts(&Context::DUMMY, &REMOTE_IPV6_REPR, &ECHOV6_REPR.into()));
-        assert_eq!(socket.process(&Context::DUMMY, &REMOTE_IPV6_REPR, &ECHOV6_REPR.into()),
-                   Ok(()));
+        assert_eq!(
+            socket.process(&Context::DUMMY, &REMOTE_IPV6_REPR, &ECHOV6_REPR.into()),
+            Ok(())
+        );
         assert!(socket.can_recv());
 
         assert!(socket.accepts(&Context::DUMMY, &REMOTE_IPV6_REPR, &ECHOV6_REPR.into()));
-        assert_eq!(socket.process(&Context::DUMMY, &REMOTE_IPV6_REPR, &ECHOV6_REPR.into()),
-                   Err(Error::Exhausted));
+        assert_eq!(
+            socket.process(&Context::DUMMY, &REMOTE_IPV6_REPR, &ECHOV6_REPR.into()),
+            Err(Error::Exhausted)
+        );
 
         assert_eq!(socket.recv(), Ok((&data[..], REMOTE_IPV6.into())));
         assert!(!socket.can_recv());
@@ -828,11 +985,16 @@ mod test_ipv6 {
         let mut bytes = [0xff; 20];
         let mut packet = Icmpv6Packet::new_unchecked(&mut bytes);
         let icmp_repr = Icmpv6Repr::EchoRequest {
-            ident:  0x4321,
+            ident: 0x4321,
             seq_no: 0x5678,
-            data:   &[0xff; 16]
+            data: &[0xff; 16],
         };
-        icmp_repr.emit(&LOCAL_IPV6.into(), &REMOTE_IPV6.into(), &mut packet, &checksum);
+        icmp_repr.emit(
+            &LOCAL_IPV6.into(),
+            &REMOTE_IPV6.into(),
+            &mut packet,
+            &checksum,
+        );
 
         // Ensure that a packet with an identifier that isn't the bound
         // ID is not accepted
@@ -854,7 +1016,8 @@ mod test_ipv6 {
             &LOCAL_IPV6.into(),
             UDP_PAYLOAD.len(),
             |buf| buf.copy_from_slice(UDP_PAYLOAD),
-            &checksum);
+            &checksum,
+        );
 
         let data = &packet.into_inner()[..];
 
@@ -865,16 +1028,16 @@ mod test_ipv6 {
                 dst_addr: REMOTE_IPV6,
                 next_header: IpProtocol::Icmpv6,
                 payload_len: 12,
-                hop_limit: 0x40
+                hop_limit: 0x40,
             },
-            data: data
+            data: data,
         };
         let ip_repr = IpRepr::Unspecified {
             src_addr: REMOTE_IPV6.into(),
             dst_addr: LOCAL_IPV6.into(),
             protocol: IpProtocol::Icmpv6,
             payload_len: icmp_repr.buffer_len(),
-            hop_limit: 0x40
+            hop_limit: 0x40,
         };
 
         assert!(!socket.can_recv());
@@ -882,14 +1045,24 @@ mod test_ipv6 {
         // Ensure we can accept ICMP error response to the bound
         // UDP port
         assert!(socket.accepts(&Context::DUMMY, &ip_repr, &icmp_repr.into()));
-        assert_eq!(socket.process(&Context::DUMMY, &ip_repr, &icmp_repr.into()),
-                   Ok(()));
+        assert_eq!(
+            socket.process(&Context::DUMMY, &ip_repr, &icmp_repr.into()),
+            Ok(())
+        );
         assert!(socket.can_recv());
 
         let mut bytes = [0x00; 66];
         let mut packet = Icmpv6Packet::new_unchecked(&mut bytes[..]);
-        icmp_repr.emit(&LOCAL_IPV6.into(), &REMOTE_IPV6.into(), &mut packet, &checksum);
-        assert_eq!(socket.recv(), Ok((&packet.into_inner()[..], REMOTE_IPV6.into())));
+        icmp_repr.emit(
+            &LOCAL_IPV6.into(),
+            &REMOTE_IPV6.into(),
+            &mut packet,
+            &checksum,
+        );
+        assert_eq!(
+            socket.recv(),
+            Ok((&packet.into_inner()[..], REMOTE_IPV6.into()))
+        );
         assert!(!socket.can_recv());
     }
 }

+ 35 - 23
src/socket/meta.rs

@@ -1,6 +1,6 @@
-use crate::wire::IpAddress;
-use crate::socket::{SocketHandle, PollAt};
+use crate::socket::{PollAt, SocketHandle};
 use crate::time::{Duration, Instant};
+use crate::wire::IpAddress;
 
 /// Neighbor dependency.
 ///
@@ -16,7 +16,7 @@ enum NeighborState {
     Waiting {
         neighbor: IpAddress,
         silent_until: Instant,
-    }
+    },
 }
 
 impl Default for NeighborState {
@@ -36,7 +36,7 @@ pub struct Meta {
     /// Mainly useful for debug output.
     pub(crate) handle: SocketHandle,
     /// See [NeighborState](struct.NeighborState.html).
-    neighbor_state:    NeighborState,
+    neighbor_state: NeighborState,
 }
 
 impl Meta {
@@ -46,34 +46,41 @@ impl Meta {
     /// See also `iface::NeighborCache::SILENT_TIME`.
     pub(crate) const DISCOVERY_SILENT_TIME: Duration = Duration { millis: 3_000 };
 
-    pub(crate) fn poll_at<F>(&self, socket_poll_at: PollAt, has_neighbor: F) -> PollAt 
-        where F: Fn(IpAddress) -> bool
+    pub(crate) fn poll_at<F>(&self, socket_poll_at: PollAt, has_neighbor: F) -> PollAt
+    where
+        F: Fn(IpAddress) -> bool,
     {
         match self.neighbor_state {
-            NeighborState::Active =>
-                socket_poll_at,
-            NeighborState::Waiting { neighbor, .. }
-                    if has_neighbor(neighbor) =>
-                socket_poll_at,
-            NeighborState::Waiting { silent_until, .. } =>
-                PollAt::Time(silent_until)
+            NeighborState::Active => socket_poll_at,
+            NeighborState::Waiting { neighbor, .. } if has_neighbor(neighbor) => socket_poll_at,
+            NeighborState::Waiting { silent_until, .. } => PollAt::Time(silent_until),
         }
     }
 
     pub(crate) fn egress_permitted<F>(&mut self, timestamp: Instant, has_neighbor: F) -> bool
-        where F: Fn(IpAddress) -> bool
+    where
+        F: Fn(IpAddress) -> bool,
     {
         match self.neighbor_state {
-            NeighborState::Active =>
-                true,
-            NeighborState::Waiting { neighbor, silent_until } => {
+            NeighborState::Active => true,
+            NeighborState::Waiting {
+                neighbor,
+                silent_until,
+            } => {
                 if has_neighbor(neighbor) {
-                    net_trace!("{}: neighbor {} discovered, unsilencing",
-                               self.handle, neighbor);
+                    net_trace!(
+                        "{}: neighbor {} discovered, unsilencing",
+                        self.handle,
+                        neighbor
+                    );
                     self.neighbor_state = NeighborState::Active;
                     true
                 } else if timestamp >= silent_until {
-                    net_trace!("{}: neighbor {} silence timer expired, rediscovering", self.handle, neighbor);
+                    net_trace!(
+                        "{}: neighbor {} silence timer expired, rediscovering",
+                        self.handle,
+                        neighbor
+                    );
                     true
                 } else {
                     false
@@ -83,10 +90,15 @@ impl Meta {
     }
 
     pub(crate) fn neighbor_missing(&mut self, timestamp: Instant, neighbor: IpAddress) {
-        net_trace!("{}: neighbor {} missing, silencing until t+{}",
-                   self.handle, neighbor, Self::DISCOVERY_SILENT_TIME);
+        net_trace!(
+            "{}: neighbor {} missing, silencing until t+{}",
+            self.handle,
+            neighbor,
+            Self::DISCOVERY_SILENT_TIME
+        );
         self.neighbor_state = NeighborState::Waiting {
-            neighbor, silent_until: timestamp + Self::DISCOVERY_SILENT_TIME
+            neighbor,
+            silent_until: timestamp + Self::DISCOVERY_SILENT_TIME,
         };
     }
 }

+ 35 - 36
src/socket/mod.rs

@@ -14,19 +14,22 @@ size for a buffer, allocate it, and let the networking stack use it.
 use crate::phy::DeviceCapabilities;
 use crate::time::Instant;
 
+#[cfg(feature = "socket-dhcpv4")]
+mod dhcpv4;
+#[cfg(all(
+    feature = "socket-icmp",
+    any(feature = "proto-ipv4", feature = "proto-ipv6")
+))]
+mod icmp;
 mod meta;
 #[cfg(feature = "socket-raw")]
 mod raw;
-#[cfg(all(feature = "socket-icmp", any(feature = "proto-ipv4", feature = "proto-ipv6")))]
-mod icmp;
-#[cfg(feature = "socket-udp")]
-mod udp;
+mod ref_;
+mod set;
 #[cfg(feature = "socket-tcp")]
 mod tcp;
-#[cfg(feature = "socket-dhcpv4")]
-mod dhcpv4;
-mod set;
-mod ref_;
+#[cfg(feature = "socket-udp")]
+mod udp;
 
 #[cfg(feature = "async")]
 mod waker;
@@ -36,30 +39,24 @@ pub(crate) use self::meta::Meta as SocketMeta;
 pub(crate) use self::waker::WakerRegistration;
 
 #[cfg(feature = "socket-raw")]
-pub use self::raw::{RawPacketMetadata,
-                    RawSocketBuffer,
-                    RawSocket};
+pub use self::raw::{RawPacketMetadata, RawSocket, RawSocketBuffer};
 
-#[cfg(all(feature = "socket-icmp", any(feature = "proto-ipv4", feature = "proto-ipv6")))]
-pub use self::icmp::{IcmpPacketMetadata,
-                     IcmpSocketBuffer,
-                     Endpoint as IcmpEndpoint,
-                     IcmpSocket};
+#[cfg(all(
+    feature = "socket-icmp",
+    any(feature = "proto-ipv4", feature = "proto-ipv6")
+))]
+pub use self::icmp::{Endpoint as IcmpEndpoint, IcmpPacketMetadata, IcmpSocket, IcmpSocketBuffer};
 
 #[cfg(feature = "socket-udp")]
-pub use self::udp::{UdpPacketMetadata,
-                    UdpSocketBuffer,
-                    UdpSocket};
+pub use self::udp::{UdpPacketMetadata, UdpSocket, UdpSocketBuffer};
 
 #[cfg(feature = "socket-tcp")]
-pub use self::tcp::{SocketBuffer as TcpSocketBuffer,
-                    State as TcpState,
-                    TcpSocket};
+pub use self::tcp::{SocketBuffer as TcpSocketBuffer, State as TcpState, TcpSocket};
 
 #[cfg(feature = "socket-dhcpv4")]
-pub use self::dhcpv4::{Dhcpv4Socket, Config as Dhcpv4Config, Event as Dhcpv4Event};
+pub use self::dhcpv4::{Config as Dhcpv4Config, Dhcpv4Socket, Event as Dhcpv4Event};
 
-pub use self::set::{Set as SocketSet, Item as SocketSetItem, Handle as SocketHandle};
+pub use self::set::{Handle as SocketHandle, Item as SocketSetItem, Set as SocketSet};
 pub use self::set::{Iter as SocketSetIter, IterMut as SocketSetIterMut};
 
 pub use self::ref_::Ref as SocketRef;
@@ -91,7 +88,10 @@ pub(crate) enum PollAt {
 pub enum Socket<'a> {
     #[cfg(feature = "socket-raw")]
     Raw(RawSocket<'a>),
-    #[cfg(all(feature = "socket-icmp", any(feature = "proto-ipv4", feature = "proto-ipv6")))]
+    #[cfg(all(
+        feature = "socket-icmp",
+        any(feature = "proto-ipv4", feature = "proto-ipv6")
+    ))]
     Icmp(IcmpSocket<'a>),
     #[cfg(feature = "socket-udp")]
     Udp(UdpSocket<'a>),
@@ -152,15 +152,13 @@ impl<'a> SocketSession for Socket<'a> {
 
 /// A conversion trait for network sockets.
 pub trait AnySocket<'a>: SocketSession + Sized {
-    fn downcast<'c>(socket_ref: SocketRef<'c, Socket<'a>>) ->
-                   Option<SocketRef<'c, Self>>;
+    fn downcast<'c>(socket_ref: SocketRef<'c, Socket<'a>>) -> Option<SocketRef<'c, Self>>;
 }
 
 macro_rules! from_socket {
     ($socket:ty, $variant:ident) => {
         impl<'a> AnySocket<'a> for $socket {
-            fn downcast<'c>(ref_: SocketRef<'c, Socket<'a>>) ->
-                           Option<SocketRef<'c, Self>> {
+            fn downcast<'c>(ref_: SocketRef<'c, Socket<'a>>) -> Option<SocketRef<'c, Self>> {
                 if let Socket::$variant(ref mut socket) = SocketRef::into_inner(ref_) {
                     Some(SocketRef::new(socket))
                 } else {
@@ -168,12 +166,15 @@ macro_rules! from_socket {
                 }
             }
         }
-    }
+    };
 }
 
 #[cfg(feature = "socket-raw")]
 from_socket!(RawSocket<'a>, Raw);
-#[cfg(all(feature = "socket-icmp", any(feature = "proto-ipv4", feature = "proto-ipv6")))]
+#[cfg(all(
+    feature = "socket-icmp",
+    any(feature = "proto-ipv4", feature = "proto-ipv6")
+))]
 from_socket!(IcmpSocket<'a>, Icmp);
 #[cfg(feature = "socket-udp")]
 from_socket!(UdpSocket<'a>, Udp);
@@ -193,14 +194,13 @@ pub(crate) struct Context {
 
 #[cfg(test)]
 impl Context {
-
     pub(crate) const DUMMY: Context = Context {
         caps: DeviceCapabilities {
             #[cfg(feature = "medium-ethernet")]
             medium: crate::phy::Medium::Ethernet,
             #[cfg(not(feature = "medium-ethernet"))]
             medium: crate::phy::Medium::Ip,
-            checksum: crate::phy::ChecksumCapabilities{
+            checksum: crate::phy::ChecksumCapabilities {
                 #[cfg(feature = "proto-ipv4")]
                 icmpv4: crate::phy::Checksum::Both,
                 #[cfg(feature = "proto-ipv6")]
@@ -216,7 +216,6 @@ impl Context {
             max_transmission_unit: 1500,
         },
         ethernet_address: None,
-        now: Instant{millis: 0},
+        now: Instant { millis: 0 },
     };
-
-}
+}

+ 205 - 119
src/socket/raw.rs

@@ -2,18 +2,18 @@ use core::cmp::min;
 #[cfg(feature = "async")]
 use core::task::Waker;
 
-use crate::{Error, Result};
 use crate::phy::ChecksumCapabilities;
-use crate::socket::{Socket, SocketMeta, SocketHandle, PollAt, Context};
-use crate::storage::{PacketBuffer, PacketMetadata};
 #[cfg(feature = "async")]
 use crate::socket::WakerRegistration;
+use crate::socket::{Context, PollAt, Socket, SocketHandle, SocketMeta};
+use crate::storage::{PacketBuffer, PacketMetadata};
+use crate::{Error, Result};
 
-use crate::wire::{IpVersion, IpRepr, IpProtocol};
+use crate::wire::{IpProtocol, IpRepr, IpVersion};
 #[cfg(feature = "proto-ipv4")]
-use crate::wire::{Ipv4Repr, Ipv4Packet};
+use crate::wire::{Ipv4Packet, Ipv4Repr};
 #[cfg(feature = "proto-ipv6")]
-use crate::wire::{Ipv6Repr, Ipv6Packet};
+use crate::wire::{Ipv6Packet, Ipv6Repr};
 
 /// A UDP packet metadata.
 pub type RawPacketMetadata = PacketMetadata<()>;
@@ -28,10 +28,10 @@ pub type RawSocketBuffer<'a> = PacketBuffer<'a, ()>;
 #[derive(Debug)]
 pub struct RawSocket<'a> {
     pub(crate) meta: SocketMeta,
-    ip_version:  IpVersion,
+    ip_version: IpVersion,
     ip_protocol: IpProtocol,
-    rx_buffer:   RawSocketBuffer<'a>,
-    tx_buffer:   RawSocketBuffer<'a>,
+    rx_buffer: RawSocketBuffer<'a>,
+    tx_buffer: RawSocketBuffer<'a>,
     #[cfg(feature = "async")]
     rx_waker: WakerRegistration,
     #[cfg(feature = "async")]
@@ -41,9 +41,12 @@ pub struct RawSocket<'a> {
 impl<'a> RawSocket<'a> {
     /// Create a raw IP socket bound to the given IP version and datagram protocol,
     /// with the given buffers.
-    pub fn new(ip_version: IpVersion, ip_protocol: IpProtocol,
-               rx_buffer: RawSocketBuffer<'a>,
-               tx_buffer: RawSocketBuffer<'a>) -> RawSocket<'a> {
+    pub fn new(
+        ip_version: IpVersion,
+        ip_protocol: IpProtocol,
+        rx_buffer: RawSocketBuffer<'a>,
+        tx_buffer: RawSocketBuffer<'a>,
+    ) -> RawSocket<'a> {
         RawSocket {
             meta: SocketMeta::default(),
             ip_version,
@@ -61,12 +64,12 @@ impl<'a> RawSocket<'a> {
     ///
     /// The waker is woken on state changes that might affect the return value
     /// of `recv` method calls, such as receiving data, or the socket closing.
-    /// 
+    ///
     /// Notes:
     ///
     /// - Only one waker can be registered at a time. If another waker was previously registered,
     ///   it is overwritten and will no longer be woken.
-    /// - The Waker is woken only once. Once woken, you must register it again to receive more wakes. 
+    /// - The Waker is woken only once. Once woken, you must register it again to receive more wakes.
     /// - "Spurious wakes" are allowed: a wake doesn't guarantee the result of `recv` has
     ///   necessarily changed.
     #[cfg(feature = "async")]
@@ -79,12 +82,12 @@ impl<'a> RawSocket<'a> {
     /// The waker is woken on state changes that might affect the return value
     /// of `send` method calls, such as space becoming available in the transmit
     /// buffer, or the socket closing.
-    /// 
+    ///
     /// Notes:
     ///
     /// - Only one waker can be registered at a time. If another waker was previously registered,
     ///   it is overwritten and will no longer be woken.
-    /// - The Waker is woken only once. Once woken, you must register it again to receive more wakes. 
+    /// - The Waker is woken only once. Once woken, you must register it again to receive more wakes.
     /// - "Spurious wakes" are allowed: a wake doesn't guarantee the result of `send` has
     ///   necessarily changed.
     #[cfg(feature = "async")]
@@ -160,9 +163,13 @@ impl<'a> RawSocket<'a> {
     pub fn send(&mut self, size: usize) -> Result<&mut [u8]> {
         let packet_buf = self.tx_buffer.enqueue(size, ())?;
 
-        net_trace!("{}:{}:{}: buffer to send {} octets",
-                   self.meta.handle, self.ip_version, self.ip_protocol,
-                   packet_buf.len());
+        net_trace!(
+            "{}:{}:{}: buffer to send {} octets",
+            self.meta.handle,
+            self.ip_version,
+            self.ip_protocol,
+            packet_buf.len()
+        );
         Ok(packet_buf)
     }
 
@@ -183,9 +190,13 @@ impl<'a> RawSocket<'a> {
     pub fn recv(&mut self) -> Result<&[u8]> {
         let ((), packet_buf) = self.rx_buffer.dequeue()?;
 
-        net_trace!("{}:{}:{}: receive {} buffered octets",
-                   self.meta.handle, self.ip_version, self.ip_protocol,
-                   packet_buf.len());
+        net_trace!(
+            "{}:{}:{}: receive {} buffered octets",
+            self.meta.handle,
+            self.ip_version,
+            self.ip_protocol,
+            packet_buf.len()
+        );
         Ok(packet_buf)
     }
 
@@ -200,8 +211,12 @@ impl<'a> RawSocket<'a> {
     }
 
     pub(crate) fn accepts(&self, ip_repr: &IpRepr) -> bool {
-        if ip_repr.version() != self.ip_version { return false }
-        if ip_repr.protocol() != self.ip_protocol { return false }
+        if ip_repr.version() != self.ip_version {
+            return false;
+        }
+        if ip_repr.protocol() != self.ip_protocol {
+            return false;
+        }
 
         true
     }
@@ -210,14 +225,18 @@ impl<'a> RawSocket<'a> {
         debug_assert!(self.accepts(ip_repr));
 
         let header_len = ip_repr.buffer_len();
-        let total_len  = header_len + payload.len();
+        let total_len = header_len + payload.len();
         let packet_buf = self.rx_buffer.enqueue(total_len, ())?;
         ip_repr.emit(&mut packet_buf[..header_len], &cx.caps.checksum);
         packet_buf[header_len..].copy_from_slice(payload);
 
-        net_trace!("{}:{}:{}: receiving {} octets",
-                   self.meta.handle, self.ip_version, self.ip_protocol,
-                   packet_buf.len());
+        net_trace!(
+            "{}:{}:{}: receiving {} octets",
+            self.meta.handle,
+            self.ip_version,
+            self.ip_protocol,
+            packet_buf.len()
+        );
 
         #[cfg(feature = "async")]
         self.rx_waker.wake();
@@ -226,14 +245,21 @@ impl<'a> RawSocket<'a> {
     }
 
     pub(crate) fn dispatch<F>(&mut self, cx: &Context, emit: F) -> Result<()>
-            where F: FnOnce((IpRepr, &[u8])) -> Result<()> {
-        fn prepare<'a>(protocol: IpProtocol, buffer: &'a mut [u8],
-                   _checksum_caps: &ChecksumCapabilities) -> Result<(IpRepr, &'a [u8])> {
+    where
+        F: FnOnce((IpRepr, &[u8])) -> Result<()>,
+    {
+        fn prepare<'a>(
+            protocol: IpProtocol,
+            buffer: &'a mut [u8],
+            _checksum_caps: &ChecksumCapabilities,
+        ) -> Result<(IpRepr, &'a [u8])> {
             match IpVersion::of_packet(buffer)? {
                 #[cfg(feature = "proto-ipv4")]
                 IpVersion::Ipv4 => {
                     let mut packet = Ipv4Packet::new_checked(buffer)?;
-                    if packet.protocol() != protocol { return Err(Error::Unaddressable) }
+                    if packet.protocol() != protocol {
+                        return Err(Error::Unaddressable);
+                    }
                     if _checksum_caps.ipv4.tx() {
                         packet.fill_checksum();
                     } else {
@@ -249,7 +275,9 @@ impl<'a> RawSocket<'a> {
                 #[cfg(feature = "proto-ipv6")]
                 IpVersion::Ipv6 => {
                     let packet = Ipv6Packet::new_checked(buffer)?;
-                    if packet.next_header() != protocol { return Err(Error::Unaddressable) }
+                    if packet.next_header() != protocol {
+                        return Err(Error::Unaddressable);
+                    }
                     let packet = Ipv6Packet::new_unchecked(&*packet.into_inner());
                     let ipv6_repr = Ipv6Repr::parse(&packet)?;
                     Ok((IpRepr::Ipv6(ipv6_repr), packet.payload()))
@@ -258,21 +286,29 @@ impl<'a> RawSocket<'a> {
             }
         }
 
-        let handle      = self.meta.handle;
+        let handle = self.meta.handle;
         let ip_protocol = self.ip_protocol;
-        let ip_version  = self.ip_version;
+        let ip_version = self.ip_version;
         self.tx_buffer.dequeue_with(|&mut (), packet_buf| {
             match prepare(ip_protocol, packet_buf, &cx.caps.checksum) {
                 Ok((ip_repr, raw_packet)) => {
-                    net_trace!("{}:{}:{}: sending {} octets",
-                               handle, ip_version, ip_protocol,
-                               ip_repr.buffer_len() + raw_packet.len());
+                    net_trace!(
+                        "{}:{}:{}: sending {} octets",
+                        handle,
+                        ip_version,
+                        ip_protocol,
+                        ip_repr.buffer_len() + raw_packet.len()
+                    );
                     emit((ip_repr, raw_packet))
                 }
                 Err(error) => {
-                    net_debug!("{}:{}:{}: dropping outgoing packet ({})",
-                               handle, ip_version, ip_protocol,
-                               error);
+                    net_debug!(
+                        "{}:{}:{}: dropping outgoing packet ({})",
+                        handle,
+                        ip_version,
+                        ip_protocol,
+                        error
+                    );
                     // Return Ok(()) so the packet is dequeued.
                     Ok(())
                 }
@@ -302,26 +338,34 @@ impl<'a> Into<Socket<'a>> for RawSocket<'a> {
 
 #[cfg(test)]
 mod test {
+    use super::*;
     use crate::wire::IpRepr;
     #[cfg(feature = "proto-ipv4")]
     use crate::wire::{Ipv4Address, Ipv4Repr};
     #[cfg(feature = "proto-ipv6")]
     use crate::wire::{Ipv6Address, Ipv6Repr};
-    use super::*;
 
     fn buffer(packets: usize) -> RawSocketBuffer<'static> {
-        RawSocketBuffer::new(vec![RawPacketMetadata::EMPTY; packets], vec![0; 48 * packets])
+        RawSocketBuffer::new(
+            vec![RawPacketMetadata::EMPTY; packets],
+            vec![0; 48 * packets],
+        )
     }
 
     #[cfg(feature = "proto-ipv4")]
     mod ipv4_locals {
         use super::*;
 
-        pub fn socket(rx_buffer: RawSocketBuffer<'static>,
-                      tx_buffer: RawSocketBuffer<'static>)
-                     -> RawSocket<'static> {
-            RawSocket::new(IpVersion::Ipv4, IpProtocol::Unknown(IP_PROTO),
-                           rx_buffer, tx_buffer)
+        pub fn socket(
+            rx_buffer: RawSocketBuffer<'static>,
+            tx_buffer: RawSocketBuffer<'static>,
+        ) -> RawSocket<'static> {
+            RawSocket::new(
+                IpVersion::Ipv4,
+                IpProtocol::Unknown(IP_PROTO),
+                rx_buffer,
+                tx_buffer,
+            )
         }
 
         pub const IP_PROTO: u8 = 63;
@@ -330,60 +374,54 @@ mod test {
             dst_addr: Ipv4Address([10, 0, 0, 2]),
             protocol: IpProtocol::Unknown(IP_PROTO),
             payload_len: 4,
-            hop_limit: 64
+            hop_limit: 64,
         });
         pub const PACKET_BYTES: [u8; 24] = [
-            0x45, 0x00, 0x00, 0x18,
-            0x00, 0x00, 0x40, 0x00,
-            0x40, 0x3f, 0x00, 0x00,
-            0x0a, 0x00, 0x00, 0x01,
-            0x0a, 0x00, 0x00, 0x02,
-            0xaa, 0x00, 0x00, 0xff
-        ];
-        pub const PACKET_PAYLOAD: [u8; 4] = [
-            0xaa, 0x00, 0x00, 0xff
+            0x45, 0x00, 0x00, 0x18, 0x00, 0x00, 0x40, 0x00, 0x40, 0x3f, 0x00, 0x00, 0x0a, 0x00,
+            0x00, 0x01, 0x0a, 0x00, 0x00, 0x02, 0xaa, 0x00, 0x00, 0xff,
         ];
+        pub const PACKET_PAYLOAD: [u8; 4] = [0xaa, 0x00, 0x00, 0xff];
     }
 
     #[cfg(feature = "proto-ipv6")]
     mod ipv6_locals {
         use super::*;
 
-        pub fn socket(rx_buffer: RawSocketBuffer<'static>,
-                      tx_buffer: RawSocketBuffer<'static>)
-                     -> RawSocket<'static> {
-            RawSocket::new(IpVersion::Ipv6, IpProtocol::Unknown(IP_PROTO),
-                           rx_buffer, tx_buffer)
+        pub fn socket(
+            rx_buffer: RawSocketBuffer<'static>,
+            tx_buffer: RawSocketBuffer<'static>,
+        ) -> RawSocket<'static> {
+            RawSocket::new(
+                IpVersion::Ipv6,
+                IpProtocol::Unknown(IP_PROTO),
+                rx_buffer,
+                tx_buffer,
+            )
         }
 
         pub const IP_PROTO: u8 = 63;
         pub const HEADER_REPR: IpRepr = IpRepr::Ipv6(Ipv6Repr {
-            src_addr: Ipv6Address([0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                                   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01]),
-            dst_addr: Ipv6Address([0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                                   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02]),
+            src_addr: Ipv6Address([
+                0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                0x00, 0x01,
+            ]),
+            dst_addr: Ipv6Address([
+                0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                0x00, 0x02,
+            ]),
             next_header: IpProtocol::Unknown(IP_PROTO),
             payload_len: 4,
-            hop_limit: 64
+            hop_limit: 64,
         });
 
         pub const PACKET_BYTES: [u8; 44] = [
-            0x60, 0x00, 0x00, 0x00,
-            0x00, 0x04, 0x3f, 0x40,
-            0xfe, 0x80, 0x00, 0x00,
-            0x00, 0x00, 0x00, 0x00,
-            0x00, 0x00, 0x00, 0x00,
-            0x00, 0x00, 0x00, 0x01,
-            0xfe, 0x80, 0x00, 0x00,
-            0x00, 0x00, 0x00, 0x00,
-            0x00, 0x00, 0x00, 0x00,
-            0x00, 0x00, 0x00, 0x02,
-            0xaa, 0x00, 0x00, 0xff
+            0x60, 0x00, 0x00, 0x00, 0x00, 0x04, 0x3f, 0x40, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xfe, 0x80, 0x00, 0x00,
+            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xaa, 0x00,
+            0x00, 0xff,
         ];
 
-        pub const PACKET_PAYLOAD: [u8; 4] = [
-            0xaa, 0x00, 0x00, 0xff
-        ];
+        pub const PACKET_PAYLOAD: [u8; 4] = [0xaa, 0x00, 0x00, 0xff];
     }
 
     macro_rules! reusable_ip_specific_tests {
@@ -402,25 +440,33 @@ mod test {
                     let mut socket = $socket(buffer(0), buffer(1));
 
                     assert!(socket.can_send());
-                    assert_eq!(socket.dispatch(&Context::DUMMY, |_| unreachable!()),
-                               Err(Error::Exhausted));
+                    assert_eq!(
+                        socket.dispatch(&Context::DUMMY, |_| unreachable!()),
+                        Err(Error::Exhausted)
+                    );
 
                     assert_eq!(socket.send_slice(&$packet[..]), Ok(()));
                     assert_eq!(socket.send_slice(b""), Err(Error::Exhausted));
                     assert!(!socket.can_send());
 
-                    assert_eq!(socket.dispatch(&Context::DUMMY, |(ip_repr, ip_payload)| {
-                        assert_eq!(ip_repr, $hdr);
-                        assert_eq!(ip_payload, &$payload);
+                    assert_eq!(
+                        socket.dispatch(&Context::DUMMY, |(ip_repr, ip_payload)| {
+                            assert_eq!(ip_repr, $hdr);
+                            assert_eq!(ip_payload, &$payload);
+                            Err(Error::Unaddressable)
+                        }),
                         Err(Error::Unaddressable)
-                    }), Err(Error::Unaddressable));
+                    );
                     assert!(!socket.can_send());
 
-                    assert_eq!(socket.dispatch(&Context::DUMMY, |(ip_repr, ip_payload)| {
-                        assert_eq!(ip_repr, $hdr);
-                        assert_eq!(ip_payload, &$payload);
+                    assert_eq!(
+                        socket.dispatch(&Context::DUMMY, |(ip_repr, ip_payload)| {
+                            assert_eq!(ip_repr, $hdr);
+                            assert_eq!(ip_payload, &$payload);
+                            Ok(())
+                        }),
                         Ok(())
-                    }), Ok(()));
+                    );
                     assert!(socket.can_send());
                 }
 
@@ -444,20 +490,32 @@ mod test {
                     buffer[..$packet.len()].copy_from_slice(&$packet[..]);
 
                     assert!(socket.accepts(&$hdr));
-                    assert_eq!(socket.process(&Context::DUMMY, &$hdr, &buffer), Err(Error::Truncated));
+                    assert_eq!(
+                        socket.process(&Context::DUMMY, &$hdr, &buffer),
+                        Err(Error::Truncated)
+                    );
                 }
             }
-        }
+        };
     }
 
     #[cfg(feature = "proto-ipv4")]
-    reusable_ip_specific_tests!(ipv4, ipv4_locals::socket, ipv4_locals::HEADER_REPR,
-                                ipv4_locals::PACKET_BYTES, ipv4_locals::PACKET_PAYLOAD);
+    reusable_ip_specific_tests!(
+        ipv4,
+        ipv4_locals::socket,
+        ipv4_locals::HEADER_REPR,
+        ipv4_locals::PACKET_BYTES,
+        ipv4_locals::PACKET_PAYLOAD
+    );
 
     #[cfg(feature = "proto-ipv6")]
-    reusable_ip_specific_tests!(ipv6, ipv6_locals::socket, ipv6_locals::HEADER_REPR,
-                                ipv6_locals::PACKET_BYTES, ipv6_locals::PACKET_PAYLOAD);
-
+    reusable_ip_specific_tests!(
+        ipv6,
+        ipv6_locals::socket,
+        ipv6_locals::HEADER_REPR,
+        ipv6_locals::PACKET_BYTES,
+        ipv6_locals::PACKET_PAYLOAD
+    );
 
     #[test]
     #[cfg(feature = "proto-ipv4")]
@@ -470,15 +528,13 @@ mod test {
             Ipv4Packet::new_unchecked(&mut wrong_version).set_version(6);
 
             assert_eq!(socket.send_slice(&wrong_version[..]), Ok(()));
-            assert_eq!(socket.dispatch(&Context::DUMMY, |_| unreachable!()),
-                       Ok(()));
+            assert_eq!(socket.dispatch(&Context::DUMMY, |_| unreachable!()), Ok(()));
 
             let mut wrong_protocol = ipv4_locals::PACKET_BYTES;
             Ipv4Packet::new_unchecked(&mut wrong_protocol).set_protocol(IpProtocol::Tcp);
 
             assert_eq!(socket.send_slice(&wrong_protocol[..]), Ok(()));
-            assert_eq!(socket.dispatch(&Context::DUMMY, |_| unreachable!()),
-                       Ok(()));
+            assert_eq!(socket.dispatch(&Context::DUMMY, |_| unreachable!()), Ok(()));
         }
         #[cfg(feature = "proto-ipv6")]
         {
@@ -488,15 +544,13 @@ mod test {
             Ipv6Packet::new_unchecked(&mut wrong_version[..]).set_version(4);
 
             assert_eq!(socket.send_slice(&wrong_version[..]), Ok(()));
-            assert_eq!(socket.dispatch(&Context::DUMMY, |_| unreachable!()),
-                       Ok(()));
+            assert_eq!(socket.dispatch(&Context::DUMMY, |_| unreachable!()), Ok(()));
 
             let mut wrong_protocol = ipv6_locals::PACKET_BYTES;
             Ipv6Packet::new_unchecked(&mut wrong_protocol[..]).set_next_header(IpProtocol::Tcp);
 
             assert_eq!(socket.send_slice(&wrong_protocol[..]), Ok(()));
-            assert_eq!(socket.dispatch(&Context::DUMMY, |_| unreachable!()),
-                       Ok(()));
+            assert_eq!(socket.dispatch(&Context::DUMMY, |_| unreachable!()), Ok(()));
         }
     }
 
@@ -512,13 +566,25 @@ mod test {
 
             assert_eq!(socket.recv(), Err(Error::Exhausted));
             assert!(socket.accepts(&ipv4_locals::HEADER_REPR));
-            assert_eq!(socket.process(&Context::DUMMY, &ipv4_locals::HEADER_REPR, &ipv4_locals::PACKET_PAYLOAD),
-                       Ok(()));
+            assert_eq!(
+                socket.process(
+                    &Context::DUMMY,
+                    &ipv4_locals::HEADER_REPR,
+                    &ipv4_locals::PACKET_PAYLOAD
+                ),
+                Ok(())
+            );
             assert!(socket.can_recv());
 
             assert!(socket.accepts(&ipv4_locals::HEADER_REPR));
-            assert_eq!(socket.process(&Context::DUMMY, &ipv4_locals::HEADER_REPR, &ipv4_locals::PACKET_PAYLOAD),
-                       Err(Error::Exhausted));
+            assert_eq!(
+                socket.process(
+                    &Context::DUMMY,
+                    &ipv4_locals::HEADER_REPR,
+                    &ipv4_locals::PACKET_PAYLOAD
+                ),
+                Err(Error::Exhausted)
+            );
             assert_eq!(socket.recv(), Ok(&cksumd_packet[..]));
             assert!(!socket.can_recv());
         }
@@ -529,13 +595,25 @@ mod test {
 
             assert_eq!(socket.recv(), Err(Error::Exhausted));
             assert!(socket.accepts(&ipv6_locals::HEADER_REPR));
-            assert_eq!(socket.process(&Context::DUMMY, &ipv6_locals::HEADER_REPR, &ipv6_locals::PACKET_PAYLOAD),
-                       Ok(()));
+            assert_eq!(
+                socket.process(
+                    &Context::DUMMY,
+                    &ipv6_locals::HEADER_REPR,
+                    &ipv6_locals::PACKET_PAYLOAD
+                ),
+                Ok(())
+            );
             assert!(socket.can_recv());
 
             assert!(socket.accepts(&ipv6_locals::HEADER_REPR));
-            assert_eq!(socket.process(&Context::DUMMY, &ipv6_locals::HEADER_REPR, &ipv6_locals::PACKET_PAYLOAD),
-                       Err(Error::Exhausted));
+            assert_eq!(
+                socket.process(
+                    &Context::DUMMY,
+                    &ipv6_locals::HEADER_REPR,
+                    &ipv6_locals::PACKET_PAYLOAD
+                ),
+                Err(Error::Exhausted)
+            );
             assert_eq!(socket.recv(), Ok(&ipv6_locals::PACKET_BYTES[..]));
             assert!(!socket.can_recv());
         }
@@ -545,16 +623,24 @@ mod test {
     fn test_doesnt_accept_wrong_proto() {
         #[cfg(feature = "proto-ipv4")]
         {
-            let socket = RawSocket::new(IpVersion::Ipv4,
-                IpProtocol::Unknown(ipv4_locals::IP_PROTO+1), buffer(1), buffer(1));
+            let socket = RawSocket::new(
+                IpVersion::Ipv4,
+                IpProtocol::Unknown(ipv4_locals::IP_PROTO + 1),
+                buffer(1),
+                buffer(1),
+            );
             assert!(!socket.accepts(&ipv4_locals::HEADER_REPR));
             #[cfg(feature = "proto-ipv6")]
             assert!(!socket.accepts(&ipv6_locals::HEADER_REPR));
         }
         #[cfg(feature = "proto-ipv6")]
         {
-            let socket = RawSocket::new(IpVersion::Ipv6,
-                IpProtocol::Unknown(ipv6_locals::IP_PROTO+1), buffer(1), buffer(1));
+            let socket = RawSocket::new(
+                IpVersion::Ipv6,
+                IpProtocol::Unknown(ipv6_locals::IP_PROTO + 1),
+                buffer(1),
+                buffer(1),
+            );
             assert!(!socket.accepts(&ipv6_locals::HEADER_REPR));
             #[cfg(feature = "proto-ipv4")]
             assert!(!socket.accepts(&ipv4_locals::HEADER_REPR));

+ 7 - 3
src/socket/ref_.rs

@@ -1,6 +1,5 @@
 use core::ops::{Deref, DerefMut};
 
-
 /// A trait for tracking a socket usage session.
 ///
 /// Allows implementation of custom drop logic that runs only if the socket was changed
@@ -13,7 +12,10 @@ pub trait Session {
 
 #[cfg(feature = "socket-raw")]
 impl<'a> Session for crate::socket::RawSocket<'a> {}
-#[cfg(all(feature = "socket-icmp", any(feature = "proto-ipv4", feature = "proto-ipv6")))]
+#[cfg(all(
+    feature = "socket-icmp",
+    any(feature = "proto-ipv4", feature = "proto-ipv6")
+))]
 impl<'a> Session for crate::socket::IcmpSocket<'a> {}
 #[cfg(feature = "socket-udp")]
 impl<'a> Session for crate::socket::UdpSocket<'a> {}
@@ -41,7 +43,9 @@ impl<'a, T: Session + 'a> Ref<'a, T> {
     ///
     /// [into_inner]: #method.into_inner
     pub fn new(socket: &'a mut T) -> Self {
-        Ref { socket: Some(socket) }
+        Ref {
+            socket: Some(socket),
+        }
     }
 
     /// Unwrap a smart pointer to a socket.

+ 47 - 37
src/socket/set.rs

@@ -1,9 +1,9 @@
 use core::{fmt, slice};
 use managed::ManagedSlice;
 
-use crate::socket::{Socket, SocketRef, AnySocket};
 #[cfg(feature = "socket-tcp")]
 use crate::socket::TcpState;
+use crate::socket::{AnySocket, Socket, SocketRef};
 
 /// An item of a socket set.
 ///
@@ -12,7 +12,7 @@ use crate::socket::TcpState;
 #[derive(Debug)]
 pub struct Item<'a> {
     socket: Socket<'a>,
-    refs:   usize
+    refs: usize,
 }
 
 /// A handle, identifying a socket in a set.
@@ -31,13 +31,15 @@ impl fmt::Display for Handle {
 /// The lifetime `'a` is used when storing a `Socket<'a>`.
 #[derive(Debug)]
 pub struct Set<'a> {
-    sockets: ManagedSlice<'a, Option<Item<'a>>>
+    sockets: ManagedSlice<'a, Option<Item<'a>>>,
 }
 
 impl<'a> Set<'a> {
     /// Create a socket set using the provided storage.
     pub fn new<SocketsT>(sockets: SocketsT) -> Set<'a>
-            where SocketsT: Into<ManagedSlice<'a, Option<Item<'a>>>> {
+    where
+        SocketsT: Into<ManagedSlice<'a, Option<Item<'a>>>>,
+    {
         let sockets = sockets.into();
         Set { sockets }
     }
@@ -47,10 +49,10 @@ impl<'a> Set<'a> {
     /// # Panics
     /// This function panics if the storage is fixed-size (not a `Vec`) and is full.
     pub fn add<T>(&mut self, socket: T) -> Handle
-        where T: Into<Socket<'a>>
+    where
+        T: Into<Socket<'a>>,
     {
-        fn put<'a>(index: usize, slot: &mut Option<Item<'a>>,
-                       mut socket: Socket<'a>) -> Handle {
+        fn put<'a>(index: usize, slot: &mut Option<Item<'a>>, mut socket: Socket<'a>) -> Handle {
             net_trace!("[{}]: adding", index);
             let handle = Handle(index);
             socket.meta_mut().handle = handle;
@@ -62,7 +64,7 @@ impl<'a> Set<'a> {
 
         for (index, slot) in self.sockets.iter_mut().enumerate() {
             if slot.is_none() {
-                return put(index, slot, socket)
+                return put(index, slot, socket);
             }
         }
 
@@ -86,11 +88,9 @@ impl<'a> Set<'a> {
     /// or the socket has the wrong type.
     pub fn get<T: AnySocket<'a>>(&mut self, handle: Handle) -> SocketRef<T> {
         match self.sockets[handle.0].as_mut() {
-            Some(item) => {
-                T::downcast(SocketRef::new(&mut item.socket))
-                  .expect("handle refers to a socket of a wrong type")
-            }
-            None => panic!("handle does not refer to a valid socket")
+            Some(item) => T::downcast(SocketRef::new(&mut item.socket))
+                .expect("handle refers to a socket of a wrong type"),
+            None => panic!("handle does not refer to a valid socket"),
         }
     }
 
@@ -102,7 +102,7 @@ impl<'a> Set<'a> {
         net_trace!("[{}]: removing", handle.0);
         match self.sockets[handle.0].take() {
             Some(item) => item.socket,
-            None => panic!("handle does not refer to a valid socket")
+            None => panic!("handle does not refer to a valid socket"),
         }
     }
 
@@ -124,10 +124,12 @@ impl<'a> Set<'a> {
     /// or if the reference count is already zero.
     pub fn release(&mut self, handle: Handle) {
         let refs = &mut self.sockets[handle.0]
-                            .as_mut()
-                            .expect("handle does not refer to a valid socket")
-                            .refs;
-        if *refs == 0 { panic!("decreasing reference count past zero") }
+            .as_mut()
+            .expect("handle does not refer to a valid socket")
+            .refs;
+        if *refs == 0 {
+            panic!("decreasing reference count past zero")
+        }
         *refs -= 1
     }
 
@@ -138,27 +140,31 @@ impl<'a> Set<'a> {
     pub fn prune(&mut self) {
         for (index, item) in self.sockets.iter_mut().enumerate() {
             let mut may_remove = false;
-            if let Some(Item { refs: 0, ref mut socket }) = *item {
+            if let Some(Item {
+                refs: 0,
+                ref mut socket,
+            }) = *item
+            {
                 match *socket {
                     #[cfg(feature = "socket-raw")]
-                    Socket::Raw(_) =>
-                        may_remove = true,
-                    #[cfg(all(feature = "socket-icmp", any(feature = "proto-ipv4", feature = "proto-ipv6")))]
-                    Socket::Icmp(_) =>
-                        may_remove = true,
+                    Socket::Raw(_) => may_remove = true,
+                    #[cfg(all(
+                        feature = "socket-icmp",
+                        any(feature = "proto-ipv4", feature = "proto-ipv6")
+                    ))]
+                    Socket::Icmp(_) => may_remove = true,
                     #[cfg(feature = "socket-udp")]
-                    Socket::Udp(_) =>
-                        may_remove = true,
+                    Socket::Udp(_) => may_remove = true,
                     #[cfg(feature = "socket-tcp")]
-                    Socket::Tcp(ref mut socket) =>
+                    Socket::Tcp(ref mut socket) => {
                         if socket.state() == TcpState::Closed {
                             may_remove = true
                         } else {
                             socket.close()
-                        },
+                        }
+                    }
                     #[cfg(feature = "socket-dhcpv4")]
-                    Socket::Dhcpv4(_) =>
-                        may_remove = true,
+                    Socket::Dhcpv4(_) => may_remove = true,
                 }
             }
             if may_remove {
@@ -170,12 +176,16 @@ impl<'a> Set<'a> {
 
     /// Iterate every socket in this set.
     pub fn iter<'d>(&'d self) -> Iter<'d, 'a> {
-        Iter { lower: self.sockets.iter() }
+        Iter {
+            lower: self.sockets.iter(),
+        }
     }
 
     /// Iterate every socket in this set, as SocketRef.
     pub fn iter_mut<'d>(&'d mut self) -> IterMut<'d, 'a> {
-        IterMut { lower: self.sockets.iter_mut() }
+        IterMut {
+            lower: self.sockets.iter_mut(),
+        }
     }
 }
 
@@ -184,16 +194,16 @@ impl<'a> Set<'a> {
 /// This struct is created by the [iter](struct.SocketSet.html#method.iter)
 /// on [socket sets](struct.SocketSet.html).
 pub struct Iter<'a, 'b: 'a> {
-    lower: slice::Iter<'a, Option<Item<'b>>>
+    lower: slice::Iter<'a, Option<Item<'b>>>,
 }
 
 impl<'a, 'b: 'a> Iterator for Iter<'a, 'b> {
     type Item = &'a Socket<'b>;
 
     fn next(&mut self) -> Option<Self::Item> {
-        while let Some(item_opt) = self.lower.next() {
+        for item_opt in &mut self.lower {
             if let Some(item) = item_opt.as_ref() {
-                return Some(&item.socket)
+                return Some(&item.socket);
             }
         }
         None
@@ -212,9 +222,9 @@ impl<'a, 'b: 'a> Iterator for IterMut<'a, 'b> {
     type Item = SocketRef<'a, Socket<'b>>;
 
     fn next(&mut self) -> Option<Self::Item> {
-        while let Some(item_opt) = self.lower.next() {
+        for item_opt in &mut self.lower {
             if let Some(item) = item_opt.as_mut() {
-                return Some(SocketRef::new(&mut item.socket))
+                return Some(SocketRef::new(&mut item.socket));
             }
         }
         None

File diff suppressed because it is too large
+ 401 - 236
src/socket/tcp.rs


+ 246 - 114
src/socket/udp.rs

@@ -2,12 +2,12 @@ use core::cmp::min;
 #[cfg(feature = "async")]
 use core::task::Waker;
 
-use crate::{Error, Result};
-use crate::socket::{Socket, SocketMeta, SocketHandle, PollAt, Context};
-use crate::storage::{PacketBuffer, PacketMetadata};
-use crate::wire::{IpProtocol, IpRepr, IpEndpoint, UdpRepr};
 #[cfg(feature = "async")]
 use crate::socket::WakerRegistration;
+use crate::socket::{Context, PollAt, Socket, SocketHandle, SocketMeta};
+use crate::storage::{PacketBuffer, PacketMetadata};
+use crate::wire::{IpEndpoint, IpProtocol, IpRepr, UdpRepr};
+use crate::{Error, Result};
 
 /// A UDP packet metadata.
 pub type UdpPacketMetadata = PacketMetadata<IpEndpoint>;
@@ -22,7 +22,7 @@ pub type UdpSocketBuffer<'a> = PacketBuffer<'a, IpEndpoint>;
 #[derive(Debug)]
 pub struct UdpSocket<'a> {
     pub(crate) meta: SocketMeta,
-    endpoint:  IpEndpoint,
+    endpoint: IpEndpoint,
     rx_buffer: UdpSocketBuffer<'a>,
     tx_buffer: UdpSocketBuffer<'a>,
     /// The time-to-live (IPv4) or hop limit (IPv6) value used in outgoing packets.
@@ -35,11 +35,10 @@ pub struct UdpSocket<'a> {
 
 impl<'a> UdpSocket<'a> {
     /// Create an UDP socket with the given buffers.
-    pub fn new(rx_buffer: UdpSocketBuffer<'a>,
-               tx_buffer: UdpSocketBuffer<'a>) -> UdpSocket<'a> {
+    pub fn new(rx_buffer: UdpSocketBuffer<'a>, tx_buffer: UdpSocketBuffer<'a>) -> UdpSocket<'a> {
         UdpSocket {
-            meta:      SocketMeta::default(),
-            endpoint:  IpEndpoint::default(),
+            meta: SocketMeta::default(),
+            endpoint: IpEndpoint::default(),
             rx_buffer: rx_buffer,
             tx_buffer: tx_buffer,
             hop_limit: None,
@@ -131,9 +130,13 @@ impl<'a> UdpSocket<'a> {
     /// if the port in the given endpoint is zero.
     pub fn bind<T: Into<IpEndpoint>>(&mut self, endpoint: T) -> Result<()> {
         let endpoint = endpoint.into();
-        if endpoint.port == 0 { return Err(Error::Unaddressable) }
+        if endpoint.port == 0 {
+            return Err(Error::Unaddressable);
+        }
 
-        if self.is_open() { return Err(Error::Illegal) }
+        if self.is_open() {
+            return Err(Error::Illegal);
+        }
 
         self.endpoint = endpoint;
 
@@ -212,13 +215,22 @@ impl<'a> UdpSocket<'a> {
     /// and `Err(Error::Truncated)` if there is not enough transmit buffer capacity
     /// to ever send this packet.
     pub fn send(&mut self, size: usize, endpoint: IpEndpoint) -> Result<&mut [u8]> {
-        if self.endpoint.port == 0 { return Err(Error::Unaddressable) }
-        if !endpoint.is_specified() { return Err(Error::Unaddressable) }
+        if self.endpoint.port == 0 {
+            return Err(Error::Unaddressable);
+        }
+        if !endpoint.is_specified() {
+            return Err(Error::Unaddressable);
+        }
 
         let payload_buf = self.tx_buffer.enqueue(size, endpoint)?;
 
-        net_trace!("{}:{}:{}: buffer to send {} octets",
-                   self.meta.handle, self.endpoint, endpoint, size);
+        net_trace!(
+            "{}:{}:{}: buffer to send {} octets",
+            self.meta.handle,
+            self.endpoint,
+            endpoint,
+            size
+        );
         Ok(payload_buf)
     }
 
@@ -237,9 +249,13 @@ impl<'a> UdpSocket<'a> {
     pub fn recv(&mut self) -> Result<(&[u8], IpEndpoint)> {
         let (endpoint, payload_buf) = self.rx_buffer.dequeue()?;
 
-        net_trace!("{}:{}:{}: receive {} buffered octets",
-                   self.meta.handle, self.endpoint,
-                   endpoint, payload_buf.len());
+        net_trace!(
+            "{}:{}:{}: receive {} buffered octets",
+            self.meta.handle,
+            self.endpoint,
+            endpoint,
+            payload_buf.len()
+        );
         Ok((payload_buf, endpoint))
     }
 
@@ -263,10 +279,14 @@ impl<'a> UdpSocket<'a> {
         let handle = self.meta.handle;
         let endpoint = self.endpoint;
         self.rx_buffer.peek().map(|(remote_endpoint, payload_buf)| {
-            net_trace!("{}:{}:{}: peek {} buffered octets",
-                       handle, endpoint,
-                       remote_endpoint, payload_buf.len());
-           (payload_buf, remote_endpoint)
+            net_trace!(
+                "{}:{}:{}: peek {} buffered octets",
+                handle,
+                endpoint,
+                remote_endpoint,
+                payload_buf.len()
+            );
+            (payload_buf, remote_endpoint)
         })
     }
 
@@ -284,26 +304,46 @@ impl<'a> UdpSocket<'a> {
     }
 
     pub(crate) fn accepts(&self, ip_repr: &IpRepr, repr: &UdpRepr) -> bool {
-        if self.endpoint.port != repr.dst_port { return false }
-        if !self.endpoint.addr.is_unspecified() &&
-            self.endpoint.addr != ip_repr.dst_addr() &&
-            !ip_repr.dst_addr().is_broadcast() &&
-            !ip_repr.dst_addr().is_multicast() { return false }
+        if self.endpoint.port != repr.dst_port {
+            return false;
+        }
+        if !self.endpoint.addr.is_unspecified()
+            && self.endpoint.addr != ip_repr.dst_addr()
+            && !ip_repr.dst_addr().is_broadcast()
+            && !ip_repr.dst_addr().is_multicast()
+        {
+            return false;
+        }
 
         true
     }
 
-    pub(crate) fn process(&mut self, _cx: &Context, ip_repr: &IpRepr, repr: &UdpRepr, payload: &[u8]) -> Result<()> {
+    pub(crate) fn process(
+        &mut self,
+        _cx: &Context,
+        ip_repr: &IpRepr,
+        repr: &UdpRepr,
+        payload: &[u8],
+    ) -> Result<()> {
         debug_assert!(self.accepts(ip_repr, repr));
 
         let size = payload.len();
 
-        let endpoint = IpEndpoint { addr: ip_repr.src_addr(), port: repr.src_port };
-        self.rx_buffer.enqueue(size, endpoint)?.copy_from_slice(payload);
-
-        net_trace!("{}:{}:{}: receiving {} octets",
-                   self.meta.handle, self.endpoint,
-                   endpoint, size);
+        let endpoint = IpEndpoint {
+            addr: ip_repr.src_addr(),
+            port: repr.src_port,
+        };
+        self.rx_buffer
+            .enqueue(size, endpoint)?
+            .copy_from_slice(payload);
+
+        net_trace!(
+            "{}:{}:{}: receiving {} octets",
+            self.meta.handle,
+            self.endpoint,
+            endpoint,
+            size
+        );
 
         #[cfg(feature = "async")]
         self.rx_waker.wake();
@@ -312,29 +352,36 @@ impl<'a> UdpSocket<'a> {
     }
 
     pub(crate) fn dispatch<F>(&mut self, _cx: &Context, emit: F) -> Result<()>
-            where F: FnOnce((IpRepr, UdpRepr, &[u8])) -> Result<()> {
-        let handle    = self.handle();
-        let endpoint  = self.endpoint;
+    where
+        F: FnOnce((IpRepr, UdpRepr, &[u8])) -> Result<()>,
+    {
+        let handle = self.handle();
+        let endpoint = self.endpoint;
         let hop_limit = self.hop_limit.unwrap_or(64);
 
-        self.tx_buffer.dequeue_with(|remote_endpoint, payload_buf| {
-            net_trace!("{}:{}:{}: sending {} octets",
-                        handle, endpoint,
-                        endpoint, payload_buf.len());
-
-            let repr = UdpRepr {
-                src_port: endpoint.port,
-                dst_port: remote_endpoint.port,
-            };
-            let ip_repr = IpRepr::Unspecified {
-                src_addr:    endpoint.addr,
-                dst_addr:    remote_endpoint.addr,
-                protocol:    IpProtocol::Udp,
-                payload_len: repr.header_len() + payload_buf.len(),
-                hop_limit:   hop_limit,
-            };
-            emit((ip_repr, repr, payload_buf))
-        })?;
+        self.tx_buffer
+            .dequeue_with(|remote_endpoint, payload_buf| {
+                net_trace!(
+                    "{}:{}:{}: sending {} octets",
+                    handle,
+                    endpoint,
+                    endpoint,
+                    payload_buf.len()
+                );
+
+                let repr = UdpRepr {
+                    src_port: endpoint.port,
+                    dst_port: remote_endpoint.port,
+                };
+                let ip_repr = IpRepr::Unspecified {
+                    src_addr: endpoint.addr,
+                    dst_addr: remote_endpoint.addr,
+                    protocol: IpProtocol::Udp,
+                    payload_len: repr.header_len() + payload_buf.len(),
+                    hop_limit: hop_limit,
+                };
+                emit((ip_repr, repr, payload_buf))
+            })?;
 
         #[cfg(feature = "async")]
         self.tx_waker.wake();
@@ -359,29 +406,39 @@ impl<'a> Into<Socket<'a>> for UdpSocket<'a> {
 
 #[cfg(test)]
 mod test {
-    use crate::wire::{IpAddress, IpRepr, UdpRepr};
+    use super::*;
+    use crate::wire::ip::test::{MOCK_IP_ADDR_1, MOCK_IP_ADDR_2, MOCK_IP_ADDR_3};
     #[cfg(feature = "proto-ipv4")]
     use crate::wire::Ipv4Repr;
     #[cfg(feature = "proto-ipv6")]
     use crate::wire::Ipv6Repr;
-    use crate::wire::ip::test::{MOCK_IP_ADDR_1, MOCK_IP_ADDR_2, MOCK_IP_ADDR_3};
-    use super::*;
+    use crate::wire::{IpAddress, IpRepr, UdpRepr};
 
     fn buffer(packets: usize) -> UdpSocketBuffer<'static> {
-        UdpSocketBuffer::new(vec![UdpPacketMetadata::EMPTY; packets], vec![0; 16 * packets])
+        UdpSocketBuffer::new(
+            vec![UdpPacketMetadata::EMPTY; packets],
+            vec![0; 16 * packets],
+        )
     }
 
-    fn socket(rx_buffer: UdpSocketBuffer<'static>,
-              tx_buffer: UdpSocketBuffer<'static>)
-            -> UdpSocket<'static> {
+    fn socket(
+        rx_buffer: UdpSocketBuffer<'static>,
+        tx_buffer: UdpSocketBuffer<'static>,
+    ) -> UdpSocket<'static> {
         UdpSocket::new(rx_buffer, tx_buffer)
     }
 
-    const LOCAL_PORT:  u16        = 53;
-    const REMOTE_PORT: u16        = 49500;
+    const LOCAL_PORT: u16 = 53;
+    const REMOTE_PORT: u16 = 49500;
 
-    pub const LOCAL_END:   IpEndpoint = IpEndpoint { addr: MOCK_IP_ADDR_1, port: LOCAL_PORT  };
-    pub const REMOTE_END:  IpEndpoint = IpEndpoint { addr: MOCK_IP_ADDR_2, port: REMOTE_PORT };
+    pub const LOCAL_END: IpEndpoint = IpEndpoint {
+        addr: MOCK_IP_ADDR_1,
+        port: LOCAL_PORT,
+    };
+    pub const REMOTE_END: IpEndpoint = IpEndpoint {
+        addr: MOCK_IP_ADDR_2,
+        port: REMOTE_PORT,
+    };
 
     pub const LOCAL_IP_REPR: IpRepr = IpRepr::Unspecified {
         src_addr: MOCK_IP_ADDR_1,
@@ -411,7 +468,7 @@ mod test {
                 dst_addr: dst,
                 protocol: IpProtocol::Udp,
                 payload_len: 8 + 6,
-                hop_limit: 64
+                hop_limit: 64,
             }),
             #[cfg(feature = "proto-ipv6")]
             (IpAddress::Ipv6(src), IpAddress::Ipv6(dst)) => IpRepr::Ipv6(Ipv6Repr {
@@ -419,9 +476,9 @@ mod test {
                 dst_addr: dst,
                 next_header: IpProtocol::Udp,
                 payload_len: 8 + 6,
-                hop_limit: 64
+                hop_limit: 64,
             }),
-            _ => unreachable!()
+            _ => unreachable!(),
         }
     }
 
@@ -448,14 +505,31 @@ mod test {
     #[test]
     fn test_send_unaddressable() {
         let mut socket = socket(buffer(0), buffer(1));
-        assert_eq!(socket.send_slice(b"abcdef", REMOTE_END), Err(Error::Unaddressable));
+        assert_eq!(
+            socket.send_slice(b"abcdef", REMOTE_END),
+            Err(Error::Unaddressable)
+        );
         assert_eq!(socket.bind(LOCAL_PORT), Ok(()));
-        assert_eq!(socket.send_slice(b"abcdef",
-                                     IpEndpoint { addr: IpAddress::Unspecified, ..REMOTE_END }),
-                   Err(Error::Unaddressable));
-        assert_eq!(socket.send_slice(b"abcdef",
-                                     IpEndpoint { port: 0, ..REMOTE_END }),
-                   Err(Error::Unaddressable));
+        assert_eq!(
+            socket.send_slice(
+                b"abcdef",
+                IpEndpoint {
+                    addr: IpAddress::Unspecified,
+                    ..REMOTE_END
+                }
+            ),
+            Err(Error::Unaddressable)
+        );
+        assert_eq!(
+            socket.send_slice(
+                b"abcdef",
+                IpEndpoint {
+                    port: 0,
+                    ..REMOTE_END
+                }
+            ),
+            Err(Error::Unaddressable)
+        );
         assert_eq!(socket.send_slice(b"abcdef", REMOTE_END), Ok(()));
     }
 
@@ -465,27 +539,38 @@ mod test {
         assert_eq!(socket.bind(LOCAL_END), Ok(()));
 
         assert!(socket.can_send());
-        assert_eq!(socket.dispatch(&Context::DUMMY, |_| unreachable!()),
-                   Err(Error::Exhausted));
+        assert_eq!(
+            socket.dispatch(&Context::DUMMY, |_| unreachable!()),
+            Err(Error::Exhausted)
+        );
 
         assert_eq!(socket.send_slice(b"abcdef", REMOTE_END), Ok(()));
-        assert_eq!(socket.send_slice(b"123456", REMOTE_END), Err(Error::Exhausted));
+        assert_eq!(
+            socket.send_slice(b"123456", REMOTE_END),
+            Err(Error::Exhausted)
+        );
         assert!(!socket.can_send());
 
-        assert_eq!(socket.dispatch(&Context::DUMMY, |(ip_repr, udp_repr, payload)| {
-            assert_eq!(ip_repr, LOCAL_IP_REPR);
-            assert_eq!(udp_repr, LOCAL_UDP_REPR);
-            assert_eq!(payload, PAYLOAD);
+        assert_eq!(
+            socket.dispatch(&Context::DUMMY, |(ip_repr, udp_repr, payload)| {
+                assert_eq!(ip_repr, LOCAL_IP_REPR);
+                assert_eq!(udp_repr, LOCAL_UDP_REPR);
+                assert_eq!(payload, PAYLOAD);
+                Err(Error::Unaddressable)
+            }),
             Err(Error::Unaddressable)
-        }), Err(Error::Unaddressable));
+        );
         assert!(!socket.can_send());
 
-        assert_eq!(socket.dispatch(&Context::DUMMY, |(ip_repr, udp_repr, payload)| {
-            assert_eq!(ip_repr, LOCAL_IP_REPR);
-            assert_eq!(udp_repr, LOCAL_UDP_REPR);
-            assert_eq!(payload, PAYLOAD);
+        assert_eq!(
+            socket.dispatch(&Context::DUMMY, |(ip_repr, udp_repr, payload)| {
+                assert_eq!(ip_repr, LOCAL_IP_REPR);
+                assert_eq!(udp_repr, LOCAL_UDP_REPR);
+                assert_eq!(payload, PAYLOAD);
+                Ok(())
+            }),
             Ok(())
-        }), Ok(()));
+        );
         assert!(socket.can_send());
     }
 
@@ -498,13 +583,27 @@ mod test {
         assert_eq!(socket.recv(), Err(Error::Exhausted));
 
         assert!(socket.accepts(&remote_ip_repr(), &REMOTE_UDP_REPR));
-        assert_eq!(socket.process(&Context::DUMMY, &remote_ip_repr(), &REMOTE_UDP_REPR, PAYLOAD),
-                   Ok(()));
+        assert_eq!(
+            socket.process(
+                &Context::DUMMY,
+                &remote_ip_repr(),
+                &REMOTE_UDP_REPR,
+                PAYLOAD
+            ),
+            Ok(())
+        );
         assert!(socket.can_recv());
 
         assert!(socket.accepts(&remote_ip_repr(), &REMOTE_UDP_REPR));
-        assert_eq!(socket.process(&Context::DUMMY, &remote_ip_repr(), &REMOTE_UDP_REPR, PAYLOAD),
-                   Err(Error::Exhausted));
+        assert_eq!(
+            socket.process(
+                &Context::DUMMY,
+                &remote_ip_repr(),
+                &REMOTE_UDP_REPR,
+                PAYLOAD
+            ),
+            Err(Error::Exhausted)
+        );
         assert_eq!(socket.recv(), Ok((&b"abcdef"[..], REMOTE_END)));
         assert!(!socket.can_recv());
     }
@@ -516,8 +615,15 @@ mod test {
 
         assert_eq!(socket.peek(), Err(Error::Exhausted));
 
-        assert_eq!(socket.process(&Context::DUMMY, &remote_ip_repr(), &REMOTE_UDP_REPR, PAYLOAD),
-                   Ok(()));
+        assert_eq!(
+            socket.process(
+                &Context::DUMMY,
+                &remote_ip_repr(),
+                &REMOTE_UDP_REPR,
+                PAYLOAD
+            ),
+            Ok(())
+        );
         assert_eq!(socket.peek(), Ok((&b"abcdef"[..], &REMOTE_END)));
         assert_eq!(socket.recv(), Ok((&b"abcdef"[..], REMOTE_END)));
         assert_eq!(socket.peek(), Err(Error::Exhausted));
@@ -529,8 +635,15 @@ mod test {
         assert_eq!(socket.bind(LOCAL_PORT), Ok(()));
 
         assert!(socket.accepts(&remote_ip_repr(), &REMOTE_UDP_REPR));
-        assert_eq!(socket.process(&Context::DUMMY, &remote_ip_repr(), &REMOTE_UDP_REPR, PAYLOAD),
-                   Ok(()));
+        assert_eq!(
+            socket.process(
+                &Context::DUMMY,
+                &remote_ip_repr(),
+                &REMOTE_UDP_REPR,
+                PAYLOAD
+            ),
+            Ok(())
+        );
 
         let mut slice = [0; 4];
         assert_eq!(socket.recv_slice(&mut slice[..]), Ok((4, REMOTE_END)));
@@ -542,8 +655,15 @@ mod test {
         let mut socket = socket(buffer(1), buffer(0));
         assert_eq!(socket.bind(LOCAL_PORT), Ok(()));
 
-        assert_eq!(socket.process(&Context::DUMMY, &remote_ip_repr(), &REMOTE_UDP_REPR, PAYLOAD),
-                   Ok(()));
+        assert_eq!(
+            socket.process(
+                &Context::DUMMY,
+                &remote_ip_repr(),
+                &REMOTE_UDP_REPR,
+                PAYLOAD
+            ),
+            Ok(())
+        );
 
         let mut slice = [0; 4];
         assert_eq!(socket.peek_slice(&mut slice[..]), Ok((4, &REMOTE_END)));
@@ -560,16 +680,22 @@ mod test {
 
         s.set_hop_limit(Some(0x2a));
         assert_eq!(s.send_slice(b"abcdef", REMOTE_END), Ok(()));
-        assert_eq!(s.dispatch(&Context::DUMMY, |(ip_repr, _, _)| {
-            assert_eq!(ip_repr, IpRepr::Unspecified{
-                src_addr: MOCK_IP_ADDR_1,
-                dst_addr: MOCK_IP_ADDR_2,
-                protocol: IpProtocol::Udp,
-                payload_len: 8 + 6,
-                hop_limit: 0x2a,
-            });
+        assert_eq!(
+            s.dispatch(&Context::DUMMY, |(ip_repr, _, _)| {
+                assert_eq!(
+                    ip_repr,
+                    IpRepr::Unspecified {
+                        src_addr: MOCK_IP_ADDR_1,
+                        dst_addr: MOCK_IP_ADDR_2,
+                        protocol: IpProtocol::Udp,
+                        payload_len: 8 + 6,
+                        hop_limit: 0x2a,
+                    }
+                );
+                Ok(())
+            }),
             Ok(())
-        }), Ok(()));
+        );
     }
 
     #[test]
@@ -593,7 +719,7 @@ mod test {
                     dst_addr: dst,
                     protocol: IpProtocol::Udp,
                     payload_len: 8 + 6,
-                    hop_limit: 64
+                    hop_limit: 64,
                 }),
                 #[cfg(feature = "proto-ipv6")]
                 (IpAddress::Ipv6(src), IpAddress::Ipv6(dst)) => IpRepr::Ipv6(Ipv6Repr {
@@ -601,9 +727,9 @@ mod test {
                     dst_addr: dst,
                     next_header: IpProtocol::Udp,
                     payload_len: 8 + 6,
-                    hop_limit: 64
+                    hop_limit: 64,
                 }),
-                _ => unreachable!()
+                _ => unreachable!(),
             }
         }
 
@@ -623,8 +749,11 @@ mod test {
         assert_eq!(socket.bind(LOCAL_END), Ok(()));
 
         let too_large = b"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdefx";
-        assert_eq!(socket.send_slice(too_large, REMOTE_END), Err(Error::Truncated));
-        assert_eq!(socket.send_slice(&too_large[..16*4], REMOTE_END), Ok(()));
+        assert_eq!(
+            socket.send_slice(too_large, REMOTE_END),
+            Err(Error::Truncated)
+        );
+        assert_eq!(socket.send_slice(&too_large[..16 * 4], REMOTE_END), Ok(()));
     }
 
     #[test]
@@ -637,7 +766,10 @@ mod test {
             src_port: REMOTE_PORT,
             dst_port: LOCAL_PORT,
         };
-        assert_eq!(socket.process(&Context::DUMMY, &remote_ip_repr(), &repr, &[]), Ok(()));
+        assert_eq!(
+            socket.process(&Context::DUMMY, &remote_ip_repr(), &repr, &[]),
+            Ok(())
+        );
         assert_eq!(socket.recv(), Ok((&[][..], REMOTE_END)));
     }
 

+ 1 - 1
src/socket/waker.rs

@@ -30,4 +30,4 @@ impl WakerRegistration {
     pub fn wake(&mut self) {
         self.waker.take().map(|w| w.wake());
     }
-}
+}

+ 46 - 28
src/storage/assembler.rs

@@ -8,29 +8,44 @@ pub struct TooManyHolesError;
 #[cfg_attr(feature = "defmt", derive(defmt::Format))]
 struct Contig {
     hole_size: usize,
-    data_size: usize
+    data_size: usize,
 }
 
 impl fmt::Display for Contig {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        if self.has_hole() { write!(f, "({})", self.hole_size)?; }
-        if self.has_hole() && self.has_data() { write!(f, " ")?; }
-        if self.has_data() { write!(f, "{}",   self.data_size)?; }
+        if self.has_hole() {
+            write!(f, "({})", self.hole_size)?;
+        }
+        if self.has_hole() && self.has_data() {
+            write!(f, " ")?;
+        }
+        if self.has_data() {
+            write!(f, "{}", self.data_size)?;
+        }
         Ok(())
     }
 }
 
 impl Contig {
     fn empty() -> Contig {
-        Contig { hole_size: 0, data_size: 0 }
+        Contig {
+            hole_size: 0,
+            data_size: 0,
+        }
     }
 
     fn hole(size: usize) -> Contig {
-        Contig { hole_size: size, data_size: 0 }
+        Contig {
+            hole_size: size,
+            data_size: 0,
+        }
     }
 
     fn hole_and_data(hole_size: usize, data_size: usize) -> Contig {
-        Contig { hole_size, data_size }
+        Contig {
+            hole_size,
+            data_size,
+        }
     }
 
     fn has_hole(&self) -> bool {
@@ -66,10 +81,10 @@ impl Contig {
     }
 }
 
-#[cfg(feature = "std")]
-use std::boxed::Box;
 #[cfg(all(feature = "alloc", not(feature = "std")))]
 use alloc::boxed::Box;
+#[cfg(feature = "std")]
+use std::boxed::Box;
 #[cfg(any(feature = "std", feature = "alloc"))]
 const CONTIG_COUNT: usize = 32;
 
@@ -93,7 +108,9 @@ impl fmt::Display for Assembler {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         write!(f, "[ ")?;
         for contig in self.contigs.iter() {
-            if contig.is_empty() { break }
+            if contig.is_empty() {
+                break;
+            }
             write!(f, "{} ", contig)?;
         }
         write!(f, "]")?;
@@ -115,10 +132,7 @@ impl Assembler {
     /// FIXME(whitequark): remove this once I'm certain enough that the assembler works well.
     #[allow(dead_code)]
     pub(crate) fn total_size(&self) -> usize {
-        self.contigs
-            .iter()
-            .map(|contig| contig.total_size())
-            .sum()
+        self.contigs.iter().map(|contig| contig.total_size()).sum()
     }
 
     fn front(&self) -> Contig {
@@ -143,7 +157,7 @@ impl Assembler {
             self.contigs[i] = self.contigs[i + 1];
             if !self.contigs[i].has_data() {
                 self.contigs[i + 1] = Contig::empty();
-                return &mut self.contigs[i]
+                return &mut self.contigs[i];
             }
         }
 
@@ -156,7 +170,9 @@ impl Assembler {
     fn add_contig_at(&mut self, at: usize) -> Result<&mut Contig, TooManyHolesError> {
         debug_assert!(!self.contigs[at].is_empty());
 
-        if !self.back().is_empty() { return Err(TooManyHolesError) }
+        if !self.back().is_empty() {
+            return Err(TooManyHolesError);
+        }
 
         for i in (at + 1..self.contigs.len()).rev() {
             self.contigs[i] = self.contigs[i - 1];
@@ -201,11 +217,11 @@ impl Assembler {
                 // The range being added covers a part of the hole but not of the data
                 // in this contig, add a new contig containing the range.
                 {
-                  let inserted = self.add_contig_at(index)?;
-                  *inserted = Contig::hole_and_data(offset, size);
+                    let inserted = self.add_contig_at(index)?;
+                    *inserted = Contig::hole_and_data(offset, size);
                 }
                 // Previous contigs[index] got moved to contigs[index+1]
-                self.contigs[index+1].shrink_hole_by(offset + size);
+                self.contigs[index + 1].shrink_hole_by(offset + size);
                 index += 2;
             } else {
                 unreachable!()
@@ -215,7 +231,7 @@ impl Assembler {
             if offset >= contig.total_size() {
                 offset = offset.saturating_sub(contig.total_size());
             } else {
-                size   = (offset + size).saturating_sub(contig.total_size());
+                size = (offset + size).saturating_sub(contig.total_size());
                 offset = 0;
             }
         }
@@ -258,7 +274,7 @@ pub struct AssemblerIter<'a> {
     offset: usize,
     index: usize,
     left: usize,
-    right: usize
+    right: usize,
 }
 
 impl<'a> AssemblerIter<'a> {
@@ -268,7 +284,7 @@ impl<'a> AssemblerIter<'a> {
             offset: offset,
             index: 0,
             left: 0,
-            right: 0
+            right: 0,
         }
     }
 }
@@ -297,8 +313,8 @@ impl<'a> Iterator for AssemblerIter<'a> {
 
 #[cfg(test)]
 mod test {
-    use std::vec::Vec;
     use super::*;
+    use std::vec::Vec;
 
     impl From<Vec<(usize, usize)>> for Assembler {
         fn from(vec: Vec<(usize, usize)>) -> Assembler {
@@ -307,7 +323,10 @@ mod test {
             #[cfg(any(feature = "std", feature = "alloc"))]
             let mut contigs = Box::new([Contig::empty(); CONTIG_COUNT]);
             for (i, &(hole_size, data_size)) in vec.iter().enumerate() {
-                contigs[i] = Contig { hole_size, data_size };
+                contigs[i] = Contig {
+                    hole_size,
+                    data_size,
+                };
             }
             Assembler { contigs }
         }
@@ -412,9 +431,9 @@ mod test {
 
     #[test]
     fn test_rejected_add_keeps_state() {
-        let mut assr = Assembler::new(CONTIG_COUNT*20);
-        for c in 1..=CONTIG_COUNT-1 {
-          assert_eq!(assr.add(c*10, 3), Ok(()));
+        let mut assr = Assembler::new(CONTIG_COUNT * 20);
+        for c in 1..=CONTIG_COUNT - 1 {
+            assert_eq!(assr.add(c * 10, 3), Ok(()));
         }
         // Maximum of allowed holes is reached
         let assr_before = assr.clone();
@@ -440,7 +459,6 @@ mod test {
         let mut assr = contigs![(0, 4), (4, 4)];
         assert_eq!(assr.remove_front(), Some(4));
         assert_eq!(assr, contigs![(4, 4), (4, 0)]);
-
     }
 
     #[test]

+ 2 - 2
src/storage/mod.rs

@@ -6,12 +6,12 @@ or `alloc` crates being available, and heap-allocated memory.
 */
 
 mod assembler;
-mod ring_buffer;
 mod packet_buffer;
+mod ring_buffer;
 
 pub use self::assembler::Assembler;
-pub use self::ring_buffer::RingBuffer;
 pub use self::packet_buffer::{PacketBuffer, PacketMetadata};
+pub use self::ring_buffer::RingBuffer;
 
 /// A trait for setting a value to a known state.
 ///

+ 69 - 40
src/storage/packet_buffer.rs

@@ -1,31 +1,34 @@
 use managed::ManagedSlice;
 
-use crate::{Error, Result};
 use crate::storage::RingBuffer;
+use crate::{Error, Result};
 
 /// Size and header of a packet.
 #[derive(Debug, Clone, Copy)]
 #[cfg_attr(feature = "defmt", derive(defmt::Format))]
 pub struct PacketMetadata<H> {
-    size:   usize,
-    header: Option<H>
+    size: usize,
+    header: Option<H>,
 }
 
 impl<H> PacketMetadata<H> {
     /// Empty packet description.
-    pub const EMPTY: PacketMetadata<H> = PacketMetadata { size: 0, header: None };
+    pub const EMPTY: PacketMetadata<H> = PacketMetadata {
+        size: 0,
+        header: None,
+    };
 
     fn padding(size: usize) -> PacketMetadata<H> {
         PacketMetadata {
-            size:   size,
-            header: None
+            size: size,
+            header: None,
         }
     }
 
     fn packet(size: usize, header: H) -> PacketMetadata<H> {
         PacketMetadata {
-            size:   size,
-            header: Some(header)
+            size: size,
+            header: Some(header),
         }
     }
 
@@ -36,9 +39,9 @@ impl<H> PacketMetadata<H> {
 
 /// An UDP packet ring buffer.
 #[derive(Debug)]
-pub struct PacketBuffer<'a,  H: 'a> {
+pub struct PacketBuffer<'a, H: 'a> {
     metadata_ring: RingBuffer<'a, PacketMetadata<H>>,
-    payload_ring:  RingBuffer<'a, u8>,
+    payload_ring: RingBuffer<'a, u8>,
 }
 
 impl<'a, H> PacketBuffer<'a, H> {
@@ -47,12 +50,13 @@ impl<'a, H> PacketBuffer<'a, H> {
     /// Metadata storage limits the maximum _number_ of packets in the buffer and payload
     /// storage limits the maximum _total size_ of packets.
     pub fn new<MS, PS>(metadata_storage: MS, payload_storage: PS) -> PacketBuffer<'a, H>
-        where MS: Into<ManagedSlice<'a, PacketMetadata<H>>>,
-              PS: Into<ManagedSlice<'a, u8>>,
+    where
+        MS: Into<ManagedSlice<'a, PacketMetadata<H>>>,
+        PS: Into<ManagedSlice<'a, u8>>,
     {
         PacketBuffer {
             metadata_ring: RingBuffer::new(metadata_storage),
-            payload_ring:  RingBuffer::new(payload_storage),
+            payload_ring: RingBuffer::new(payload_storage),
         }
     }
 
@@ -75,25 +79,25 @@ impl<'a, H> PacketBuffer<'a, H> {
     /// does not have enough spare payload space.
     pub fn enqueue(&mut self, size: usize, header: H) -> Result<&mut [u8]> {
         if self.payload_ring.capacity() < size {
-            return Err(Error::Truncated)
+            return Err(Error::Truncated);
         }
 
         if self.metadata_ring.is_full() {
-            return Err(Error::Exhausted)
+            return Err(Error::Exhausted);
         }
 
         let window = self.payload_ring.window();
         let contig_window = self.payload_ring.contiguous_window();
 
         if window < size {
-            return Err(Error::Exhausted)
+            return Err(Error::Exhausted);
         } else if contig_window < size {
             if window - contig_window < size {
                 // The buffer length is larger than the current contiguous window
                 // and is larger than the contiguous window will be after adding
                 // the padding necessary to circle around to the beginning of the
                 // ring buffer.
-                return Err(Error::Exhausted)
+                return Err(Error::Exhausted);
             } else {
                 // Add padding to the end of the ring buffer so that the
                 // contiguous window is at the beginning of the ring buffer.
@@ -110,7 +114,10 @@ impl<'a, H> PacketBuffer<'a, H> {
     }
 
     fn dequeue_padding(&mut self) {
-        let Self { ref mut metadata_ring, ref mut payload_ring } = *self;
+        let Self {
+            ref mut metadata_ring,
+            ref mut payload_ring,
+        } = *self;
 
         let _ = metadata_ring.dequeue_one_with(|metadata| {
             if metadata.is_padding() {
@@ -125,22 +132,32 @@ impl<'a, H> PacketBuffer<'a, H> {
     /// Call `f` with a single packet from the buffer, and dequeue the packet if `f`
     /// returns successfully, or return `Err(Error::Exhausted)` if the buffer is empty.
     pub fn dequeue_with<'c, R, F>(&'c mut self, f: F) -> Result<R>
-            where F: FnOnce(&mut H, &'c mut [u8]) -> Result<R> {
+    where
+        F: FnOnce(&mut H, &'c mut [u8]) -> Result<R>,
+    {
         self.dequeue_padding();
 
-        let Self { ref mut metadata_ring, ref mut payload_ring } = *self;
+        let Self {
+            ref mut metadata_ring,
+            ref mut payload_ring,
+        } = *self;
 
         metadata_ring.dequeue_one_with(move |metadata| {
-            let PacketMetadata { ref mut header, size } = *metadata;
-
-            payload_ring.dequeue_many_with(|payload_buf| {
-                debug_assert!(payload_buf.len() >= size);
-
-                match f(header.as_mut().unwrap(), &mut payload_buf[..size]) {
-                    Ok(val)  => (size, Ok(val)),
-                    Err(err) => (0,    Err(err)),
-                }
-            }).1
+            let PacketMetadata {
+                ref mut header,
+                size,
+            } = *metadata;
+
+            payload_ring
+                .dequeue_many_with(|payload_buf| {
+                    debug_assert!(payload_buf.len() >= size);
+
+                    match f(header.as_mut().unwrap(), &mut payload_buf[..size]) {
+                        Ok(val) => (size, Ok(val)),
+                        Err(err) => (0, Err(err)),
+                    }
+                })
+                .1
         })
     }
 
@@ -149,7 +166,10 @@ impl<'a, H> PacketBuffer<'a, H> {
     pub fn dequeue(&mut self) -> Result<(H, &mut [u8])> {
         self.dequeue_padding();
 
-        let PacketMetadata { ref mut header, size } = *self.metadata_ring.dequeue_one()?;
+        let PacketMetadata {
+            ref mut header,
+            size,
+        } = *self.metadata_ring.dequeue_one()?;
 
         let payload_buf = self.payload_ring.dequeue_many(size);
         debug_assert!(payload_buf.len() == size);
@@ -164,7 +184,10 @@ impl<'a, H> PacketBuffer<'a, H> {
         self.dequeue_padding();
 
         if let Some(metadata) = self.metadata_ring.get_allocated(0, 1).first() {
-            Ok((metadata.header.as_ref().unwrap(), self.payload_ring.get_allocated(0, metadata.size)))
+            Ok((
+                metadata.header.as_ref().unwrap(),
+                self.payload_ring.get_allocated(0, metadata.size),
+            ))
         } else {
             Err(Error::Exhausted)
         }
@@ -193,8 +216,7 @@ mod test {
     use super::*;
 
     fn buffer() -> PacketBuffer<'static, ()> {
-        PacketBuffer::new(vec![PacketMetadata::EMPTY; 4],
-                          vec![0u8; 16])
+        PacketBuffer::new(vec![PacketMetadata::EMPTY; 4], vec![0u8; 16])
     }
 
     #[test]
@@ -237,7 +259,10 @@ mod test {
         let mut buffer = buffer();
         assert!(buffer.enqueue(12, ()).is_ok());
         assert!(buffer.dequeue().is_ok());
-        buffer.enqueue(12, ()).unwrap().copy_from_slice(b"abcdefghijkl");
+        buffer
+            .enqueue(12, ())
+            .unwrap()
+            .copy_from_slice(b"abcdefghijkl");
     }
 
     #[test]
@@ -250,13 +275,17 @@ mod test {
         assert_eq!(buffer.metadata_ring.len(), 3);
         assert!(buffer.dequeue().is_ok());
 
-        assert!(buffer.dequeue_with(|_, _| Err(Error::Unaddressable) as Result<()>).is_err());
+        assert!(buffer
+            .dequeue_with(|_, _| Err(Error::Unaddressable) as Result<()>)
+            .is_err());
         assert_eq!(buffer.metadata_ring.len(), 1);
 
-        assert!(buffer.dequeue_with(|&mut (), payload| {
-            assert_eq!(payload, &b"abcd"[..]);
-            Ok(())
-        }).is_ok());
+        assert!(buffer
+            .dequeue_with(|&mut (), payload| {
+                assert_eq!(payload, &b"abcd"[..]);
+                Ok(())
+            })
+            .is_ok());
         assert_eq!(buffer.metadata_ring.len(), 0);
     }
 

+ 91 - 43
src/storage/ring_buffer.rs

@@ -4,8 +4,8 @@
 use core::cmp;
 use managed::ManagedSlice;
 
-use crate::{Error, Result};
 use crate::storage::Resettable;
+use crate::{Error, Result};
 
 /// A ring buffer.
 ///
@@ -25,7 +25,7 @@ use crate::storage::Resettable;
 pub struct RingBuffer<'a, T: 'a> {
     storage: ManagedSlice<'a, T>,
     read_at: usize,
-    length:  usize,
+    length: usize,
 }
 
 impl<'a, T: 'a> RingBuffer<'a, T> {
@@ -33,19 +33,20 @@ impl<'a, T: 'a> RingBuffer<'a, T> {
     ///
     /// During creation, every element in `storage` is reset.
     pub fn new<S>(storage: S) -> RingBuffer<'a, T>
-        where S: Into<ManagedSlice<'a, T>>,
+    where
+        S: Into<ManagedSlice<'a, T>>,
     {
         RingBuffer {
             storage: storage.into(),
             read_at: 0,
-            length:  0,
+            length: 0,
         }
     }
 
     /// Clear the ring buffer.
     pub fn clear(&mut self) {
         self.read_at = 0;
-        self.length  = 0;
+        self.length = 0;
     }
 
     /// Return the maximum number of elements in the ring buffer.
@@ -55,7 +56,9 @@ impl<'a, T: 'a> RingBuffer<'a, T> {
 
     /// Clear the ring buffer, and reset every element.
     pub fn reset(&mut self)
-            where T: Resettable {
+    where
+        T: Resettable,
+    {
         self.clear();
         for elem in self.storage.iter_mut() {
             elem.reset();
@@ -112,8 +115,12 @@ impl<'a, T: 'a> RingBuffer<'a, T> {
     /// Call `f` with a single buffer element, and enqueue the element if `f`
     /// returns successfully, or return `Err(Error::Exhausted)` if the buffer is full.
     pub fn enqueue_one_with<'b, R, F>(&'b mut self, f: F) -> Result<R>
-            where F: FnOnce(&'b mut T) -> Result<R> {
-        if self.is_full() { return Err(Error::Exhausted) }
+    where
+        F: FnOnce(&'b mut T) -> Result<R>,
+    {
+        if self.is_full() {
+            return Err(Error::Exhausted);
+        }
 
         let index = self.get_idx_unchecked(self.length);
         match f(&mut self.storage[index]) {
@@ -121,7 +128,7 @@ impl<'a, T: 'a> RingBuffer<'a, T> {
                 self.length += 1;
                 Ok(result)
             }
-            Err(error) => Err(error)
+            Err(error) => Err(error),
         }
     }
 
@@ -136,8 +143,12 @@ impl<'a, T: 'a> RingBuffer<'a, T> {
     /// Call `f` with a single buffer element, and dequeue the element if `f`
     /// returns successfully, or return `Err(Error::Exhausted)` if the buffer is empty.
     pub fn dequeue_one_with<'b, R, F>(&'b mut self, f: F) -> Result<R>
-            where F: FnOnce(&'b mut T) -> Result<R> {
-        if self.is_empty() { return Err(Error::Exhausted) }
+    where
+        F: FnOnce(&'b mut T) -> Result<R>,
+    {
+        if self.is_empty() {
+            return Err(Error::Exhausted);
+        }
 
         let next_at = self.get_idx_unchecked(1);
         match f(&mut self.storage[self.read_at]) {
@@ -146,7 +157,7 @@ impl<'a, T: 'a> RingBuffer<'a, T> {
                 self.read_at = next_at;
                 Ok(result)
             }
-            Err(error) => Err(error)
+            Err(error) => Err(error),
         }
     }
 
@@ -169,7 +180,9 @@ impl<'a, T: 'a> RingBuffer<'a, T> {
     /// This function panics if the amount of elements returned by `f` is larger
     /// than the size of the slice passed into it.
     pub fn enqueue_many_with<'b, R, F>(&'b mut self, f: F) -> (usize, R)
-            where F: FnOnce(&'b mut [T]) -> (usize, R) {
+    where
+        F: FnOnce(&'b mut [T]) -> (usize, R),
+    {
         if self.length == 0 {
             // Ring is currently empty. Reset `read_at` to optimize
             // for contiguous space.
@@ -194,14 +207,17 @@ impl<'a, T: 'a> RingBuffer<'a, T> {
         self.enqueue_many_with(|buf| {
             let size = cmp::min(size, buf.len());
             (size, &mut buf[..size])
-        }).1
+        })
+        .1
     }
 
     /// Enqueue as many elements from the given slice into the buffer as possible,
     /// and return the amount of elements that could fit.
     // #[must_use]
     pub fn enqueue_slice(&mut self, data: &[T]) -> usize
-            where T: Copy {
+    where
+        T: Copy,
+    {
         let (size_1, data) = self.enqueue_many_with(|buf| {
             let size = cmp::min(buf.len(), data.len());
             buf[..size].copy_from_slice(&data[..size]);
@@ -222,7 +238,9 @@ impl<'a, T: 'a> RingBuffer<'a, T> {
     /// This function panics if the amount of elements returned by `f` is larger
     /// than the size of the slice passed into it.
     pub fn dequeue_many_with<'b, R, F>(&'b mut self, f: F) -> (usize, R)
-            where F: FnOnce(&'b mut [T]) -> (usize, R) {
+    where
+        F: FnOnce(&'b mut [T]) -> (usize, R),
+    {
         let capacity = self.capacity();
         let max_size = cmp::min(self.len(), capacity - self.read_at);
         let (size, result) = f(&mut self.storage[self.read_at..self.read_at + max_size]);
@@ -246,14 +264,17 @@ impl<'a, T: 'a> RingBuffer<'a, T> {
         self.dequeue_many_with(|buf| {
             let size = cmp::min(size, buf.len());
             (size, &mut buf[..size])
-        }).1
+        })
+        .1
     }
 
     /// Dequeue as many elements from the buffer into the given slice as possible,
     /// and return the amount of elements that could fit.
     // #[must_use]
     pub fn dequeue_slice(&mut self, data: &mut [T]) -> usize
-            where T: Copy {
+    where
+        T: Copy,
+    {
         let (size_1, data) = self.dequeue_many_with(|buf| {
             let size = cmp::min(buf.len(), data.len());
             data[..size].copy_from_slice(&buf[..size]);
@@ -277,13 +298,19 @@ impl<'a, T: 'a> RingBuffer<'a, T> {
     pub fn get_unallocated(&mut self, offset: usize, mut size: usize) -> &mut [T] {
         let start_at = self.get_idx(self.length + offset);
         // We can't access past the end of unallocated data.
-        if offset > self.window() { return &mut [] }
+        if offset > self.window() {
+            return &mut [];
+        }
         // We can't enqueue more than there is free space.
         let clamped_window = self.window() - offset;
-        if size > clamped_window { size = clamped_window }
+        if size > clamped_window {
+            size = clamped_window
+        }
         // We can't contiguously enqueue past the end of the storage.
         let until_end = self.capacity() - start_at;
-        if size > until_end { size = until_end }
+        if size > until_end {
+            size = until_end
+        }
 
         &mut self.storage[start_at..start_at + size]
     }
@@ -293,7 +320,9 @@ impl<'a, T: 'a> RingBuffer<'a, T> {
     /// the amount written.
     // #[must_use]
     pub fn write_unallocated(&mut self, offset: usize, data: &[T]) -> usize
-            where T: Copy {
+    where
+        T: Copy,
+    {
         let (size_1, offset, data) = {
             let slice = self.get_unallocated(offset, data.len());
             let slice_len = slice.len();
@@ -324,13 +353,19 @@ impl<'a, T: 'a> RingBuffer<'a, T> {
     pub fn get_allocated(&self, offset: usize, mut size: usize) -> &[T] {
         let start_at = self.get_idx(offset);
         // We can't read past the end of the allocated data.
-        if offset > self.length { return &mut [] }
+        if offset > self.length {
+            return &mut [];
+        }
         // We can't read more than we have allocated.
         let clamped_length = self.length - offset;
-        if size > clamped_length { size = clamped_length }
+        if size > clamped_length {
+            size = clamped_length
+        }
         // We can't contiguously dequeue past the end of the storage.
         let until_end = self.capacity() - start_at;
-        if size > until_end { size = until_end }
+        if size > until_end {
+            size = until_end
+        }
 
         &self.storage[start_at..start_at + size]
     }
@@ -340,7 +375,9 @@ impl<'a, T: 'a> RingBuffer<'a, T> {
     /// the amount read.
     // #[must_use]
     pub fn read_allocated(&mut self, offset: usize, data: &mut [T]) -> usize
-            where T: Copy {
+    where
+        T: Copy,
+    {
         let (size_1, offset, data) = {
             let slice = self.get_allocated(offset, data.len());
             data[..slice.len()].copy_from_slice(slice);
@@ -402,8 +439,10 @@ mod test {
     #[test]
     fn test_buffer_enqueue_dequeue_one_with() {
         let mut ring = RingBuffer::new(vec![0; 5]);
-        assert_eq!(ring.dequeue_one_with(|_| unreachable!()) as Result<()>,
-                   Err(Error::Exhausted));
+        assert_eq!(
+            ring.dequeue_one_with(|_| unreachable!()) as Result<()>,
+            Err(Error::Exhausted)
+        );
 
         ring.enqueue_one_with(Ok).unwrap();
         assert!(!ring.is_empty());
@@ -414,15 +453,19 @@ mod test {
             assert!(!ring.is_empty());
         }
         assert!(ring.is_full());
-        assert_eq!(ring.enqueue_one_with(|_| unreachable!()) as Result<()>,
-                   Err(Error::Exhausted));
+        assert_eq!(
+            ring.enqueue_one_with(|_| unreachable!()) as Result<()>,
+            Err(Error::Exhausted)
+        );
 
         for i in 0..5 {
             assert_eq!(ring.dequeue_one_with(|e| Ok(*e)).unwrap(), i);
             assert!(!ring.is_full());
         }
-        assert_eq!(ring.dequeue_one_with(|_| unreachable!()) as Result<()>,
-                   Err(Error::Exhausted));
+        assert_eq!(
+            ring.dequeue_one_with(|_| unreachable!()) as Result<()>,
+            Err(Error::Exhausted)
+        );
         assert!(ring.is_empty());
     }
 
@@ -454,11 +497,14 @@ mod test {
     fn test_buffer_enqueue_many_with() {
         let mut ring = RingBuffer::new(vec![b'.'; 12]);
 
-        assert_eq!(ring.enqueue_many_with(|buf| {
-            assert_eq!(buf.len(), 12);
-            buf[0..2].copy_from_slice(b"ab");
+        assert_eq!(
+            ring.enqueue_many_with(|buf| {
+                assert_eq!(buf.len(), 12);
+                buf[0..2].copy_from_slice(b"ab");
+                (2, true)
+            }),
             (2, true)
-        }), (2, true));
+        );
         assert_eq!(ring.len(), 2);
         assert_eq!(&ring.storage[..], b"ab..........");
 
@@ -545,12 +591,15 @@ mod test {
 
         assert_eq!(ring.enqueue_slice(b"abcdefghijkl"), 12);
 
-        assert_eq!(ring.dequeue_many_with(|buf| {
-            assert_eq!(buf.len(), 12);
-            assert_eq!(buf, b"abcdefghijkl");
-            buf[..4].copy_from_slice(b"....");
+        assert_eq!(
+            ring.dequeue_many_with(|buf| {
+                assert_eq!(buf.len(), 12);
+                assert_eq!(buf, b"abcdefghijkl");
+                buf[..4].copy_from_slice(b"....");
+                (4, true)
+            }),
             (4, true)
-        }), (4, true));
+        );
         assert_eq!(ring.len(), 8);
         assert_eq!(&ring.storage[..], b"....efghijkl");
 
@@ -679,7 +728,7 @@ mod test {
         let mut ring = RingBuffer::new(vec![b'.'; 12]);
 
         assert_eq!(ring.get_allocated(16, 4), b"");
-        assert_eq!(ring.get_allocated(0, 4),  b"");
+        assert_eq!(ring.get_allocated(0, 4), b"");
 
         ring.enqueue_slice(b"abcd");
         assert_eq!(ring.get_allocated(0, 8), b"abcd");
@@ -711,7 +760,6 @@ mod test {
         let mut data = [0; 6];
         assert_eq!(ring.read_allocated(6, &mut data[..]), 3);
         assert_eq!(&data[..], b"mno\x00\x00\x00");
-
     }
 
     #[test]

+ 48 - 23
src/time.rs

@@ -10,7 +10,7 @@ absolute and relative time.
 [Duration]: struct.Duration.html
 */
 
-use core::{ops, fmt};
+use core::{fmt, ops};
 
 /// A representation of an absolute time value.
 ///
@@ -30,12 +30,16 @@ pub struct Instant {
 impl Instant {
     /// Create a new `Instant` from a number of milliseconds.
     pub fn from_millis<T: Into<i64>>(millis: T) -> Instant {
-        Instant { millis: millis.into() }
+        Instant {
+            millis: millis.into(),
+        }
     }
 
     /// Create a new `Instant` from a number of seconds.
     pub fn from_secs<T: Into<i64>>(secs: T) -> Instant {
-        Instant { millis: secs.into() * 1000 }
+        Instant {
+            millis: secs.into() * 1000,
+        }
     }
 
     /// Create a new `Instant` from the current [std::time::SystemTime].
@@ -79,7 +83,8 @@ impl From<::std::time::Instant> for Instant {
 #[cfg(feature = "std")]
 impl From<::std::time::SystemTime> for Instant {
     fn from(other: ::std::time::SystemTime) -> Instant {
-        let n = other.duration_since(::std::time::UNIX_EPOCH)
+        let n = other
+            .duration_since(::std::time::UNIX_EPOCH)
             .expect("start time must not be before the unix epoch");
         Self::from_millis(n.as_secs() as i64 * 1000 + n.subsec_millis() as i64)
     }
@@ -149,7 +154,9 @@ impl Duration {
 
     /// Create a new `Instant` from a number of seconds.
     pub const fn from_secs(secs: u64) -> Duration {
-        Duration { millis: secs * 1000 }
+        Duration {
+            millis: secs * 1000,
+        }
     }
 
     /// The fractional number of milliseconds in this `Duration`.
@@ -193,14 +200,19 @@ impl ops::Sub<Duration> for Duration {
 
     fn sub(self, rhs: Duration) -> Duration {
         Duration::from_millis(
-            self.millis.checked_sub(rhs.total_millis()).expect("overflow when subtracting durations"))
+            self.millis
+                .checked_sub(rhs.total_millis())
+                .expect("overflow when subtracting durations"),
+        )
     }
 }
 
 impl ops::SubAssign<Duration> for Duration {
     fn sub_assign(&mut self, rhs: Duration) {
-        self.millis = self.millis.checked_sub(
-            rhs.total_millis()).expect("overflow when subtracting durations");
+        self.millis = self
+            .millis
+            .checked_sub(rhs.total_millis())
+            .expect("overflow when subtracting durations");
     }
 }
 
@@ -234,7 +246,7 @@ impl ops::DivAssign<u32> for Duration {
 
 impl ops::Shl<u32> for Duration {
     type Output = Duration;
-    
+
     fn shl(self, rhs: u32) -> Duration {
         Duration::from_millis(self.millis << rhs)
     }
@@ -248,7 +260,7 @@ impl ops::ShlAssign<u32> for Duration {
 
 impl ops::Shr<u32> for Duration {
     type Output = Duration;
-    
+
     fn shr(self, rhs: u32) -> Duration {
         Duration::from_millis(self.millis >> rhs)
     }
@@ -262,17 +274,13 @@ impl ops::ShrAssign<u32> for Duration {
 
 impl From<::core::time::Duration> for Duration {
     fn from(other: ::core::time::Duration) -> Duration {
-        Duration::from_millis(
-            other.as_secs() * 1000 + other.subsec_millis() as u64
-        )
+        Duration::from_millis(other.as_secs() * 1000 + other.subsec_millis() as u64)
     }
 }
 
 impl Into<::core::time::Duration> for Duration {
     fn into(self) -> ::core::time::Duration {
-        ::core::time::Duration::from_millis(
-            self.total_millis()
-        )
+        ::core::time::Duration::from_millis(self.total_millis())
     }
 }
 
@@ -283,9 +291,15 @@ mod test {
     #[test]
     fn test_instant_ops() {
         // std::ops::Add
-        assert_eq!(Instant::from_millis(4) + Duration::from_millis(6), Instant::from_millis(10));
+        assert_eq!(
+            Instant::from_millis(4) + Duration::from_millis(6),
+            Instant::from_millis(10)
+        );
         // std::ops::Sub
-        assert_eq!(Instant::from_millis(7) - Duration::from_millis(5), Instant::from_millis(2));
+        assert_eq!(
+            Instant::from_millis(7) - Duration::from_millis(5),
+            Instant::from_millis(2)
+        );
     }
 
     #[test]
@@ -306,19 +320,30 @@ mod test {
     #[cfg(feature = "std")]
     fn test_instant_conversions() {
         let mut epoc: ::std::time::SystemTime = Instant::from_millis(0).into();
-        assert_eq!(Instant::from(::std::time::UNIX_EPOCH),
-                   Instant::from_millis(0));
+        assert_eq!(
+            Instant::from(::std::time::UNIX_EPOCH),
+            Instant::from_millis(0)
+        );
         assert_eq!(epoc, ::std::time::UNIX_EPOCH);
         epoc = Instant::from_millis(2085955200i64 * 1000).into();
-        assert_eq!(epoc, ::std::time::UNIX_EPOCH + ::std::time::Duration::from_secs(2085955200));
+        assert_eq!(
+            epoc,
+            ::std::time::UNIX_EPOCH + ::std::time::Duration::from_secs(2085955200)
+        );
     }
 
     #[test]
     fn test_duration_ops() {
         // std::ops::Add
-        assert_eq!(Duration::from_millis(40) + Duration::from_millis(2), Duration::from_millis(42));
+        assert_eq!(
+            Duration::from_millis(40) + Duration::from_millis(2),
+            Duration::from_millis(42)
+        );
         // std::ops::Sub
-        assert_eq!(Duration::from_millis(555) - Duration::from_millis(42), Duration::from_millis(513));
+        assert_eq!(
+            Duration::from_millis(555) - Duration::from_millis(42),
+            Duration::from_millis(513)
+        );
         // std::ops::Mul
         assert_eq!(Duration::from_millis(13) * 22, Duration::from_millis(286));
         // std::ops::Div

+ 83 - 63
src/wire/arp.rs

@@ -1,5 +1,5 @@
-use core::fmt;
 use byteorder::{ByteOrder, NetworkEndian};
+use core::fmt;
 
 use crate::{Error, Result};
 
@@ -24,7 +24,7 @@ enum_with_unknown! {
 #[derive(Debug, PartialEq, Clone)]
 #[cfg_attr(feature = "defmt", derive(defmt::Format))]
 pub struct Packet<T: AsRef<[u8]>> {
-    buffer: T
+    buffer: T,
 }
 
 mod field {
@@ -34,9 +34,9 @@ mod field {
 
     pub const HTYPE: Field = 0..2;
     pub const PTYPE: Field = 2..4;
-    pub const HLEN:  usize = 4;
-    pub const PLEN:  usize = 5;
-    pub const OPER:  Field = 6..8;
+    pub const HLEN: usize = 4;
+    pub const PLEN: usize = 5;
+    pub const OPER: Field = 6..8;
 
     #[inline]
     pub fn SHA(hardware_len: u8, _protocol_len: u8) -> Field {
@@ -263,7 +263,7 @@ pub enum Repr {
         source_hardware_addr: EthernetAddress,
         source_protocol_addr: Ipv4Address,
         target_hardware_addr: EthernetAddress,
-        target_protocol_addr: Ipv4Address
+        target_protocol_addr: Ipv4Address,
     },
 }
 
@@ -271,22 +271,20 @@ impl Repr {
     /// Parse an Address Resolution Protocol packet and return a high-level representation,
     /// or return `Err(Error::Unrecognized)` if the packet is not recognized.
     pub fn parse<T: AsRef<[u8]>>(packet: &Packet<T>) -> Result<Repr> {
-        match (packet.hardware_type(), packet.protocol_type(),
-               packet.hardware_len(), packet.protocol_len()) {
-            (Hardware::Ethernet, Protocol::Ipv4, 6, 4) => {
-                Ok(Repr::EthernetIpv4 {
-                    operation: packet.operation(),
-                    source_hardware_addr:
-                        EthernetAddress::from_bytes(packet.source_hardware_addr()),
-                    source_protocol_addr:
-                        Ipv4Address::from_bytes(packet.source_protocol_addr()),
-                    target_hardware_addr:
-                        EthernetAddress::from_bytes(packet.target_hardware_addr()),
-                    target_protocol_addr:
-                        Ipv4Address::from_bytes(packet.target_protocol_addr())
-                })
-            },
-            _ => Err(Error::Unrecognized)
+        match (
+            packet.hardware_type(),
+            packet.protocol_type(),
+            packet.hardware_len(),
+            packet.protocol_len(),
+        ) {
+            (Hardware::Ethernet, Protocol::Ipv4, 6, 4) => Ok(Repr::EthernetIpv4 {
+                operation: packet.operation(),
+                source_hardware_addr: EthernetAddress::from_bytes(packet.source_hardware_addr()),
+                source_protocol_addr: Ipv4Address::from_bytes(packet.source_protocol_addr()),
+                target_hardware_addr: EthernetAddress::from_bytes(packet.target_hardware_addr()),
+                target_protocol_addr: Ipv4Address::from_bytes(packet.target_protocol_addr()),
+            }),
+            _ => Err(Error::Unrecognized),
         }
     }
 
@@ -302,8 +300,10 @@ impl Repr {
         match *self {
             Repr::EthernetIpv4 {
                 operation,
-                source_hardware_addr, source_protocol_addr,
-                target_hardware_addr, target_protocol_addr
+                source_hardware_addr,
+                source_protocol_addr,
+                target_hardware_addr,
+                target_protocol_addr,
             } => {
                 packet.set_hardware_type(Hardware::Ethernet);
                 packet.set_protocol_type(Protocol::Ipv4);
@@ -314,7 +314,7 @@ impl Repr {
                 packet.set_source_protocol_addr(source_protocol_addr.as_bytes());
                 packet.set_target_hardware_addr(target_hardware_addr.as_bytes());
                 packet.set_target_protocol_addr(target_protocol_addr.as_bytes());
-            },
+            }
         }
     }
 }
@@ -325,13 +325,23 @@ impl<T: AsRef<[u8]>> fmt::Display for Packet<T> {
             Ok(repr) => write!(f, "{}", repr),
             _ => {
                 write!(f, "ARP (unrecognized)")?;
-                write!(f, " htype={:?} ptype={:?} hlen={:?} plen={:?} op={:?}",
-                       self.hardware_type(), self.protocol_type(),
-                       self.hardware_len(), self.protocol_len(),
-                       self.operation())?;
-                write!(f, " sha={:?} spa={:?} tha={:?} tpa={:?}",
-                       self.source_hardware_addr(), self.source_protocol_addr(),
-                       self.target_hardware_addr(), self.target_protocol_addr())?;
+                write!(
+                    f,
+                    " htype={:?} ptype={:?} hlen={:?} plen={:?} op={:?}",
+                    self.hardware_type(),
+                    self.protocol_type(),
+                    self.hardware_len(),
+                    self.protocol_len(),
+                    self.operation()
+                )?;
+                write!(
+                    f,
+                    " sha={:?} spa={:?} tha={:?} tpa={:?}",
+                    self.source_hardware_addr(),
+                    self.source_protocol_addr(),
+                    self.target_hardware_addr(),
+                    self.target_protocol_addr()
+                )?;
                 Ok(())
             }
         }
@@ -343,26 +353,36 @@ impl fmt::Display for Repr {
         match *self {
             Repr::EthernetIpv4 {
                 operation,
-                source_hardware_addr, source_protocol_addr,
-                target_hardware_addr, target_protocol_addr
+                source_hardware_addr,
+                source_protocol_addr,
+                target_hardware_addr,
+                target_protocol_addr,
             } => {
-                write!(f, "ARP type=Ethernet+IPv4 src={}/{} tgt={}/{} op={:?}",
-                       source_hardware_addr, source_protocol_addr,
-                       target_hardware_addr, target_protocol_addr,
-                       operation)
-            },
+                write!(
+                    f,
+                    "ARP type=Ethernet+IPv4 src={}/{} tgt={}/{} op={:?}",
+                    source_hardware_addr,
+                    source_protocol_addr,
+                    target_hardware_addr,
+                    target_protocol_addr,
+                    operation
+                )
+            }
         }
     }
 }
 
-use crate::wire::pretty_print::{PrettyPrint, PrettyIndent};
+use crate::wire::pretty_print::{PrettyIndent, PrettyPrint};
 
 impl<T: AsRef<[u8]>> PrettyPrint for Packet<T> {
-    fn pretty_print(buffer: &dyn AsRef<[u8]>, f: &mut fmt::Formatter,
-                    indent: &mut PrettyIndent) -> fmt::Result {
+    fn pretty_print(
+        buffer: &dyn AsRef<[u8]>,
+        f: &mut fmt::Formatter,
+        indent: &mut PrettyIndent,
+    ) -> fmt::Result {
         match Packet::new_checked(buffer) {
             Err(err) => write!(f, "{}({})", indent, err),
-            Ok(packet) => write!(f, "{}{}", indent, packet)
+            Ok(packet) => write!(f, "{}{}", indent, packet),
         }
     }
 }
@@ -371,16 +391,10 @@ impl<T: AsRef<[u8]>> PrettyPrint for Packet<T> {
 mod test {
     use super::*;
 
-    static PACKET_BYTES: [u8; 28] =
-        [0x00, 0x01,
-         0x08, 0x00,
-         0x06,
-         0x04,
-         0x00, 0x01,
-         0x11, 0x12, 0x13, 0x14, 0x15, 0x16,
-         0x21, 0x22, 0x23, 0x24,
-         0x31, 0x32, 0x33, 0x34, 0x35, 0x36,
-         0x41, 0x42, 0x43, 0x44];
+    static PACKET_BYTES: [u8; 28] = [
+        0x00, 0x01, 0x08, 0x00, 0x06, 0x04, 0x00, 0x01, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x21,
+        0x22, 0x23, 0x24, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x41, 0x42, 0x43, 0x44,
+    ];
 
     #[test]
     fn test_deconstruct() {
@@ -390,9 +404,15 @@ mod test {
         assert_eq!(packet.hardware_len(), 6);
         assert_eq!(packet.protocol_len(), 4);
         assert_eq!(packet.operation(), Operation::Request);
-        assert_eq!(packet.source_hardware_addr(), &[0x11, 0x12, 0x13, 0x14, 0x15, 0x16]);
+        assert_eq!(
+            packet.source_hardware_addr(),
+            &[0x11, 0x12, 0x13, 0x14, 0x15, 0x16]
+        );
         assert_eq!(packet.source_protocol_addr(), &[0x21, 0x22, 0x23, 0x24]);
-        assert_eq!(packet.target_hardware_addr(), &[0x31, 0x32, 0x33, 0x34, 0x35, 0x36]);
+        assert_eq!(
+            packet.target_hardware_addr(),
+            &[0x31, 0x32, 0x33, 0x34, 0x35, 0x36]
+        );
         assert_eq!(packet.target_protocol_addr(), &[0x41, 0x42, 0x43, 0x44]);
     }
 
@@ -415,14 +435,14 @@ mod test {
     fn packet_repr() -> Repr {
         Repr::EthernetIpv4 {
             operation: Operation::Request,
-            source_hardware_addr:
-                EthernetAddress::from_bytes(&[0x11, 0x12, 0x13, 0x14, 0x15, 0x16]),
-            source_protocol_addr:
-                Ipv4Address::from_bytes(&[0x21, 0x22, 0x23, 0x24]),
-            target_hardware_addr:
-                EthernetAddress::from_bytes(&[0x31, 0x32, 0x33, 0x34, 0x35, 0x36]),
-            target_protocol_addr:
-                Ipv4Address::from_bytes(&[0x41, 0x42, 0x43, 0x44])
+            source_hardware_addr: EthernetAddress::from_bytes(&[
+                0x11, 0x12, 0x13, 0x14, 0x15, 0x16,
+            ]),
+            source_protocol_addr: Ipv4Address::from_bytes(&[0x21, 0x22, 0x23, 0x24]),
+            target_hardware_addr: EthernetAddress::from_bytes(&[
+                0x31, 0x32, 0x33, 0x34, 0x35, 0x36,
+            ]),
+            target_protocol_addr: Ipv4Address::from_bytes(&[0x41, 0x42, 0x43, 0x44]),
         }
     }
 

+ 185 - 121
src/wire/dhcpv4.rs

@@ -2,9 +2,9 @@
 
 use byteorder::{ByteOrder, NetworkEndian};
 
-use crate::{Error, Result};
-use crate::wire::{EthernetAddress, Ipv4Address};
 use crate::wire::arp::Hardware;
+use crate::wire::{EthernetAddress, Ipv4Address};
+use crate::{Error, Result};
 
 pub const SERVER_PORT: u16 = 67;
 pub const CLIENT_PORT: u16 = 68;
@@ -37,8 +37,11 @@ enum_with_unknown! {
 impl MessageType {
     fn opcode(&self) -> OpCode {
         match *self {
-            MessageType::Discover | MessageType::Inform | MessageType::Request |
-                MessageType::Decline | MessageType::Release => OpCode::Request,
+            MessageType::Discover
+            | MessageType::Inform
+            | MessageType::Request
+            | MessageType::Decline
+            | MessageType::Release => OpCode::Request,
             MessageType::Offer | MessageType::Ack | MessageType::Nak => OpCode::Reply,
             MessageType::Unknown(_) => OpCode::Unknown(0),
         }
@@ -59,7 +62,7 @@ pub enum DhcpOption<'a> {
     Router(Ipv4Address),
     SubnetMask(Ipv4Address),
     MaximumDhcpMessageSize(u16),
-    Other { kind: u8, data: &'a [u8] }
+    Other { kind: u8, data: &'a [u8] },
 }
 
 impl<'a> DhcpOption<'a> {
@@ -81,12 +84,10 @@ impl<'a> DhcpOption<'a> {
                 skip_len = length + 2;
                 let data = buffer.get(2..skip_len).ok_or(Error::Truncated)?;
                 match (kind, length) {
-                    (field::OPT_END, _) |
-                    (field::OPT_PAD, _) =>
-                        unreachable!(),
+                    (field::OPT_END, _) | (field::OPT_PAD, _) => unreachable!(),
                     (field::OPT_DHCP_MESSAGE_TYPE, 1) => {
                         option = DhcpOption::MessageType(MessageType::from(data[0]));
-                    },
+                    }
                     (field::OPT_REQUESTED_IP, 4) => {
                         option = DhcpOption::RequestedIp(Ipv4Address::from_bytes(data));
                     }
@@ -95,7 +96,8 @@ impl<'a> DhcpOption<'a> {
                         if hardware_type != Hardware::Ethernet {
                             return Err(Error::Unrecognized);
                         }
-                        option = DhcpOption::ClientIdentifier(EthernetAddress::from_bytes(&data[1..]));
+                        option =
+                            DhcpOption::ClientIdentifier(EthernetAddress::from_bytes(&data[1..]));
                     }
                     (field::OPT_SERVER_IDENTIFIER, 4) => {
                         option = DhcpOption::ServerIdentifier(Ipv4Address::from_bytes(data));
@@ -107,13 +109,20 @@ impl<'a> DhcpOption<'a> {
                         option = DhcpOption::SubnetMask(Ipv4Address::from_bytes(data));
                     }
                     (field::OPT_MAX_DHCP_MESSAGE_SIZE, 2) => {
-                        option = DhcpOption::MaximumDhcpMessageSize(u16::from_be_bytes([data[0], data[1]]));
+                        option = DhcpOption::MaximumDhcpMessageSize(u16::from_be_bytes([
+                            data[0], data[1],
+                        ]));
                     }
                     (field::OPT_IP_LEASE_TIME, 4) => {
-                        option = DhcpOption::IpLeaseTime(u32::from_be_bytes([data[0], data[1], data[2], data[3]]))
+                        option = DhcpOption::IpLeaseTime(u32::from_be_bytes([
+                            data[0], data[1], data[2], data[3],
+                        ]))
                     }
                     (_, _) => {
-                        option = DhcpOption::Other { kind: kind, data: data };
+                        option = DhcpOption::Other {
+                            kind: kind,
+                            data: data,
+                        };
                     }
                 }
             }
@@ -126,20 +135,14 @@ impl<'a> DhcpOption<'a> {
             &DhcpOption::EndOfList => 1,
             &DhcpOption::Pad => 1,
             &DhcpOption::MessageType(_) => 3,
-            &DhcpOption::ClientIdentifier(eth_addr) => {
-                3 + eth_addr.as_bytes().len()
-            }
-            &DhcpOption::RequestedIp(ip) |
-            &DhcpOption::ServerIdentifier(ip) |
-            &DhcpOption::Router(ip) |
-            &DhcpOption::SubnetMask(ip) => {
-                2 + ip.as_bytes().len()
-            },
-            &DhcpOption::MaximumDhcpMessageSize(_) => {
-                4
-            }
+            &DhcpOption::ClientIdentifier(eth_addr) => 3 + eth_addr.as_bytes().len(),
+            &DhcpOption::RequestedIp(ip)
+            | &DhcpOption::ServerIdentifier(ip)
+            | &DhcpOption::Router(ip)
+            | &DhcpOption::SubnetMask(ip) => 2 + ip.as_bytes().len(),
+            &DhcpOption::MaximumDhcpMessageSize(_) => 4,
             &DhcpOption::IpLeaseTime(_) => 6,
-            &DhcpOption::Other { data, .. } => 2 + data.len()
+            &DhcpOption::Other { data, .. } => 2 + data.len(),
         }
     }
 
@@ -168,19 +171,19 @@ impl<'a> DhcpOption<'a> {
                         buffer[2] = u16::from(Hardware::Ethernet) as u8;
                         buffer[3..9].copy_from_slice(eth_addr.as_bytes());
                     }
-                    DhcpOption::RequestedIp(ip)  => {
+                    DhcpOption::RequestedIp(ip) => {
                         buffer[0] = field::OPT_REQUESTED_IP;
                         buffer[2..6].copy_from_slice(ip.as_bytes());
                     }
-                    DhcpOption::ServerIdentifier(ip)  => {
+                    DhcpOption::ServerIdentifier(ip) => {
                         buffer[0] = field::OPT_SERVER_IDENTIFIER;
                         buffer[2..6].copy_from_slice(ip.as_bytes());
                     }
-                    DhcpOption::Router(ip)  => {
+                    DhcpOption::Router(ip) => {
                         buffer[0] = field::OPT_ROUTER;
                         buffer[2..6].copy_from_slice(ip.as_bytes());
                     }
-                    DhcpOption::SubnetMask(mask)  => {
+                    DhcpOption::SubnetMask(mask) => {
                         buffer[0] = field::OPT_SUBNET_MASK;
                         buffer[2..6].copy_from_slice(mask.as_bytes());
                     }
@@ -192,7 +195,10 @@ impl<'a> DhcpOption<'a> {
                         buffer[0] = field::OPT_IP_LEASE_TIME;
                         buffer[2..6].copy_from_slice(&lease_time.to_be_bytes()[..]);
                     }
-                    DhcpOption::Other { kind, data: provided } => {
+                    DhcpOption::Other {
+                        kind,
+                        data: provided,
+                    } => {
                         buffer[0] = kind;
                         buffer[2..skip_length].copy_from_slice(provided);
                     }
@@ -207,7 +213,7 @@ impl<'a> DhcpOption<'a> {
 #[derive(Debug, PartialEq)]
 #[cfg_attr(feature = "defmt", derive(defmt::Format))]
 pub struct Packet<T: AsRef<[u8]>> {
-    buffer: T
+    buffer: T,
 }
 
 pub(crate) mod field {
@@ -691,7 +697,7 @@ pub struct Repr<'a> {
     /// The maximum size dhcp packet the interface can receive
     pub max_size: Option<u16>,
     /// The DHCP IP lease duration, specified in seconds.
-    pub lease_duration: Option<u32>
+    pub lease_duration: Option<u32>,
 }
 
 impl<'a> Repr<'a> {
@@ -700,22 +706,39 @@ impl<'a> Repr<'a> {
         let mut len = field::OPTIONS.start;
         // message type and end-of-options options
         len += 3 + 1;
-        if self.requested_ip.is_some() { len += 6; }
-        if self.client_identifier.is_some() { len += 9; }
-        if self.server_identifier.is_some() { len += 6; }
-        if self.max_size.is_some() { len += 4; }
-        if self.router.is_some() { len += 6; }
-        if self.subnet_mask.is_some() { len += 6; }
-        if self.lease_duration.is_some() { len += 6; }
-        if let Some(list) = self.parameter_request_list { len += list.len() + 2; }
+        if self.requested_ip.is_some() {
+            len += 6;
+        }
+        if self.client_identifier.is_some() {
+            len += 9;
+        }
+        if self.server_identifier.is_some() {
+            len += 6;
+        }
+        if self.max_size.is_some() {
+            len += 4;
+        }
+        if self.router.is_some() {
+            len += 6;
+        }
+        if self.subnet_mask.is_some() {
+            len += 6;
+        }
+        if self.lease_duration.is_some() {
+            len += 6;
+        }
+        if let Some(list) = self.parameter_request_list {
+            len += list.len() + 2;
+        }
 
         len
     }
 
     /// Parse a DHCP packet and return a high-level representation.
     pub fn parse<T>(packet: &Packet<&'a T>) -> Result<Self>
-            where T: AsRef<[u8]> + ?Sized {
-
+    where
+        T: AsRef<[u8]> + ?Sized,
+    {
         let transaction_id = packet.transaction_id();
         let client_hardware_address = packet.client_hardware_address();
         let client_ip = packet.client_ip();
@@ -753,12 +776,12 @@ impl<'a> Repr<'a> {
             let (next_options, option) = DhcpOption::parse(options)?;
             match option {
                 DhcpOption::EndOfList => break,
-                DhcpOption::Pad => {},
+                DhcpOption::Pad => {}
                 DhcpOption::MessageType(value) => {
                     if value.opcode() == packet.opcode() {
                         message_type = Ok(value);
                     }
-                },
+                }
                 DhcpOption::RequestedIp(ip) => {
                     requested_ip = Some(ip);
                 }
@@ -773,24 +796,30 @@ impl<'a> Repr<'a> {
                 }
                 DhcpOption::SubnetMask(mask) => {
                     subnet_mask = Some(mask);
-                },
+                }
                 DhcpOption::MaximumDhcpMessageSize(size) => {
                     max_size = Some(size);
                 }
                 DhcpOption::IpLeaseTime(duration) => {
                     lease_duration = Some(duration);
                 }
-                DhcpOption::Other {kind: field::OPT_PARAMETER_REQUEST_LIST, data} => {
+                DhcpOption::Other {
+                    kind: field::OPT_PARAMETER_REQUEST_LIST,
+                    data,
+                } => {
                     parameter_request_list = Some(data);
                 }
-                DhcpOption::Other {kind: field::OPT_DOMAIN_NAME_SERVER, data} => {
+                DhcpOption::Other {
+                    kind: field::OPT_DOMAIN_NAME_SERVER,
+                    data,
+                } => {
                     let mut servers = [None; MAX_DNS_SERVER_COUNT];
                     for (server, chunk) in servers.iter_mut().zip(data.chunks(4)) {
                         *server = Some(Ipv4Address::from_bytes(chunk));
                     }
                     dns_servers = Some(servers);
                 }
-                DhcpOption::Other {..} => {}
+                DhcpOption::Other { .. } => {}
             }
             options = next_options;
         }
@@ -798,9 +827,21 @@ impl<'a> Repr<'a> {
         let broadcast = packet.broadcast_flag();
 
         Ok(Repr {
-            transaction_id, client_hardware_address, client_ip, your_ip, server_ip, relay_agent_ip,
-            broadcast, requested_ip, server_identifier, router,
-            subnet_mask, client_identifier, parameter_request_list, dns_servers, max_size,
+            transaction_id,
+            client_hardware_address,
+            client_ip,
+            your_ip,
+            server_ip,
+            relay_agent_ip,
+            broadcast,
+            requested_ip,
+            server_identifier,
+            router,
+            subnet_mask,
+            client_identifier,
+            parameter_request_list,
+            dns_servers,
+            max_size,
             lease_duration,
             message_type: message_type?,
         })
@@ -809,7 +850,9 @@ impl<'a> Repr<'a> {
     /// Emit a high-level representation into a Dynamic Host
     /// Configuration Protocol packet.
     pub fn emit<T>(&self, packet: &mut Packet<&mut T>) -> Result<()>
-            where T: AsRef<[u8]> + AsMut<[u8]> + ?Sized {
+    where
+        T: AsRef<[u8]> + AsMut<[u8]> + ?Sized,
+    {
         packet.set_sname_and_boot_file_to_zero();
         packet.set_opcode(self.message_type.opcode());
         packet.set_hardware_type(Hardware::Ethernet);
@@ -850,7 +893,11 @@ impl<'a> Repr<'a> {
                 options = DhcpOption::IpLeaseTime(duration).emit(options);
             }
             if let Some(list) = self.parameter_request_list {
-                options = DhcpOption::Other{ kind: field::OPT_PARAMETER_REQUEST_LIST, data: list }.emit(options);
+                options = DhcpOption::Other {
+                    kind: field::OPT_PARAMETER_REQUEST_LIST,
+                    data: list,
+                }
+                .emit(options);
             }
             DhcpOption::EndOfList.emit(options);
         }
@@ -861,75 +908,80 @@ impl<'a> Repr<'a> {
 
 #[cfg(test)]
 mod test {
-    use crate::wire::Ipv4Address;
     use super::*;
+    use crate::wire::Ipv4Address;
 
     const MAGIC_COOKIE: u32 = 0x63825363;
 
     static DISCOVER_BYTES: &[u8] = &[
-        0x01, 0x01, 0x06, 0x00, 0x00, 0x00, 0x3d, 0x1d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x82, 0x01,
-        0xfc, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x82, 0x53, 0x63,
-        0x35, 0x01, 0x01, 0x3d, 0x07, 0x01, 0x00, 0x0b, 0x82, 0x01, 0xfc, 0x42, 0x32, 0x04, 0x00, 0x00,
-        0x00, 0x00, 0x39, 0x2, 0x5, 0xdc, 0x37, 0x04, 0x01, 0x03, 0x06, 0x2a, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x01, 0x01, 0x06, 0x00, 0x00, 0x00, 0x3d, 0x1d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b,
+        0x82, 0x01, 0xfc, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x82, 0x53, 0x63,
+        0x35, 0x01, 0x01, 0x3d, 0x07, 0x01, 0x00, 0x0b, 0x82, 0x01, 0xfc, 0x42, 0x32, 0x04, 0x00,
+        0x00, 0x00, 0x00, 0x39, 0x2, 0x5, 0xdc, 0x37, 0x04, 0x01, 0x03, 0x06, 0x2a, 0xff, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     ];
 
     static ACK_DNS_SERVER_BYTES: &[u8] = &[
-        0x02, 0x01, 0x06, 0x00, 0xcc, 0x34, 0x75, 0xab, 0x00, 0x00, 0x80, 0x00, 0x0a, 0xff, 0x06, 0x91,
-        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0xff, 0x06, 0xfe, 0x34, 0x17, 0xeb, 0xc9,
-        0xaa, 0x2f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x82, 0x53, 0x63,
-        0x35, 0x01, 0x05, 0x36, 0x04, 0xa3, 0x01, 0x4a, 0x16, 0x01, 0x04, 0xff, 0xff, 0xff, 0x00, 0x2b,
-        0x05, 0xdc, 0x03, 0x4e, 0x41, 0x50, 0x0f, 0x15, 0x6e, 0x61, 0x74, 0x2e, 0x70, 0x68, 0x79, 0x73,
-        0x69, 0x63, 0x73, 0x2e, 0x6f, 0x78, 0x2e, 0x61, 0x63, 0x2e, 0x75, 0x6b, 0x00, 0x03, 0x04, 0x0a,
-        0xff, 0x06, 0xfe, 0x06, 0x10, 0xa3, 0x01, 0x4a, 0x06, 0xa3, 0x01, 0x4a, 0x07, 0xa3, 0x01, 0x4a,
-        0x03, 0xa3, 0x01, 0x4a, 0x04, 0x2c, 0x10, 0xa3, 0x01, 0x4a, 0x03, 0xa3, 0x01, 0x4a, 0x04, 0xa3,
-        0x01, 0x4a, 0x06, 0xa3, 0x01, 0x4a, 0x07, 0x2e, 0x01, 0x08, 0xff
+        0x02, 0x01, 0x06, 0x00, 0xcc, 0x34, 0x75, 0xab, 0x00, 0x00, 0x80, 0x00, 0x0a, 0xff, 0x06,
+        0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0xff, 0x06, 0xfe, 0x34, 0x17,
+        0xeb, 0xc9, 0xaa, 0x2f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x82, 0x53, 0x63,
+        0x35, 0x01, 0x05, 0x36, 0x04, 0xa3, 0x01, 0x4a, 0x16, 0x01, 0x04, 0xff, 0xff, 0xff, 0x00,
+        0x2b, 0x05, 0xdc, 0x03, 0x4e, 0x41, 0x50, 0x0f, 0x15, 0x6e, 0x61, 0x74, 0x2e, 0x70, 0x68,
+        0x79, 0x73, 0x69, 0x63, 0x73, 0x2e, 0x6f, 0x78, 0x2e, 0x61, 0x63, 0x2e, 0x75, 0x6b, 0x00,
+        0x03, 0x04, 0x0a, 0xff, 0x06, 0xfe, 0x06, 0x10, 0xa3, 0x01, 0x4a, 0x06, 0xa3, 0x01, 0x4a,
+        0x07, 0xa3, 0x01, 0x4a, 0x03, 0xa3, 0x01, 0x4a, 0x04, 0x2c, 0x10, 0xa3, 0x01, 0x4a, 0x03,
+        0xa3, 0x01, 0x4a, 0x04, 0xa3, 0x01, 0x4a, 0x06, 0xa3, 0x01, 0x4a, 0x07, 0x2e, 0x01, 0x08,
+        0xff,
     ];
 
     static ACK_LEASE_TIME_BYTES: &[u8] = &[
-        0x02, 0x01, 0x06, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-        0x0a, 0x22, 0x10, 0x0b, 0x0a, 0x22, 0x10, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x04, 0x91, 0x62, 0xd2,
-        0xa8, 0x6f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x82, 0x53, 0x63,
-        0x35, 0x01, 0x05, 0x36, 0x04, 0x0a, 0x22, 0x10, 0x0a, 0x33, 0x04, 0x00, 0x00, 0x02, 0x56, 0x01,
-        0x04, 0xff, 0xff, 0xff, 0x00, 0x03, 0x04, 0x0a, 0x22, 0x10, 0x0a, 0xff, 0x00, 0x00, 0x00, 0x00,
-        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x02, 0x01, 0x06, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x0a, 0x22, 0x10, 0x0b, 0x0a, 0x22, 0x10, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x04, 0x91,
+        0x62, 0xd2, 0xa8, 0x6f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x82, 0x53, 0x63,
+        0x35, 0x01, 0x05, 0x36, 0x04, 0x0a, 0x22, 0x10, 0x0a, 0x33, 0x04, 0x00, 0x00, 0x02, 0x56,
+        0x01, 0x04, 0xff, 0xff, 0xff, 0x00, 0x03, 0x04, 0x0a, 0x22, 0x10, 0x0a, 0xff, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     ];
 
     const IP_NULL: Ipv4Address = Ipv4Address([0, 0, 0, 0]);
@@ -971,9 +1023,13 @@ mod test {
         assert_eq!(options.len(), 6 + 1 + 7);
 
         let (options, client_id) = DhcpOption::parse(options).unwrap();
-        assert_eq!(client_id, DhcpOption::Other {
-            kind: field::OPT_PARAMETER_REQUEST_LIST, data: &[1, 3, 6, 42]
-        });
+        assert_eq!(
+            client_id,
+            DhcpOption::Other {
+                kind: field::OPT_PARAMETER_REQUEST_LIST,
+                data: &[1, 3, 6, 42]
+            }
+        );
         assert_eq!(options.len(), 1 + 7);
 
         let (options, client_id) = DhcpOption::parse(options).unwrap();
@@ -1007,7 +1063,8 @@ mod test {
             options = DhcpOption::RequestedIp(IP_NULL).emit(options);
             options = DhcpOption::MaximumDhcpMessageSize(DHCP_SIZE).emit(options);
             let option = DhcpOption::Other {
-                kind: field::OPT_PARAMETER_REQUEST_LIST, data: &[1, 3, 6, 42],
+                kind: field::OPT_PARAMETER_REQUEST_LIST,
+                data: &[1, 3, 6, 42],
             };
             options = option.emit(options);
             DhcpOption::EndOfList.emit(options);
@@ -1106,7 +1163,10 @@ mod test {
             let rest = dhcp_option.emit(&mut bytes);
             assert_eq!(rest.len(), 0);
         }
-        assert_eq!(&bytes[0..2], &[field::OPT_PARAMETER_REQUEST_LIST, DATA.len() as u8]);
+        assert_eq!(
+            &bytes[0..2],
+            &[field::OPT_PARAMETER_REQUEST_LIST, DATA.len() as u8]
+        );
         assert_eq!(&bytes[2..], DATA);
     }
 
@@ -1118,10 +1178,14 @@ mod test {
         // The packet described by ACK_BYTES advertises 4 DNS servers
         // Here we ensure that we correctly parse the first 3 into our fixed
         // length-3 array (see issue #305)
-        assert_eq!(repr.dns_servers,  Some([
-            Some(Ipv4Address([163, 1, 74, 6])),
-            Some(Ipv4Address([163, 1, 74, 7])),
-            Some(Ipv4Address([163, 1, 74, 3]))]));
+        assert_eq!(
+            repr.dns_servers,
+            Some([
+                Some(Ipv4Address([163, 1, 74, 6])),
+                Some(Ipv4Address([163, 1, 74, 7])),
+                Some(Ipv4Address([163, 1, 74, 3]))
+            ])
+        );
     }
 
     #[test]

+ 75 - 63
src/wire/ethernet.rs

@@ -1,5 +1,5 @@
-use core::fmt;
 use byteorder::{ByteOrder, NetworkEndian};
+use core::fmt;
 
 use crate::{Error, Result};
 
@@ -17,8 +17,8 @@ impl fmt::Display for EtherType {
         match *self {
             EtherType::Ipv4 => write!(f, "IPv4"),
             EtherType::Ipv6 => write!(f, "IPv6"),
-            EtherType::Arp  => write!(f, "ARP"),
-            EtherType::Unknown(id) => write!(f, "0x{:04x}", id)
+            EtherType::Arp => write!(f, "ARP"),
+            EtherType::Unknown(id) => write!(f, "0x{:04x}", id),
         }
     }
 }
@@ -49,8 +49,7 @@ impl Address {
 
     /// Query whether the address is an unicast address.
     pub fn is_unicast(&self) -> bool {
-        !(self.is_broadcast() ||
-          self.is_multicast())
+        !(self.is_broadcast() || self.is_multicast())
     }
 
     /// Query whether this address is the broadcast address.
@@ -72,8 +71,11 @@ impl Address {
 impl fmt::Display for Address {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         let bytes = self.0;
-        write!(f, "{:02x}-{:02x}-{:02x}-{:02x}-{:02x}-{:02x}",
-               bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5])
+        write!(
+            f,
+            "{:02x}-{:02x}-{:02x}-{:02x}-{:02x}-{:02x}",
+            bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5]
+        )
     }
 }
 
@@ -81,16 +83,16 @@ impl fmt::Display for Address {
 #[derive(Debug, Clone)]
 #[cfg_attr(feature = "defmt", derive(defmt::Format))]
 pub struct Frame<T: AsRef<[u8]>> {
-    buffer: T
+    buffer: T,
 }
 
 mod field {
     use crate::wire::field::*;
 
-    pub const DESTINATION: Field =  0..6;
-    pub const SOURCE:      Field =  6..12;
-    pub const ETHERTYPE:   Field = 12..14;
-    pub const PAYLOAD:     Rest  = 14..;
+    pub const DESTINATION: Field = 0..6;
+    pub const SOURCE: Field = 6..12;
+    pub const ETHERTYPE: Field = 12..14;
+    pub const PAYLOAD: Rest = 14..;
 }
 
 /// The Ethernet header length
@@ -209,19 +211,27 @@ impl<T: AsRef<[u8]>> AsRef<[u8]> for Frame<T> {
 
 impl<T: AsRef<[u8]>> fmt::Display for Frame<T> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        write!(f, "EthernetII src={} dst={} type={}",
-               self.src_addr(), self.dst_addr(), self.ethertype())
+        write!(
+            f,
+            "EthernetII src={} dst={} type={}",
+            self.src_addr(),
+            self.dst_addr(),
+            self.ethertype()
+        )
     }
 }
 
-use crate::wire::pretty_print::{PrettyPrint, PrettyIndent};
+use crate::wire::pretty_print::{PrettyIndent, PrettyPrint};
 
 impl<T: AsRef<[u8]>> PrettyPrint for Frame<T> {
-    fn pretty_print(buffer: &dyn AsRef<[u8]>, f: &mut fmt::Formatter,
-                    indent: &mut PrettyIndent) -> fmt::Result {
+    fn pretty_print(
+        buffer: &dyn AsRef<[u8]>,
+        f: &mut fmt::Formatter,
+        indent: &mut PrettyIndent,
+    ) -> fmt::Result {
         let frame = match Frame::new_checked(buffer) {
-            Err(err)  => return write!(f, "{}({})", indent, err),
-            Ok(frame) => frame
+            Err(err) => return write!(f, "{}({})", indent, err),
+            Ok(frame) => frame,
         };
         write!(f, "{}{}", indent, frame)?;
 
@@ -241,7 +251,7 @@ impl<T: AsRef<[u8]>> PrettyPrint for Frame<T> {
                 indent.increase(f)?;
                 super::Ipv6Packet::<&[u8]>::pretty_print(&frame.payload(), f, indent)
             }
-            _ => Ok(())
+            _ => Ok(()),
         }
     }
 }
@@ -250,9 +260,9 @@ impl<T: AsRef<[u8]>> PrettyPrint for Frame<T> {
 #[derive(Debug, PartialEq, Eq, Clone, Copy)]
 #[cfg_attr(feature = "defmt", derive(defmt::Format))]
 pub struct Repr {
-    pub src_addr:    Address,
-    pub dst_addr:    Address,
-    pub ethertype:   EtherType,
+    pub src_addr: Address,
+    pub dst_addr: Address,
+    pub ethertype: EtherType,
 }
 
 impl Repr {
@@ -300,32 +310,32 @@ mod test_ipv4 {
     // Tests that are valid only with "proto-ipv4"
     use super::*;
 
-    static FRAME_BYTES: [u8; 64] =
-        [0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
-         0x11, 0x12, 0x13, 0x14, 0x15, 0x16,
-         0x08, 0x00,
-         0xaa, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-         0x00, 0xff];
-
-    static PAYLOAD_BYTES: [u8; 50] =
-        [0xaa, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-         0x00, 0xff];
+    static FRAME_BYTES: [u8; 64] = [
+        0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x08, 0x00, 0xaa,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0xff,
+    ];
+
+    static PAYLOAD_BYTES: [u8; 50] = [
+        0xaa, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0xff,
+    ];
 
     #[test]
     fn test_deconstruct() {
         let frame = Frame::new_unchecked(&FRAME_BYTES[..]);
-        assert_eq!(frame.dst_addr(), Address([0x01, 0x02, 0x03, 0x04, 0x05, 0x06]));
-        assert_eq!(frame.src_addr(), Address([0x11, 0x12, 0x13, 0x14, 0x15, 0x16]));
+        assert_eq!(
+            frame.dst_addr(),
+            Address([0x01, 0x02, 0x03, 0x04, 0x05, 0x06])
+        );
+        assert_eq!(
+            frame.src_addr(),
+            Address([0x11, 0x12, 0x13, 0x14, 0x15, 0x16])
+        );
         assert_eq!(frame.ethertype(), EtherType::Ipv4);
         assert_eq!(frame.payload(), &PAYLOAD_BYTES[..]);
     }
@@ -348,28 +358,30 @@ mod test_ipv6 {
     // Tests that are valid only with "proto-ipv6"
     use super::*;
 
-    static FRAME_BYTES: [u8; 54] =
-        [0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
-         0x11, 0x12, 0x13, 0x14, 0x15, 0x16,
-         0x86, 0xdd,
-         0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-         0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
-         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01];
-
-    static PAYLOAD_BYTES: [u8; 40] =
-        [0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-         0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
-         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01];
+    static FRAME_BYTES: [u8; 54] = [
+        0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x86, 0xdd, 0x60,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+    ];
+
+    static PAYLOAD_BYTES: [u8; 40] = [
+        0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+    ];
 
     #[test]
     fn test_deconstruct() {
         let frame = Frame::new_unchecked(&FRAME_BYTES[..]);
-        assert_eq!(frame.dst_addr(), Address([0x01, 0x02, 0x03, 0x04, 0x05, 0x06]));
-        assert_eq!(frame.src_addr(), Address([0x11, 0x12, 0x13, 0x14, 0x15, 0x16]));
+        assert_eq!(
+            frame.dst_addr(),
+            Address([0x01, 0x02, 0x03, 0x04, 0x05, 0x06])
+        );
+        assert_eq!(
+            frame.src_addr(),
+            Address([0x11, 0x12, 0x13, 0x14, 0x15, 0x16])
+        );
         assert_eq!(frame.ethertype(), EtherType::Ipv6);
         assert_eq!(frame.payload(), &PAYLOAD_BYTES[..]);
     }

+ 140 - 119
src/wire/icmpv4.rs

@@ -1,10 +1,10 @@
-use core::{cmp, fmt};
 use byteorder::{ByteOrder, NetworkEndian};
+use core::{cmp, fmt};
 
-use crate::{Error, Result};
 use crate::phy::ChecksumCapabilities;
 use crate::wire::ip::checksum;
 use crate::wire::{Ipv4Packet, Ipv4Repr};
+use crate::{Error, Result};
 
 enum_with_unknown! {
     /// Internet protocol control message type.
@@ -35,17 +35,17 @@ enum_with_unknown! {
 impl fmt::Display for Message {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match *self {
-            Message::EchoReply      => write!(f, "echo reply"),
+            Message::EchoReply => write!(f, "echo reply"),
             Message::DstUnreachable => write!(f, "destination unreachable"),
-            Message::Redirect       => write!(f, "message redirect"),
-            Message::EchoRequest    => write!(f, "echo request"),
-            Message::RouterAdvert   => write!(f, "router advertisement"),
-            Message::RouterSolicit  => write!(f, "router solicitation"),
-            Message::TimeExceeded   => write!(f, "time exceeded"),
-            Message::ParamProblem   => write!(f, "parameter problem"),
-            Message::Timestamp      => write!(f, "timestamp"),
+            Message::Redirect => write!(f, "message redirect"),
+            Message::EchoRequest => write!(f, "echo request"),
+            Message::RouterAdvert => write!(f, "router advertisement"),
+            Message::RouterSolicit => write!(f, "router solicitation"),
+            Message::TimeExceeded => write!(f, "time exceeded"),
+            Message::ParamProblem => write!(f, "parameter problem"),
+            Message::Timestamp => write!(f, "timestamp"),
             Message::TimestampReply => write!(f, "timestamp reply"),
-            Message::Unknown(id) => write!(f, "{}", id)
+            Message::Unknown(id) => write!(f, "{}", id),
         }
     }
 }
@@ -91,40 +91,25 @@ enum_with_unknown! {
 impl fmt::Display for DstUnreachable {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match *self {
-            DstUnreachable::NetUnreachable =>
-               write!(f, "destination network unreachable"),
-            DstUnreachable::HostUnreachable =>
-               write!(f, "destination host unreachable"),
-            DstUnreachable::ProtoUnreachable =>
-               write!(f, "destination protocol unreachable"),
-            DstUnreachable::PortUnreachable =>
-               write!(f, "destination port unreachable"),
-            DstUnreachable::FragRequired =>
-               write!(f, "fragmentation required, and DF flag set"),
-            DstUnreachable::SrcRouteFailed =>
-               write!(f, "source route failed"),
-            DstUnreachable::DstNetUnknown =>
-               write!(f, "destination network unknown"),
-            DstUnreachable::DstHostUnknown =>
-               write!(f, "destination host unknown"),
-            DstUnreachable::SrcHostIsolated =>
-               write!(f, "source host isolated"),
-            DstUnreachable::NetProhibited =>
-               write!(f, "network administratively prohibited"),
-            DstUnreachable::HostProhibited =>
-               write!(f, "host administratively prohibited"),
-            DstUnreachable::NetUnreachToS =>
-               write!(f, "network unreachable for ToS"),
-            DstUnreachable::HostUnreachToS =>
-               write!(f, "host unreachable for ToS"),
-            DstUnreachable::CommProhibited =>
-               write!(f, "communication administratively prohibited"),
-            DstUnreachable::HostPrecedViol =>
-               write!(f, "host precedence violation"),
-            DstUnreachable::PrecedCutoff =>
-               write!(f, "precedence cutoff in effect"),
-            DstUnreachable::Unknown(id) =>
-                write!(f, "{}", id)
+            DstUnreachable::NetUnreachable => write!(f, "destination network unreachable"),
+            DstUnreachable::HostUnreachable => write!(f, "destination host unreachable"),
+            DstUnreachable::ProtoUnreachable => write!(f, "destination protocol unreachable"),
+            DstUnreachable::PortUnreachable => write!(f, "destination port unreachable"),
+            DstUnreachable::FragRequired => write!(f, "fragmentation required, and DF flag set"),
+            DstUnreachable::SrcRouteFailed => write!(f, "source route failed"),
+            DstUnreachable::DstNetUnknown => write!(f, "destination network unknown"),
+            DstUnreachable::DstHostUnknown => write!(f, "destination host unknown"),
+            DstUnreachable::SrcHostIsolated => write!(f, "source host isolated"),
+            DstUnreachable::NetProhibited => write!(f, "network administratively prohibited"),
+            DstUnreachable::HostProhibited => write!(f, "host administratively prohibited"),
+            DstUnreachable::NetUnreachToS => write!(f, "network unreachable for ToS"),
+            DstUnreachable::HostUnreachToS => write!(f, "host unreachable for ToS"),
+            DstUnreachable::CommProhibited => {
+                write!(f, "communication administratively prohibited")
+            }
+            DstUnreachable::HostPrecedViol => write!(f, "host precedence violation"),
+            DstUnreachable::PrecedCutoff => write!(f, "precedence cutoff in effect"),
+            DstUnreachable::Unknown(id) => write!(f, "{}", id),
         }
     }
 }
@@ -169,17 +154,17 @@ enum_with_unknown! {
 #[derive(Debug, PartialEq, Clone)]
 #[cfg_attr(feature = "defmt", derive(defmt::Format))]
 pub struct Packet<T: AsRef<[u8]>> {
-    buffer: T
+    buffer: T,
 }
 
 mod field {
     use crate::wire::field::*;
 
-    pub const TYPE:       usize = 0;
-    pub const CODE:       usize = 1;
-    pub const CHECKSUM:   Field = 2..4;
+    pub const TYPE: usize = 0;
+    pub const CODE: usize = 1;
+    pub const CHECKSUM: Field = 2..4;
 
-    pub const UNUSED:     Field = 4..8;
+    pub const UNUSED: Field = 4..8;
 
     pub const ECHO_IDENT: Field = 4..6;
     pub const ECHO_SEQNO: Field = 6..8;
@@ -268,10 +253,10 @@ impl<T: AsRef<[u8]>> Packet<T> {
     /// The result depends on the value of the message type field.
     pub fn header_len(&self) -> usize {
         match self.msg_type() {
-            Message::EchoRequest    => field::ECHO_SEQNO.end,
-            Message::EchoReply      => field::ECHO_SEQNO.end,
+            Message::EchoRequest => field::ECHO_SEQNO.end,
+            Message::EchoReply => field::ECHO_SEQNO.end,
             Message::DstUnreachable => field::UNUSED.end,
-            _ => field::UNUSED.end // make a conservative assumption
+            _ => field::UNUSED.end, // make a conservative assumption
         }
     }
 
@@ -280,7 +265,9 @@ impl<T: AsRef<[u8]>> Packet<T> {
     /// # Fuzzing
     /// This function always returns `true` when fuzzing.
     pub fn verify_checksum(&self) -> bool {
-        if cfg!(fuzzing) { return true }
+        if cfg!(fuzzing) {
+            return true;
+        }
 
         let data = self.buffer.as_ref();
         checksum::data(data) == !0
@@ -371,47 +358,49 @@ impl<T: AsRef<[u8]>> AsRef<[u8]> for Packet<T> {
 #[non_exhaustive]
 pub enum Repr<'a> {
     EchoRequest {
-        ident:  u16,
+        ident: u16,
         seq_no: u16,
-        data:   &'a [u8]
+        data: &'a [u8],
     },
     EchoReply {
-        ident:  u16,
+        ident: u16,
         seq_no: u16,
-        data:   &'a [u8]
+        data: &'a [u8],
     },
     DstUnreachable {
         reason: DstUnreachable,
         header: Ipv4Repr,
-        data:   &'a [u8]
+        data: &'a [u8],
     },
 }
 
 impl<'a> Repr<'a> {
     /// Parse an Internet Control Message Protocol version 4 packet and return
     /// a high-level representation.
-    pub fn parse<T>(packet: &Packet<&'a T>, checksum_caps: &ChecksumCapabilities)
-                   -> Result<Repr<'a>>
-                where T: AsRef<[u8]> + ?Sized {
+    pub fn parse<T>(
+        packet: &Packet<&'a T>,
+        checksum_caps: &ChecksumCapabilities,
+    ) -> Result<Repr<'a>>
+    where
+        T: AsRef<[u8]> + ?Sized,
+    {
         // Valid checksum is expected.
-        if checksum_caps.icmpv4.rx() && !packet.verify_checksum() { return Err(Error::Checksum) }
+        if checksum_caps.icmpv4.rx() && !packet.verify_checksum() {
+            return Err(Error::Checksum);
+        }
 
         match (packet.msg_type(), packet.msg_code()) {
-            (Message::EchoRequest, 0) => {
-                Ok(Repr::EchoRequest {
-                    ident:  packet.echo_ident(),
-                    seq_no: packet.echo_seq_no(),
-                    data:   packet.data()
-                })
-            },
-
-            (Message::EchoReply, 0) => {
-                Ok(Repr::EchoReply {
-                    ident:  packet.echo_ident(),
-                    seq_no: packet.echo_seq_no(),
-                    data:   packet.data()
-                })
-            },
+            (Message::EchoRequest, 0) => Ok(Repr::EchoRequest {
+                ident: packet.echo_ident(),
+                seq_no: packet.echo_seq_no(),
+                data: packet.data(),
+            }),
+
+            (Message::EchoReply, 0) => Ok(Repr::EchoReply {
+                ident: packet.echo_ident(),
+                seq_no: packet.echo_seq_no(),
+                data: packet.data(),
+            }),
 
             (Message::DstUnreachable, code) => {
                 let ip_packet = Ipv4Packet::new_checked(packet.data())?;
@@ -419,7 +408,9 @@ impl<'a> Repr<'a> {
                 let payload = &packet.data()[ip_packet.header_len() as usize..];
                 // RFC 792 requires exactly eight bytes to be returned.
                 // We allow more, since there isn't a reason not to, but require at least eight.
-                if payload.len() < 8 { return Err(Error::Truncated) }
+                if payload.len() < 8 {
+                    return Err(Error::Truncated);
+                }
 
                 Ok(Repr::DstUnreachable {
                     reason: DstUnreachable::from(code),
@@ -428,22 +419,21 @@ impl<'a> Repr<'a> {
                         dst_addr: ip_packet.dst_addr(),
                         protocol: ip_packet.protocol(),
                         payload_len: payload.len(),
-                        hop_limit: ip_packet.hop_limit()
+                        hop_limit: ip_packet.hop_limit(),
                     },
-                    data: payload
+                    data: payload,
                 })
             }
-            _ => Err(Error::Unrecognized)
+            _ => Err(Error::Unrecognized),
         }
     }
 
     /// Return the length of a packet that will be emitted from this high-level representation.
     pub fn buffer_len(&self) -> usize {
         match self {
-            &Repr::EchoRequest { data, .. } |
-            &Repr::EchoReply { data, .. } => {
+            &Repr::EchoRequest { data, .. } | &Repr::EchoReply { data, .. } => {
                 field::ECHO_SEQNO.end + data.len()
-            },
+            }
             &Repr::DstUnreachable { header, data, .. } => {
                 field::UNUSED.end + header.buffer_len() + data.len()
             }
@@ -453,35 +443,49 @@ impl<'a> Repr<'a> {
     /// Emit a high-level representation into an Internet Control Message Protocol version 4
     /// packet.
     pub fn emit<T>(&self, packet: &mut Packet<&mut T>, checksum_caps: &ChecksumCapabilities)
-            where T: AsRef<[u8]> + AsMut<[u8]> + ?Sized {
+    where
+        T: AsRef<[u8]> + AsMut<[u8]> + ?Sized,
+    {
         packet.set_msg_code(0);
         match *self {
-            Repr::EchoRequest { ident, seq_no, data } => {
+            Repr::EchoRequest {
+                ident,
+                seq_no,
+                data,
+            } => {
                 packet.set_msg_type(Message::EchoRequest);
                 packet.set_msg_code(0);
                 packet.set_echo_ident(ident);
                 packet.set_echo_seq_no(seq_no);
                 let data_len = cmp::min(packet.data_mut().len(), data.len());
                 packet.data_mut()[..data_len].copy_from_slice(&data[..data_len])
-            },
+            }
 
-            Repr::EchoReply { ident, seq_no, data } => {
+            Repr::EchoReply {
+                ident,
+                seq_no,
+                data,
+            } => {
                 packet.set_msg_type(Message::EchoReply);
                 packet.set_msg_code(0);
                 packet.set_echo_ident(ident);
                 packet.set_echo_seq_no(seq_no);
                 let data_len = cmp::min(packet.data_mut().len(), data.len());
                 packet.data_mut()[..data_len].copy_from_slice(&data[..data_len])
-            },
+            }
 
-            Repr::DstUnreachable { reason, header, data } => {
+            Repr::DstUnreachable {
+                reason,
+                header,
+                data,
+            } => {
                 packet.set_msg_type(Message::DstUnreachable);
                 packet.set_msg_code(reason.into());
 
                 let mut ip_packet = Ipv4Packet::new_unchecked(packet.data_mut());
                 header.emit(&mut ip_packet, checksum_caps);
                 let payload = &mut ip_packet.into_inner()[header.buffer_len()..];
-                payload.copy_from_slice(&data[..])
+                payload.copy_from_slice(data)
             }
         }
 
@@ -503,9 +507,10 @@ impl<'a, T: AsRef<[u8]> + ?Sized> fmt::Display for Packet<&'a T> {
                 write!(f, "ICMPv4 ({})", err)?;
                 write!(f, " type={:?}", self.msg_type())?;
                 match self.msg_type() {
-                    Message::DstUnreachable =>
-                        write!(f, " code={:?}", DstUnreachable::from(self.msg_code())),
-                    _ => write!(f, " code={}", self.msg_code())
+                    Message::DstUnreachable => {
+                        write!(f, " code={:?}", DstUnreachable::from(self.msg_code()))
+                    }
+                    _ => write!(f, " code={}", self.msg_code()),
                 }
             }
         }
@@ -515,27 +520,46 @@ impl<'a, T: AsRef<[u8]> + ?Sized> fmt::Display for Packet<&'a T> {
 impl<'a> fmt::Display for Repr<'a> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match *self {
-            Repr::EchoRequest { ident, seq_no, data } =>
-               write!(f, "ICMPv4 echo request id={} seq={} len={}",
-                      ident, seq_no, data.len()),
-            Repr::EchoReply { ident, seq_no, data } =>
-               write!(f, "ICMPv4 echo reply id={} seq={} len={}",
-                      ident, seq_no, data.len()),
-            Repr::DstUnreachable { reason, .. } =>
-               write!(f, "ICMPv4 destination unreachable ({})",
-                      reason),
+            Repr::EchoRequest {
+                ident,
+                seq_no,
+                data,
+            } => write!(
+                f,
+                "ICMPv4 echo request id={} seq={} len={}",
+                ident,
+                seq_no,
+                data.len()
+            ),
+            Repr::EchoReply {
+                ident,
+                seq_no,
+                data,
+            } => write!(
+                f,
+                "ICMPv4 echo reply id={} seq={} len={}",
+                ident,
+                seq_no,
+                data.len()
+            ),
+            Repr::DstUnreachable { reason, .. } => {
+                write!(f, "ICMPv4 destination unreachable ({})", reason)
+            }
         }
     }
 }
 
-use crate::wire::pretty_print::{PrettyPrint, PrettyIndent};
+use crate::wire::pretty_print::{PrettyIndent, PrettyPrint};
 
 impl<T: AsRef<[u8]>> PrettyPrint for Packet<T> {
-    fn pretty_print(buffer: &dyn AsRef<[u8]>, f: &mut fmt::Formatter,
-                    indent: &mut PrettyIndent) -> fmt::Result {
+    fn pretty_print(
+        buffer: &dyn AsRef<[u8]>,
+        f: &mut fmt::Formatter,
+        indent: &mut PrettyIndent,
+    ) -> fmt::Result {
         let packet = match Packet::new_checked(buffer) {
-            Err(err)   => return write!(f, "{}({})", indent, err),
-            Ok(packet) => packet
+            Err(err) => return write!(f, "{}({})", indent, err),
+            Ok(packet) => packet,
         };
         write!(f, "{}{}", indent, packet)?;
 
@@ -544,7 +568,7 @@ impl<T: AsRef<[u8]>> PrettyPrint for Packet<T> {
                 indent.increase(f)?;
                 super::Ipv4Packet::<&[u8]>::pretty_print(&packet.data(), f, indent)
             }
-            _ => Ok(())
+            _ => Ok(()),
         }
     }
 }
@@ -553,13 +577,11 @@ impl<T: AsRef<[u8]>> PrettyPrint for Packet<T> {
 mod test {
     use super::*;
 
-    static ECHO_PACKET_BYTES: [u8; 12] =
-        [0x08, 0x00, 0x8e, 0xfe,
-         0x12, 0x34, 0xab, 0xcd,
-         0xaa, 0x00, 0x00, 0xff];
+    static ECHO_PACKET_BYTES: [u8; 12] = [
+        0x08, 0x00, 0x8e, 0xfe, 0x12, 0x34, 0xab, 0xcd, 0xaa, 0x00, 0x00, 0xff,
+    ];
 
-    static ECHO_DATA_BYTES: [u8; 4] =
-        [0xaa, 0x00, 0x00, 0xff];
+    static ECHO_DATA_BYTES: [u8; 4] = [0xaa, 0x00, 0x00, 0xff];
 
     #[test]
     fn test_echo_deconstruct() {
@@ -590,7 +612,7 @@ mod test {
         Repr::EchoRequest {
             ident: 0x1234,
             seq_no: 0xabcd,
-            data: &ECHO_DATA_BYTES
+            data: &ECHO_DATA_BYTES,
         }
     }
 
@@ -612,8 +634,7 @@ mod test {
 
     #[test]
     fn test_check_len() {
-        let bytes = [0x0b, 0x00, 0x00, 0x00,
-                     0x00, 0x00, 0x00, 0x00];
+        let bytes = [0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00];
         assert_eq!(Packet::new_checked(&[]), Err(Error::Truncated));
         assert_eq!(Packet::new_checked(&bytes[..4]), Err(Error::Truncated));
         assert!(Packet::new_checked(&bytes[..]).is_ok());

+ 276 - 255
src/wire/icmpv6.rs

@@ -1,13 +1,13 @@
-use core::{cmp, fmt};
 use byteorder::{ByteOrder, NetworkEndian};
+use core::{cmp, fmt};
 
-use crate::{Error, Result};
 use crate::phy::ChecksumCapabilities;
 use crate::wire::ip::checksum;
-use crate::wire::{IpAddress, IpProtocol, Ipv6Packet, Ipv6Repr};
 use crate::wire::MldRepr;
 #[cfg(feature = "medium-ethernet")]
 use crate::wire::NdiscRepr;
+use crate::wire::{IpAddress, IpProtocol, Ipv6Packet, Ipv6Repr};
+use crate::{Error, Result};
 
 enum_with_unknown! {
     /// Internet protocol control message type.
@@ -57,8 +57,11 @@ impl Message {
     /// [NDISC]: https://tools.ietf.org/html/rfc4861
     pub fn is_ndisc(&self) -> bool {
         match *self {
-            Message::RouterSolicit | Message::RouterAdvert | Message::NeighborSolicit |
-            Message::NeighborAdvert | Message::Redirect => true,
+            Message::RouterSolicit
+            | Message::RouterAdvert
+            | Message::NeighborSolicit
+            | Message::NeighborAdvert
+            | Message::Redirect => true,
             _ => false,
         }
     }
@@ -78,20 +81,20 @@ impl Message {
 impl fmt::Display for Message {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match *self {
-            Message::DstUnreachable  => write!(f, "destination unreachable"),
-            Message::PktTooBig       => write!(f, "packet too big"),
-            Message::TimeExceeded    => write!(f, "time exceeded"),
-            Message::ParamProblem    => write!(f, "parameter problem"),
-            Message::EchoReply       => write!(f, "echo reply"),
-            Message::EchoRequest     => write!(f, "echo request"),
-            Message::RouterSolicit   => write!(f, "router solicitation"),
-            Message::RouterAdvert    => write!(f, "router advertisement"),
+            Message::DstUnreachable => write!(f, "destination unreachable"),
+            Message::PktTooBig => write!(f, "packet too big"),
+            Message::TimeExceeded => write!(f, "time exceeded"),
+            Message::ParamProblem => write!(f, "parameter problem"),
+            Message::EchoReply => write!(f, "echo reply"),
+            Message::EchoRequest => write!(f, "echo request"),
+            Message::RouterSolicit => write!(f, "router solicitation"),
+            Message::RouterAdvert => write!(f, "router advertisement"),
             Message::NeighborSolicit => write!(f, "neighbor solicitation"),
-            Message::NeighborAdvert  => write!(f, "neighbor advert"),
-            Message::Redirect        => write!(f, "redirect"),
-            Message::MldQuery        => write!(f, "multicast listener query"),
-            Message::MldReport       => write!(f, "multicast listener report"),
-            Message::Unknown(id)     => write!(f, "{}", id)
+            Message::NeighborAdvert => write!(f, "neighbor advert"),
+            Message::Redirect => write!(f, "redirect"),
+            Message::MldQuery => write!(f, "multicast listener query"),
+            Message::MldReport => write!(f, "multicast listener report"),
+            Message::Unknown(id) => write!(f, "{}", id),
         }
     }
 }
@@ -119,22 +122,19 @@ enum_with_unknown! {
 impl fmt::Display for DstUnreachable {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match *self {
-            DstUnreachable::NoRoute =>
-               write!(f, "no route to destination"),
-            DstUnreachable::AdminProhibit =>
-               write!(f, "communication with destination administratively prohibited"),
-            DstUnreachable::BeyondScope =>
-               write!(f, "beyond scope of source address"),
-            DstUnreachable::AddrUnreachable =>
-               write!(f, "address unreachable"),
-            DstUnreachable::PortUnreachable =>
-               write!(f, "port unreachable"),
-            DstUnreachable::FailedPolicy =>
-               write!(f, "source address failed ingress/egress policy"),
-            DstUnreachable::RejectRoute =>
-               write!(f, "reject route to destination"),
-            DstUnreachable::Unknown(id) =>
-                write!(f, "{}", id)
+            DstUnreachable::NoRoute => write!(f, "no route to destination"),
+            DstUnreachable::AdminProhibit => write!(
+                f,
+                "communication with destination administratively prohibited"
+            ),
+            DstUnreachable::BeyondScope => write!(f, "beyond scope of source address"),
+            DstUnreachable::AddrUnreachable => write!(f, "address unreachable"),
+            DstUnreachable::PortUnreachable => write!(f, "port unreachable"),
+            DstUnreachable::FailedPolicy => {
+                write!(f, "source address failed ingress/egress policy")
+            }
+            DstUnreachable::RejectRoute => write!(f, "reject route to destination"),
+            DstUnreachable::Unknown(id) => write!(f, "{}", id),
         }
     }
 }
@@ -154,14 +154,10 @@ enum_with_unknown! {
 impl fmt::Display for ParamProblem {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match *self {
-            ParamProblem::ErroneousHdrField  =>
-               write!(f, "erroneous header field."),
-            ParamProblem::UnrecognizedNxtHdr =>
-               write!(f, "unrecognized next header type."),
-            ParamProblem::UnrecognizedOption =>
-               write!(f, "unrecognized IPv6 option."),
-            ParamProblem::Unknown(id) =>
-                write!(f, "{}", id)
+            ParamProblem::ErroneousHdrField => write!(f, "erroneous header field."),
+            ParamProblem::UnrecognizedNxtHdr => write!(f, "unrecognized next header type."),
+            ParamProblem::UnrecognizedOption => write!(f, "unrecognized IPv6 option."),
+            ParamProblem::Unknown(id) => write!(f, "{}", id),
         }
     }
 }
@@ -179,12 +175,9 @@ enum_with_unknown! {
 impl fmt::Display for TimeExceeded {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match *self {
-            TimeExceeded::HopLimitExceeded =>
-               write!(f, "hop limit exceeded in transit"),
-            TimeExceeded::FragReassemExceeded =>
-               write!(f, "fragment reassembly time exceeded"),
-            TimeExceeded::Unknown(id) =>
-                write!(f, "{}", id)
+            TimeExceeded::HopLimitExceeded => write!(f, "hop limit exceeded in transit"),
+            TimeExceeded::FragReassemExceeded => write!(f, "fragment reassembly time exceeded"),
+            TimeExceeded::Unknown(id) => write!(f, "{}", id),
         }
     }
 }
@@ -193,7 +186,7 @@ impl fmt::Display for TimeExceeded {
 #[derive(Debug, PartialEq, Clone)]
 #[cfg_attr(feature = "defmt", derive(defmt::Format))]
 pub struct Packet<T: AsRef<[u8]>> {
-    pub(super) buffer: T
+    pub(super) buffer: T,
 }
 
 // Ranges and constants describing key boundaries in the ICMPv6 header.
@@ -201,54 +194,54 @@ pub(super) mod field {
     use crate::wire::field::*;
 
     // ICMPv6: See https://tools.ietf.org/html/rfc4443
-    pub const TYPE:              usize = 0;
-    pub const CODE:              usize = 1;
-    pub const CHECKSUM:          Field = 2..4;
+    pub const TYPE: usize = 0;
+    pub const CODE: usize = 1;
+    pub const CHECKSUM: Field = 2..4;
 
-    pub const UNUSED:            Field = 4..8;
-    pub const MTU:               Field = 4..8;
-    pub const POINTER:           Field = 4..8;
-    pub const ECHO_IDENT:        Field = 4..6;
-    pub const ECHO_SEQNO:        Field = 6..8;
+    pub const UNUSED: Field = 4..8;
+    pub const MTU: Field = 4..8;
+    pub const POINTER: Field = 4..8;
+    pub const ECHO_IDENT: Field = 4..6;
+    pub const ECHO_SEQNO: Field = 6..8;
 
-    pub const HEADER_END:        usize = 8;
+    pub const HEADER_END: usize = 8;
 
     // NDISC: See https://tools.ietf.org/html/rfc4861
     // Router Advertisement message offsets
-    pub const CUR_HOP_LIMIT:     usize = 4;
-    pub const ROUTER_FLAGS:      usize = 5;
-    pub const ROUTER_LT:         Field = 6..8;
-    pub const REACHABLE_TM:      Field = 8..12;
-    pub const RETRANS_TM:        Field = 12..16;
+    pub const CUR_HOP_LIMIT: usize = 4;
+    pub const ROUTER_FLAGS: usize = 5;
+    pub const ROUTER_LT: Field = 6..8;
+    pub const REACHABLE_TM: Field = 8..12;
+    pub const RETRANS_TM: Field = 12..16;
 
     // Neighbor Solicitation message offsets
-    pub const TARGET_ADDR:       Field = 8..24;
+    pub const TARGET_ADDR: Field = 8..24;
 
     // Neighbor Advertisement message offsets
-    pub const NEIGH_FLAGS:       usize = 4;
+    pub const NEIGH_FLAGS: usize = 4;
 
     // Redirected Header message offsets
-    pub const DEST_ADDR:         Field = 24..40;
+    pub const DEST_ADDR: Field = 24..40;
 
     // MLD:
     //   - https://tools.ietf.org/html/rfc3810
     //   - https://tools.ietf.org/html/rfc3810
     // Multicast Listener Query message
-    pub const MAX_RESP_CODE:     Field = 4..6;
-    pub const QUERY_RESV:        Field = 6..8;
-    pub const QUERY_MCAST_ADDR:  Field = 8..24;
-    pub const SQRV:              usize = 24;
-    pub const QQIC:              usize = 25;
-    pub const QUERY_NUM_SRCS:    Field = 26..28;
+    pub const MAX_RESP_CODE: Field = 4..6;
+    pub const QUERY_RESV: Field = 6..8;
+    pub const QUERY_MCAST_ADDR: Field = 8..24;
+    pub const SQRV: usize = 24;
+    pub const QQIC: usize = 25;
+    pub const QUERY_NUM_SRCS: Field = 26..28;
 
     // Multicast Listener Report Message
-    pub const RECORD_RESV:       Field = 4..6;
-    pub const NR_MCAST_RCRDS:    Field = 6..8;
+    pub const RECORD_RESV: Field = 4..6;
+    pub const NR_MCAST_RCRDS: Field = 6..8;
 
     // Multicast Address Record Offsets
-    pub const RECORD_TYPE:       usize = 0;
-    pub const AUX_DATA_LEN:      usize = 1;
-    pub const RECORD_NUM_SRCS:   Field = 2..4;
+    pub const RECORD_TYPE: usize = 0;
+    pub const AUX_DATA_LEN: usize = 1;
+    pub const RECORD_NUM_SRCS: Field = 2..4;
     pub const RECORD_MCAST_ADDR: Field = 4..20;
 }
 
@@ -333,29 +326,28 @@ impl<T: AsRef<[u8]>> Packet<T> {
         NetworkEndian::read_u32(&data[field::POINTER])
     }
 
-
     /// Return the header length. The result depends on the value of
     /// the message type field.
     pub fn header_len(&self) -> usize {
         match self.msg_type() {
-            Message::DstUnreachable  => field::UNUSED.end,
-            Message::PktTooBig       => field::MTU.end,
-            Message::TimeExceeded    => field::UNUSED.end,
-            Message::ParamProblem    => field::POINTER.end,
-            Message::EchoRequest     => field::ECHO_SEQNO.end,
-            Message::EchoReply       => field::ECHO_SEQNO.end,
-            Message::RouterSolicit   => field::UNUSED.end,
-            Message::RouterAdvert    => field::RETRANS_TM.end,
+            Message::DstUnreachable => field::UNUSED.end,
+            Message::PktTooBig => field::MTU.end,
+            Message::TimeExceeded => field::UNUSED.end,
+            Message::ParamProblem => field::POINTER.end,
+            Message::EchoRequest => field::ECHO_SEQNO.end,
+            Message::EchoReply => field::ECHO_SEQNO.end,
+            Message::RouterSolicit => field::UNUSED.end,
+            Message::RouterAdvert => field::RETRANS_TM.end,
             Message::NeighborSolicit => field::TARGET_ADDR.end,
-            Message::NeighborAdvert  => field::TARGET_ADDR.end,
-            Message::Redirect        => field::DEST_ADDR.end,
-            Message::MldQuery        => field::QUERY_NUM_SRCS.end,
-            Message::MldReport       => field::NR_MCAST_RCRDS.end,
+            Message::NeighborAdvert => field::TARGET_ADDR.end,
+            Message::Redirect => field::DEST_ADDR.end,
+            Message::MldQuery => field::QUERY_NUM_SRCS.end,
+            Message::MldReport => field::NR_MCAST_RCRDS.end,
             // For packets that are not included in RFC 4443, do not
             // include the last 32 bits of the ICMPv6 header in
             // `header_bytes`. This must be done so that these bytes
             // can be accessed in the `payload`.
-            _ => field::CHECKSUM.end
+            _ => field::CHECKSUM.end,
         }
     }
 
@@ -364,13 +356,14 @@ impl<T: AsRef<[u8]>> Packet<T> {
     /// # Fuzzing
     /// This function always returns `true` when fuzzing.
     pub fn verify_checksum(&self, src_addr: &IpAddress, dst_addr: &IpAddress) -> bool {
-        if cfg!(fuzzing) { return true }
+        if cfg!(fuzzing) {
+            return true;
+        }
 
         let data = self.buffer.as_ref();
         checksum::combine(&[
-            checksum::pseudo_header(src_addr, dst_addr, IpProtocol::Icmpv6,
-                                    data.len() as u32),
-            checksum::data(data)
+            checksum::pseudo_header(src_addr, dst_addr, IpProtocol::Icmpv6, data.len() as u32),
+            checksum::data(data),
         ]) == !0
     }
 }
@@ -409,16 +402,18 @@ impl<T: AsRef<[u8]> + AsMut<[u8]>> Packet<T> {
     #[inline]
     pub fn clear_reserved(&mut self) {
         match self.msg_type() {
-            Message::RouterSolicit | Message::NeighborSolicit |
-            Message::NeighborAdvert | Message::Redirect => {
+            Message::RouterSolicit
+            | Message::NeighborSolicit
+            | Message::NeighborAdvert
+            | Message::Redirect => {
                 let data = self.buffer.as_mut();
                 NetworkEndian::write_u32(&mut data[field::UNUSED], 0);
-            },
+            }
             Message::MldQuery => {
                 let data = self.buffer.as_mut();
                 NetworkEndian::write_u16(&mut data[field::QUERY_RESV], 0);
                 data[field::SQRV] &= 0xf;
-            },
+            }
             Message::MldReport => {
                 let data = self.buffer.as_mut();
                 NetworkEndian::write_u16(&mut data[field::RECORD_RESV], 0);
@@ -479,9 +474,8 @@ impl<T: AsRef<[u8]> + AsMut<[u8]>> Packet<T> {
         let checksum = {
             let data = self.buffer.as_ref();
             !checksum::combine(&[
-                checksum::pseudo_header(src_addr, dst_addr, IpProtocol::Icmpv6,
-                                        data.len() as u32),
-                checksum::data(data)
+                checksum::pseudo_header(src_addr, dst_addr, IpProtocol::Icmpv6, data.len() as u32),
+                checksum::data(data),
             ])
         };
         self.set_checksum(checksum)
@@ -510,33 +504,33 @@ pub enum Repr<'a> {
     DstUnreachable {
         reason: DstUnreachable,
         header: Ipv6Repr,
-        data:   &'a [u8]
+        data: &'a [u8],
     },
     PktTooBig {
         mtu: u32,
         header: Ipv6Repr,
-        data:   &'a [u8]
+        data: &'a [u8],
     },
     TimeExceeded {
         reason: TimeExceeded,
         header: Ipv6Repr,
-        data:   &'a [u8]
+        data: &'a [u8],
     },
     ParamProblem {
-        reason:  ParamProblem,
+        reason: ParamProblem,
         pointer: u32,
-        header:  Ipv6Repr,
-        data:    &'a [u8]
+        header: Ipv6Repr,
+        data: &'a [u8],
     },
     EchoRequest {
-        ident:  u16,
+        ident: u16,
         seq_no: u16,
-        data:   &'a [u8]
+        data: &'a [u8],
     },
     EchoReply {
-        ident:  u16,
+        ident: u16,
         seq_no: u16,
-        data:   &'a [u8]
+        data: &'a [u8],
     },
     #[cfg(feature = "medium-ethernet")]
     Ndisc(NdiscRepr<'a>),
@@ -546,29 +540,37 @@ pub enum Repr<'a> {
 impl<'a> Repr<'a> {
     /// Parse an Internet Control Message Protocol version 6 packet and return
     /// a high-level representation.
-    pub fn parse<T>(src_addr: &IpAddress, dst_addr: &IpAddress,
-                    packet: &Packet<&'a T>, checksum_caps: &ChecksumCapabilities)
-                   -> Result<Repr<'a>>
-                where T: AsRef<[u8]> + ?Sized {
-        fn create_packet_from_payload<'a, T>(packet: &Packet<&'a T>)
-                                            -> Result<(&'a [u8], Ipv6Repr)>
-                where T: AsRef<[u8]> + ?Sized {
+    pub fn parse<T>(
+        src_addr: &IpAddress,
+        dst_addr: &IpAddress,
+        packet: &Packet<&'a T>,
+        checksum_caps: &ChecksumCapabilities,
+    ) -> Result<Repr<'a>>
+    where
+        T: AsRef<[u8]> + ?Sized,
+    {
+        fn create_packet_from_payload<'a, T>(packet: &Packet<&'a T>) -> Result<(&'a [u8], Ipv6Repr)>
+        where
+            T: AsRef<[u8]> + ?Sized,
+        {
             let ip_packet = Ipv6Packet::new_checked(packet.payload())?;
 
             let payload = &packet.payload()[ip_packet.header_len() as usize..];
-            if payload.len() < 8 { return Err(Error::Truncated) }
+            if payload.len() < 8 {
+                return Err(Error::Truncated);
+            }
             let repr = Ipv6Repr {
                 src_addr: ip_packet.src_addr(),
                 dst_addr: ip_packet.dst_addr(),
                 next_header: ip_packet.next_header(),
                 payload_len: payload.len(),
-                hop_limit: ip_packet.hop_limit()
+                hop_limit: ip_packet.hop_limit(),
             };
             Ok((payload, repr))
         }
         // Valid checksum is expected.
         if checksum_caps.icmpv6.rx() && !packet.verify_checksum(src_addr, dst_addr) {
-            return Err(Error::Checksum)
+            return Err(Error::Checksum);
         }
 
         match (packet.msg_type(), packet.msg_code()) {
@@ -577,149 +579,161 @@ impl<'a> Repr<'a> {
                 Ok(Repr::DstUnreachable {
                     reason: DstUnreachable::from(code),
                     header: repr,
-                    data: payload
+                    data: payload,
                 })
-            },
+            }
             (Message::PktTooBig, 0) => {
                 let (payload, repr) = create_packet_from_payload(packet)?;
                 Ok(Repr::PktTooBig {
                     mtu: packet.pkt_too_big_mtu(),
                     header: repr,
-                    data: payload
+                    data: payload,
                 })
-            },
+            }
             (Message::TimeExceeded, code) => {
                 let (payload, repr) = create_packet_from_payload(packet)?;
                 Ok(Repr::TimeExceeded {
                     reason: TimeExceeded::from(code),
                     header: repr,
-                    data: payload
+                    data: payload,
                 })
-            },
+            }
             (Message::ParamProblem, code) => {
                 let (payload, repr) = create_packet_from_payload(packet)?;
                 Ok(Repr::ParamProblem {
                     reason: ParamProblem::from(code),
                     pointer: packet.param_problem_ptr(),
                     header: repr,
-                    data: payload
+                    data: payload,
                 })
-            },
-            (Message::EchoRequest, 0) => {
-                Ok(Repr::EchoRequest {
-                    ident:  packet.echo_ident(),
-                    seq_no: packet.echo_seq_no(),
-                    data:   packet.payload()
-                })
-            },
-            (Message::EchoReply, 0) => {
-                Ok(Repr::EchoReply {
-                    ident:  packet.echo_ident(),
-                    seq_no: packet.echo_seq_no(),
-                    data:   packet.payload()
-                })
-            },
+            }
+            (Message::EchoRequest, 0) => Ok(Repr::EchoRequest {
+                ident: packet.echo_ident(),
+                seq_no: packet.echo_seq_no(),
+                data: packet.payload(),
+            }),
+            (Message::EchoReply, 0) => Ok(Repr::EchoReply {
+                ident: packet.echo_ident(),
+                seq_no: packet.echo_seq_no(),
+                data: packet.payload(),
+            }),
             #[cfg(feature = "medium-ethernet")]
-            (msg_type, 0) if msg_type.is_ndisc() => {
-                NdiscRepr::parse(packet).map(Repr::Ndisc)
-            },
-            (msg_type, 0) if msg_type.is_mld() => {
-                MldRepr::parse(packet).map(Repr::Mld)
-            },
-            _ => Err(Error::Unrecognized)
+            (msg_type, 0) if msg_type.is_ndisc() => NdiscRepr::parse(packet).map(Repr::Ndisc),
+            (msg_type, 0) if msg_type.is_mld() => MldRepr::parse(packet).map(Repr::Mld),
+            _ => Err(Error::Unrecognized),
         }
     }
 
     /// Return the length of a packet that will be emitted from this high-level representation.
     pub fn buffer_len(&self) -> usize {
         match self {
-            &Repr::DstUnreachable { header, data, .. } | &Repr::PktTooBig { header, data, .. } |
-            &Repr::TimeExceeded { header, data, .. } | &Repr::ParamProblem { header, data, .. } => {
+            &Repr::DstUnreachable { header, data, .. }
+            | &Repr::PktTooBig { header, data, .. }
+            | &Repr::TimeExceeded { header, data, .. }
+            | &Repr::ParamProblem { header, data, .. } => {
                 field::UNUSED.end + header.buffer_len() + data.len()
             }
-            &Repr::EchoRequest { data, .. } |
-            &Repr::EchoReply { data, .. } => {
+            &Repr::EchoRequest { data, .. } | &Repr::EchoReply { data, .. } => {
                 field::ECHO_SEQNO.end + data.len()
-            },
+            }
             #[cfg(feature = "medium-ethernet")]
-            &Repr::Ndisc(ndisc) => {
-                ndisc.buffer_len()
-            },
-            &Repr::Mld(mld) => {
-                mld.buffer_len()
-            },
+            &Repr::Ndisc(ndisc) => ndisc.buffer_len(),
+            &Repr::Mld(mld) => mld.buffer_len(),
         }
     }
 
     /// Emit a high-level representation into an Internet Control Message Protocol version 6
     /// packet.
-    pub fn emit<T>(&self, src_addr: &IpAddress, dst_addr: &IpAddress,
-                   packet: &mut Packet<&mut T>, checksum_caps: &ChecksumCapabilities)
-            where T: AsRef<[u8]> + AsMut<[u8]> + ?Sized {
+    pub fn emit<T>(
+        &self,
+        src_addr: &IpAddress,
+        dst_addr: &IpAddress,
+        packet: &mut Packet<&mut T>,
+        checksum_caps: &ChecksumCapabilities,
+    ) where
+        T: AsRef<[u8]> + AsMut<[u8]> + ?Sized,
+    {
         fn emit_contained_packet(buffer: &mut [u8], header: Ipv6Repr, data: &[u8]) {
             let mut ip_packet = Ipv6Packet::new_unchecked(buffer);
             header.emit(&mut ip_packet);
             let payload = &mut ip_packet.into_inner()[header.buffer_len()..];
-            payload.copy_from_slice(&data[..]);
+            payload.copy_from_slice(data);
         }
 
         match *self {
-            Repr::DstUnreachable { reason, header, data } => {
+            Repr::DstUnreachable {
+                reason,
+                header,
+                data,
+            } => {
                 packet.set_msg_type(Message::DstUnreachable);
                 packet.set_msg_code(reason.into());
 
-                emit_contained_packet(packet.payload_mut(), header, &data);
-            },
+                emit_contained_packet(packet.payload_mut(), header, data);
+            }
 
             Repr::PktTooBig { mtu, header, data } => {
                 packet.set_msg_type(Message::PktTooBig);
                 packet.set_msg_code(0);
                 packet.set_pkt_too_big_mtu(mtu);
 
-                emit_contained_packet(packet.payload_mut(), header, &data);
-            },
+                emit_contained_packet(packet.payload_mut(), header, data);
+            }
 
-            Repr::TimeExceeded { reason, header, data } => {
+            Repr::TimeExceeded {
+                reason,
+                header,
+                data,
+            } => {
                 packet.set_msg_type(Message::TimeExceeded);
                 packet.set_msg_code(reason.into());
 
-                emit_contained_packet(packet.payload_mut(), header, &data);
-            },
+                emit_contained_packet(packet.payload_mut(), header, data);
+            }
 
-            Repr::ParamProblem { reason, pointer, header, data } => {
+            Repr::ParamProblem {
+                reason,
+                pointer,
+                header,
+                data,
+            } => {
                 packet.set_msg_type(Message::ParamProblem);
                 packet.set_msg_code(reason.into());
                 packet.set_param_problem_ptr(pointer);
 
-                emit_contained_packet(packet.payload_mut(), header, &data);
-            },
+                emit_contained_packet(packet.payload_mut(), header, data);
+            }
 
-            Repr::EchoRequest { ident, seq_no, data } => {
+            Repr::EchoRequest {
+                ident,
+                seq_no,
+                data,
+            } => {
                 packet.set_msg_type(Message::EchoRequest);
                 packet.set_msg_code(0);
                 packet.set_echo_ident(ident);
                 packet.set_echo_seq_no(seq_no);
                 let data_len = cmp::min(packet.payload_mut().len(), data.len());
                 packet.payload_mut()[..data_len].copy_from_slice(&data[..data_len])
-            },
+            }
 
-            Repr::EchoReply { ident, seq_no, data } => {
+            Repr::EchoReply {
+                ident,
+                seq_no,
+                data,
+            } => {
                 packet.set_msg_type(Message::EchoReply);
                 packet.set_msg_code(0);
                 packet.set_echo_ident(ident);
                 packet.set_echo_seq_no(seq_no);
                 let data_len = cmp::min(packet.payload_mut().len(), data.len());
                 packet.payload_mut()[..data_len].copy_from_slice(&data[..data_len])
-            },
+            }
 
             #[cfg(feature = "medium-ethernet")]
-            Repr::Ndisc(ndisc) => {
-                ndisc.emit(packet)
-            },
+            Repr::Ndisc(ndisc) => ndisc.emit(packet),
 
-            Repr::Mld(mld) => {
-                mld.emit(packet)
-            },
+            Repr::Mld(mld) => mld.emit(packet),
         }
 
         if checksum_caps.icmpv6.tx() {
@@ -733,60 +747,39 @@ impl<'a> Repr<'a> {
 
 #[cfg(test)]
 mod test {
-    use crate::wire::{Ipv6Address, Ipv6Repr, IpProtocol};
-    use crate::wire::ip::test::{MOCK_IP_ADDR_1, MOCK_IP_ADDR_2};
     use super::*;
+    use crate::wire::ip::test::{MOCK_IP_ADDR_1, MOCK_IP_ADDR_2};
+    use crate::wire::{IpProtocol, Ipv6Address, Ipv6Repr};
+
+    static ECHO_PACKET_BYTES: [u8; 12] = [
+        0x80, 0x00, 0x19, 0xb3, 0x12, 0x34, 0xab, 0xcd, 0xaa, 0x00, 0x00, 0xff,
+    ];
+
+    static ECHO_PACKET_PAYLOAD: [u8; 4] = [0xaa, 0x00, 0x00, 0xff];
+
+    static PKT_TOO_BIG_BYTES: [u8; 60] = [
+        0x02, 0x00, 0x0f, 0xc9, 0x00, 0x00, 0x05, 0xdc, 0x60, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x11,
+        0x40, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x01, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x02, 0xbf, 0x00, 0x00, 0x35, 0x00, 0x0c, 0x12, 0x4d, 0xaa, 0x00, 0x00, 0xff,
+    ];
+
+    static PKT_TOO_BIG_IP_PAYLOAD: [u8; 52] = [
+        0x60, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x11, 0x40, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xbf, 0x00, 0x00, 0x35, 0x00,
+        0x0c, 0x12, 0x4d, 0xaa, 0x00, 0x00, 0xff,
+    ];
 
-    static ECHO_PACKET_BYTES: [u8; 12] =
-        [0x80, 0x00, 0x19, 0xb3,
-         0x12, 0x34, 0xab, 0xcd,
-         0xaa, 0x00, 0x00, 0xff];
-
-    static ECHO_PACKET_PAYLOAD: [u8; 4] =
-        [0xaa, 0x00, 0x00, 0xff];
-
-    static PKT_TOO_BIG_BYTES: [u8; 60] =
-        [0x02, 0x00, 0x0f, 0xc9,
-         0x00, 0x00, 0x05, 0xdc,
-         0x60, 0x00, 0x00, 0x00,
-         0x00, 0x0c, 0x11, 0x40,
-         0xfe, 0x80, 0x00, 0x00,
-         0x00, 0x00, 0x00, 0x00,
-         0x00, 0x00, 0x00, 0x00,
-         0x00, 0x00, 0x00, 0x01,
-         0xfe, 0x80, 0x00, 0x00,
-         0x00, 0x00, 0x00, 0x00,
-         0x00, 0x00, 0x00, 0x00,
-         0x00, 0x00, 0x00, 0x02,
-         0xbf, 0x00, 0x00, 0x35,
-         0x00, 0x0c, 0x12, 0x4d,
-         0xaa, 0x00, 0x00, 0xff];
-
-    static PKT_TOO_BIG_IP_PAYLOAD: [u8; 52] =
-        [0x60, 0x00, 0x00, 0x00,
-         0x00, 0x0c, 0x11, 0x40,
-         0xfe, 0x80, 0x00, 0x00,
-         0x00, 0x00, 0x00, 0x00,
-         0x00, 0x00, 0x00, 0x00,
-         0x00, 0x00, 0x00, 0x01,
-         0xfe, 0x80, 0x00, 0x00,
-         0x00, 0x00, 0x00, 0x00,
-         0x00, 0x00, 0x00, 0x00,
-         0x00, 0x00, 0x00, 0x02,
-         0xbf, 0x00, 0x00, 0x35,
-         0x00, 0x0c, 0x12, 0x4d,
-         0xaa, 0x00, 0x00, 0xff];
-
-    static PKT_TOO_BIG_UDP_PAYLOAD: [u8; 12] =
-        [0xbf, 0x00, 0x00, 0x35,
-         0x00, 0x0c, 0x12, 0x4d,
-         0xaa, 0x00, 0x00, 0xff];
+    static PKT_TOO_BIG_UDP_PAYLOAD: [u8; 12] = [
+        0xbf, 0x00, 0x00, 0x35, 0x00, 0x0c, 0x12, 0x4d, 0xaa, 0x00, 0x00, 0xff,
+    ];
 
     fn echo_packet_repr() -> Repr<'static> {
         Repr::EchoRequest {
             ident: 0x1234,
             seq_no: 0xabcd,
-            data: &ECHO_PACKET_PAYLOAD
+            data: &ECHO_PACKET_PAYLOAD,
         }
     }
 
@@ -794,17 +787,17 @@ mod test {
         Repr::PktTooBig {
             mtu: 1500,
             header: Ipv6Repr {
-                src_addr: Ipv6Address([0xfe, 0x80, 0x00, 0x00,
-                                       0x00, 0x00, 0x00, 0x00,
-                                       0x00, 0x00, 0x00, 0x00,
-                                       0x00, 0x00, 0x00, 0x01]),
-                dst_addr: Ipv6Address([0xfe, 0x80, 0x00, 0x00,
-                                       0x00, 0x00, 0x00, 0x00,
-                                       0x00, 0x00, 0x00, 0x00,
-                                       0x00, 0x00, 0x00, 0x02]),
+                src_addr: Ipv6Address([
+                    0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                    0x00, 0x00, 0x01,
+                ]),
+                dst_addr: Ipv6Address([
+                    0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                    0x00, 0x00, 0x02,
+                ]),
                 next_header: IpProtocol::Udp,
                 payload_len: 12,
-                hop_limit: 0x40
+                hop_limit: 0x40,
             },
             data: &PKT_TOO_BIG_UDP_PAYLOAD,
         }
@@ -819,7 +812,10 @@ mod test {
         assert_eq!(packet.echo_ident(), 0x1234);
         assert_eq!(packet.echo_seq_no(), 0xabcd);
         assert_eq!(packet.payload(), &ECHO_PACKET_PAYLOAD[..]);
-        assert_eq!(packet.verify_checksum(&MOCK_IP_ADDR_1, &MOCK_IP_ADDR_2), true);
+        assert_eq!(
+            packet.verify_checksum(&MOCK_IP_ADDR_1, &MOCK_IP_ADDR_2),
+            true
+        );
         assert!(!packet.msg_type().is_error());
     }
 
@@ -831,7 +827,9 @@ mod test {
         packet.set_msg_code(0);
         packet.set_echo_ident(0x1234);
         packet.set_echo_seq_no(0xabcd);
-        packet.payload_mut().copy_from_slice(&ECHO_PACKET_PAYLOAD[..]);
+        packet
+            .payload_mut()
+            .copy_from_slice(&ECHO_PACKET_PAYLOAD[..]);
         packet.fill_checksum(&MOCK_IP_ADDR_1, &MOCK_IP_ADDR_2);
         assert_eq!(&packet.into_inner()[..], &ECHO_PACKET_BYTES[..]);
     }
@@ -839,8 +837,13 @@ mod test {
     #[test]
     fn test_echo_repr_parse() {
         let packet = Packet::new_unchecked(&ECHO_PACKET_BYTES[..]);
-        let repr = Repr::parse(&MOCK_IP_ADDR_1, &MOCK_IP_ADDR_2,
-                               &packet, &ChecksumCapabilities::default()).unwrap();
+        let repr = Repr::parse(
+            &MOCK_IP_ADDR_1,
+            &MOCK_IP_ADDR_2,
+            &packet,
+            &ChecksumCapabilities::default(),
+        )
+        .unwrap();
         assert_eq!(repr, echo_packet_repr());
     }
 
@@ -849,8 +852,12 @@ mod test {
         let repr = echo_packet_repr();
         let mut bytes = vec![0xa5; repr.buffer_len()];
         let mut packet = Packet::new_unchecked(&mut bytes);
-        repr.emit(&MOCK_IP_ADDR_1, &MOCK_IP_ADDR_2,
-                  &mut packet, &ChecksumCapabilities::default());
+        repr.emit(
+            &MOCK_IP_ADDR_1,
+            &MOCK_IP_ADDR_2,
+            &mut packet,
+            &ChecksumCapabilities::default(),
+        );
         assert_eq!(&packet.into_inner()[..], &ECHO_PACKET_BYTES[..]);
     }
 
@@ -862,7 +869,10 @@ mod test {
         assert_eq!(packet.checksum(), 0x0fc9);
         assert_eq!(packet.pkt_too_big_mtu(), 1500);
         assert_eq!(packet.payload(), &PKT_TOO_BIG_IP_PAYLOAD[..]);
-        assert_eq!(packet.verify_checksum(&MOCK_IP_ADDR_1, &MOCK_IP_ADDR_2), true);
+        assert_eq!(
+            packet.verify_checksum(&MOCK_IP_ADDR_1, &MOCK_IP_ADDR_2),
+            true
+        );
         assert!(packet.msg_type().is_error());
     }
 
@@ -873,7 +883,9 @@ mod test {
         packet.set_msg_type(Message::PktTooBig);
         packet.set_msg_code(0);
         packet.set_pkt_too_big_mtu(1500);
-        packet.payload_mut().copy_from_slice(&PKT_TOO_BIG_IP_PAYLOAD[..]);
+        packet
+            .payload_mut()
+            .copy_from_slice(&PKT_TOO_BIG_IP_PAYLOAD[..]);
         packet.fill_checksum(&MOCK_IP_ADDR_1, &MOCK_IP_ADDR_2);
         assert_eq!(&packet.into_inner()[..], &PKT_TOO_BIG_BYTES[..]);
     }
@@ -881,8 +893,13 @@ mod test {
     #[test]
     fn test_too_big_repr_parse() {
         let packet = Packet::new_unchecked(&PKT_TOO_BIG_BYTES[..]);
-        let repr = Repr::parse(&MOCK_IP_ADDR_1, &MOCK_IP_ADDR_2,
-                               &packet, &ChecksumCapabilities::default()).unwrap();
+        let repr = Repr::parse(
+            &MOCK_IP_ADDR_1,
+            &MOCK_IP_ADDR_2,
+            &packet,
+            &ChecksumCapabilities::default(),
+        )
+        .unwrap();
         assert_eq!(repr, too_big_packet_repr());
     }
 
@@ -891,8 +908,12 @@ mod test {
         let repr = too_big_packet_repr();
         let mut bytes = vec![0xa5; repr.buffer_len()];
         let mut packet = Packet::new_unchecked(&mut bytes);
-        repr.emit(&MOCK_IP_ADDR_1, &MOCK_IP_ADDR_2,
-                  &mut packet, &ChecksumCapabilities::default());
+        repr.emit(
+            &MOCK_IP_ADDR_1,
+            &MOCK_IP_ADDR_2,
+            &mut packet,
+            &ChecksumCapabilities::default(),
+        );
         assert_eq!(&packet.into_inner()[..], &PKT_TOO_BIG_BYTES[..]);
     }
 }

+ 43 - 38
src/wire/igmp.rs

@@ -1,9 +1,9 @@
-use core::fmt;
 use byteorder::{ByteOrder, NetworkEndian};
+use core::fmt;
 
-use crate::{Error, Result};
-use crate::wire::ip::checksum;
 use crate::time::Duration;
+use crate::wire::ip::checksum;
+use crate::{Error, Result};
 
 use crate::wire::Ipv4Address;
 
@@ -202,7 +202,8 @@ impl Repr {
     /// Parse an Internet Group Management Protocol v1/v2 packet and return
     /// a high-level representation.
     pub fn parse<T>(packet: &Packet<&T>) -> Result<Repr>
-        where T: AsRef<[u8]> + ?Sized
+    where
+        T: AsRef<[u8]> + ?Sized,
     {
         // Check if the address is 0.0.0.0 or multicast
         let addr = packet.group_addr();
@@ -226,13 +227,13 @@ impl Repr {
                     version,
                 })
             }
-            Message::MembershipReportV2 => {
-                Ok(Repr::MembershipReport {
-                    group_addr: packet.group_addr(),
-                    version: IgmpVersion::Version2,
-                })
-            }
-            Message::LeaveGroup => Ok(Repr::LeaveGroup { group_addr: packet.group_addr() }),
+            Message::MembershipReportV2 => Ok(Repr::MembershipReport {
+                group_addr: packet.group_addr(),
+                version: IgmpVersion::Version2,
+            }),
+            Message::LeaveGroup => Ok(Repr::LeaveGroup {
+                group_addr: packet.group_addr(),
+            }),
             Message::MembershipReportV1 => {
                 // for backwards compatibility with IGMPv1
                 Ok(Repr::MembershipReport {
@@ -252,20 +253,21 @@ impl Repr {
 
     /// Emit a high-level representation into an Internet Group Management Protocol v2 packet.
     pub fn emit<T>(&self, packet: &mut Packet<&mut T>)
-        where T: AsRef<[u8]> + AsMut<[u8]> + ?Sized
+    where
+        T: AsRef<[u8]> + AsMut<[u8]> + ?Sized,
     {
         match *self {
             Repr::MembershipQuery {
                 max_resp_time,
                 group_addr,
-                version
+                version,
             } => {
                 packet.set_msg_type(Message::MembershipQuery);
                 match version {
-                    IgmpVersion::Version1 =>
-                        packet.set_max_resp_code(0),
-                    IgmpVersion::Version2 =>
-                        packet.set_max_resp_code(duration_to_max_resp_code(max_resp_time)),
+                    IgmpVersion::Version1 => packet.set_max_resp_code(0),
+                    IgmpVersion::Version2 => {
+                        packet.set_max_resp_code(duration_to_max_resp_code(max_resp_time))
+                    }
                 }
                 packet.set_group_address(group_addr);
             }
@@ -336,20 +338,21 @@ impl<'a> fmt::Display for Repr {
                 group_addr,
                 version,
             } => {
-                write!(f,
-                       "IGMP membership query max_resp_time={} group_addr={} version={:?}",
-                       max_resp_time,
-                       group_addr,
-                       version)
+                write!(
+                    f,
+                    "IGMP membership query max_resp_time={} group_addr={} version={:?}",
+                    max_resp_time, group_addr, version
+                )
             }
             Repr::MembershipReport {
                 group_addr,
                 version,
             } => {
-                write!(f,
-                       "IGMP membership report group_addr={} version={:?}",
-                       group_addr,
-                       version)
+                write!(
+                    f,
+                    "IGMP membership report group_addr={} version={:?}",
+                    group_addr, version
+                )
             }
             Repr::LeaveGroup { group_addr } => {
                 write!(f, "IGMP leave group group_addr={})", group_addr)
@@ -361,10 +364,11 @@ impl<'a> fmt::Display for Repr {
 use crate::wire::pretty_print::{PrettyIndent, PrettyPrint};
 
 impl<T: AsRef<[u8]>> PrettyPrint for Packet<T> {
-    fn pretty_print(buffer: &dyn AsRef<[u8]>,
-                    f: &mut fmt::Formatter,
-                    indent: &mut PrettyIndent)
-                    -> fmt::Result {
+    fn pretty_print(
+        buffer: &dyn AsRef<[u8]>,
+        f: &mut fmt::Formatter,
+        indent: &mut PrettyIndent,
+    ) -> fmt::Result {
         match Packet::new_checked(buffer) {
             Err(err) => writeln!(f, "{}({})", indent, err),
             Ok(packet) => writeln!(f, "{}{}", indent, packet),
@@ -376,7 +380,6 @@ impl<T: AsRef<[u8]>> PrettyPrint for Packet<T> {
 mod test {
     use super::*;
 
-
     static LEAVE_PACKET_BYTES: [u8; 8] = [0x17, 0x00, 0x02, 0x69, 0xe0, 0x00, 0x06, 0x96];
     static REPORT_PACKET_BYTES: [u8; 8] = [0x16, 0x00, 0x08, 0xda, 0xe1, 0x00, 0x00, 0x25];
 
@@ -386,8 +389,10 @@ mod test {
         assert_eq!(packet.msg_type(), Message::LeaveGroup);
         assert_eq!(packet.max_resp_code(), 0);
         assert_eq!(packet.checksum(), 0x269);
-        assert_eq!(packet.group_addr(),
-                   Ipv4Address::from_bytes(&[224, 0, 6, 150]));
+        assert_eq!(
+            packet.group_addr(),
+            Ipv4Address::from_bytes(&[224, 0, 6, 150])
+        );
         assert_eq!(packet.verify_checksum(), true);
     }
 
@@ -397,8 +402,10 @@ mod test {
         assert_eq!(packet.msg_type(), Message::MembershipReportV2);
         assert_eq!(packet.max_resp_code(), 0);
         assert_eq!(packet.checksum(), 0x08da);
-        assert_eq!(packet.group_addr(),
-                   Ipv4Address::from_bytes(&[225, 0, 0, 37]));
+        assert_eq!(
+            packet.group_addr(),
+            Ipv4Address::from_bytes(&[225, 0, 0, 37])
+        );
         assert_eq!(packet.verify_checksum(), true);
     }
 
@@ -437,9 +444,7 @@ mod test {
     #[test]
     fn duration_to_max_resp_time_max() {
         for duration in 31744..65536 {
-            let time = duration_to_max_resp_code(
-                Duration::from_millis(duration * 100)
-            );
+            let time = duration_to_max_resp_code(Duration::from_millis(duration * 100));
             assert_eq!(time, 0xFF);
         }
     }

File diff suppressed because it is too large
+ 318 - 241
src/wire/ip.rs


+ 310 - 184
src/wire/ipv4.rs

@@ -1,9 +1,9 @@
-use core::fmt;
 use byteorder::{ByteOrder, NetworkEndian};
+use core::fmt;
 
-use crate::{Error, Result};
 use crate::phy::ChecksumCapabilities;
 use crate::wire::ip::{checksum, pretty_print_ip_payload};
+use crate::{Error, Result};
 
 pub use super::IpProtocol as Protocol;
 
@@ -27,10 +27,10 @@ pub struct Address(pub [u8; 4]);
 
 impl Address {
     /// An unspecified address.
-    pub const UNSPECIFIED:           Address = Address([0x00; 4]);
+    pub const UNSPECIFIED: Address = Address([0x00; 4]);
 
     /// The broadcast address.
-    pub const BROADCAST:             Address = Address([0xff; 4]);
+    pub const BROADCAST: Address = Address([0xff; 4]);
 
     /// All multicast-capable nodes
     pub const MULTICAST_ALL_SYSTEMS: Address = Address([224, 0, 0, 1]);
@@ -60,9 +60,7 @@ impl Address {
 
     /// Query whether the address is an unicast address.
     pub fn is_unicast(&self) -> bool {
-        !(self.is_broadcast() ||
-          self.is_multicast() ||
-          self.is_unspecified())
+        !(self.is_broadcast() || self.is_multicast() || self.is_unspecified())
     }
 
     /// Query whether the address is the broadcast address.
@@ -115,7 +113,14 @@ 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])
+        defmt::write!(
+            f,
+            "{=u8}.{=u8}.{=u8}.{=u8}",
+            self.0[0],
+            self.0[1],
+            self.0[2],
+            self.0[3]
+        )
     }
 }
 
@@ -123,7 +128,7 @@ impl defmt::Format for Address {
 /// subnet masking prefix length.
 #[derive(Debug, Hash, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Default)]
 pub struct Cidr {
-    address:    Address,
+    address: Address,
     prefix_len: u8,
 }
 
@@ -137,14 +142,20 @@ impl Cidr {
         // Replace with const panic (or assert) when stabilized
         // see: https://github.com/rust-lang/rust/issues/51999
         ["Prefix length should be <= 32"][(prefix_len > 32) as usize];
-        Cidr { address, prefix_len }
+        Cidr {
+            address,
+            prefix_len,
+        }
     }
 
     /// Create an IPv4 CIDR block from the given address and network mask.
     pub fn from_netmask(addr: Address, netmask: Address) -> Result<Cidr> {
         let netmask = NetworkEndian::read_u32(&netmask.0[..]);
         if netmask.leading_zeros() == 0 && netmask.trailing_zeros() == netmask.count_zeros() {
-            Ok(Cidr { address: addr, prefix_len: netmask.count_ones() as u8 })
+            Ok(Cidr {
+                address: addr,
+                prefix_len: netmask.count_ones() as u8,
+            })
         } else {
             Err(Error::Illegal)
         }
@@ -170,8 +181,8 @@ impl Cidr {
         let data = [
             ((number >> 24) & 0xff) as u8,
             ((number >> 16) & 0xff) as u8,
-            ((number >>  8) & 0xff) as u8,
-            ((number >>  0) & 0xff) as u8,
+            ((number >> 8) & 0xff) as u8,
+            ((number >> 0) & 0xff) as u8,
         ];
 
         Address(data)
@@ -190,8 +201,8 @@ impl Cidr {
         let data = [
             ((number >> 24) & 0xff) as u8,
             ((number >> 16) & 0xff) as u8,
-            ((number >>  8) & 0xff) as u8,
-            ((number >>  0) & 0xff) as u8,
+            ((number >> 8) & 0xff) as u8,
+            ((number >> 0) & 0xff) as u8,
         ];
 
         Some(Address(data))
@@ -206,14 +217,19 @@ impl Cidr {
             self.address.0[2] & mask[2],
             self.address.0[3] & mask[3],
         ];
-        Cidr { address: Address(network), prefix_len: self.prefix_len }
+        Cidr {
+            address: Address(network),
+            prefix_len: self.prefix_len,
+        }
     }
 
     /// Query whether the subnetwork described by this IPv4 CIDR block contains
     /// the given address.
     pub fn contains_addr(&self, addr: &Address) -> bool {
         // right shift by 32 is not legal
-        if self.prefix_len == 0 { return true }
+        if self.prefix_len == 0 {
+            return true;
+        }
 
         let shift = 32 - self.prefix_len;
         let self_prefix = NetworkEndian::read_u32(self.address.as_bytes()) >> shift;
@@ -245,18 +261,18 @@ impl defmt::Format for Cidr {
 #[derive(Debug, PartialEq, Clone)]
 #[cfg_attr(feature = "defmt", derive(defmt::Format))]
 pub struct Packet<T: AsRef<[u8]>> {
-    buffer: T
+    buffer: T,
 }
 
 mod field {
     use crate::wire::field::*;
 
-    pub const VER_IHL:  usize = 0;
+    pub const VER_IHL: usize = 0;
     pub const DSCP_ECN: usize = 1;
-    pub const LENGTH:   Field = 2..4;
-    pub const IDENT:    Field = 4..6;
-    pub const FLG_OFF:  Field = 6..8;
-    pub const TTL:      usize = 8;
+    pub const LENGTH: Field = 2..4;
+    pub const IDENT: Field = 4..6;
+    pub const FLG_OFF: Field = 6..8;
+    pub const TTL: usize = 8;
     pub const PROTOCOL: usize = 9;
     pub const CHECKSUM: Field = 10..12;
     pub const SRC_ADDR: Field = 12..16;
@@ -265,7 +281,6 @@ mod field {
 
 pub const HEADER_LEN: usize = field::DST_ADDR.end;
 
-
 impl<T: AsRef<[u8]>> Packet<T> {
     /// Imbue a raw octet buffer with IPv4 packet structure.
     pub fn new_unchecked(buffer: T) -> Packet<T> {
@@ -414,7 +429,9 @@ impl<T: AsRef<[u8]>> Packet<T> {
     /// # Fuzzing
     /// This function always returns `true` when fuzzing.
     pub fn verify_checksum(&self) -> bool {
-        if cfg!(fuzzing) { return true }
+        if cfg!(fuzzing) {
+            return true;
+        }
 
         let data = self.buffer.as_ref();
         checksum::data(&data[..self.header_len() as usize]) == !0
@@ -572,36 +589,46 @@ impl<T: AsRef<[u8]>> AsRef<[u8]> for Packet<T> {
 #[derive(Debug, PartialEq, Eq, Clone, Copy)]
 #[cfg_attr(feature = "defmt", derive(defmt::Format))]
 pub struct Repr {
-    pub src_addr:    Address,
-    pub dst_addr:    Address,
-    pub protocol:    Protocol,
+    pub src_addr: Address,
+    pub dst_addr: Address,
+    pub protocol: Protocol,
     pub payload_len: usize,
-    pub hop_limit:   u8
+    pub hop_limit: u8,
 }
 
 impl Repr {
     /// Parse an Internet Protocol version 4 packet and return a high-level representation.
-    pub fn parse<T: AsRef<[u8]> + ?Sized>(packet: &Packet<&T>,
-                                          checksum_caps: &ChecksumCapabilities) -> Result<Repr> {
+    pub fn parse<T: AsRef<[u8]> + ?Sized>(
+        packet: &Packet<&T>,
+        checksum_caps: &ChecksumCapabilities,
+    ) -> Result<Repr> {
         // Version 4 is expected.
-        if packet.version() != 4 { return Err(Error::Malformed) }
+        if packet.version() != 4 {
+            return Err(Error::Malformed);
+        }
         // Valid checksum is expected.
-        if checksum_caps.ipv4.rx() && !packet.verify_checksum() { return Err(Error::Checksum) }
+        if checksum_caps.ipv4.rx() && !packet.verify_checksum() {
+            return Err(Error::Checksum);
+        }
         // We do not support fragmentation.
-        if packet.more_frags() || packet.frag_offset() != 0 { return Err(Error::Fragmented) }
+        if packet.more_frags() || packet.frag_offset() != 0 {
+            return Err(Error::Fragmented);
+        }
         // Since the packet is not fragmented, it must include the entire payload.
         let payload_len = packet.total_len() as usize - packet.header_len() as usize;
-        if packet.payload().len() < payload_len  { return Err(Error::Truncated) }
+        if packet.payload().len() < payload_len {
+            return Err(Error::Truncated);
+        }
 
         // All DSCP values are acceptable, since they are of no concern to receiving endpoint.
         // All ECN values are acceptable, since ECN requires opt-in from both endpoints.
         // All TTL values are acceptable, since we do not perform routing.
         Ok(Repr {
-            src_addr:    packet.src_addr(),
-            dst_addr:    packet.dst_addr(),
-            protocol:    packet.protocol(),
+            src_addr: packet.src_addr(),
+            dst_addr: packet.dst_addr(),
+            protocol: packet.protocol(),
             payload_len: payload_len,
-            hop_limit:   packet.hop_limit()
+            hop_limit: packet.hop_limit(),
         })
     }
 
@@ -612,7 +639,11 @@ impl Repr {
     }
 
     /// Emit a high-level representation into an Internet Protocol version 4 packet.
-    pub fn emit<T: AsRef<[u8]> + AsMut<[u8]>>(&self, packet: &mut Packet<T>, checksum_caps: &ChecksumCapabilities) {
+    pub fn emit<T: AsRef<[u8]> + AsMut<[u8]>>(
+        &self,
+        packet: &mut Packet<T>,
+        checksum_caps: &ChecksumCapabilities,
+    ) {
         packet.set_version(4);
         packet.set_header_len(field::DST_ADDR.end as u8);
         packet.set_dscp(0);
@@ -645,8 +676,14 @@ impl<'a, T: AsRef<[u8]> + ?Sized> fmt::Display for Packet<&'a T> {
             Ok(repr) => write!(f, "{}", repr),
             Err(err) => {
                 write!(f, "IPv4 ({})", err)?;
-                write!(f, " src={} dst={} proto={} hop_limit={}",
-                       self.src_addr(), self.dst_addr(), self.protocol(), self.hop_limit())?;
+                write!(
+                    f,
+                    " src={} dst={} proto={} hop_limit={}",
+                    self.src_addr(),
+                    self.dst_addr(),
+                    self.protocol(),
+                    self.hop_limit()
+                )?;
                 if self.version() != 4 {
                     write!(f, " ver={}", self.version())?;
                 }
@@ -680,32 +717,36 @@ impl<'a, T: AsRef<[u8]> + ?Sized> fmt::Display for Packet<&'a T> {
 
 impl fmt::Display for Repr {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        write!(f, "IPv4 src={} dst={} proto={}",
-               self.src_addr, self.dst_addr, self.protocol)
+        write!(
+            f,
+            "IPv4 src={} dst={} proto={}",
+            self.src_addr, self.dst_addr, self.protocol
+        )
     }
 }
 
-use crate::wire::pretty_print::{PrettyPrint, PrettyIndent};
+use crate::wire::pretty_print::{PrettyIndent, PrettyPrint};
 
 impl<T: AsRef<[u8]>> PrettyPrint for Packet<T> {
-    fn pretty_print(buffer: &dyn AsRef<[u8]>, f: &mut fmt::Formatter,
-                    indent: &mut PrettyIndent) -> fmt::Result {
+    fn pretty_print(
+        buffer: &dyn AsRef<[u8]>,
+        f: &mut fmt::Formatter,
+        indent: &mut PrettyIndent,
+    ) -> fmt::Result {
         use crate::wire::ip::checksum::format_checksum;
 
         let checksum_caps = ChecksumCapabilities::ignored();
 
         let (ip_repr, payload) = match Packet::new_checked(buffer) {
             Err(err) => return write!(f, "{}({})", indent, err),
-            Ok(ip_packet) => {
-                match Repr::parse(&ip_packet, &checksum_caps) {
-                    Err(_) => return Ok(()),
-                    Ok(ip_repr) => {
-                        write!(f, "{}{}", indent, ip_repr)?;
-                        format_checksum(f, ip_packet.verify_checksum())?;
-                        (ip_repr, ip_packet.payload())
-                    }
+            Ok(ip_packet) => match Repr::parse(&ip_packet, &checksum_caps) {
+                Err(_) => return Ok(()),
+                Ok(ip_repr) => {
+                    write!(f, "{}{}", indent, ip_repr)?;
+                    format_checksum(f, ip_packet.verify_checksum())?;
+                    (ip_repr, ip_packet.payload())
                 }
-            }
+            },
         };
 
         pretty_print_ip_payload(f, indent, ip_repr, payload)
@@ -716,20 +757,12 @@ impl<T: AsRef<[u8]>> PrettyPrint for Packet<T> {
 mod test {
     use super::*;
 
-    static PACKET_BYTES: [u8; 30] =
-        [0x45, 0x00, 0x00, 0x1e,
-         0x01, 0x02, 0x62, 0x03,
-         0x1a, 0x01, 0xd5, 0x6e,
-         0x11, 0x12, 0x13, 0x14,
-         0x21, 0x22, 0x23, 0x24,
-         0xaa, 0x00, 0x00, 0x00,
-         0x00, 0x00, 0x00, 0x00,
-         0x00, 0xff];
-
-    static PAYLOAD_BYTES: [u8; 10] =
-        [0xaa, 0x00, 0x00, 0x00,
-         0x00, 0x00, 0x00, 0x00,
-         0x00, 0xff];
+    static PACKET_BYTES: [u8; 30] = [
+        0x45, 0x00, 0x00, 0x1e, 0x01, 0x02, 0x62, 0x03, 0x1a, 0x01, 0xd5, 0x6e, 0x11, 0x12, 0x13,
+        0x14, 0x21, 0x22, 0x23, 0x24, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
+    ];
+
+    static PAYLOAD_BYTES: [u8; 10] = [0xaa, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff];
 
     #[test]
     fn test_deconstruct() {
@@ -781,10 +814,14 @@ mod test {
         bytes.extend(&PACKET_BYTES[..]);
         bytes.push(0);
 
-        assert_eq!(Packet::new_unchecked(&bytes).payload().len(),
-                   PAYLOAD_BYTES.len());
-        assert_eq!(Packet::new_unchecked(&mut bytes).payload_mut().len(),
-                   PAYLOAD_BYTES.len());
+        assert_eq!(
+            Packet::new_unchecked(&bytes).payload().len(),
+            PAYLOAD_BYTES.len()
+        );
+        assert_eq!(
+            Packet::new_unchecked(&mut bytes).payload_mut().len(),
+            PAYLOAD_BYTES.len()
+        );
     }
 
     #[test]
@@ -793,28 +830,23 @@ mod test {
         bytes.extend(&PACKET_BYTES[..]);
         Packet::new_unchecked(&mut bytes).set_total_len(128);
 
-        assert_eq!(Packet::new_checked(&bytes).unwrap_err(),
-                   Error::Truncated);
+        assert_eq!(Packet::new_checked(&bytes).unwrap_err(), Error::Truncated);
     }
 
-    static REPR_PACKET_BYTES: [u8; 24] =
-        [0x45, 0x00, 0x00, 0x18,
-         0x00, 0x00, 0x40, 0x00,
-         0x40, 0x01, 0xd2, 0x79,
-         0x11, 0x12, 0x13, 0x14,
-         0x21, 0x22, 0x23, 0x24,
-         0xaa, 0x00, 0x00, 0xff];
+    static REPR_PACKET_BYTES: [u8; 24] = [
+        0x45, 0x00, 0x00, 0x18, 0x00, 0x00, 0x40, 0x00, 0x40, 0x01, 0xd2, 0x79, 0x11, 0x12, 0x13,
+        0x14, 0x21, 0x22, 0x23, 0x24, 0xaa, 0x00, 0x00, 0xff,
+    ];
 
-    static REPR_PAYLOAD_BYTES: [u8; 4] =
-        [0xaa, 0x00, 0x00, 0xff];
+    static REPR_PAYLOAD_BYTES: [u8; 4] = [0xaa, 0x00, 0x00, 0xff];
 
     fn packet_repr() -> Repr {
         Repr {
-            src_addr:    Address([0x11, 0x12, 0x13, 0x14]),
-            dst_addr:    Address([0x21, 0x22, 0x23, 0x24]),
-            protocol:    Protocol::Icmp,
+            src_addr: Address([0x11, 0x12, 0x13, 0x14]),
+            dst_addr: Address([0x21, 0x22, 0x23, 0x24]),
+            protocol: Protocol::Icmp,
             payload_len: 4,
-            hop_limit:   64
+            hop_limit: 64,
         }
     }
 
@@ -833,7 +865,10 @@ mod test {
         packet.set_version(6);
         packet.fill_checksum();
         let packet = Packet::new_unchecked(&*packet.into_inner());
-        assert_eq!(Repr::parse(&packet, &ChecksumCapabilities::default()), Err(Error::Malformed));
+        assert_eq!(
+            Repr::parse(&packet, &ChecksumCapabilities::default()),
+            Err(Error::Malformed)
+        );
     }
 
     #[test]
@@ -876,28 +911,34 @@ mod test {
         let cidr = Cidr::new(Address::new(192, 168, 1, 10), 24);
 
         let inside_subnet = [
-            [192, 168,   1,   0], [192, 168,   1,   1],
-            [192, 168,   1,   2], [192, 168,   1,  10],
-            [192, 168,   1, 127], [192, 168,   1, 255],
+            [192, 168, 1, 0],
+            [192, 168, 1, 1],
+            [192, 168, 1, 2],
+            [192, 168, 1, 10],
+            [192, 168, 1, 127],
+            [192, 168, 1, 255],
         ];
 
         let outside_subnet = [
-            [192, 168,   0,   0], [127,   0,   0,   1],
-            [192, 168,   2,   0], [192, 168,   0, 255],
-            [  0,   0,   0,   0], [255, 255, 255, 255],
+            [192, 168, 0, 0],
+            [127, 0, 0, 1],
+            [192, 168, 2, 0],
+            [192, 168, 0, 255],
+            [0, 0, 0, 0],
+            [255, 255, 255, 255],
         ];
 
         let subnets = [
-            ([192, 168,   1,   0], 32),
-            ([192, 168,   1, 255], 24),
-            ([192, 168,   1,  10], 30),
+            ([192, 168, 1, 0], 32),
+            ([192, 168, 1, 255], 24),
+            ([192, 168, 1, 10], 30),
         ];
 
         let not_subnets = [
-            ([192, 168,   1,  10], 23),
-            ([127,   0,   0,   1],  8),
-            ([192, 168,   1,   0],  0),
-            ([192, 168,   0, 255], 32),
+            ([192, 168, 1, 10], 23),
+            ([127, 0, 0, 1], 8),
+            ([192, 168, 1, 0], 0),
+            ([192, 168, 0, 255], 32),
         ];
 
         for addr in inside_subnet.iter().map(|a| Address::from_bytes(a)) {
@@ -908,13 +949,17 @@ mod test {
             assert!(!cidr.contains_addr(&addr));
         }
 
-        for subnet in subnets.iter().map(
-            |&(a, p)| Cidr::new(Address::new(a[0], a[1], a[2], a[3]), p)) {
+        for subnet in subnets
+            .iter()
+            .map(|&(a, p)| Cidr::new(Address::new(a[0], a[1], a[2], a[3]), p))
+        {
             assert!(cidr.contains_subnet(&subnet));
         }
 
-        for subnet in not_subnets.iter().map(
-            |&(a, p)| Cidr::new(Address::new(a[0], a[1], a[2], a[3]), p)) {
+        for subnet in not_subnets
+            .iter()
+            .map(|&(a, p)| Cidr::new(Address::new(a[0], a[1], a[2], a[3]), p))
+        {
             assert!(!cidr.contains_subnet(&subnet));
         }
 
@@ -924,94 +969,175 @@ mod test {
 
     #[test]
     fn test_cidr_from_netmask() {
-        assert_eq!(Cidr::from_netmask(Address([0, 0, 0, 0]), Address([1, 0, 2, 0])).is_err(),
-                   true);
-        assert_eq!(Cidr::from_netmask(Address([0, 0, 0, 0]), Address([0, 0, 0, 0])).is_err(),
-                   true);
-        assert_eq!(Cidr::from_netmask(Address([0, 0, 0, 1]), Address([255, 255, 255, 0])).unwrap(),
-                   Cidr::new(Address([0, 0, 0, 1]), 24));
-        assert_eq!(Cidr::from_netmask(Address([192, 168, 0, 1]), Address([255, 255, 0, 0])).unwrap(),
-                   Cidr::new(Address([192, 168, 0, 1]), 16));
-        assert_eq!(Cidr::from_netmask(Address([172, 16, 0, 1]), Address([255, 240, 0, 0])).unwrap(),
-                   Cidr::new(Address([172, 16, 0, 1]), 12));
-        assert_eq!(Cidr::from_netmask(Address([255, 255, 255, 1]), Address([255, 255, 255, 0])).unwrap(),
-                   Cidr::new(Address([255, 255, 255, 1]), 24));
-        assert_eq!(Cidr::from_netmask(Address([255, 255, 255, 255]), Address([255, 255, 255, 255])).unwrap(),
-                   Cidr::new(Address([255, 255, 255, 255]), 32));
+        assert_eq!(
+            Cidr::from_netmask(Address([0, 0, 0, 0]), Address([1, 0, 2, 0])).is_err(),
+            true
+        );
+        assert_eq!(
+            Cidr::from_netmask(Address([0, 0, 0, 0]), Address([0, 0, 0, 0])).is_err(),
+            true
+        );
+        assert_eq!(
+            Cidr::from_netmask(Address([0, 0, 0, 1]), Address([255, 255, 255, 0])).unwrap(),
+            Cidr::new(Address([0, 0, 0, 1]), 24)
+        );
+        assert_eq!(
+            Cidr::from_netmask(Address([192, 168, 0, 1]), Address([255, 255, 0, 0])).unwrap(),
+            Cidr::new(Address([192, 168, 0, 1]), 16)
+        );
+        assert_eq!(
+            Cidr::from_netmask(Address([172, 16, 0, 1]), Address([255, 240, 0, 0])).unwrap(),
+            Cidr::new(Address([172, 16, 0, 1]), 12)
+        );
+        assert_eq!(
+            Cidr::from_netmask(Address([255, 255, 255, 1]), Address([255, 255, 255, 0])).unwrap(),
+            Cidr::new(Address([255, 255, 255, 1]), 24)
+        );
+        assert_eq!(
+            Cidr::from_netmask(Address([255, 255, 255, 255]), Address([255, 255, 255, 255]))
+                .unwrap(),
+            Cidr::new(Address([255, 255, 255, 255]), 32)
+        );
     }
 
     #[test]
     fn test_cidr_netmask() {
-        assert_eq!(Cidr::new(Address([0, 0, 0, 0]), 0).netmask(),
-                   Address([0, 0, 0, 0]));
-        assert_eq!(Cidr::new(Address([0, 0, 0, 1]), 24).netmask(),
-                   Address([255, 255, 255, 0]));
-        assert_eq!(Cidr::new(Address([0, 0, 0, 0]), 32).netmask(),
-                   Address([255, 255, 255, 255]));
-        assert_eq!(Cidr::new(Address([127, 0, 0, 0]), 8).netmask(),
-                   Address([255, 0, 0, 0]));
-        assert_eq!(Cidr::new(Address([192, 168, 0, 0]), 16).netmask(),
-                   Address([255, 255, 0, 0]));
-        assert_eq!(Cidr::new(Address([192, 168, 1, 1]), 16).netmask(),
-                   Address([255, 255, 0, 0]));
-        assert_eq!(Cidr::new(Address([192, 168, 1, 1]), 17).netmask(),
-                   Address([255, 255, 128, 0]));
-        assert_eq!(Cidr::new(Address([172, 16, 0, 0]), 12).netmask(),
-                   Address([255, 240, 0, 0]));
-        assert_eq!(Cidr::new(Address([255, 255, 255, 1]), 24).netmask(),
-                   Address([255, 255, 255, 0]));
-        assert_eq!(Cidr::new(Address([255, 255, 255, 255]), 32).netmask(),
-                   Address([255, 255, 255, 255]));
+        assert_eq!(
+            Cidr::new(Address([0, 0, 0, 0]), 0).netmask(),
+            Address([0, 0, 0, 0])
+        );
+        assert_eq!(
+            Cidr::new(Address([0, 0, 0, 1]), 24).netmask(),
+            Address([255, 255, 255, 0])
+        );
+        assert_eq!(
+            Cidr::new(Address([0, 0, 0, 0]), 32).netmask(),
+            Address([255, 255, 255, 255])
+        );
+        assert_eq!(
+            Cidr::new(Address([127, 0, 0, 0]), 8).netmask(),
+            Address([255, 0, 0, 0])
+        );
+        assert_eq!(
+            Cidr::new(Address([192, 168, 0, 0]), 16).netmask(),
+            Address([255, 255, 0, 0])
+        );
+        assert_eq!(
+            Cidr::new(Address([192, 168, 1, 1]), 16).netmask(),
+            Address([255, 255, 0, 0])
+        );
+        assert_eq!(
+            Cidr::new(Address([192, 168, 1, 1]), 17).netmask(),
+            Address([255, 255, 128, 0])
+        );
+        assert_eq!(
+            Cidr::new(Address([172, 16, 0, 0]), 12).netmask(),
+            Address([255, 240, 0, 0])
+        );
+        assert_eq!(
+            Cidr::new(Address([255, 255, 255, 1]), 24).netmask(),
+            Address([255, 255, 255, 0])
+        );
+        assert_eq!(
+            Cidr::new(Address([255, 255, 255, 255]), 32).netmask(),
+            Address([255, 255, 255, 255])
+        );
     }
 
     #[test]
     fn test_cidr_broadcast() {
-        assert_eq!(Cidr::new(Address([0, 0, 0, 0]), 0).broadcast().unwrap(),
-                   Address([255, 255, 255, 255]));
-        assert_eq!(Cidr::new(Address([0, 0, 0, 1]), 24).broadcast().unwrap(),
-                   Address([0, 0, 0, 255]));
-        assert_eq!(Cidr::new(Address([0, 0, 0, 0]), 32).broadcast(),
-                   None);
-        assert_eq!(Cidr::new(Address([127, 0, 0, 0]), 8).broadcast().unwrap(),
-                   Address([127, 255, 255, 255]));
-        assert_eq!(Cidr::new(Address([192, 168, 0, 0]), 16).broadcast().unwrap(),
-                   Address([192, 168, 255, 255]));
-        assert_eq!(Cidr::new(Address([192, 168, 1, 1]), 16).broadcast().unwrap(),
-                   Address([192, 168, 255, 255]));
-        assert_eq!(Cidr::new(Address([192, 168, 1, 1]), 17).broadcast().unwrap(),
-                   Address([192, 168, 127, 255]));
-        assert_eq!(Cidr::new(Address([172, 16, 0, 1]), 12).broadcast().unwrap(),
-                   Address([172, 31, 255, 255]));
-        assert_eq!(Cidr::new(Address([255, 255, 255, 1]), 24).broadcast().unwrap(),
-                   Address([255, 255, 255, 255]));
-        assert_eq!(Cidr::new(Address([255, 255, 255, 254]), 31).broadcast(),
-                   None);
-        assert_eq!(Cidr::new(Address([255, 255, 255, 255]), 32).broadcast(),
-                   None);
-
+        assert_eq!(
+            Cidr::new(Address([0, 0, 0, 0]), 0).broadcast().unwrap(),
+            Address([255, 255, 255, 255])
+        );
+        assert_eq!(
+            Cidr::new(Address([0, 0, 0, 1]), 24).broadcast().unwrap(),
+            Address([0, 0, 0, 255])
+        );
+        assert_eq!(Cidr::new(Address([0, 0, 0, 0]), 32).broadcast(), None);
+        assert_eq!(
+            Cidr::new(Address([127, 0, 0, 0]), 8).broadcast().unwrap(),
+            Address([127, 255, 255, 255])
+        );
+        assert_eq!(
+            Cidr::new(Address([192, 168, 0, 0]), 16)
+                .broadcast()
+                .unwrap(),
+            Address([192, 168, 255, 255])
+        );
+        assert_eq!(
+            Cidr::new(Address([192, 168, 1, 1]), 16)
+                .broadcast()
+                .unwrap(),
+            Address([192, 168, 255, 255])
+        );
+        assert_eq!(
+            Cidr::new(Address([192, 168, 1, 1]), 17)
+                .broadcast()
+                .unwrap(),
+            Address([192, 168, 127, 255])
+        );
+        assert_eq!(
+            Cidr::new(Address([172, 16, 0, 1]), 12).broadcast().unwrap(),
+            Address([172, 31, 255, 255])
+        );
+        assert_eq!(
+            Cidr::new(Address([255, 255, 255, 1]), 24)
+                .broadcast()
+                .unwrap(),
+            Address([255, 255, 255, 255])
+        );
+        assert_eq!(
+            Cidr::new(Address([255, 255, 255, 254]), 31).broadcast(),
+            None
+        );
+        assert_eq!(
+            Cidr::new(Address([255, 255, 255, 255]), 32).broadcast(),
+            None
+        );
     }
 
     #[test]
     fn test_cidr_network() {
-        assert_eq!(Cidr::new(Address([0, 0, 0, 0]), 0).network(),
-                   Cidr::new(Address([0, 0, 0, 0]), 0));
-        assert_eq!(Cidr::new(Address([0, 0, 0, 1]), 24).network(),
-                   Cidr::new(Address([0, 0, 0, 0]), 24));
-        assert_eq!(Cidr::new(Address([0, 0, 0, 0]), 32).network(),
-                   Cidr::new(Address([0, 0, 0, 0]), 32));
-        assert_eq!(Cidr::new(Address([127, 0, 0, 0]), 8).network(),
-                   Cidr::new(Address([127, 0, 0, 0]), 8));
-        assert_eq!(Cidr::new(Address([192, 168, 0, 0]), 16).network(),
-                   Cidr::new(Address([192, 168, 0, 0]), 16));
-        assert_eq!(Cidr::new(Address([192, 168, 1, 1]), 16).network(),
-                   Cidr::new(Address([192, 168, 0, 0]), 16));
-        assert_eq!(Cidr::new(Address([192, 168, 1, 1]), 17).network(),
-                   Cidr::new(Address([192, 168, 0, 0]), 17));
-        assert_eq!(Cidr::new(Address([172,  16, 0, 1]), 12).network(),
-                   Cidr::new(Address([172,  16, 0, 0]), 12));
-        assert_eq!(Cidr::new(Address([255, 255, 255, 1]), 24).network(),
-                   Cidr::new(Address([255, 255, 255, 0]), 24));
-        assert_eq!(Cidr::new(Address([255, 255, 255, 255]), 32).network(),
-                   Cidr::new(Address([255, 255, 255, 255]), 32));
+        assert_eq!(
+            Cidr::new(Address([0, 0, 0, 0]), 0).network(),
+            Cidr::new(Address([0, 0, 0, 0]), 0)
+        );
+        assert_eq!(
+            Cidr::new(Address([0, 0, 0, 1]), 24).network(),
+            Cidr::new(Address([0, 0, 0, 0]), 24)
+        );
+        assert_eq!(
+            Cidr::new(Address([0, 0, 0, 0]), 32).network(),
+            Cidr::new(Address([0, 0, 0, 0]), 32)
+        );
+        assert_eq!(
+            Cidr::new(Address([127, 0, 0, 0]), 8).network(),
+            Cidr::new(Address([127, 0, 0, 0]), 8)
+        );
+        assert_eq!(
+            Cidr::new(Address([192, 168, 0, 0]), 16).network(),
+            Cidr::new(Address([192, 168, 0, 0]), 16)
+        );
+        assert_eq!(
+            Cidr::new(Address([192, 168, 1, 1]), 16).network(),
+            Cidr::new(Address([192, 168, 0, 0]), 16)
+        );
+        assert_eq!(
+            Cidr::new(Address([192, 168, 1, 1]), 17).network(),
+            Cidr::new(Address([192, 168, 0, 0]), 17)
+        );
+        assert_eq!(
+            Cidr::new(Address([172, 16, 0, 1]), 12).network(),
+            Cidr::new(Address([172, 16, 0, 0]), 12)
+        );
+        assert_eq!(
+            Cidr::new(Address([255, 255, 255, 1]), 24).network(),
+            Cidr::new(Address([255, 255, 255, 0]), 24)
+        );
+        assert_eq!(
+            Cidr::new(Address([255, 255, 255, 255]), 32).network(),
+            Cidr::new(Address([255, 255, 255, 255]), 32)
+        );
     }
 }

+ 295 - 192
src/wire/ipv6.rs

@@ -1,12 +1,12 @@
 #![deny(missing_docs)]
 
-use core::fmt;
 use byteorder::{ByteOrder, NetworkEndian};
+use core::fmt;
 
-use crate::{Error, Result};
 use crate::wire::ip::pretty_print_ip_payload;
 #[cfg(feature = "proto-ipv4")]
 use crate::wire::ipv4;
+use crate::{Error, Result};
 
 pub use super::IpProtocol as Protocol;
 
@@ -29,28 +29,30 @@ impl Address {
     /// The link-local [all routers multicast address].
     ///
     /// [all routers multicast address]: https://tools.ietf.org/html/rfc4291#section-2.7.1
-    pub const LINK_LOCAL_ALL_NODES: Address =
-        Address([0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01]);
+    pub const LINK_LOCAL_ALL_NODES: Address = Address([
+        0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x01,
+    ]);
 
     /// The link-local [all nodes multicast address].
     ///
     /// [all nodes multicast address]: https://tools.ietf.org/html/rfc4291#section-2.7.1
-    pub const LINK_LOCAL_ALL_ROUTERS: Address =
-        Address([0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02]);
+    pub const LINK_LOCAL_ALL_ROUTERS: Address = Address([
+        0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x02,
+    ]);
 
     /// The [loopback address].
     ///
     /// [loopback address]: https://tools.ietf.org/html/rfc4291#section-2.5.3
-    pub const LOOPBACK: Address =
-        Address([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01]);
+    pub const LOOPBACK: Address = Address([
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x01,
+    ]);
 
     /// Construct an IPv6 address from parts.
     #[allow(clippy::too_many_arguments)]
-    pub fn new(a0: u16, a1: u16, a2: u16, a3: u16,
-               a4: u16, a5: u16, a6: u16, a7: u16) -> Address {
+    pub fn new(a0: u16, a1: u16, a2: u16, a3: u16, a4: u16, a5: u16, a6: u16, a7: u16) -> Address {
         let mut addr = [0u8; 16];
         NetworkEndian::write_u16(&mut addr[0..2], a0);
         NetworkEndian::write_u16(&mut addr[2..4], a1);
@@ -127,8 +129,7 @@ impl Address {
     ///
     /// [link-local]: https://tools.ietf.org/html/rfc4291#section-2.5.6
     pub fn is_link_local(&self) -> bool {
-        self.0[0..8] == [0xfe, 0x80, 0x00, 0x00,
-                         0x00, 0x00, 0x00, 0x00]
+        self.0[0..8] == [0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
     }
 
     /// Query whether the IPv6 address is the [loopback address].
@@ -149,7 +150,9 @@ impl Address {
     /// Convert an IPv4 mapped IPv6 address to an IPv4 address.
     pub fn as_ipv4(&self) -> Option<ipv4::Address> {
         if self.is_ipv4_mapped() {
-            Some(ipv4::Address::new(self.0[12], self.0[13], self.0[14], self.0[15]))
+            Some(ipv4::Address::new(
+                self.0[12], self.0[13], self.0[14], self.0[15],
+            ))
         } else {
             None
         }
@@ -165,7 +168,7 @@ impl Address {
         let idx = (mask as usize) / 8;
         let modulus = (mask as usize) % 8;
         let (first, second) = self.0.split_at(idx);
-        bytes[0..idx].copy_from_slice(&first);
+        bytes[0..idx].copy_from_slice(first);
         if idx < 16 {
             let part = second[0];
             bytes[idx] = part & (!(0xff >> modulus) as u8);
@@ -180,8 +183,10 @@ impl Address {
     /// unicast.
     pub fn solicited_node(&self) -> Address {
         assert!(self.is_unicast());
-        let mut bytes = [0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00];
+        let mut bytes = [
+            0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+            0x00, 0x00,
+        ];
         bytes[14..].copy_from_slice(&self.0[14..]);
         Address(bytes)
     }
@@ -204,7 +209,11 @@ impl From<Address> for ::std::net::Ipv6Addr {
 impl fmt::Display for Address {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         if self.is_ipv4_mapped() {
-            return write!(f, "::ffff:{}.{}.{}.{}", self.0[12], self.0[13], self.0[14], self.0[15])
+            return write!(
+                f,
+                "::ffff:{}.{}.{}.{}",
+                self.0[12], self.0[13], self.0[14], self.0[15]
+            );
         }
 
         // The string representation of an IPv6 address should
@@ -217,7 +226,7 @@ impl fmt::Display for Address {
             Head,
             HeadBody,
             Tail,
-            TailBody
+            TailBody,
         }
         let mut words = [0u16; 8];
         self.write_parts(&mut words);
@@ -229,7 +238,7 @@ impl fmt::Display for Address {
                 (0, &State::Head) | (0, &State::HeadBody) => {
                     write!(f, "::")?;
                     State::Tail
-                },
+                }
                 // Continue iterating without writing any characters until
                 // we hit anothing non-zero value.
                 (0, &State::Tail) => State::Tail,
@@ -238,11 +247,11 @@ impl fmt::Display for Address {
                 (_, &State::Head) => {
                     write!(f, "{:x}", word)?;
                     State::HeadBody
-                },
+                }
                 (_, &State::Tail) => {
                     write!(f, "{:x}", word)?;
                     State::TailBody
-                },
+                }
                 // Write the u16 with a leading colon when parsing a value
                 // that isn't the first in a section
                 (_, &State::HeadBody) | (_, &State::TailBody) => {
@@ -260,8 +269,9 @@ impl fmt::Display for Address {
 impl From<ipv4::Address> for Address {
     fn from(address: ipv4::Address) -> Self {
         let octets = address.0;
-        Address([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff,
-                octets[0], octets[1], octets[2], octets[3]])
+        Address([
+            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, octets[0], octets[1], octets[2], octets[3],
+        ])
     }
 }
 
@@ -270,7 +280,7 @@ impl From<ipv4::Address> for Address {
 #[derive(Debug, Hash, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Default)]
 #[cfg_attr(feature = "defmt", derive(defmt::Format))]
 pub struct Cidr {
-    address:    Address,
+    address: Address,
     prefix_len: u8,
 }
 
@@ -278,12 +288,13 @@ impl Cidr {
     /// The [solicited node prefix].
     ///
     /// [solicited node prefix]: https://tools.ietf.org/html/rfc4291#section-2.7.1
-    pub const SOLICITED_NODE_PREFIX: Cidr =
-        Cidr {
-            address: Address([0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                              0x00, 0x00, 0x00, 0x01, 0xff, 0x00, 0x00, 0x00]),
-            prefix_len: 104
-        };
+    pub const SOLICITED_NODE_PREFIX: Cidr = Cidr {
+        address: Address([
+            0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0x00,
+            0x00, 0x00,
+        ]),
+        prefix_len: 104,
+    };
 
     /// Create an IPv6 CIDR block from the given address and prefix length.
     ///
@@ -291,7 +302,10 @@ impl Cidr {
     /// This function panics if the prefix length is larger than 128.
     pub fn new(address: Address, prefix_len: u8) -> Cidr {
         assert!(prefix_len <= 128);
-        Cidr { address, prefix_len }
+        Cidr {
+            address,
+            prefix_len,
+        }
     }
 
     /// Return the address of this IPv6 CIDR block.
@@ -308,7 +322,9 @@ impl Cidr {
     /// the given address.
     pub fn contains_addr(&self, addr: &Address) -> bool {
         // right shift by 128 is not legal
-        if self.prefix_len == 0 { return true }
+        if self.prefix_len == 0 {
+            return true;
+        }
 
         let shift = 128 - self.prefix_len;
         self.address.mask(shift) == addr.mask(shift)
@@ -332,7 +348,7 @@ impl fmt::Display for Cidr {
 #[derive(Debug, PartialEq, Clone)]
 #[cfg_attr(feature = "defmt", derive(defmt::Format))]
 pub struct Packet<T: AsRef<[u8]>> {
-    buffer: T
+    buffer: T,
 }
 
 // Ranges and constants describing the IPv6 header
@@ -367,17 +383,17 @@ mod field {
     pub const VER_TC_FLOW: Field = 0..4;
     // 16-bit value representing the length of the payload.
     // Note: Options are included in this length.
-    pub const LENGTH:      Field = 4..6;
+    pub const LENGTH: Field = 4..6;
     // 8-bit value identifying the type of header following this
     // one. Note: The same numbers are used in IPv4.
-    pub const NXT_HDR:     usize = 6;
+    pub const NXT_HDR: usize = 6;
     // 8-bit value decremented by each node that forwards this
     // packet. The packet is discarded when the value is 0.
-    pub const HOP_LIMIT:   usize = 7;
+    pub const HOP_LIMIT: usize = 7;
     // IPv6 address of the source node.
-    pub const SRC_ADDR:    Field = 8..24;
+    pub const SRC_ADDR: Field = 8..24;
     // IPv6 address of the destination node.
-    pub const DST_ADDR:    Field = 24..40;
+    pub const DST_ADDR: Field = 24..40;
 }
 
 /// Length of an IPv6 header.
@@ -602,15 +618,15 @@ impl<T: AsRef<[u8]>> AsRef<[u8]> for Packet<T> {
 #[cfg_attr(feature = "defmt", derive(defmt::Format))]
 pub struct Repr {
     /// IPv6 address of the source node.
-    pub src_addr:    Address,
+    pub src_addr: Address,
     /// IPv6 address of the destination node.
-    pub dst_addr:    Address,
+    pub dst_addr: Address,
     /// Protocol contained in the next header.
     pub next_header: Protocol,
     /// Length of the payload including the extension headers.
     pub payload_len: usize,
     /// The 8-bit hop limit field.
-    pub hop_limit:   u8
+    pub hop_limit: u8,
 }
 
 impl Repr {
@@ -618,13 +634,15 @@ impl Repr {
     pub fn parse<T: AsRef<[u8]> + ?Sized>(packet: &Packet<&T>) -> Result<Repr> {
         // Ensure basic accessors will work
         packet.check_len()?;
-        if packet.version() != 6 { return Err(Error::Malformed); }
+        if packet.version() != 6 {
+            return Err(Error::Malformed);
+        }
         Ok(Repr {
-            src_addr:    packet.src_addr(),
-            dst_addr:    packet.dst_addr(),
+            src_addr: packet.src_addr(),
+            dst_addr: packet.dst_addr(),
             next_header: packet.next_header(),
             payload_len: packet.payload_len() as usize,
-            hop_limit:   packet.hop_limit()
+            hop_limit: packet.hop_limit(),
         })
     }
 
@@ -651,29 +669,33 @@ impl Repr {
 
 impl fmt::Display for Repr {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        write!(f, "IPv6 src={} dst={} nxt_hdr={} hop_limit={}",
-               self.src_addr, self.dst_addr, self.next_header, self.hop_limit)
+        write!(
+            f,
+            "IPv6 src={} dst={} nxt_hdr={} hop_limit={}",
+            self.src_addr, self.dst_addr, self.next_header, self.hop_limit
+        )
     }
 }
 
-use crate::wire::pretty_print::{PrettyPrint, PrettyIndent};
+use crate::wire::pretty_print::{PrettyIndent, PrettyPrint};
 
 // TODO: This is very similar to the implementation for IPv4. Make
 // a way to have less copy and pasted code here.
 impl<T: AsRef<[u8]>> PrettyPrint for Packet<T> {
-    fn pretty_print(buffer: &dyn AsRef<[u8]>, f: &mut fmt::Formatter,
-                    indent: &mut PrettyIndent) -> fmt::Result {
+    fn pretty_print(
+        buffer: &dyn AsRef<[u8]>,
+        f: &mut fmt::Formatter,
+        indent: &mut PrettyIndent,
+    ) -> fmt::Result {
         let (ip_repr, payload) = match Packet::new_checked(buffer) {
             Err(err) => return write!(f, "{}({})", indent, err),
-            Ok(ip_packet) => {
-                match Repr::parse(&ip_packet) {
-                    Err(_) => return Ok(()),
-                    Ok(ip_repr) => {
-                        write!(f, "{}{}", indent, ip_repr)?;
-                        (ip_repr, ip_packet.payload())
-                    }
+            Ok(ip_packet) => match Repr::parse(&ip_packet) {
+                Err(_) => return Ok(()),
+                Ok(ip_repr) => {
+                    write!(f, "{}{}", indent, ip_repr)?;
+                    (ip_repr, ip_packet.payload())
                 }
-            }
+            },
         };
 
         pretty_print_ip_payload(f, indent, ip_repr, payload)
@@ -682,18 +704,18 @@ impl<T: AsRef<[u8]>> PrettyPrint for Packet<T> {
 
 #[cfg(test)]
 mod test {
-    use crate::Error;
     use super::{Address, Cidr};
     use super::{Packet, Protocol, Repr};
-    use crate::wire::pretty_print::{PrettyPrinter};
+    use crate::wire::pretty_print::PrettyPrinter;
+    use crate::Error;
 
     #[cfg(feature = "proto-ipv4")]
     use crate::wire::ipv4::Address as Ipv4Address;
 
-    static LINK_LOCAL_ADDR: Address = Address([0xfe, 0x80, 0x00, 0x00,
-                                               0x00, 0x00, 0x00, 0x00,
-                                               0x00, 0x00, 0x00, 0x00,
-                                               0x00, 0x00, 0x00, 0x01]);
+    static LINK_LOCAL_ADDR: Address = Address([
+        0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x01,
+    ]);
     #[test]
     fn test_basic_multicast() {
         assert!(!Address::LINK_LOCAL_ALL_ROUTERS.is_unspecified());
@@ -724,48 +746,62 @@ mod test {
 
     #[test]
     fn test_address_format() {
-        assert_eq!("ff02::1",
-                   format!("{}", Address::LINK_LOCAL_ALL_NODES));
-        assert_eq!("fe80::1",
-                   format!("{}", LINK_LOCAL_ADDR));
-        assert_eq!("fe80::7f00:0:1",
-                   format!("{}", Address::new(0xfe80, 0, 0, 0, 0, 0x7f00, 0x0000, 0x0001)));
-        assert_eq!("::",
-                   format!("{}", Address::UNSPECIFIED));
-        assert_eq!("::1",
-                   format!("{}", Address::LOOPBACK));
+        assert_eq!("ff02::1", format!("{}", Address::LINK_LOCAL_ALL_NODES));
+        assert_eq!("fe80::1", format!("{}", LINK_LOCAL_ADDR));
+        assert_eq!(
+            "fe80::7f00:0:1",
+            format!(
+                "{}",
+                Address::new(0xfe80, 0, 0, 0, 0, 0x7f00, 0x0000, 0x0001)
+            )
+        );
+        assert_eq!("::", format!("{}", Address::UNSPECIFIED));
+        assert_eq!("::1", format!("{}", Address::LOOPBACK));
 
         #[cfg(feature = "proto-ipv4")]
-        assert_eq!("::ffff:192.168.1.1",
-                   format!("{}", Address::from(Ipv4Address::new(192, 168, 1, 1))));
+        assert_eq!(
+            "::ffff:192.168.1.1",
+            format!("{}", Address::from(Ipv4Address::new(192, 168, 1, 1)))
+        );
     }
 
     #[test]
     fn test_new() {
-        assert_eq!(Address::new(0xff02, 0, 0, 0, 0, 0, 0, 1),
-                   Address::LINK_LOCAL_ALL_NODES);
-        assert_eq!(Address::new(0xff02, 0, 0, 0, 0, 0, 0, 2),
-                   Address::LINK_LOCAL_ALL_ROUTERS);
-        assert_eq!(Address::new(0, 0, 0, 0, 0, 0, 0, 1),
-                   Address::LOOPBACK);
-        assert_eq!(Address::new(0, 0, 0, 0, 0, 0, 0, 0),
-                   Address::UNSPECIFIED);
-        assert_eq!(Address::new(0xfe80, 0, 0, 0, 0, 0, 0, 1),
-                   LINK_LOCAL_ADDR);
+        assert_eq!(
+            Address::new(0xff02, 0, 0, 0, 0, 0, 0, 1),
+            Address::LINK_LOCAL_ALL_NODES
+        );
+        assert_eq!(
+            Address::new(0xff02, 0, 0, 0, 0, 0, 0, 2),
+            Address::LINK_LOCAL_ALL_ROUTERS
+        );
+        assert_eq!(Address::new(0, 0, 0, 0, 0, 0, 0, 1), Address::LOOPBACK);
+        assert_eq!(Address::new(0, 0, 0, 0, 0, 0, 0, 0), Address::UNSPECIFIED);
+        assert_eq!(Address::new(0xfe80, 0, 0, 0, 0, 0, 0, 1), LINK_LOCAL_ADDR);
     }
 
     #[test]
     fn test_from_parts() {
-        assert_eq!(Address::from_parts(&[0xff02, 0, 0, 0, 0, 0, 0, 1]),
-                   Address::LINK_LOCAL_ALL_NODES);
-        assert_eq!(Address::from_parts(&[0xff02, 0, 0, 0, 0, 0, 0, 2]),
-                   Address::LINK_LOCAL_ALL_ROUTERS);
-        assert_eq!(Address::from_parts(&[0, 0, 0, 0, 0, 0, 0, 1]),
-                   Address::LOOPBACK);
-        assert_eq!(Address::from_parts(&[0, 0, 0, 0, 0, 0, 0, 0]),
-                   Address::UNSPECIFIED);
-        assert_eq!(Address::from_parts(&[0xfe80, 0, 0, 0, 0, 0, 0, 1]),
-                   LINK_LOCAL_ADDR);
+        assert_eq!(
+            Address::from_parts(&[0xff02, 0, 0, 0, 0, 0, 0, 1]),
+            Address::LINK_LOCAL_ALL_NODES
+        );
+        assert_eq!(
+            Address::from_parts(&[0xff02, 0, 0, 0, 0, 0, 0, 2]),
+            Address::LINK_LOCAL_ALL_ROUTERS
+        );
+        assert_eq!(
+            Address::from_parts(&[0, 0, 0, 0, 0, 0, 0, 1]),
+            Address::LOOPBACK
+        );
+        assert_eq!(
+            Address::from_parts(&[0, 0, 0, 0, 0, 0, 0, 0]),
+            Address::UNSPECIFIED
+        );
+        assert_eq!(
+            Address::from_parts(&[0xfe80, 0, 0, 0, 0, 0, 0, 1]),
+            LINK_LOCAL_ADDR
+        );
     }
 
     #[test]
@@ -788,18 +824,36 @@ mod test {
     #[test]
     fn test_mask() {
         let addr = Address::new(0x0123, 0x4567, 0x89ab, 0, 0, 0, 0, 1);
-        assert_eq!(addr.mask(11), [0x01, 0x20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
-        assert_eq!(addr.mask(15), [0x01, 0x22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
-        assert_eq!(addr.mask(26), [0x01, 0x23, 0x45, 0x40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
-        assert_eq!(addr.mask(128), [0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]);
-        assert_eq!(addr.mask(127), [0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
+        assert_eq!(
+            addr.mask(11),
+            [0x01, 0x20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+        );
+        assert_eq!(
+            addr.mask(15),
+            [0x01, 0x22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+        );
+        assert_eq!(
+            addr.mask(26),
+            [0x01, 0x23, 0x45, 0x40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+        );
+        assert_eq!(
+            addr.mask(128),
+            [0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]
+        );
+        assert_eq!(
+            addr.mask(127),
+            [0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+        );
     }
 
     #[cfg(feature = "proto-ipv4")]
     #[test]
     fn test_is_ipv4_mapped() {
         assert_eq!(false, Address::UNSPECIFIED.is_ipv4_mapped());
-        assert_eq!(true, Address::from(Ipv4Address::new(192, 168, 1, 1)).is_ipv4_mapped());
+        assert_eq!(
+            true,
+            Address::from(Ipv4Address::new(192, 168, 1, 1)).is_ipv4_mapped()
+        );
     }
 
     #[cfg(feature = "proto-ipv4")]
@@ -814,10 +868,14 @@ mod test {
     #[cfg(feature = "proto-ipv4")]
     #[test]
     fn test_from_ipv4_address() {
-        assert_eq!(Address([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, 192, 168, 1, 1]),
-            Address::from(Ipv4Address::new(192, 168, 1, 1)));
-        assert_eq!(Address([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, 222, 1, 41, 90]),
-            Address::from(Ipv4Address::new(222, 1, 41, 90)));
+        assert_eq!(
+            Address([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, 192, 168, 1, 1]),
+            Address::from(Ipv4Address::new(192, 168, 1, 1))
+        );
+        assert_eq!(
+            Address([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, 222, 1, 41, 90]),
+            Address::from(Ipv4Address::new(222, 1, 41, 90))
+        );
     }
 
     #[test]
@@ -825,52 +883,96 @@ mod test {
         let cidr = Cidr::new(LINK_LOCAL_ADDR, 64);
 
         let inside_subnet = [
-            [0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-             0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02],
-            [0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-             0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88],
-            [0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-             0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
-            [0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-             0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff]
+            [
+                0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                0x00, 0x02,
+            ],
+            [
+                0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66,
+                0x77, 0x88,
+            ],
+            [
+                0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
+                0x00, 0x00,
+            ],
+            [
+                0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                0x00, 0xff,
+            ],
         ];
 
         let outside_subnet = [
-            [0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
-             0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01],
-            [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-             0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01],
-            [0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-             0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01],
-            [0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-             0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02]
+            [
+                0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                0x00, 0x01,
+            ],
+            [
+                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                0x00, 0x01,
+            ],
+            [
+                0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                0x00, 0x01,
+            ],
+            [
+                0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                0x00, 0x02,
+            ],
         ];
 
         let subnets = [
-            ([0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-              0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff],
-             65),
-            ([0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-              0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01],
-             128),
-            ([0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-              0x00, 0x00, 0x00, 0x00, 0x12, 0x34, 0x56, 0x78],
-             96)
+            (
+                [
+                    0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff,
+                    0xff, 0xff, 0xff,
+                ],
+                65,
+            ),
+            (
+                [
+                    0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                    0x00, 0x00, 0x01,
+                ],
+                128,
+            ),
+            (
+                [
+                    0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12,
+                    0x34, 0x56, 0x78,
+                ],
+                96,
+            ),
         ];
 
         let not_subnets = [
-            ([0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-              0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff],
-             63),
-            ([0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
-              0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff],
-             64),
-            ([0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
-              0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff],
-             65),
-            ([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-              0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01],
-             128)
+            (
+                [
+                    0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff,
+                    0xff, 0xff, 0xff,
+                ],
+                63,
+            ),
+            (
+                [
+                    0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff,
+                    0xff, 0xff, 0xff,
+                ],
+                64,
+            ),
+            (
+                [
+                    0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff,
+                    0xff, 0xff, 0xff,
+                ],
+                65,
+            ),
+            (
+                [
+                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                    0x00, 0x00, 0x01,
+                ],
+                128,
+            ),
         ];
 
         for addr in inside_subnet.iter().map(|a| Address::from_bytes(a)) {
@@ -881,13 +983,11 @@ mod test {
             assert!(!cidr.contains_addr(&addr));
         }
 
-        for subnet in subnets.iter().map(
-            |&(a, p)| Cidr::new(Address(a), p)) {
+        for subnet in subnets.iter().map(|&(a, p)| Cidr::new(Address(a), p)) {
             assert!(cidr.contains_subnet(&subnet));
         }
 
-        for subnet in not_subnets.iter().map(
-            |&(a, p)| Cidr::new(Address(a), p)) {
+        for subnet in not_subnets.iter().map(|&(a, p)| Cidr::new(Address(a), p)) {
             assert!(!cidr.contains_subnet(&subnet));
         }
 
@@ -907,33 +1007,26 @@ mod test {
         let _ = Address::from_parts(&[0u16; 7]);
     }
 
-    static REPR_PACKET_BYTES: [u8; 52] = [0x60, 0x00, 0x00, 0x00,
-                                          0x00, 0x0c, 0x11, 0x40,
-                                          0xfe, 0x80, 0x00, 0x00,
-                                          0x00, 0x00, 0x00, 0x00,
-                                          0x00, 0x00, 0x00, 0x00,
-                                          0x00, 0x00, 0x00, 0x01,
-                                          0xff, 0x02, 0x00, 0x00,
-                                          0x00, 0x00, 0x00, 0x00,
-                                          0x00, 0x00, 0x00, 0x00,
-                                          0x00, 0x00, 0x00, 0x01,
-                                          0x00, 0x01, 0x00, 0x02,
-                                          0x00, 0x0c, 0x02, 0x4e,
-                                          0xff, 0xff, 0xff, 0xff];
-    static REPR_PAYLOAD_BYTES: [u8; 12] = [0x00, 0x01, 0x00, 0x02,
-                                           0x00, 0x0c, 0x02, 0x4e,
-                                           0xff, 0xff, 0xff, 0xff];
+    static REPR_PACKET_BYTES: [u8; 52] = [
+        0x60, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x11, 0x40, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0x02, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00,
+        0x0c, 0x02, 0x4e, 0xff, 0xff, 0xff, 0xff,
+    ];
+    static REPR_PAYLOAD_BYTES: [u8; 12] = [
+        0x00, 0x01, 0x00, 0x02, 0x00, 0x0c, 0x02, 0x4e, 0xff, 0xff, 0xff, 0xff,
+    ];
 
     fn packet_repr() -> Repr {
         Repr {
-            src_addr:    Address([0xfe, 0x80, 0x00, 0x00,
-                                  0x00, 0x00, 0x00, 0x00,
-                                  0x00, 0x00, 0x00, 0x00,
-                                  0x00, 0x00, 0x00, 0x01]),
-            dst_addr:    Address::LINK_LOCAL_ALL_NODES,
+            src_addr: Address([
+                0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                0x00, 0x01,
+            ]),
+            dst_addr: Address::LINK_LOCAL_ALL_NODES,
             next_header: Protocol::Udp,
             payload_len: 12,
-            hop_limit:   64
+            hop_limit: 64,
         }
     }
 
@@ -948,10 +1041,13 @@ mod test {
         assert_eq!(packet.payload_len() as usize, REPR_PAYLOAD_BYTES.len());
         assert_eq!(packet.next_header(), Protocol::Udp);
         assert_eq!(packet.hop_limit(), 0x40);
-        assert_eq!(packet.src_addr(), Address([0xfe, 0x80, 0x00, 0x00,
-                                               0x00, 0x00, 0x00, 0x00,
-                                               0x00, 0x00, 0x00, 0x00,
-                                               0x00, 0x00, 0x00, 0x01]));
+        assert_eq!(
+            packet.src_addr(),
+            Address([
+                0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                0x00, 0x01
+            ])
+        );
         assert_eq!(packet.dst_addr(), Address::LINK_LOCAL_ALL_NODES);
         assert_eq!(packet.payload(), &REPR_PAYLOAD_BYTES[..]);
     }
@@ -976,15 +1072,14 @@ mod test {
         packet.set_hop_limit(0xfe);
         packet.set_src_addr(Address::LINK_LOCAL_ALL_ROUTERS);
         packet.set_dst_addr(Address::LINK_LOCAL_ALL_NODES);
-        packet.payload_mut().copy_from_slice(&REPR_PAYLOAD_BYTES[..]);
+        packet
+            .payload_mut()
+            .copy_from_slice(&REPR_PAYLOAD_BYTES[..]);
         let mut expected_bytes = [
-            0x69, 0x95, 0x43, 0x21, 0x00, 0x0c, 0x11, 0xfe,
-            0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
-            0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
-            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-            0x00, 0x00, 0x00, 0x00
+            0x69, 0x95, 0x43, 0x21, 0x00, 0x0c, 0x11, 0xfe, 0xff, 0x02, 0x00, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x02, 0x00, 0x00,
+            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
+            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
         ];
         let start = expected_bytes.len() - REPR_PAYLOAD_BYTES.len();
         expected_bytes[start..].copy_from_slice(&REPR_PAYLOAD_BYTES[..]);
@@ -998,10 +1093,14 @@ mod test {
         bytes.extend(&REPR_PACKET_BYTES[..]);
         bytes.push(0);
 
-        assert_eq!(Packet::new_unchecked(&bytes).payload().len(),
-                   REPR_PAYLOAD_BYTES.len());
-        assert_eq!(Packet::new_unchecked(&mut bytes).payload_mut().len(),
-                   REPR_PAYLOAD_BYTES.len());
+        assert_eq!(
+            Packet::new_unchecked(&bytes).payload().len(),
+            REPR_PAYLOAD_BYTES.len()
+        );
+        assert_eq!(
+            Packet::new_unchecked(&mut bytes).payload_mut().len(),
+            REPR_PAYLOAD_BYTES.len()
+        );
     }
 
     #[test]
@@ -1010,8 +1109,7 @@ mod test {
         bytes.extend(&REPR_PACKET_BYTES[..]);
         Packet::new_unchecked(&mut bytes).set_payload_len(0x80);
 
-        assert_eq!(Packet::new_checked(&bytes).unwrap_err(),
-                   Error::Truncated);
+        assert_eq!(Packet::new_checked(&bytes).unwrap_err(), Error::Truncated);
     }
 
     #[test]
@@ -1063,7 +1161,12 @@ mod test {
 
     #[test]
     fn test_pretty_print() {
-        assert_eq!(format!("{}", PrettyPrinter::<Packet<&'static [u8]>>::new("\n", &&REPR_PACKET_BYTES[..])),
-                   "\nIPv6 src=fe80::1 dst=ff02::1 nxt_hdr=UDP hop_limit=64\n \\ UDP src=1 dst=2 len=4");
+        assert_eq!(
+            format!(
+                "{}",
+                PrettyPrinter::<Packet<&'static [u8]>>::new("\n", &&REPR_PACKET_BYTES[..])
+            ),
+            "\nIPv6 src=fe80::1 dst=ff02::1 nxt_hdr=UDP hop_limit=64\n \\ UDP src=1 dst=2 len=4"
+        );
     }
 }

+ 56 - 25
src/wire/ipv6fragment.rs

@@ -1,5 +1,5 @@
-use core::fmt;
 use crate::{Error, Result};
+use core::fmt;
 
 use byteorder::{ByteOrder, NetworkEndian};
 
@@ -9,7 +9,7 @@ pub use super::IpProtocol as Protocol;
 #[derive(Debug, PartialEq)]
 #[cfg_attr(feature = "defmt", derive(defmt::Format))]
 pub struct Header<T: AsRef<[u8]>> {
-    buffer: T
+    buffer: T,
 }
 
 // Format of the Fragment Header
@@ -25,13 +25,13 @@ mod field {
     use crate::wire::field::*;
 
     // 8-bit identifier of the header immediately following this header.
-    pub const NXT_HDR:          usize = 0;
+    pub const NXT_HDR: usize = 0;
     // 8-bit reserved field.
-    pub const RESERVED:         usize = 1;
+    pub const RESERVED: usize = 1;
     // 16-bit field containing the fragment offset, reserved and more fragments values.
-    pub const FR_OF_M:          Field = 2..4;
+    pub const FR_OF_M: Field = 2..4;
     // 32-bit field identifying the fragmented packet
-    pub const IDENT:            Field = 4..8;
+    pub const IDENT: Field = 4..8;
 }
 
 impl<T: AsRef<[u8]>> Header<T> {
@@ -170,17 +170,19 @@ pub struct Repr {
     pub more_frags: bool,
     /// The identification for every packet that is fragmented.
     pub ident: u32,
-
 }
 
 impl Repr {
     /// Parse an IPv6 Fragment Header and return a high-level representation.
-    pub fn parse<T>(header: &Header<&T>) -> Result<Repr> where T: AsRef<[u8]> + ?Sized {
+    pub fn parse<T>(header: &Header<&T>) -> Result<Repr>
+    where
+        T: AsRef<[u8]> + ?Sized,
+    {
         Ok(Repr {
             next_header: header.next_header(),
             frag_offset: header.frag_offset(),
             more_frags: header.more_frags(),
-            ident: header.ident()
+            ident: header.ident(),
         })
     }
 
@@ -202,8 +204,11 @@ impl Repr {
 
 impl<'a> fmt::Display for Repr {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        write!(f, "IPv6 Fragment next_hdr={} offset={} more={} ident={}",
-               self.next_header, self.frag_offset, self.more_frags, self.ident)
+        write!(
+            f,
+            "IPv6 Fragment next_hdr={} offset={} more={} ident={}",
+            self.next_header, self.frag_offset, self.more_frags, self.ident
+        )
     }
 }
 
@@ -212,21 +217,23 @@ mod test {
     use super::*;
 
     // A Fragment Header with more fragments remaining
-    static BYTES_HEADER_MORE_FRAG: [u8; 8] = [0x6, 0x0, 0x0,  0x1,
-                                              0x0, 0x0, 0x30, 0x39];
+    static BYTES_HEADER_MORE_FRAG: [u8; 8] = [0x6, 0x0, 0x0, 0x1, 0x0, 0x0, 0x30, 0x39];
 
     // A Fragment Header with no more fragments remaining
-    static BYTES_HEADER_LAST_FRAG: [u8; 8] = [0x6, 0x0, 0xa, 0x0,
-                                              0x0, 0x1, 0x9, 0x32];
+    static BYTES_HEADER_LAST_FRAG: [u8; 8] = [0x6, 0x0, 0xa, 0x0, 0x0, 0x1, 0x9, 0x32];
 
     #[test]
     fn test_check_len() {
         // less than 8 bytes
-        assert_eq!(Err(Error::Truncated),
-                   Header::new_unchecked(&BYTES_HEADER_MORE_FRAG[..7]).check_len());
+        assert_eq!(
+            Err(Error::Truncated),
+            Header::new_unchecked(&BYTES_HEADER_MORE_FRAG[..7]).check_len()
+        );
         // valid
-        assert_eq!(Ok(()),
-                   Header::new_unchecked(&BYTES_HEADER_MORE_FRAG).check_len());
+        assert_eq!(
+            Ok(()),
+            Header::new_unchecked(&BYTES_HEADER_MORE_FRAG).check_len()
+        );
     }
 
     #[test]
@@ -248,24 +255,48 @@ mod test {
     fn test_repr_parse_valid() {
         let header = Header::new_unchecked(&BYTES_HEADER_MORE_FRAG);
         let repr = Repr::parse(&header).unwrap();
-        assert_eq!(repr,
-            Repr{ next_header: Protocol::Tcp, frag_offset: 0, more_frags: true, ident: 12345 });
+        assert_eq!(
+            repr,
+            Repr {
+                next_header: Protocol::Tcp,
+                frag_offset: 0,
+                more_frags: true,
+                ident: 12345
+            }
+        );
 
         let header = Header::new_unchecked(&BYTES_HEADER_LAST_FRAG);
         let repr = Repr::parse(&header).unwrap();
-        assert_eq!(repr,
-            Repr{ next_header: Protocol::Tcp, frag_offset: 320, more_frags: false, ident: 67890 });
+        assert_eq!(
+            repr,
+            Repr {
+                next_header: Protocol::Tcp,
+                frag_offset: 320,
+                more_frags: false,
+                ident: 67890
+            }
+        );
     }
 
     #[test]
     fn test_repr_emit() {
-        let repr = Repr{ next_header: Protocol::Tcp, frag_offset: 0, more_frags: true, ident: 12345 };
+        let repr = Repr {
+            next_header: Protocol::Tcp,
+            frag_offset: 0,
+            more_frags: true,
+            ident: 12345,
+        };
         let mut bytes = [0u8; 8];
         let mut header = Header::new_unchecked(&mut bytes);
         repr.emit(&mut header);
         assert_eq!(header.into_inner(), &BYTES_HEADER_MORE_FRAG[0..8]);
 
-        let repr = Repr{ next_header: Protocol::Tcp, frag_offset: 320, more_frags: false, ident: 67890 };
+        let repr = Repr {
+            next_header: Protocol::Tcp,
+            frag_offset: 320,
+            more_frags: false,
+            ident: 67890,
+        };
         let mut bytes = [0u8; 8];
         let mut header = Header::new_unchecked(&mut bytes);
         repr.emit(&mut header);

+ 86 - 46
src/wire/ipv6hopbyhop.rs

@@ -1,14 +1,14 @@
-use core::fmt;
 use crate::{Error, Result};
+use core::fmt;
 
-use crate::wire::ipv6option::Ipv6OptionsIterator;
 pub use super::IpProtocol as Protocol;
+use crate::wire::ipv6option::Ipv6OptionsIterator;
 
 /// 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<T: AsRef<[u8]>> {
-    buffer: T
+    buffer: T,
 }
 
 // Format of the Hop-by-Hop Options Header
@@ -31,13 +31,13 @@ mod field {
     use crate::wire::field::*;
 
     // Minimum size of the header.
-    pub const MIN_HEADER_SIZE:  usize = 8;
+    pub const MIN_HEADER_SIZE: usize = 8;
 
     // 8-bit identifier of the header immediately following this header.
-    pub const NXT_HDR:          usize = 0;
+    pub const NXT_HDR: usize = 0;
     // 8-bit unsigned integer. Length of the OPTIONS field in 8-octet units,
     // not including the first 8 octets.
-    pub const LENGTH:           usize = 1;
+    pub const LENGTH: usize = 1;
     // Variable-length field. Option-Type-specific data.
     //
     // Length of the header is in 8-octet units, not including the first 8 octets. The first two
@@ -111,7 +111,7 @@ impl<T: AsRef<[u8]>> Header<T> {
 impl<'a, T: AsRef<[u8]> + ?Sized> Header<&'a T> {
     /// Return the option data.
     #[inline]
-    pub fn options(&self) -> &'a[u8] {
+    pub fn options(&self) -> &'a [u8] {
         let data = self.buffer.as_ref();
         &data[field::OPTIONS(data[field::LENGTH])]
     }
@@ -163,18 +163,21 @@ pub struct Repr<'a> {
     /// The type of header immediately following the Hop-by-Hop Options header.
     pub next_header: Protocol,
     /// Length of the Hop-by-Hop Options header in 8-octet units, not including the first 8 octets.
-    pub length:      u8,
+    pub length: u8,
     /// The options contained in the Hop-by-Hop Options header.
-    pub options:     &'a [u8]
+    pub options: &'a [u8],
 }
 
 impl<'a> Repr<'a> {
     /// Parse an IPv6 Hop-by-Hop Options Header and return a high-level representation.
-    pub fn parse<T>(header: &Header<&'a T>) -> Result<Repr<'a>> where T: AsRef<[u8]> + ?Sized {
+    pub fn parse<T>(header: &Header<&'a T>) -> Result<Repr<'a>>
+    where
+        T: AsRef<[u8]> + ?Sized,
+    {
         Ok(Repr {
             next_header: header.next_header(),
             length: header.header_len(),
-            options: header.options()
+            options: header.options(),
         })
     }
 
@@ -199,7 +202,11 @@ impl<'a> Repr<'a> {
 
 impl<'a> fmt::Display for Repr<'a> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        write!(f, "IPv6 Hop-by-Hop Options next_hdr={} length={} ", self.next_header, self.length)
+        write!(
+            f,
+            "IPv6 Hop-by-Hop Options next_hdr={} length={} ",
+            self.next_header, self.length
+        )
     }
 }
 
@@ -208,36 +215,43 @@ mod test {
     use super::*;
 
     // A Hop-by-Hop Option header with a PadN option of option data length 4.
-    static REPR_PACKET_PAD4: [u8; 8] = [0x6, 0x0, 0x1, 0x4,
-                                        0x0, 0x0, 0x0, 0x0];
+    static REPR_PACKET_PAD4: [u8; 8] = [0x6, 0x0, 0x1, 0x4, 0x0, 0x0, 0x0, 0x0];
 
     // A Hop-by-Hop Option header with a PadN option of option data length 12.
-    static REPR_PACKET_PAD12: [u8; 16] = [0x06, 0x1, 0x1, 0x12,
-                                          0x0,  0x0, 0x0, 0x0,
-                                          0x0,  0x0, 0x0, 0x0,
-                                          0x0,  0x0, 0x0, 0x0];
+    static REPR_PACKET_PAD12: [u8; 16] = [
+        0x06, 0x1, 0x1, 0x12, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+    ];
 
     #[test]
     fn test_check_len() {
         // zero byte buffer
-        assert_eq!(Err(Error::Truncated),
-                   Header::new_unchecked(&REPR_PACKET_PAD4[..0]).check_len());
+        assert_eq!(
+            Err(Error::Truncated),
+            Header::new_unchecked(&REPR_PACKET_PAD4[..0]).check_len()
+        );
         // no length field
-        assert_eq!(Err(Error::Truncated),
-                   Header::new_unchecked(&REPR_PACKET_PAD4[..1]).check_len());
+        assert_eq!(
+            Err(Error::Truncated),
+            Header::new_unchecked(&REPR_PACKET_PAD4[..1]).check_len()
+        );
         // less than 8 bytes
-        assert_eq!(Err(Error::Truncated),
-                   Header::new_unchecked(&REPR_PACKET_PAD4[..7]).check_len());
+        assert_eq!(
+            Err(Error::Truncated),
+            Header::new_unchecked(&REPR_PACKET_PAD4[..7]).check_len()
+        );
         // valid
-        assert_eq!(Ok(()),
-                   Header::new_unchecked(&REPR_PACKET_PAD4).check_len());
+        assert_eq!(Ok(()), Header::new_unchecked(&REPR_PACKET_PAD4).check_len());
         // valid
-        assert_eq!(Ok(()),
-                   Header::new_unchecked(&REPR_PACKET_PAD12).check_len());
+        assert_eq!(
+            Ok(()),
+            Header::new_unchecked(&REPR_PACKET_PAD12).check_len()
+        );
         // length field value greater than number of bytes
         let header: [u8; 8] = [0x06, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0];
-        assert_eq!(Err(Error::Truncated),
-                   Header::new_unchecked(&header).check_len());
+        assert_eq!(
+            Err(Error::Truncated),
+            Header::new_unchecked(&header).check_len()
+        );
     }
 
     #[test]
@@ -259,19 +273,27 @@ mod test {
         bytes.extend(&REPR_PACKET_PAD4[..]);
         bytes.push(0);
 
-        assert_eq!(Header::new_unchecked(&bytes).options().len(),
-                   REPR_PACKET_PAD4[2..].len());
-        assert_eq!(Header::new_unchecked(&mut bytes).options_mut().len(),
-                   REPR_PACKET_PAD4[2..].len());
+        assert_eq!(
+            Header::new_unchecked(&bytes).options().len(),
+            REPR_PACKET_PAD4[2..].len()
+        );
+        assert_eq!(
+            Header::new_unchecked(&mut bytes).options_mut().len(),
+            REPR_PACKET_PAD4[2..].len()
+        );
 
         let mut bytes = vec![];
         bytes.extend(&REPR_PACKET_PAD12[..]);
         bytes.push(0);
 
-        assert_eq!(Header::new_unchecked(&bytes).options().len(),
-                   REPR_PACKET_PAD12[2..].len());
-        assert_eq!(Header::new_unchecked(&mut bytes).options_mut().len(),
-                   REPR_PACKET_PAD12[2..].len());
+        assert_eq!(
+            Header::new_unchecked(&bytes).options().len(),
+            REPR_PACKET_PAD12[2..].len()
+        );
+        assert_eq!(
+            Header::new_unchecked(&mut bytes).options_mut().len(),
+            REPR_PACKET_PAD12[2..].len()
+        );
     }
 
     #[test]
@@ -295,26 +317,44 @@ mod test {
     fn test_repr_parse_valid() {
         let header = Header::new_unchecked(&REPR_PACKET_PAD4);
         let repr = Repr::parse(&header).unwrap();
-        assert_eq!(repr, Repr {
-            next_header: Protocol::Tcp, length: 0, options: &REPR_PACKET_PAD4[2..]
-        });
+        assert_eq!(
+            repr,
+            Repr {
+                next_header: Protocol::Tcp,
+                length: 0,
+                options: &REPR_PACKET_PAD4[2..]
+            }
+        );
 
         let header = Header::new_unchecked(&REPR_PACKET_PAD12);
         let repr = Repr::parse(&header).unwrap();
-        assert_eq!(repr, Repr {
-            next_header: Protocol::Tcp, length: 1, options: &REPR_PACKET_PAD12[2..]
-        });
+        assert_eq!(
+            repr,
+            Repr {
+                next_header: Protocol::Tcp,
+                length: 1,
+                options: &REPR_PACKET_PAD12[2..]
+            }
+        );
     }
 
     #[test]
     fn test_repr_emit() {
-        let repr = Repr{ next_header: Protocol::Tcp, length: 0, options: &REPR_PACKET_PAD4[2..] };
+        let repr = Repr {
+            next_header: Protocol::Tcp,
+            length: 0,
+            options: &REPR_PACKET_PAD4[2..],
+        };
         let mut bytes = [0u8; 8];
         let mut header = Header::new_unchecked(&mut bytes);
         repr.emit(&mut header);
         assert_eq!(header.into_inner(), &REPR_PACKET_PAD4[..]);
 
-        let repr = Repr{ next_header: Protocol::Tcp, length: 1, options: &REPR_PACKET_PAD12[2..] };
+        let repr = Repr {
+            next_header: Protocol::Tcp,
+            length: 1,
+            options: &REPR_PACKET_PAD12[2..],
+        };
         let mut bytes = [0u8; 16];
         let mut header = Header::new_unchecked(&mut bytes);
         repr.emit(&mut header);

+ 105 - 78
src/wire/ipv6option.rs

@@ -1,5 +1,5 @@
-use core::fmt;
 use crate::{Error, Result};
+use core::fmt;
 
 enum_with_unknown! {
     /// IPv6 Extension Header Option Type
@@ -14,9 +14,9 @@ enum_with_unknown! {
 impl fmt::Display for Type {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match *self {
-            Type::Pad1        => write!(f, "Pad1"),
-            Type::PadN        => write!(f, "PadN"),
-            Type::Unknown(id) => write!(f, "{}", id)
+            Type::Pad1 => write!(f, "Pad1"),
+            Type::PadN => write!(f, "PadN"),
+            Type::Unknown(id) => write!(f, "{}", id),
         }
     }
 }
@@ -40,11 +40,11 @@ enum_with_unknown! {
 impl fmt::Display for FailureType {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match *self {
-            FailureType::Skip               => write!(f, "skip"),
-            FailureType::Discard            => write!(f, "discard"),
-            FailureType::DiscardSendAll     => write!(f, "discard and send error"),
+            FailureType::Skip => write!(f, "skip"),
+            FailureType::Discard => write!(f, "discard"),
+            FailureType::DiscardSendAll => write!(f, "discard and send error"),
             FailureType::DiscardSendUnicast => write!(f, "discard and send error if unicast"),
-            FailureType::Unknown(id)        => write!(f, "Unknown({})", id),
+            FailureType::Unknown(id) => write!(f, "Unknown({})", id),
         }
     }
 }
@@ -60,7 +60,7 @@ impl From<Type> for FailureType {
 #[derive(Debug, PartialEq)]
 #[cfg_attr(feature = "defmt", derive(defmt::Format))]
 pub struct Ipv6Option<T: AsRef<[u8]>> {
-    buffer: T
+    buffer: T,
 }
 
 // Format of Option
@@ -77,9 +77,9 @@ mod field {
     use crate::wire::field::*;
 
     // 8-bit identifier of the type of option.
-    pub const TYPE:     usize = 0;
+    pub const TYPE: usize = 0;
     // 8-bit unsigned integer. Length of the DATA field of this option, in octets.
-    pub const LENGTH:   usize = 1;
+    pub const LENGTH: usize = 1;
     // Variable-length field. Option-Type-specific data.
     pub fn DATA(length: u8) -> Field {
         2..length as usize + 2
@@ -221,27 +221,26 @@ pub enum Repr<'a> {
     Pad1,
     PadN(u8),
     Unknown {
-        type_:  Type,
+        type_: Type,
         length: u8,
-        data:   &'a [u8]
+        data: &'a [u8],
     },
 }
 
 impl<'a> Repr<'a> {
     /// Parse an IPv6 Extension Header Option and return a high-level representation.
-    pub fn parse<T>(opt: &Ipv6Option<&'a T>) -> Result<Repr<'a>> where T: AsRef<[u8]> + ?Sized {
+    pub fn parse<T>(opt: &Ipv6Option<&'a T>) -> Result<Repr<'a>>
+    where
+        T: AsRef<[u8]> + ?Sized,
+    {
         match opt.option_type() {
-            Type::Pad1 =>
-                Ok(Repr::Pad1),
-            Type::PadN =>
-                Ok(Repr::PadN(opt.data_len())),
-            unknown_type @ Type::Unknown(_) => {
-                Ok(Repr::Unknown {
-                    type_:  unknown_type,
-                    length: opt.data_len(),
-                    data:   opt.data(),
-                })
-            }
+            Type::Pad1 => Ok(Repr::Pad1),
+            Type::PadN => Ok(Repr::PadN(opt.data_len())),
+            unknown_type @ Type::Unknown(_) => Ok(Repr::Unknown {
+                type_: unknown_type,
+                length: opt.data_len(),
+                data: opt.data(),
+            }),
         }
     }
 
@@ -249,18 +248,15 @@ impl<'a> Repr<'a> {
     pub fn buffer_len(&self) -> usize {
         match *self {
             Repr::Pad1 => 1,
-            Repr::PadN(length) =>
-               field::DATA(length).end,
-            Repr::Unknown{ length, .. } =>
-               field::DATA(length).end,
+            Repr::PadN(length) => field::DATA(length).end,
+            Repr::Unknown { length, .. } => field::DATA(length).end,
         }
     }
 
     /// Emit a high-level representation into an IPv6 Extension Header Option.
     pub fn emit<T: AsRef<[u8]> + AsMut<[u8]> + ?Sized>(&self, opt: &mut Ipv6Option<&'a mut T>) {
         match *self {
-            Repr::Pad1 =>
-                opt.set_option_type(Type::Pad1),
+            Repr::Pad1 => opt.set_option_type(Type::Pad1),
             Repr::PadN(len) => {
                 opt.set_option_type(Type::PadN);
                 opt.set_data_len(len);
@@ -269,7 +265,11 @@ impl<'a> Repr<'a> {
                     *x = 0
                 }
             }
-            Repr::Unknown{ type_, length, data } => {
+            Repr::Unknown {
+                type_,
+                length,
+                data,
+            } => {
                 opt.set_option_type(type_);
                 opt.set_data_len(length);
                 opt.data_mut().copy_from_slice(&data[..length as usize]);
@@ -285,7 +285,7 @@ pub struct Ipv6OptionsIterator<'a> {
     pos: usize,
     length: usize,
     data: &'a [u8],
-    hit_error: bool
+    hit_error: bool,
 }
 
 impl<'a> Ipv6OptionsIterator<'a> {
@@ -301,7 +301,8 @@ impl<'a> Ipv6OptionsIterator<'a> {
         Ipv6OptionsIterator {
             pos: 0,
             hit_error: false,
-            length, data
+            length,
+            data,
         }
     }
 }
@@ -314,18 +315,16 @@ impl<'a> Iterator for Ipv6OptionsIterator<'a> {
             // If we still have data to parse and we have not previously
             // hit an error, attempt to parse the next option.
             match Ipv6Option::new_checked(&self.data[self.pos..]) {
-                Ok(hdr) => {
-                    match Repr::parse(&hdr) {
-                        Ok(repr) => {
-                            self.pos += repr.buffer_len();
-                            Some(Ok(repr))
-                        }
-                        Err(e) => {
-                            self.hit_error = true;
-                            Some(Err(e))
-                        }
+                Ok(hdr) => match Repr::parse(&hdr) {
+                    Ok(repr) => {
+                        self.pos += repr.buffer_len();
+                        Some(Ok(repr))
                     }
-                }
+                    Err(e) => {
+                        self.hit_error = true;
+                        Some(Err(e))
+                    }
+                },
                 Err(e) => {
                     self.hit_error = true;
                     Some(Err(e))
@@ -343,12 +342,9 @@ impl<'a> fmt::Display for Repr<'a> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         write!(f, "IPv6 Option ")?;
         match *self {
-            Repr::Pad1 =>
-               write!(f, "{} ", Type::Pad1),
-            Repr::PadN(len) =>
-               write!(f, "{} length={} ", Type::PadN, len),
-            Repr::Unknown{ type_, length, .. } =>
-               write!(f, "{} length={} ", type_, length),
+            Repr::Pad1 => write!(f, "{} ", Type::Pad1),
+            Repr::PadN(len) => write!(f, "{} length={} ", Type::PadN, len),
+            Repr::Unknown { type_, length, .. } => write!(f, "{} length={} ", type_, length),
         }
     }
 }
@@ -357,35 +353,49 @@ impl<'a> fmt::Display for Repr<'a> {
 mod test {
     use super::*;
 
-    static IPV6OPTION_BYTES_PAD1:    [u8; 1] = [0x0];
-    static IPV6OPTION_BYTES_PADN:    [u8; 3] = [0x1, 0x1, 0x0];
+    static IPV6OPTION_BYTES_PAD1: [u8; 1] = [0x0];
+    static IPV6OPTION_BYTES_PADN: [u8; 3] = [0x1, 0x1, 0x0];
     static IPV6OPTION_BYTES_UNKNOWN: [u8; 5] = [0xff, 0x3, 0x0, 0x0, 0x0];
 
     #[test]
     fn test_check_len() {
         let bytes = [0u8];
         // zero byte buffer
-        assert_eq!(Err(Error::Truncated),
-                   Ipv6Option::new_unchecked(&bytes[..0]).check_len());
+        assert_eq!(
+            Err(Error::Truncated),
+            Ipv6Option::new_unchecked(&bytes[..0]).check_len()
+        );
         // pad1
-        assert_eq!(Ok(()),
-                   Ipv6Option::new_unchecked(&IPV6OPTION_BYTES_PAD1).check_len());
+        assert_eq!(
+            Ok(()),
+            Ipv6Option::new_unchecked(&IPV6OPTION_BYTES_PAD1).check_len()
+        );
 
         // padn with truncated data
-        assert_eq!(Err(Error::Truncated),
-                   Ipv6Option::new_unchecked(&IPV6OPTION_BYTES_PADN[..2]).check_len());
+        assert_eq!(
+            Err(Error::Truncated),
+            Ipv6Option::new_unchecked(&IPV6OPTION_BYTES_PADN[..2]).check_len()
+        );
         // padn
-        assert_eq!(Ok(()),
-                   Ipv6Option::new_unchecked(&IPV6OPTION_BYTES_PADN).check_len());
+        assert_eq!(
+            Ok(()),
+            Ipv6Option::new_unchecked(&IPV6OPTION_BYTES_PADN).check_len()
+        );
 
         // unknown option type with truncated data
-        assert_eq!(Err(Error::Truncated),
-                   Ipv6Option::new_unchecked(&IPV6OPTION_BYTES_UNKNOWN[..4]).check_len());
-        assert_eq!(Err(Error::Truncated),
-                   Ipv6Option::new_unchecked(&IPV6OPTION_BYTES_UNKNOWN[..1]).check_len());
+        assert_eq!(
+            Err(Error::Truncated),
+            Ipv6Option::new_unchecked(&IPV6OPTION_BYTES_UNKNOWN[..4]).check_len()
+        );
+        assert_eq!(
+            Err(Error::Truncated),
+            Ipv6Option::new_unchecked(&IPV6OPTION_BYTES_UNKNOWN[..1]).check_len()
+        );
         // unknown type
-        assert_eq!(Ok(()),
-                   Ipv6Option::new_unchecked(&IPV6OPTION_BYTES_UNKNOWN).check_len());
+        assert_eq!(
+            Ok(()),
+            Ipv6Option::new_unchecked(&IPV6OPTION_BYTES_UNKNOWN).check_len()
+        );
     }
 
     #[test]
@@ -402,7 +412,7 @@ mod test {
         assert_eq!(opt.option_type(), Type::Pad1);
 
         // two octets of padding
-        let bytes:  [u8; 2] = [0x1, 0x0];
+        let bytes: [u8; 2] = [0x1, 0x0];
         let opt = Ipv6Option::new_unchecked(&bytes);
         assert_eq!(opt.option_type(), Type::PadN);
         assert_eq!(opt.data_len(), 0);
@@ -414,14 +424,14 @@ mod test {
         assert_eq!(opt.data(), &[0]);
 
         // extra bytes in buffer
-        let bytes:  [u8; 10] = [0x1, 0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff];
+        let bytes: [u8; 10] = [0x1, 0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff];
         let opt = Ipv6Option::new_unchecked(&bytes);
         assert_eq!(opt.option_type(), Type::PadN);
         assert_eq!(opt.data_len(), 7);
         assert_eq!(opt.data(), &[0, 0, 0, 0, 0, 0, 0]);
 
         // unrecognized option
-        let bytes:  [u8; 1] = [0xff];
+        let bytes: [u8; 1] = [0xff];
         let opt = Ipv6Option::new_unchecked(&bytes);
         assert_eq!(opt.option_type(), Type::Unknown(255));
 
@@ -447,7 +457,14 @@ mod test {
         let data = [0u8; 3];
         let opt = Ipv6Option::new_unchecked(&IPV6OPTION_BYTES_UNKNOWN);
         let unknown = Repr::parse(&opt).unwrap();
-        assert_eq!(unknown, Repr::Unknown { type_: Type::Unknown(255), length: 3, data: &data });
+        assert_eq!(
+            unknown,
+            Repr::Unknown {
+                type_: Type::Unknown(255),
+                length: 3,
+                data: &data
+            }
+        );
     }
 
     #[test]
@@ -465,7 +482,11 @@ mod test {
         assert_eq!(opt.into_inner(), &IPV6OPTION_BYTES_PADN);
 
         let data = [0u8; 3];
-        let repr = Repr::Unknown { type_: Type::Unknown(255), length: 3, data: &data };
+        let repr = Repr::Unknown {
+            type_: Type::Unknown(255),
+            length: 3,
+            data: &data,
+        };
         let mut bytes = [254u8; 5]; // don't assume bytes are initialized to zero
         let mut opt = Ipv6Option::new_unchecked(&mut bytes);
         repr.emit(&mut opt);
@@ -488,10 +509,10 @@ mod test {
 
     #[test]
     fn test_options_iter() {
-        let options = [0x00, 0x01, 0x01, 0x00,
-                       0x01, 0x02, 0x00, 0x00,
-                       0x01, 0x00, 0x00, 0x11,
-                       0x00, 0x01, 0x08, 0x00];
+        let options = [
+            0x00, 0x01, 0x01, 0x00, 0x01, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x11, 0x00, 0x01,
+            0x08, 0x00,
+        ];
 
         let mut iterator = Ipv6OptionsIterator::new(&options, 0);
         assert_eq!(iterator.next(), None);
@@ -504,8 +525,14 @@ mod test {
                 (2, Ok(Repr::PadN(2))) => continue,
                 (3, Ok(Repr::PadN(0))) => continue,
                 (4, Ok(Repr::Pad1)) => continue,
-                (5, Ok(Repr::Unknown { type_: Type::Unknown(0x11), length: 0, .. })) =>
-                    continue,
+                (
+                    5,
+                    Ok(Repr::Unknown {
+                        type_: Type::Unknown(0x11),
+                        length: 0,
+                        ..
+                    }),
+                ) => continue,
                 (6, Err(Error::Truncated)) => continue,
                 (i, res) => panic!("Unexpected option `{:?}` at index {}", res, i),
             }

+ 129 - 96
src/wire/ipv6routing.rs

@@ -1,5 +1,5 @@
-use core::fmt;
 use crate::{Error, Result};
+use core::fmt;
 
 use crate::wire::IpProtocol as Protocol;
 use crate::wire::Ipv6Address as Address;
@@ -37,14 +37,14 @@ enum_with_unknown! {
 impl fmt::Display for Type {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match *self {
-            Type::Type0            => write!(f, "Type0"),
-            Type::Nimrod           => write!(f, "Nimrod"),
-            Type::Type2            => write!(f, "Type2"),
-            Type::Rpl              => write!(f, "Rpl"),
-            Type::Experiment1      => write!(f, "Experiment1"),
-            Type::Experiment2      => write!(f, "Experiment2"),
-            Type::Reserved         => write!(f, "Reserved"),
-            Type::Unknown(id)      => write!(f, "{}", id)
+            Type::Type0 => write!(f, "Type0"),
+            Type::Nimrod => write!(f, "Nimrod"),
+            Type::Type2 => write!(f, "Type2"),
+            Type::Rpl => write!(f, "Rpl"),
+            Type::Experiment1 => write!(f, "Experiment1"),
+            Type::Experiment2 => write!(f, "Experiment2"),
+            Type::Reserved => write!(f, "Reserved"),
+            Type::Unknown(id) => write!(f, "{}", id),
         }
     }
 }
@@ -53,7 +53,7 @@ impl fmt::Display for Type {
 #[derive(Debug, PartialEq)]
 #[cfg_attr(feature = "defmt", derive(defmt::Format))]
 pub struct Header<T: AsRef<[u8]>> {
-    buffer: T
+    buffer: T,
 }
 
 // Format of the Routing Header
@@ -76,15 +76,15 @@ mod field {
     use crate::wire::field::*;
 
     // Minimum size of the header.
-    pub const MIN_HEADER_SIZE:  usize = 4;
+    pub const MIN_HEADER_SIZE: usize = 4;
 
     // 8-bit identifier of the header immediately following this header.
-    pub const NXT_HDR:  usize = 0;
+    pub const NXT_HDR: usize = 0;
     // 8-bit unsigned integer. Length of the DATA field in 8-octet units,
     // not including the first 8 octets.
-    pub const LENGTH:   usize = 1;
+    pub const LENGTH: usize = 1;
     // 8-bit identifier of a particular Routing header variant.
-    pub const TYPE:     usize = 2;
+    pub const TYPE: usize = 2;
     // 8-bit unsigned integer. The number of route segments remaining.
     pub const SEG_LEFT: usize = 3;
     // Variable-length field. Routing-Type-specific data.
@@ -130,9 +130,9 @@ mod field {
     // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 
     // 8-bit field containing the CmprI and CmprE values.
-    pub const CMPR:  usize = 4;
+    pub const CMPR: usize = 4;
     // 8-bit field containing the Pad value.
-    pub const PAD:   usize = 5;
+    pub const PAD: usize = 5;
     // Variable length field containing addresses
     pub fn ADDRESSES(length_field: u8) -> Field {
         let data = DATA(length_field);
@@ -234,7 +234,6 @@ impl<T: AsRef<[u8]>> Header<T> {
         data[field::CMPR] >> 4
     }
 
-
     /// Return the number of prefix octects elided from the last address (`addresses[n]`).
     ///
     /// # Panics
@@ -316,7 +315,7 @@ impl<T: AsRef<[u8]> + AsMut<[u8]>> Header<T> {
                 data[7] = 0;
             }
 
-            _ => panic!("Unrecognized routing type when clearing reserved fields.")
+            _ => panic!("Unrecognized routing type when clearing reserved fields."),
         }
     }
 }
@@ -395,59 +394,57 @@ impl<'a, T: AsRef<[u8]> + ?Sized> fmt::Display for Header<&'a T> {
 pub enum Repr<'a> {
     Type2 {
         /// The type of header immediately following the Routing header.
-        next_header:    Protocol,
+        next_header: Protocol,
         /// Length of the Routing header in 8-octet units, not including the first 8 octets.
-        length:         u8,
+        length: u8,
         /// Number of route segments remaining.
-        segments_left:  u8,
+        segments_left: u8,
         /// The home address of the destination mobile node.
         home_address: Address,
     },
     Rpl {
         /// The type of header immediately following the Routing header.
-        next_header:    Protocol,
+        next_header: Protocol,
         /// Length of the Routing header in 8-octet units, not including the first 8 octets.
-        length:         u8,
+        length: u8,
         /// Number of route segments remaining.
-        segments_left:  u8,
+        segments_left: u8,
         /// Number of prefix octets from each segment, except the last segment, that are elided.
-        cmpr_i:         u8,
+        cmpr_i: u8,
         /// Number of prefix octets from the last segment that are elided.
-        cmpr_e:         u8,
+        cmpr_e: u8,
         /// Number of octets that are used for padding after `address[n]` at the end of the
         /// RPL Source Route Header.
-        pad:            u8,
+        pad: u8,
         /// Vector of addresses, numbered 1 to `n`.
-        addresses:      &'a[u8],
+        addresses: &'a [u8],
     },
 }
 
-
 impl<'a> Repr<'a> {
     /// Parse an IPv6 Routing Header and return a high-level representation.
-    pub fn parse<T>(header: &'a Header<&'a T>) -> Result<Repr<'a>> where T: AsRef<[u8]> + ?Sized {
+    pub fn parse<T>(header: &'a Header<&'a T>) -> Result<Repr<'a>>
+    where
+        T: AsRef<[u8]> + ?Sized,
+    {
         match header.routing_type() {
-            Type::Type2 => {
-                Ok(Repr::Type2 {
-                    next_header: header.next_header(),
-                    length: header.header_len(),
-                    segments_left: header.segments_left(),
-                    home_address: header.home_address(),
-                })
-            }
-            Type::Rpl => {
-                Ok(Repr::Rpl {
-                    next_header: header.next_header(),
-                    length: header.header_len(),
-                    segments_left: header.segments_left(),
-                    cmpr_i: header.cmpr_i(),
-                    cmpr_e: header.cmpr_e(),
-                    pad: header.pad(),
-                    addresses: header.addresses(),
-                })
-            }
-
-            _ => Err(Error::Unrecognized)
+            Type::Type2 => Ok(Repr::Type2 {
+                next_header: header.next_header(),
+                length: header.header_len(),
+                segments_left: header.segments_left(),
+                home_address: header.home_address(),
+            }),
+            Type::Rpl => Ok(Repr::Rpl {
+                next_header: header.next_header(),
+                length: header.header_len(),
+                segments_left: header.segments_left(),
+                cmpr_i: header.cmpr_i(),
+                cmpr_e: header.cmpr_e(),
+                pad: header.pad(),
+                addresses: header.addresses(),
+            }),
+
+            _ => Err(Error::Unrecognized),
         }
     }
 
@@ -455,16 +452,19 @@ impl<'a> Repr<'a> {
     /// representation.
     pub fn buffer_len(&self) -> usize {
         match self {
-            &Repr::Rpl { length, .. } | &Repr::Type2 { length, .. } => {
-                field::DATA(length).end
-            }
+            &Repr::Rpl { length, .. } | &Repr::Type2 { length, .. } => field::DATA(length).end,
         }
     }
 
     /// Emit a high-level representation into an IPv6 Routing Header.
     pub fn emit<T: AsRef<[u8]> + AsMut<[u8]> + ?Sized>(&self, header: &mut Header<&mut T>) {
         match *self {
-            Repr::Type2 { next_header, length, segments_left, home_address } => {
+            Repr::Type2 {
+                next_header,
+                length,
+                segments_left,
+                home_address,
+            } => {
                 header.set_next_header(next_header);
                 header.set_header_len(length);
                 header.set_routing_type(Type::Type2);
@@ -472,7 +472,15 @@ impl<'a> Repr<'a> {
                 header.clear_reserved();
                 header.set_home_address(home_address);
             }
-            Repr::Rpl { next_header, length, segments_left, cmpr_i, cmpr_e, pad, addresses } => {
+            Repr::Rpl {
+                next_header,
+                length,
+                segments_left,
+                cmpr_i,
+                cmpr_e,
+                pad,
+                addresses,
+            } => {
                 header.set_next_header(next_header);
                 header.set_header_len(length);
                 header.set_routing_type(Type::Rpl);
@@ -490,11 +498,31 @@ impl<'a> Repr<'a> {
 impl<'a> fmt::Display for Repr<'a> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match *self {
-            Repr::Type2 { next_header, length, segments_left, home_address } => {
-                write!(f, "IPv6 Routing next_hdr={} length={} type={} seg_left={} home_address={}",
-                       next_header, length, Type::Type2, segments_left, home_address)
+            Repr::Type2 {
+                next_header,
+                length,
+                segments_left,
+                home_address,
+            } => {
+                write!(
+                    f,
+                    "IPv6 Routing next_hdr={} length={} type={} seg_left={} home_address={}",
+                    next_header,
+                    length,
+                    Type::Type2,
+                    segments_left,
+                    home_address
+                )
             }
-            Repr::Rpl { next_header, length, segments_left, cmpr_i, cmpr_e, pad, .. } => {
+            Repr::Rpl {
+                next_header,
+                length,
+                segments_left,
+                cmpr_i,
+                cmpr_e,
+                pad,
+                ..
+            } => {
                 write!(f, "IPv6 Routing next_hdr={} length={} type={} seg_left={} cmpr_i={} cmpr_e={} pad={}",
                        next_header, length, Type::Rpl, segments_left, cmpr_i, cmpr_e, pad)
             }
@@ -507,12 +535,10 @@ mod test {
     use super::*;
 
     // A Type 2 Routing Header
-    static BYTES_TYPE2: [u8; 24] = [0x6, 0x2, 0x2, 0x1,
-                                    0x0, 0x0, 0x0, 0x0,
-                                    0x0, 0x0, 0x0, 0x0,
-                                    0x0, 0x0, 0x0, 0x0,
-                                    0x0, 0x0, 0x0, 0x0,
-                                    0x0, 0x0, 0x0, 0x1];
+    static BYTES_TYPE2: [u8; 24] = [
+        0x6, 0x2, 0x2, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+        0x0, 0x0, 0x0, 0x0, 0x0, 0x1,
+    ];
 
     // A representation of a Type 2 Routing header
     static REPR_TYPE2: Repr = Repr::Type2 {
@@ -523,16 +549,11 @@ mod test {
     };
 
     // A Source Routing Header with full IPv6 addresses in bytes
-    static BYTES_SRH_FULL: [u8; 40] = [0x6,  0x4, 0x3, 0x2,
-                                       0x0,  0x0, 0x0, 0x0,
-                                       0xfd, 0x0, 0x0, 0x0,
-                                       0x0,  0x0, 0x0, 0x0,
-                                       0x0,  0x0, 0x0, 0x0,
-                                       0x0,  0x0, 0x0, 0x2,
-                                       0xfd, 0x0, 0x0, 0x0,
-                                       0x0,  0x0, 0x0, 0x0,
-                                       0x0,  0x0, 0x0, 0x0,
-                                       0x0,  0x0, 0x3, 0x1];
+    static BYTES_SRH_FULL: [u8; 40] = [
+        0x6, 0x4, 0x3, 0x2, 0x0, 0x0, 0x0, 0x0, 0xfd, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+        0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0xfd, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+        0x0, 0x0, 0x3, 0x1,
+    ];
 
     // A representation of a Source Routing Header with full IPv6 addresses
     static REPR_SRH_FULL: Repr = Repr::Rpl {
@@ -542,21 +563,16 @@ mod test {
         cmpr_i: 0,
         cmpr_e: 0,
         pad: 0,
-        addresses: &[0xfd, 0x0, 0x0, 0x0,
-                     0x0,  0x0, 0x0, 0x0,
-                     0x0,  0x0, 0x0, 0x0,
-                     0x0,  0x0, 0x0, 0x2,
-                     0xfd, 0x0, 0x0, 0x0,
-                     0x0,  0x0, 0x0, 0x0,
-                     0x0,  0x0, 0x0, 0x0,
-                     0x0,  0x0, 0x3, 0x1]
+        addresses: &[
+            0xfd, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0xfd,
+            0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0x1,
+        ],
     };
 
     // A Source Routing Header with elided IPv6 addresses in bytes
-    static BYTES_SRH_ELIDED: [u8; 16] = [0x6,  0x1,  0x3,  0x2,
-                                         0xfe, 0x50, 0x0,  0x0,
-                                         0x2,  0x3,  0x1,  0x0,
-                                         0x0,  0x0,  0x0,  0x0];
+    static BYTES_SRH_ELIDED: [u8; 16] = [
+        0x6, 0x1, 0x3, 0x2, 0xfe, 0x50, 0x0, 0x0, 0x2, 0x3, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0,
+    ];
 
     // A representation of a Source Routing Header with elided IPv6 addresses
     static REPR_SRH_ELIDED: Repr = Repr::Rpl {
@@ -566,20 +582,37 @@ mod test {
         cmpr_i: 15,
         cmpr_e: 14,
         pad: 5,
-        addresses: &[0x2, 0x3, 0x1, 0x0,
-                     0x0, 0x0, 0x0, 0x0]
+        addresses: &[0x2, 0x3, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0],
     };
 
     #[test]
     fn test_check_len() {
         // less than min header size
-        assert_eq!(Err(Error::Truncated), Header::new(&BYTES_TYPE2[..3]).check_len());
-        assert_eq!(Err(Error::Truncated), Header::new(&BYTES_SRH_FULL[..3]).check_len());
-        assert_eq!(Err(Error::Truncated), Header::new(&BYTES_SRH_ELIDED[..3]).check_len());
+        assert_eq!(
+            Err(Error::Truncated),
+            Header::new(&BYTES_TYPE2[..3]).check_len()
+        );
+        assert_eq!(
+            Err(Error::Truncated),
+            Header::new(&BYTES_SRH_FULL[..3]).check_len()
+        );
+        assert_eq!(
+            Err(Error::Truncated),
+            Header::new(&BYTES_SRH_ELIDED[..3]).check_len()
+        );
         // less than specfied length field
-        assert_eq!(Err(Error::Truncated), Header::new(&BYTES_TYPE2[..23]).check_len());
-        assert_eq!(Err(Error::Truncated), Header::new(&BYTES_SRH_FULL[..39]).check_len());
-        assert_eq!(Err(Error::Truncated), Header::new(&BYTES_SRH_ELIDED[..11]).check_len());
+        assert_eq!(
+            Err(Error::Truncated),
+            Header::new(&BYTES_TYPE2[..23]).check_len()
+        );
+        assert_eq!(
+            Err(Error::Truncated),
+            Header::new(&BYTES_SRH_FULL[..39]).check_len()
+        );
+        assert_eq!(
+            Err(Error::Truncated),
+            Header::new(&BYTES_SRH_ELIDED[..11]).check_len()
+        );
         // valid
         assert_eq!(Ok(()), Header::new(&BYTES_TYPE2[..]).check_len());
         assert_eq!(Ok(()), Header::new(&BYTES_SRH_FULL[..]).check_len());

+ 123 - 123
src/wire/mld.rs

@@ -6,9 +6,9 @@
 
 use byteorder::{ByteOrder, NetworkEndian};
 
-use crate::{Error, Result};
 use crate::wire::icmpv6::{field, Message, Packet};
 use crate::wire::Ipv6Address;
+use crate::{Error, Result};
 
 enum_with_unknown! {
     /// MLDv2 Multicast Listener Report Record Type. See [RFC 3810 § 5.2.12] for
@@ -168,7 +168,7 @@ impl<T: AsRef<[u8]> + AsMut<[u8]>> Packet<T> {
 #[derive(Debug, PartialEq, Clone)]
 #[cfg_attr(feature = "defmt", derive(defmt::Format))]
 pub struct AddressRecord<T: AsRef<[u8]>> {
-    buffer: T
+    buffer: T,
 }
 
 impl<T: AsRef<[u8]>> AddressRecord<T> {
@@ -305,58 +305,61 @@ pub enum Repr<'a> {
         qrv: u8,
         qqic: u8,
         num_srcs: u16,
-        data: &'a [u8]
+        data: &'a [u8],
     },
     Report {
         nr_mcast_addr_rcrds: u16,
-        data: &'a [u8]
-    }
+        data: &'a [u8],
+    },
 }
 
 impl<'a> Repr<'a> {
     /// Parse an MLDv2 packet and return a high-level representation.
     pub fn parse<T>(packet: &Packet<&'a T>) -> Result<Repr<'a>>
-            where T: AsRef<[u8]> + ?Sized {
+    where
+        T: AsRef<[u8]> + ?Sized,
+    {
         match packet.msg_type() {
-            Message::MldQuery => {
-                Ok(Repr::Query {
-                    max_resp_code: packet.max_resp_code(),
-                    mcast_addr: packet.mcast_addr(),
-                    s_flag: packet.s_flag(),
-                    qrv: packet.qrv(),
-                    qqic: packet.qqic(),
-                    num_srcs: packet.num_srcs(),
-                    data: packet.payload()
-                })
-            },
-            Message::MldReport => {
-                Ok(Repr::Report {
-                    nr_mcast_addr_rcrds: packet.nr_mcast_addr_rcrds(),
-                    data: packet.payload()
-                })
-            },
-            _ => Err(Error::Unrecognized)
+            Message::MldQuery => Ok(Repr::Query {
+                max_resp_code: packet.max_resp_code(),
+                mcast_addr: packet.mcast_addr(),
+                s_flag: packet.s_flag(),
+                qrv: packet.qrv(),
+                qqic: packet.qqic(),
+                num_srcs: packet.num_srcs(),
+                data: packet.payload(),
+            }),
+            Message::MldReport => Ok(Repr::Report {
+                nr_mcast_addr_rcrds: packet.nr_mcast_addr_rcrds(),
+                data: packet.payload(),
+            }),
+            _ => Err(Error::Unrecognized),
         }
     }
 
     /// Return the length of a packet that will be emitted from this high-level representation.
     pub fn buffer_len(&self) -> usize {
         match self {
-            Repr::Query { .. } => {
-                field::QUERY_NUM_SRCS.end
-            }
-            Repr::Report { .. } => {
-                field::NR_MCAST_RCRDS.end
-            }
+            Repr::Query { .. } => field::QUERY_NUM_SRCS.end,
+            Repr::Report { .. } => field::NR_MCAST_RCRDS.end,
         }
     }
 
     /// Emit a high-level representation into an MLDv2 packet.
     pub fn emit<T>(&self, packet: &mut Packet<&mut T>)
-            where T: AsRef<[u8]> + AsMut<[u8]> + ?Sized {
+    where
+        T: AsRef<[u8]> + AsMut<[u8]> + ?Sized,
+    {
         match self {
-            Repr::Query { max_resp_code, mcast_addr, s_flag,
-                          qrv, qqic, num_srcs, data } => {
+            Repr::Query {
+                max_resp_code,
+                mcast_addr,
+                s_flag,
+                qrv,
+                qqic,
+                num_srcs,
+                data,
+            } => {
                 packet.set_msg_type(Message::MldQuery);
                 packet.set_msg_code(0);
                 packet.clear_reserved();
@@ -371,8 +374,11 @@ impl<'a> Repr<'a> {
                 packet.set_qqic(*qqic);
                 packet.set_num_srcs(*num_srcs);
                 packet.payload_mut().copy_from_slice(&data[..]);
-            },
-            Repr::Report { nr_mcast_addr_rcrds, data } => {
+            }
+            Repr::Report {
+                nr_mcast_addr_rcrds,
+                data,
+            } => {
                 packet.set_msg_type(Message::MldReport);
                 packet.set_msg_code(0);
                 packet.clear_reserved();
@@ -385,74 +391,49 @@ impl<'a> Repr<'a> {
 
 #[cfg(test)]
 mod test {
+    use super::*;
     use crate::phy::ChecksumCapabilities;
-    use crate::wire::Icmpv6Repr;
     use crate::wire::icmpv6::Message;
-    use super::*;
-
-    static QUERY_PACKET_BYTES: [u8; 44] =
-        [0x82, 0x00, 0x73, 0x74,
-         0x04, 0x00, 0x00, 0x00,
-         0xff, 0x02, 0x00, 0x00,
-         0x00, 0x00, 0x00, 0x00,
-         0x00, 0x00, 0x00, 0x00,
-         0x00, 0x00, 0x00, 0x01,
-         0x0a, 0x12, 0x00, 0x01,
-         0xff, 0x02, 0x00, 0x00,
-         0x00, 0x00, 0x00, 0x00,
-         0x00, 0x00, 0x00, 0x00,
-         0x00, 0x00, 0x00, 0x02];
-
-    static QUERY_PACKET_PAYLOAD: [u8; 16] =
-        [0xff, 0x02, 0x00, 0x00,
-         0x00, 0x00, 0x00, 0x00,
-         0x00, 0x00, 0x00, 0x00,
-         0x00, 0x00, 0x00, 0x02];
-
-    static REPORT_PACKET_BYTES: [u8; 44] =
-        [0x8f, 0x00, 0x73, 0x85,
-         0x00, 0x00, 0x00, 0x01,
-         0x01, 0x00, 0x00, 0x01,
-         0xff, 0x02, 0x00, 0x00,
-         0x00, 0x00, 0x00, 0x00,
-         0x00, 0x00, 0x00, 0x00,
-         0x00, 0x00, 0x00, 0x01,
-         0xff, 0x02, 0x00, 0x00,
-         0x00, 0x00, 0x00, 0x00,
-         0x00, 0x00, 0x00, 0x00,
-         0x00, 0x00, 0x00, 0x02];
-
-    static REPORT_PACKET_PAYLOAD: [u8; 36] =
-        [0x01, 0x00, 0x00, 0x01,
-         0xff, 0x02, 0x00, 0x00,
-         0x00, 0x00, 0x00, 0x00,
-         0x00, 0x00, 0x00, 0x00,
-         0x00, 0x00, 0x00, 0x01,
-         0xff, 0x02, 0x00, 0x00,
-         0x00, 0x00, 0x00, 0x00,
-         0x00, 0x00, 0x00, 0x00,
-         0x00, 0x00, 0x00, 0x02];
+    use crate::wire::Icmpv6Repr;
 
+    static QUERY_PACKET_BYTES: [u8; 44] = [
+        0x82, 0x00, 0x73, 0x74, 0x04, 0x00, 0x00, 0x00, 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x0a, 0x12, 0x00, 0x01, 0xff, 0x02,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+    ];
+
+    static QUERY_PACKET_PAYLOAD: [u8; 16] = [
+        0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x02,
+    ];
+
+    static REPORT_PACKET_BYTES: [u8; 44] = [
+        0x8f, 0x00, 0x73, 0x85, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0xff, 0x02, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0x02,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+    ];
+
+    static REPORT_PACKET_PAYLOAD: [u8; 36] = [
+        0x01, 0x00, 0x00, 0x01, 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+    ];
 
     fn create_repr<'a>(ty: Message) -> Icmpv6Repr<'a> {
         match ty {
-            Message::MldQuery => {
-                Icmpv6Repr::Mld(Repr::Query {
-                    max_resp_code: 0x400,
-                    mcast_addr: Ipv6Address::LINK_LOCAL_ALL_NODES,
-                    s_flag: true,
-                    qrv: 0x02,
-                    qqic: 0x12,
-                    num_srcs: 0x01,
-                    data: &QUERY_PACKET_PAYLOAD
-                })
-            },
-            Message::MldReport => {
-                Icmpv6Repr::Mld(Repr::Report {
-                    nr_mcast_addr_rcrds: 1,
-                    data: &REPORT_PACKET_PAYLOAD
-                })
-            },
+            Message::MldQuery => Icmpv6Repr::Mld(Repr::Query {
+                max_resp_code: 0x400,
+                mcast_addr: Ipv6Address::LINK_LOCAL_ALL_NODES,
+                s_flag: true,
+                qrv: 0x02,
+                qqic: 0x12,
+                num_srcs: 0x01,
+                data: &QUERY_PACKET_PAYLOAD,
+            }),
+            Message::MldReport => Icmpv6Repr::Mld(Repr::Report {
+                nr_mcast_addr_rcrds: 1,
+                data: &REPORT_PACKET_PAYLOAD,
+            }),
             _ => {
                 panic!("Message type must be a MLDv2 message type");
             }
@@ -471,8 +452,10 @@ mod test {
         assert_eq!(packet.qrv(), 0x02);
         assert_eq!(packet.qqic(), 0x12);
         assert_eq!(packet.num_srcs(), 0x01);
-        assert_eq!(Ipv6Address::from_bytes(packet.payload()),
-                   Ipv6Address::LINK_LOCAL_ALL_ROUTERS);
+        assert_eq!(
+            Ipv6Address::from_bytes(packet.payload()),
+            Ipv6Address::LINK_LOCAL_ALL_ROUTERS
+        );
     }
 
     #[test]
@@ -487,10 +470,14 @@ mod test {
         packet.set_qrv(0x02);
         packet.set_qqic(0x12);
         packet.set_num_srcs(0x01);
-        packet.payload_mut().copy_from_slice(Ipv6Address::LINK_LOCAL_ALL_ROUTERS.as_bytes());
+        packet
+            .payload_mut()
+            .copy_from_slice(Ipv6Address::LINK_LOCAL_ALL_ROUTERS.as_bytes());
         packet.clear_reserved();
-        packet.fill_checksum(&Ipv6Address::LINK_LOCAL_ALL_NODES.into(),
-                             &Ipv6Address::LINK_LOCAL_ALL_ROUTERS.into());
+        packet.fill_checksum(
+            &Ipv6Address::LINK_LOCAL_ALL_NODES.into(),
+            &Ipv6Address::LINK_LOCAL_ALL_ROUTERS.into(),
+        );
         assert_eq!(&packet.into_inner()[..], &QUERY_PACKET_BYTES[..]);
     }
 
@@ -506,8 +493,10 @@ mod test {
         assert_eq!(addr_rcrd.aux_data_len(), 0x00);
         assert_eq!(addr_rcrd.num_srcs(), 0x01);
         assert_eq!(addr_rcrd.mcast_addr(), Ipv6Address::LINK_LOCAL_ALL_NODES);
-        assert_eq!(Ipv6Address::from_bytes(addr_rcrd.payload()),
-                   Ipv6Address::LINK_LOCAL_ALL_ROUTERS);
+        assert_eq!(
+            Ipv6Address::from_bytes(addr_rcrd.payload()),
+            Ipv6Address::LINK_LOCAL_ALL_ROUTERS
+        );
     }
 
     #[test]
@@ -524,31 +513,38 @@ mod test {
             addr_rcrd.set_aux_data_len(0);
             addr_rcrd.set_num_srcs(1);
             addr_rcrd.set_mcast_addr(Ipv6Address::LINK_LOCAL_ALL_NODES);
-            addr_rcrd.payload_mut()
+            addr_rcrd
+                .payload_mut()
                 .copy_from_slice(Ipv6Address::LINK_LOCAL_ALL_ROUTERS.as_bytes());
         }
-        packet.fill_checksum(&Ipv6Address::LINK_LOCAL_ALL_NODES.into(),
-                             &Ipv6Address::LINK_LOCAL_ALL_ROUTERS.into());
+        packet.fill_checksum(
+            &Ipv6Address::LINK_LOCAL_ALL_NODES.into(),
+            &Ipv6Address::LINK_LOCAL_ALL_ROUTERS.into(),
+        );
         assert_eq!(&packet.into_inner()[..], &REPORT_PACKET_BYTES[..]);
     }
 
     #[test]
     fn test_query_repr_parse() {
         let packet = Packet::new_unchecked(&QUERY_PACKET_BYTES[..]);
-        let repr = Icmpv6Repr::parse(&Ipv6Address::LINK_LOCAL_ALL_NODES.into(),
-                                     &Ipv6Address::LINK_LOCAL_ALL_ROUTERS.into(),
-                                     &packet,
-                                     &ChecksumCapabilities::default());
+        let repr = Icmpv6Repr::parse(
+            &Ipv6Address::LINK_LOCAL_ALL_NODES.into(),
+            &Ipv6Address::LINK_LOCAL_ALL_ROUTERS.into(),
+            &packet,
+            &ChecksumCapabilities::default(),
+        );
         assert_eq!(repr, Ok(create_repr(Message::MldQuery)));
     }
 
     #[test]
     fn test_report_repr_parse() {
         let packet = Packet::new_unchecked(&REPORT_PACKET_BYTES[..]);
-        let repr = Icmpv6Repr::parse(&Ipv6Address::LINK_LOCAL_ALL_NODES.into(),
-                                     &Ipv6Address::LINK_LOCAL_ALL_ROUTERS.into(),
-                                     &packet,
-                                     &ChecksumCapabilities::default());
+        let repr = Icmpv6Repr::parse(
+            &Ipv6Address::LINK_LOCAL_ALL_NODES.into(),
+            &Ipv6Address::LINK_LOCAL_ALL_ROUTERS.into(),
+            &packet,
+            &ChecksumCapabilities::default(),
+        );
         assert_eq!(repr, Ok(create_repr(Message::MldReport)));
     }
 
@@ -557,10 +553,12 @@ mod test {
         let mut bytes = [0x2a; 44];
         let mut packet = Packet::new_unchecked(&mut bytes[..]);
         let repr = create_repr(Message::MldQuery);
-        repr.emit(&Ipv6Address::LINK_LOCAL_ALL_NODES.into(),
-                  &Ipv6Address::LINK_LOCAL_ALL_ROUTERS.into(),
-                  &mut packet,
-                  &ChecksumCapabilities::default());
+        repr.emit(
+            &Ipv6Address::LINK_LOCAL_ALL_NODES.into(),
+            &Ipv6Address::LINK_LOCAL_ALL_ROUTERS.into(),
+            &mut packet,
+            &ChecksumCapabilities::default(),
+        );
         assert_eq!(&packet.into_inner()[..], &QUERY_PACKET_BYTES[..]);
     }
 
@@ -569,10 +567,12 @@ mod test {
         let mut bytes = [0x2a; 44];
         let mut packet = Packet::new_unchecked(&mut bytes[..]);
         let repr = create_repr(Message::MldReport);
-        repr.emit(&Ipv6Address::LINK_LOCAL_ALL_NODES.into(),
-                  &Ipv6Address::LINK_LOCAL_ALL_ROUTERS.into(),
-                  &mut packet,
-                  &ChecksumCapabilities::default());
+        repr.emit(
+            &Ipv6Address::LINK_LOCAL_ALL_NODES.into(),
+            &Ipv6Address::LINK_LOCAL_ALL_ROUTERS.into(),
+            &mut packet,
+            &ChecksumCapabilities::default(),
+        );
         assert_eq!(&packet.into_inner()[..], &REPORT_PACKET_BYTES[..]);
     }
 }

+ 73 - 98
src/wire/mod.rs

@@ -72,161 +72,136 @@ let mut buffer = vec![0; repr.buffer_len() + repr.payload_len];
 
 mod field {
     pub type Field = ::core::ops::Range<usize>;
-    pub type Rest  = ::core::ops::RangeFrom<usize>;
+    pub type Rest = ::core::ops::RangeFrom<usize>;
 }
 
 pub mod pretty_print;
 
-#[cfg(feature = "medium-ethernet")]
-mod ethernet;
 #[cfg(all(feature = "proto-ipv4", feature = "medium-ethernet"))]
 mod arp;
+#[cfg(feature = "proto-dhcpv4")]
+pub(crate) mod dhcpv4;
+#[cfg(feature = "medium-ethernet")]
+mod ethernet;
+#[cfg(any(feature = "proto-ipv4", feature = "proto-ipv6"))]
+mod icmp;
+#[cfg(feature = "proto-ipv4")]
+mod icmpv4;
+#[cfg(feature = "proto-ipv6")]
+mod icmpv6;
+#[cfg(feature = "proto-igmp")]
+mod igmp;
 pub(crate) mod ip;
 #[cfg(feature = "proto-ipv4")]
 mod ipv4;
 #[cfg(feature = "proto-ipv6")]
 mod ipv6;
 #[cfg(feature = "proto-ipv6")]
-mod ipv6option;
+mod ipv6fragment;
 #[cfg(feature = "proto-ipv6")]
 mod ipv6hopbyhop;
 #[cfg(feature = "proto-ipv6")]
-mod ipv6fragment;
+mod ipv6option;
 #[cfg(feature = "proto-ipv6")]
 mod ipv6routing;
-#[cfg(feature = "proto-ipv4")]
-mod icmpv4;
 #[cfg(feature = "proto-ipv6")]
-mod icmpv6;
-#[cfg(any(feature = "proto-ipv4", feature = "proto-ipv6"))]
-mod icmp;
-#[cfg(feature = "proto-igmp")]
-mod igmp;
+mod mld;
 #[cfg(all(feature = "proto-ipv6", feature = "medium-ethernet"))]
 mod ndisc;
 #[cfg(all(feature = "proto-ipv6", feature = "medium-ethernet"))]
 mod ndiscoption;
-#[cfg(feature = "proto-ipv6")]
-mod mld;
-mod udp;
 mod tcp;
-#[cfg(feature = "proto-dhcpv4")]
-pub(crate) mod dhcpv4;
+mod udp;
 
 pub use self::pretty_print::PrettyPrinter;
 
 #[cfg(feature = "medium-ethernet")]
-pub use self::ethernet::{EtherType as EthernetProtocol,
-                         Address as EthernetAddress,
-                         Frame as EthernetFrame,
-                         HEADER_LEN as ETHERNET_HEADER_LEN,
-                         Repr as EthernetRepr};
+pub use self::ethernet::{
+    Address as EthernetAddress, EtherType as EthernetProtocol, Frame as EthernetFrame,
+    Repr as EthernetRepr, HEADER_LEN as ETHERNET_HEADER_LEN,
+};
 
 #[cfg(all(feature = "proto-ipv4", feature = "medium-ethernet"))]
-pub use self::arp::{Hardware as ArpHardware,
-                    Operation as ArpOperation,
-                    Packet as ArpPacket,
-                    Repr as ArpRepr};
-
-pub use self::ip::{Version as IpVersion,
-                   Protocol as IpProtocol,
-                   Address as IpAddress,
-                   Endpoint as IpEndpoint,
-                   Repr as IpRepr,
-                   Cidr as IpCidr};
+pub use self::arp::{
+    Hardware as ArpHardware, Operation as ArpOperation, Packet as ArpPacket, Repr as ArpRepr,
+};
+
+pub use self::ip::{
+    Address as IpAddress, Cidr as IpCidr, Endpoint as IpEndpoint, Protocol as IpProtocol,
+    Repr as IpRepr, Version as IpVersion,
+};
 
 #[cfg(feature = "proto-ipv4")]
-pub use self::ipv4::{Address as Ipv4Address,
-                     Packet as Ipv4Packet,
-                     Repr as Ipv4Repr,
-                     Cidr as Ipv4Cidr,
-                         HEADER_LEN as IPV4_HEADER_LEN,
-                         MIN_MTU as IPV4_MIN_MTU};
+pub use self::ipv4::{
+    Address as Ipv4Address, Cidr as Ipv4Cidr, Packet as Ipv4Packet, Repr as Ipv4Repr,
+    HEADER_LEN as IPV4_HEADER_LEN, MIN_MTU as IPV4_MIN_MTU,
+};
 
 #[cfg(feature = "proto-ipv6")]
-pub use self::ipv6::{Address as Ipv6Address,
-                     Packet as Ipv6Packet,
-                     Repr as Ipv6Repr,
-                     Cidr as Ipv6Cidr,
-                     HEADER_LEN as IPV6_HEADER_LEN,
-                     MIN_MTU as IPV6_MIN_MTU};
+pub use self::ipv6::{
+    Address as Ipv6Address, Cidr as Ipv6Cidr, Packet as Ipv6Packet, Repr as Ipv6Repr,
+    HEADER_LEN as IPV6_HEADER_LEN, MIN_MTU as IPV6_MIN_MTU,
+};
 
 #[cfg(feature = "proto-ipv6")]
-pub use self::ipv6option::{Ipv6Option,
-                           Repr as Ipv6OptionRepr,
-                           Type as Ipv6OptionType,
-                           FailureType as Ipv6OptionFailureType};
+pub use self::ipv6option::{
+    FailureType as Ipv6OptionFailureType, Ipv6Option, Repr as Ipv6OptionRepr,
+    Type as Ipv6OptionType,
+};
 
 #[cfg(feature = "proto-ipv6")]
-pub use self::ipv6hopbyhop::{Header as Ipv6HopByHopHeader,
-                             Repr as Ipv6HopByHopRepr};
+pub use self::ipv6hopbyhop::{Header as Ipv6HopByHopHeader, Repr as Ipv6HopByHopRepr};
 
 #[cfg(feature = "proto-ipv6")]
-pub use self::ipv6fragment::{Header as Ipv6FragmentHeader,
-                             Repr as Ipv6FragmentRepr};
+pub use self::ipv6fragment::{Header as Ipv6FragmentHeader, Repr as Ipv6FragmentRepr};
 
 #[cfg(feature = "proto-ipv6")]
-pub use self::ipv6routing::{Header as Ipv6RoutingHeader,
-                            Repr as Ipv6RoutingRepr};
+pub use self::ipv6routing::{Header as Ipv6RoutingHeader, Repr as Ipv6RoutingRepr};
 
 #[cfg(feature = "proto-ipv4")]
-pub use self::icmpv4::{Message as Icmpv4Message,
-                       DstUnreachable as Icmpv4DstUnreachable,
-                       Redirect as Icmpv4Redirect,
-                       TimeExceeded as Icmpv4TimeExceeded,
-                       ParamProblem as Icmpv4ParamProblem,
-                       Packet as Icmpv4Packet,
-                       Repr as Icmpv4Repr};
+pub use self::icmpv4::{
+    DstUnreachable as Icmpv4DstUnreachable, Message as Icmpv4Message, Packet as Icmpv4Packet,
+    ParamProblem as Icmpv4ParamProblem, Redirect as Icmpv4Redirect, Repr as Icmpv4Repr,
+    TimeExceeded as Icmpv4TimeExceeded,
+};
 
 #[cfg(feature = "proto-igmp")]
-pub use self::igmp::{Packet as IgmpPacket,
-                     Repr as IgmpRepr,
-                     IgmpVersion};
+pub use self::igmp::{IgmpVersion, Packet as IgmpPacket, Repr as IgmpRepr};
 
 #[cfg(feature = "proto-ipv6")]
-pub use self::icmpv6::{Message as Icmpv6Message,
-                       DstUnreachable as Icmpv6DstUnreachable,
-                       TimeExceeded as Icmpv6TimeExceeded,
-                       ParamProblem as Icmpv6ParamProblem,
-                       Packet as Icmpv6Packet,
-                       Repr as Icmpv6Repr};
+pub use self::icmpv6::{
+    DstUnreachable as Icmpv6DstUnreachable, Message as Icmpv6Message, Packet as Icmpv6Packet,
+    ParamProblem as Icmpv6ParamProblem, Repr as Icmpv6Repr, TimeExceeded as Icmpv6TimeExceeded,
+};
 
 #[cfg(any(feature = "proto-ipv4", feature = "proto-ipv6"))]
 pub use self::icmp::Repr as IcmpRepr;
 
-
 #[cfg(all(feature = "proto-ipv6", feature = "medium-ethernet"))]
-pub use self::ndisc::{Repr as NdiscRepr,
-                      RouterFlags as NdiscRouterFlags,
-                      NeighborFlags as NdiscNeighborFlags};
+pub use self::ndisc::{
+    NeighborFlags as NdiscNeighborFlags, Repr as NdiscRepr, RouterFlags as NdiscRouterFlags,
+};
 
 #[cfg(all(feature = "proto-ipv6", feature = "medium-ethernet"))]
-pub use self::ndiscoption::{NdiscOption,
-                            Repr as NdiscOptionRepr,
-                            Type as NdiscOptionType,
-                            PrefixInformation as NdiscPrefixInformation,
-                            RedirectedHeader as NdiscRedirectedHeader,
-                            PrefixInfoFlags as NdiscPrefixInfoFlags};
+pub use self::ndiscoption::{
+    NdiscOption, PrefixInfoFlags as NdiscPrefixInfoFlags,
+    PrefixInformation as NdiscPrefixInformation, RedirectedHeader as NdiscRedirectedHeader,
+    Repr as NdiscOptionRepr, Type as NdiscOptionType,
+};
 
 #[cfg(feature = "proto-ipv6")]
-pub use self::mld::{AddressRecord as MldAddressRecord,
-                    Repr as MldRepr};
+pub use self::mld::{AddressRecord as MldAddressRecord, Repr as MldRepr};
 
-pub use self::udp::{Packet as UdpPacket,
-                    Repr as UdpRepr,
-                    HEADER_LEN as UDP_HEADER_LEN};
+pub use self::udp::{Packet as UdpPacket, Repr as UdpRepr, HEADER_LEN as UDP_HEADER_LEN};
 
-pub use self::tcp::{SeqNumber as TcpSeqNumber,
-                    Packet as TcpPacket,
-                    TcpOption,
-                    Repr as TcpRepr,
-                    Control as TcpControl,
-                    HEADER_LEN as TCP_HEADER_LEN};
+pub use self::tcp::{
+    Control as TcpControl, Packet as TcpPacket, Repr as TcpRepr, SeqNumber as TcpSeqNumber,
+    TcpOption, HEADER_LEN as TCP_HEADER_LEN,
+};
 
 #[cfg(feature = "proto-dhcpv4")]
-pub use self::dhcpv4::{Packet as DhcpPacket,
-                       Repr as DhcpRepr,
-                       MessageType as DhcpMessageType,
-                       CLIENT_PORT as DHCP_CLIENT_PORT,
-                       SERVER_PORT as DHCP_SERVER_PORT,
-                       MAX_DNS_SERVER_COUNT as DHCP_MAX_DNS_SERVER_COUNT};
+pub use self::dhcpv4::{
+    MessageType as DhcpMessageType, Packet as DhcpPacket, Repr as DhcpRepr,
+    CLIENT_PORT as DHCP_CLIENT_PORT, MAX_DNS_SERVER_COUNT as DHCP_MAX_DNS_SERVER_COUNT,
+    SERVER_PORT as DHCP_SERVER_PORT,
+};

+ 129 - 81
src/wire/ndisc.rs

@@ -1,13 +1,13 @@
-use byteorder::{ByteOrder, NetworkEndian};
 use bitflags::bitflags;
+use byteorder::{ByteOrder, NetworkEndian};
 
-use crate::{Error, Result};
+use crate::time::Duration;
 use crate::wire::icmpv6::{field, Message, Packet};
-use crate::wire::{EthernetAddress, Ipv6Repr, Ipv6Packet};
+use crate::wire::Ipv6Address;
+use crate::wire::{EthernetAddress, Ipv6Packet, Ipv6Repr};
 use crate::wire::{NdiscOption, NdiscOptionRepr, NdiscOptionType};
 use crate::wire::{NdiscPrefixInformation, NdiscRedirectedHeader};
-use crate::time::Duration;
-use crate::wire::Ipv6Address;
+use crate::{Error, Result};
 
 bitflags! {
     #[cfg_attr(feature = "defmt", derive(defmt::Format))]
@@ -82,7 +82,6 @@ impl<T: AsRef<[u8]>> Packet<T> {
     }
 }
 
-
 /// Getters for the Neighbor Solicitation message header.
 /// See [RFC 4861 § 4.3].
 ///
@@ -194,7 +193,7 @@ impl<T: AsRef<[u8]> + AsMut<[u8]>> Packet<T> {
 #[cfg_attr(feature = "defmt", derive(defmt::Format))]
 pub enum Repr<'a> {
     RouterSolicit {
-        lladdr: Option<EthernetAddress>
+        lladdr: Option<EthernetAddress>,
     },
     RouterAdvert {
         hop_limit: u8,
@@ -204,44 +203,47 @@ pub enum Repr<'a> {
         retrans_time: Duration,
         lladdr: Option<EthernetAddress>,
         mtu: Option<u32>,
-        prefix_info: Option<NdiscPrefixInformation>
+        prefix_info: Option<NdiscPrefixInformation>,
     },
     NeighborSolicit {
         target_addr: Ipv6Address,
-        lladdr: Option<EthernetAddress>
+        lladdr: Option<EthernetAddress>,
     },
     NeighborAdvert {
         flags: NeighborFlags,
         target_addr: Ipv6Address,
-        lladdr: Option<EthernetAddress>
+        lladdr: Option<EthernetAddress>,
     },
     Redirect {
         target_addr: Ipv6Address,
         dest_addr: Ipv6Address,
         lladdr: Option<EthernetAddress>,
-        redirected_hdr: Option<NdiscRedirectedHeader<'a>>
-    }
+        redirected_hdr: Option<NdiscRedirectedHeader<'a>>,
+    },
 }
 
 impl<'a> Repr<'a> {
     /// Parse an NDISC packet and return a high-level representation of the
     /// packet.
-    pub fn parse<T>(packet: &Packet<&'a T>)
-                   -> Result<Repr<'a>>
-                where T: AsRef<[u8]> + ?Sized {
+    pub fn parse<T>(packet: &Packet<&'a T>) -> Result<Repr<'a>>
+    where
+        T: AsRef<[u8]> + ?Sized,
+    {
         match packet.msg_type() {
             Message::RouterSolicit => {
                 let lladdr = if !packet.payload().is_empty() {
                     let opt = NdiscOption::new_checked(packet.payload())?;
                     match opt.option_type() {
                         NdiscOptionType::SourceLinkLayerAddr => Some(opt.link_layer_addr()),
-                        _ => { return Err(Error::Unrecognized); }
+                        _ => {
+                            return Err(Error::Unrecognized);
+                        }
                     }
                 } else {
                     None
                 };
                 Ok(Repr::RouterSolicit { lladdr })
-            },
+            }
             Message::RouterAdvert => {
                 let mut offset = 0;
                 let (mut lladdr, mut mtu, mut prefix_info) = (None, None, None);
@@ -252,7 +254,9 @@ impl<'a> Repr<'a> {
                         NdiscOptionRepr::SourceLinkLayerAddr(addr) => lladdr = Some(addr),
                         NdiscOptionRepr::Mtu(val) => mtu = Some(val),
                         NdiscOptionRepr::PrefixInformation(info) => prefix_info = Some(info),
-                        _ => { return Err(Error::Unrecognized); }
+                        _ => {
+                            return Err(Error::Unrecognized);
+                        }
                     }
                     offset += opt.buffer_len();
                 }
@@ -262,29 +266,36 @@ impl<'a> Repr<'a> {
                     router_lifetime: packet.router_lifetime(),
                     reachable_time: packet.reachable_time(),
                     retrans_time: packet.retrans_time(),
-                    lladdr, mtu, prefix_info
+                    lladdr,
+                    mtu,
+                    prefix_info,
                 })
-            },
+            }
             Message::NeighborSolicit => {
                 let lladdr = if !packet.payload().is_empty() {
                     let opt = NdiscOption::new_checked(packet.payload())?;
                     match opt.option_type() {
                         NdiscOptionType::SourceLinkLayerAddr => Some(opt.link_layer_addr()),
-                        _ => { return Err(Error::Unrecognized); }
+                        _ => {
+                            return Err(Error::Unrecognized);
+                        }
                     }
                 } else {
                     None
                 };
                 Ok(Repr::NeighborSolicit {
-                    target_addr: packet.target_addr(), lladdr
+                    target_addr: packet.target_addr(),
+                    lladdr,
                 })
-            },
+            }
             Message::NeighborAdvert => {
                 let lladdr = if !packet.payload().is_empty() {
                     let opt = NdiscOption::new_checked(packet.payload())?;
                     match opt.option_type() {
                         NdiscOptionType::TargetLinkLayerAddr => Some(opt.link_layer_addr()),
-                        _ => { return Err(Error::Unrecognized); }
+                        _ => {
+                            return Err(Error::Unrecognized);
+                        }
                     }
                 } else {
                     None
@@ -292,9 +303,9 @@ impl<'a> Repr<'a> {
                 Ok(Repr::NeighborAdvert {
                     flags: packet.neighbor_flags(),
                     target_addr: packet.target_addr(),
-                    lladdr
+                    lladdr,
                 })
-            },
+            }
             Message::Redirect => {
                 let mut offset = 0;
                 let (mut lladdr, mut redirected_hdr) = (None, None);
@@ -304,43 +315,50 @@ impl<'a> Repr<'a> {
                         NdiscOptionType::SourceLinkLayerAddr => {
                             lladdr = Some(opt.link_layer_addr());
                             offset += 8;
-                        },
+                        }
                         NdiscOptionType::RedirectedHeader => {
                             if opt.data_len() < 6 {
-                                return Err(Error::Truncated)
+                                return Err(Error::Truncated);
                             } else {
                                 let ip_packet =
                                     Ipv6Packet::new_unchecked(&opt.data()[offset + 8..]);
                                 let ip_repr = Ipv6Repr::parse(&ip_packet)?;
                                 let data = &opt.data()[offset + 8 + ip_repr.buffer_len()..];
                                 redirected_hdr = Some(NdiscRedirectedHeader {
-                                    header: ip_repr, data
+                                    header: ip_repr,
+                                    data,
                                 });
                                 offset += 8 + ip_repr.buffer_len() + data.len();
                             }
                         }
-                        _ => { return Err(Error::Unrecognized); }
+                        _ => {
+                            return Err(Error::Unrecognized);
+                        }
                     }
                 }
                 Ok(Repr::Redirect {
                     target_addr: packet.target_addr(),
                     dest_addr: packet.dest_addr(),
-                    lladdr, redirected_hdr
+                    lladdr,
+                    redirected_hdr,
                 })
-            },
-            _ => Err(Error::Unrecognized)
+            }
+            _ => Err(Error::Unrecognized),
         }
     }
 
     pub fn buffer_len(&self) -> usize {
         match self {
-            &Repr::RouterSolicit { lladdr } => {
-                match lladdr {
-                    Some(_) => field::UNUSED.end + 8,
-                    None => field::UNUSED.end,
-                }
+            &Repr::RouterSolicit { lladdr } => match lladdr {
+                Some(_) => field::UNUSED.end + 8,
+                None => field::UNUSED.end,
             },
-            &Repr::RouterAdvert { lladdr, mtu, prefix_info, .. } => {
+            &Repr::RouterAdvert {
+                lladdr,
+                mtu,
+                prefix_info,
+                ..
+            } => {
                 let mut offset = 0;
                 if lladdr.is_some() {
                     offset += 8;
@@ -352,14 +370,18 @@ impl<'a> Repr<'a> {
                     offset += 32;
                 }
                 field::RETRANS_TM.end + offset
-            },
+            }
             &Repr::NeighborSolicit { lladdr, .. } | &Repr::NeighborAdvert { lladdr, .. } => {
                 match lladdr {
                     Some(_) => field::TARGET_ADDR.end + 8,
                     None => field::TARGET_ADDR.end,
                 }
-            },
-            &Repr::Redirect { lladdr, redirected_hdr, .. } => {
+            }
+            &Repr::Redirect {
+                lladdr,
+                redirected_hdr,
+                ..
+            } => {
                 let mut offset = 0;
                 if lladdr.is_some() {
                     offset += 8;
@@ -373,7 +395,9 @@ impl<'a> Repr<'a> {
     }
 
     pub fn emit<T>(&self, packet: &mut Packet<&mut T>)
-            where T: AsRef<[u8]> + AsMut<[u8]> + ?Sized {
+    where
+        T: AsRef<[u8]> + AsMut<[u8]> + ?Sized,
+    {
         match *self {
             Repr::RouterSolicit { lladdr } => {
                 packet.set_msg_type(Message::RouterSolicit);
@@ -383,10 +407,18 @@ impl<'a> Repr<'a> {
                     let mut opt_pkt = NdiscOption::new_unchecked(packet.payload_mut());
                     NdiscOptionRepr::SourceLinkLayerAddr(lladdr).emit(&mut opt_pkt);
                 }
-            },
+            }
 
-            Repr::RouterAdvert { hop_limit, flags, router_lifetime, reachable_time,
-                                  retrans_time, lladdr, mtu, prefix_info } => {
+            Repr::RouterAdvert {
+                hop_limit,
+                flags,
+                router_lifetime,
+                reachable_time,
+                retrans_time,
+                lladdr,
+                mtu,
+                prefix_info,
+            } => {
                 packet.set_msg_type(Message::RouterAdvert);
                 packet.set_msg_code(0);
                 packet.set_current_hop_limit(hop_limit);
@@ -396,8 +428,7 @@ impl<'a> Repr<'a> {
                 packet.set_retrans_time(retrans_time);
                 let mut offset = 0;
                 if let Some(lladdr) = lladdr {
-                    let mut opt_pkt =
-                        NdiscOption::new_unchecked(packet.payload_mut());
+                    let mut opt_pkt = NdiscOption::new_unchecked(packet.payload_mut());
                     NdiscOptionRepr::SourceLinkLayerAddr(lladdr).emit(&mut opt_pkt);
                     offset += 8;
                 }
@@ -412,34 +443,44 @@ impl<'a> Repr<'a> {
                         NdiscOption::new_unchecked(&mut packet.payload_mut()[offset..]);
                     NdiscOptionRepr::PrefixInformation(prefix_info).emit(&mut opt_pkt)
                 }
-            },
+            }
 
-            Repr::NeighborSolicit { target_addr, lladdr } => {
+            Repr::NeighborSolicit {
+                target_addr,
+                lladdr,
+            } => {
                 packet.set_msg_type(Message::NeighborSolicit);
                 packet.set_msg_code(0);
                 packet.clear_reserved();
                 packet.set_target_addr(target_addr);
                 if let Some(lladdr) = lladdr {
-                    let mut opt_pkt =
-                        NdiscOption::new_unchecked(packet.payload_mut());
+                    let mut opt_pkt = NdiscOption::new_unchecked(packet.payload_mut());
                     NdiscOptionRepr::SourceLinkLayerAddr(lladdr).emit(&mut opt_pkt);
                 }
-            },
+            }
 
-            Repr::NeighborAdvert { flags, target_addr, lladdr } => {
+            Repr::NeighborAdvert {
+                flags,
+                target_addr,
+                lladdr,
+            } => {
                 packet.set_msg_type(Message::NeighborAdvert);
                 packet.set_msg_code(0);
                 packet.clear_reserved();
                 packet.set_neighbor_flags(flags);
                 packet.set_target_addr(target_addr);
                 if let Some(lladdr) = lladdr {
-                    let mut opt_pkt =
-                        NdiscOption::new_unchecked(packet.payload_mut());
+                    let mut opt_pkt = NdiscOption::new_unchecked(packet.payload_mut());
                     NdiscOptionRepr::TargetLinkLayerAddr(lladdr).emit(&mut opt_pkt);
                 }
-            },
+            }
 
-            Repr::Redirect { target_addr, dest_addr, lladdr, redirected_hdr } => {
+            Repr::Redirect {
+                target_addr,
+                dest_addr,
+                lladdr,
+                redirected_hdr,
+            } => {
                 packet.set_msg_type(Message::Redirect);
                 packet.set_msg_code(0);
                 packet.clear_reserved();
@@ -447,11 +488,10 @@ impl<'a> Repr<'a> {
                 packet.set_dest_addr(dest_addr);
                 let offset = match lladdr {
                     Some(lladdr) => {
-                        let mut opt_pkt =
-                            NdiscOption::new_unchecked(packet.payload_mut());
+                        let mut opt_pkt = NdiscOption::new_unchecked(packet.payload_mut());
                         NdiscOptionRepr::TargetLinkLayerAddr(lladdr).emit(&mut opt_pkt);
                         8
-                    },
+                    }
                     None => 0,
                 };
                 if let Some(redirected_hdr) = redirected_hdr {
@@ -459,28 +499,23 @@ impl<'a> Repr<'a> {
                         NdiscOption::new_unchecked(&mut packet.payload_mut()[offset..]);
                     NdiscOptionRepr::RedirectedHeader(redirected_hdr).emit(&mut opt_pkt);
                 }
-            },
+            }
         }
     }
 }
 
 #[cfg(test)]
 mod test {
-    use crate::phy::ChecksumCapabilities;
     use super::*;
-    use crate::wire::Icmpv6Repr;
+    use crate::phy::ChecksumCapabilities;
     use crate::wire::ip::test::{MOCK_IP_ADDR_1, MOCK_IP_ADDR_2};
+    use crate::wire::Icmpv6Repr;
 
-    static ROUTER_ADVERT_BYTES: [u8; 24] =
-        [0x86, 0x00, 0xa9, 0xde,
-         0x40, 0x80, 0x03, 0x84,
-         0x00, 0x00, 0x03, 0x84,
-         0x00, 0x00, 0x03, 0x84,
-         0x01, 0x01, 0x52, 0x54,
-         0x00, 0x12, 0x34, 0x56];
-    static SOURCE_LINK_LAYER_OPT: [u8; 8] =
-        [0x01, 0x01, 0x52, 0x54,
-         0x00, 0x12, 0x34, 0x56];
+    static ROUTER_ADVERT_BYTES: [u8; 24] = [
+        0x86, 0x00, 0xa9, 0xde, 0x40, 0x80, 0x03, 0x84, 0x00, 0x00, 0x03, 0x84, 0x00, 0x00, 0x03,
+        0x84, 0x01, 0x01, 0x52, 0x54, 0x00, 0x12, 0x34, 0x56,
+    ];
+    static SOURCE_LINK_LAYER_OPT: [u8; 8] = [0x01, 0x01, 0x52, 0x54, 0x00, 0x12, 0x34, 0x56];
 
     fn create_repr<'a>() -> Icmpv6Repr<'a> {
         Icmpv6Repr::Ndisc(Repr::RouterAdvert {
@@ -491,7 +526,7 @@ mod test {
             retrans_time: Duration::from_millis(900),
             lladdr: Some(EthernetAddress([0x52, 0x54, 0x00, 0x12, 0x34, 0x56])),
             mtu: None,
-            prefix_info: None
+            prefix_info: None,
         })
     }
 
@@ -519,7 +554,9 @@ mod test {
         packet.set_router_lifetime(Duration::from_secs(900));
         packet.set_reachable_time(Duration::from_millis(900));
         packet.set_retrans_time(Duration::from_millis(900));
-        packet.payload_mut().copy_from_slice(&SOURCE_LINK_LAYER_OPT[..]);
+        packet
+            .payload_mut()
+            .copy_from_slice(&SOURCE_LINK_LAYER_OPT[..]);
         packet.fill_checksum(&MOCK_IP_ADDR_1, &MOCK_IP_ADDR_2);
         assert_eq!(&packet.into_inner()[..], &ROUTER_ADVERT_BYTES[..]);
     }
@@ -527,17 +564,28 @@ mod test {
     #[test]
     fn test_router_advert_repr_parse() {
         let packet = Packet::new_unchecked(&ROUTER_ADVERT_BYTES[..]);
-        assert_eq!(Icmpv6Repr::parse(&MOCK_IP_ADDR_1, &MOCK_IP_ADDR_2,
-                                     &packet, &ChecksumCapabilities::default()).unwrap(),
-                   create_repr());
+        assert_eq!(
+            Icmpv6Repr::parse(
+                &MOCK_IP_ADDR_1,
+                &MOCK_IP_ADDR_2,
+                &packet,
+                &ChecksumCapabilities::default()
+            )
+            .unwrap(),
+            create_repr()
+        );
     }
 
     #[test]
     fn test_router_advert_repr_emit() {
         let mut bytes = vec![0x2a; 24];
         let mut packet = Packet::new_unchecked(&mut bytes[..]);
-        create_repr().emit(&MOCK_IP_ADDR_1, &MOCK_IP_ADDR_2,
-                           &mut packet, &ChecksumCapabilities::default());
+        create_repr().emit(
+            &MOCK_IP_ADDR_1,
+            &MOCK_IP_ADDR_2,
+            &mut packet,
+            &ChecksumCapabilities::default(),
+        );
         assert_eq!(&packet.into_inner()[..], &ROUTER_ADVERT_BYTES[..]);
     }
 }

+ 121 - 116
src/wire/ndiscoption.rs

@@ -1,10 +1,10 @@
-use core::fmt;
-use byteorder::{NetworkEndian, ByteOrder};
 use bitflags::bitflags;
+use byteorder::{ByteOrder, NetworkEndian};
+use core::fmt;
 
-use crate::{Error, Result};
 use crate::time::Duration;
 use crate::wire::{EthernetAddress, Ipv6Address, Ipv6Packet, Ipv6Repr};
+use crate::{Error, Result};
 
 enum_with_unknown! {
     /// NDISC Option Type
@@ -27,10 +27,10 @@ impl fmt::Display for Type {
         match self {
             Type::SourceLinkLayerAddr => write!(f, "source link-layer address"),
             Type::TargetLinkLayerAddr => write!(f, "target link-layer address"),
-            Type::PrefixInformation   => write!(f, "prefix information"),
-            Type::RedirectedHeader    => write!(f, "redirected header"),
-            Type::Mtu                 => write!(f, "mtu"),
-            Type::Unknown(id) => write!(f, "{}", id)
+            Type::PrefixInformation => write!(f, "prefix information"),
+            Type::RedirectedHeader => write!(f, "redirected header"),
+            Type::Mtu => write!(f, "mtu"),
+            Type::Unknown(id) => write!(f, "{}", id),
         }
     }
 }
@@ -49,7 +49,7 @@ bitflags! {
 #[derive(Debug, PartialEq)]
 #[cfg_attr(feature = "defmt", derive(defmt::Format))]
 pub struct NdiscOption<T: AsRef<[u8]>> {
-    buffer: T
+    buffer: T,
 }
 
 // Format of an NDISC Option
@@ -67,11 +67,11 @@ mod field {
     use crate::wire::field::*;
 
     // 8-bit identifier of the type of option.
-    pub const TYPE:          usize = 0;
+    pub const TYPE: usize = 0;
     // 8-bit unsigned integer. Length of the option, in units of 8 octests.
-    pub const LENGTH:        usize = 1;
+    pub const LENGTH: usize = 1;
     // Minimum length of an option.
-    pub const MIN_OPT_LEN:   usize = 8;
+    pub const MIN_OPT_LEN: usize = 8;
     // Variable-length field. Option-Type-specific data.
     pub fn DATA(length: u8) -> Field {
         2..length as usize * 8
@@ -83,7 +83,7 @@ mod field {
     // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 
     // Link-Layer Address
-    pub const LL_ADDR:       Field = 2..8;
+    pub const LL_ADDR: Field = 2..8;
 
     // Prefix Information Option fields.
     //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
@@ -105,17 +105,17 @@ mod field {
     //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 
     // Prefix length.
-    pub const PREFIX_LEN:    usize = 2;
+    pub const PREFIX_LEN: usize = 2;
     // Flags field of prefix header.
-    pub const FLAGS:         usize = 3;
+    pub const FLAGS: usize = 3;
     // Valid lifetime.
-    pub const VALID_LT:      Field = 4..8;
+    pub const VALID_LT: Field = 4..8;
     // Preferred lifetime.
-    pub const PREF_LT:       Field = 8..12;
+    pub const PREF_LT: Field = 8..12;
     // Reserved bits
     pub const PREF_RESERVED: Field = 12..16;
     // Prefix
-    pub const PREFIX:        Field = 16..32;
+    pub const PREFIX: Field = 16..32;
 
     // Redirected Header Option fields.
     //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
@@ -129,10 +129,10 @@ mod field {
     //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 
     // Reserved bits.
-    pub const IP_RESERVED:   Field = 4..8;
+    pub const IP_RESERVED: Field = 4..8;
     // Redirected header IP header + data.
-    pub const IP_DATA:       usize = 8;
-    pub const REDIR_MIN_SZ:  usize = 48;
+    pub const IP_DATA: usize = 8;
+    pub const REDIR_MIN_SZ: usize = 48;
 
     // MTU Option fields
     //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
@@ -142,7 +142,7 @@ mod field {
     //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 
     //  MTU
-    pub const MTU:           Field = 4..8;
+    pub const MTU: Field = 4..8;
 }
 
 /// Core getter methods relevant to any type of NDISC option.
@@ -180,16 +180,11 @@ impl<T: AsRef<[u8]>> NdiscOption<T> {
                 Err(Error::Truncated)
             } else {
                 match self.option_type() {
-                    Type::SourceLinkLayerAddr | Type::TargetLinkLayerAddr | Type::Mtu =>
-                        Ok(()),
-                    Type::PrefixInformation if data_range.end >= field::PREFIX.end =>
-                        Ok(()),
-                    Type::RedirectedHeader if data_range.end >= field::REDIR_MIN_SZ =>
-                        Ok(()),
-                    Type::Unknown(_) =>
-                        Ok(()),
-                    _ =>
-                        Err(Error::Truncated),
+                    Type::SourceLinkLayerAddr | Type::TargetLinkLayerAddr | Type::Mtu => Ok(()),
+                    Type::PrefixInformation if data_range.end >= field::PREFIX.end => Ok(()),
+                    Type::RedirectedHeader if data_range.end >= field::REDIR_MIN_SZ => Ok(()),
+                    Type::Unknown(_) => Ok(()),
+                    _ => Err(Error::Truncated),
                 }
             }
         }
@@ -371,7 +366,6 @@ impl<T: AsRef<[u8]> + AsMut<[u8]>> NdiscOption<T> {
     }
 }
 
-
 impl<'a, T: AsRef<[u8]> + AsMut<[u8]> + ?Sized> NdiscOption<&'a mut T> {
     /// Return a mutable pointer to the option data.
     #[inline]
@@ -401,14 +395,14 @@ pub struct PrefixInformation {
     pub flags: PrefixInfoFlags,
     pub valid_lifetime: Duration,
     pub preferred_lifetime: Duration,
-    pub prefix: Ipv6Address
+    pub prefix: Ipv6Address,
 }
 
 #[derive(Debug, PartialEq, Eq, Clone, Copy)]
 #[cfg_attr(feature = "defmt", derive(defmt::Format))]
 pub struct RedirectedHeader<'a> {
     pub header: Ipv6Repr,
-    pub data: &'a [u8]
+    pub data: &'a [u8],
 }
 
 /// A high-level representation of an NDISC Option.
@@ -421,16 +415,18 @@ pub enum Repr<'a> {
     RedirectedHeader(RedirectedHeader<'a>),
     Mtu(u32),
     Unknown {
-        type_:  u8,
+        type_: u8,
         length: u8,
-        data:   &'a [u8]
+        data: &'a [u8],
     },
 }
 
 impl<'a> Repr<'a> {
     /// Parse an NDISC Option and return a high-level representation.
     pub fn parse<T>(opt: &'a NdiscOption<&'a T>) -> Result<Repr<'a>>
-            where T: AsRef<[u8]> + ?Sized {
+    where
+        T: AsRef<[u8]> + ?Sized,
+    {
         match opt.option_type() {
             Type::SourceLinkLayerAddr => {
                 if opt.data_len() == 1 {
@@ -438,14 +434,14 @@ impl<'a> Repr<'a> {
                 } else {
                     Err(Error::Malformed)
                 }
-            },
+            }
             Type::TargetLinkLayerAddr => {
                 if opt.data_len() == 1 {
                     Ok(Repr::TargetLinkLayerAddr(opt.link_layer_addr()))
                 } else {
                     Err(Error::Malformed)
                 }
-            },
+            }
             Type::PrefixInformation => {
                 if opt.data_len() == 4 {
                     Ok(Repr::PrefixInformation(PrefixInformation {
@@ -453,12 +449,12 @@ impl<'a> Repr<'a> {
                         flags: opt.prefix_flags(),
                         valid_lifetime: opt.valid_lifetime(),
                         preferred_lifetime: opt.preferred_lifetime(),
-                        prefix: opt.prefix()
+                        prefix: opt.prefix(),
                     }))
                 } else {
                     Err(Error::Malformed)
                 }
-            },
+            }
             Type::RedirectedHeader => {
                 // If the options data length is less than 6, the option
                 // does not have enough data to fill out the IP header
@@ -470,60 +466,60 @@ impl<'a> Repr<'a> {
                     let ip_repr = Ipv6Repr::parse(&ip_packet)?;
                     Ok(Repr::RedirectedHeader(RedirectedHeader {
                         header: ip_repr,
-                        data: &opt.data()[field::IP_DATA + ip_repr.buffer_len()..]
+                        data: &opt.data()[field::IP_DATA + ip_repr.buffer_len()..],
                     }))
                 }
-            },
+            }
             Type::Mtu => {
                 if opt.data_len() == 1 {
                     Ok(Repr::Mtu(opt.mtu()))
                 } else {
                     Err(Error::Malformed)
                 }
-            },
-            Type::Unknown(id) => {
-                Ok(Repr::Unknown {
-                    type_: id,
-                    length: opt.data_len(),
-                    data: opt.data()
-                })
             }
+            Type::Unknown(id) => Ok(Repr::Unknown {
+                type_: id,
+                length: opt.data_len(),
+                data: opt.data(),
+            }),
         }
     }
 
     /// Return the length of a header that will be emitted from this high-level representation.
     pub fn buffer_len(&self) -> usize {
         match self {
-            &Repr::SourceLinkLayerAddr(_) | &Repr::TargetLinkLayerAddr(_) =>
-                field::LL_ADDR.end,
-            &Repr::PrefixInformation(_) =>
-                field::PREFIX.end,
-            &Repr::RedirectedHeader(RedirectedHeader { header, data }) =>
-                field::IP_DATA + header.buffer_len() + data.len(),
-            &Repr::Mtu(_) =>
-                field::MTU.end,
-            &Repr::Unknown { length, .. } =>
-                field::DATA(length).end
+            &Repr::SourceLinkLayerAddr(_) | &Repr::TargetLinkLayerAddr(_) => field::LL_ADDR.end,
+            &Repr::PrefixInformation(_) => field::PREFIX.end,
+            &Repr::RedirectedHeader(RedirectedHeader { header, data }) => {
+                field::IP_DATA + header.buffer_len() + data.len()
+            }
+            &Repr::Mtu(_) => field::MTU.end,
+            &Repr::Unknown { length, .. } => field::DATA(length).end,
         }
     }
 
     /// Emit a high-level representation into an NDISC Option.
     pub fn emit<T>(&self, opt: &mut NdiscOption<&'a mut T>)
-            where T: AsRef<[u8]> + AsMut<[u8]> + ?Sized {
+    where
+        T: AsRef<[u8]> + AsMut<[u8]> + ?Sized,
+    {
         match *self {
             Repr::SourceLinkLayerAddr(addr) => {
                 opt.set_option_type(Type::SourceLinkLayerAddr);
                 opt.set_data_len(1);
                 opt.set_link_layer_addr(addr);
-            },
+            }
             Repr::TargetLinkLayerAddr(addr) => {
                 opt.set_option_type(Type::TargetLinkLayerAddr);
                 opt.set_data_len(1);
                 opt.set_link_layer_addr(addr);
-            },
+            }
             Repr::PrefixInformation(PrefixInformation {
-                prefix_len, flags, valid_lifetime,
-                preferred_lifetime, prefix
+                prefix_len,
+                flags,
+                valid_lifetime,
+                preferred_lifetime,
+                prefix,
             }) => {
                 opt.clear_prefix_reserved();
                 opt.set_option_type(Type::PrefixInformation);
@@ -533,10 +529,8 @@ impl<'a> Repr<'a> {
                 opt.set_valid_lifetime(valid_lifetime);
                 opt.set_preferred_lifetime(preferred_lifetime);
                 opt.set_prefix(prefix);
-            },
-            Repr::RedirectedHeader(RedirectedHeader {
-                header, data
-            }) => {
+            }
+            Repr::RedirectedHeader(RedirectedHeader { header, data }) => {
                 let data_len = data.len() / 8;
                 opt.clear_redirected_reserved();
                 opt.set_option_type(Type::RedirectedHeader);
@@ -552,7 +546,11 @@ impl<'a> Repr<'a> {
                 opt.set_data_len(1);
                 opt.set_mtu(mtu);
             }
-            Repr::Unknown { type_: id, length, data } => {
+            Repr::Unknown {
+                type_: id,
+                length,
+                data,
+            } => {
                 opt.set_option_type(Type::Unknown(id));
                 opt.set_data_len(length);
                 opt.data_mut().copy_from_slice(data);
@@ -567,67 +565,61 @@ impl<'a> fmt::Display for Repr<'a> {
         match *self {
             Repr::SourceLinkLayerAddr(addr) => {
                 write!(f, "SourceLinkLayer addr={}", addr)
-            },
+            }
             Repr::TargetLinkLayerAddr(addr) => {
                 write!(f, "TargetLinkLayer addr={}", addr)
-            },
+            }
             Repr::PrefixInformation(PrefixInformation {
-                prefix, prefix_len,
-                ..
+                prefix, prefix_len, ..
             }) => {
                 write!(f, "PrefixInformation prefix={}/{}", prefix, prefix_len)
-            },
-            Repr::RedirectedHeader(RedirectedHeader {
-                header,
-                ..
-            }) => {
+            }
+            Repr::RedirectedHeader(RedirectedHeader { header, .. }) => {
                 write!(f, "RedirectedHeader header={}", header)
-            },
+            }
             Repr::Mtu(mtu) => {
                 write!(f, "MTU mtu={}", mtu)
-            },
-            Repr::Unknown { type_: id, length, .. } => {
+            }
+            Repr::Unknown {
+                type_: id, length, ..
+            } => {
                 write!(f, "Unknown({}) length={}", id, length)
             }
         }
     }
 }
 
-use crate::wire::pretty_print::{PrettyPrint, PrettyIndent};
+use crate::wire::pretty_print::{PrettyIndent, PrettyPrint};
 
 impl<T: AsRef<[u8]>> PrettyPrint for NdiscOption<T> {
-    fn pretty_print(buffer: &dyn AsRef<[u8]>, f: &mut fmt::Formatter,
-                    indent: &mut PrettyIndent) -> fmt::Result {
+    fn pretty_print(
+        buffer: &dyn AsRef<[u8]>,
+        f: &mut fmt::Formatter,
+        indent: &mut PrettyIndent,
+    ) -> fmt::Result {
         match NdiscOption::new_checked(buffer) {
             Err(err) => return write!(f, "{}({})", indent, err),
-            Ok(ndisc) => {
-                match Repr::parse(&ndisc) {
-                    Err(_) => Ok(()),
-                    Ok(repr) => {
-                        write!(f, "{}{}", indent, repr)
-                    }
+            Ok(ndisc) => match Repr::parse(&ndisc) {
+                Err(_) => Ok(()),
+                Ok(repr) => {
+                    write!(f, "{}{}", indent, repr)
                 }
-            }
+            },
         }
     }
 }
 
 #[cfg(test)]
 mod test {
-    use crate::Error;
+    use super::{NdiscOption, PrefixInfoFlags, PrefixInformation, Repr, Type};
     use crate::time::Duration;
     use crate::wire::{EthernetAddress, Ipv6Address};
-    use super::{NdiscOption, Type, PrefixInfoFlags, PrefixInformation, Repr};
+    use crate::Error;
 
     static PREFIX_OPT_BYTES: [u8; 32] = [
-        0x03, 0x04, 0x40, 0xc0,
-        0x00, 0x00, 0x03, 0x84,
-        0x00, 0x00, 0x03, 0xe8,
-        0x00, 0x00, 0x00, 0x00,
-        0xfe, 0x80, 0x00, 0x00,
-        0x00, 0x00, 0x00, 0x00,
-        0x00, 0x00, 0x00, 0x00,
-        0x00, 0x00, 0x00, 0x01
+        0x03, 0x04, 0x40, 0xc0, 0x00, 0x00, 0x03, 0x84, 0x00, 0x00, 0x03, 0xe8, 0x00, 0x00, 0x00,
+        0x00, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x01,
     ];
 
     #[test]
@@ -636,7 +628,10 @@ mod test {
         assert_eq!(opt.option_type(), Type::PrefixInformation);
         assert_eq!(opt.data_len(), 4);
         assert_eq!(opt.prefix_len(), 64);
-        assert_eq!(opt.prefix_flags(), PrefixInfoFlags::ON_LINK | PrefixInfoFlags::ADDRCONF);
+        assert_eq!(
+            opt.prefix_flags(),
+            PrefixInfoFlags::ON_LINK | PrefixInfoFlags::ADDRCONF
+        );
         assert_eq!(opt.valid_lifetime(), Duration::from_secs(900));
         assert_eq!(opt.preferred_lifetime(), Duration::from_secs(1000));
         assert_eq!(opt.prefix(), Ipv6Address::new(0xfe80, 0, 0, 0, 0, 0, 0, 1));
@@ -658,11 +653,11 @@ mod test {
 
     #[test]
     fn test_short_packet() {
-        assert_eq!(NdiscOption::new_checked(&[0x00, 0x00]), Err(Error::Truncated));
-        let bytes = [
-            0x03, 0x01, 0x00, 0x00,
-            0x00, 0x00, 0x00, 0x00
-        ];
+        assert_eq!(
+            NdiscOption::new_checked(&[0x00, 0x00]),
+            Err(Error::Truncated)
+        );
+        let bytes = [0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00];
         assert_eq!(NdiscOption::new_checked(&bytes), Err(Error::Truncated));
     }
 
@@ -671,13 +666,17 @@ mod test {
         let mut bytes = [0x01, 0x01, 0x54, 0x52, 0x00, 0x12, 0x23, 0x34];
         let addr = EthernetAddress([0x54, 0x52, 0x00, 0x12, 0x23, 0x34]);
         {
-            assert_eq!(Repr::parse(&NdiscOption::new_unchecked(&bytes)),
-                       Ok(Repr::SourceLinkLayerAddr(addr)));
+            assert_eq!(
+                Repr::parse(&NdiscOption::new_unchecked(&bytes)),
+                Ok(Repr::SourceLinkLayerAddr(addr))
+            );
         }
         bytes[0] = 0x02;
         {
-            assert_eq!(Repr::parse(&NdiscOption::new_unchecked(&bytes)),
-                       Ok(Repr::TargetLinkLayerAddr(addr)));
+            assert_eq!(
+                Repr::parse(&NdiscOption::new_unchecked(&bytes)),
+                Ok(Repr::TargetLinkLayerAddr(addr))
+            );
         }
     }
 
@@ -688,9 +687,12 @@ mod test {
             flags: PrefixInfoFlags::ON_LINK | PrefixInfoFlags::ADDRCONF,
             valid_lifetime: Duration::from_secs(900),
             preferred_lifetime: Duration::from_secs(1000),
-            prefix: Ipv6Address::new(0xfe80, 0, 0, 0, 0, 0, 0, 1)
+            prefix: Ipv6Address::new(0xfe80, 0, 0, 0, 0, 0, 0, 1),
         });
-        assert_eq!(Repr::parse(&NdiscOption::new_unchecked(&PREFIX_OPT_BYTES)), Ok(repr));
+        assert_eq!(
+            Repr::parse(&NdiscOption::new_unchecked(&PREFIX_OPT_BYTES)),
+            Ok(repr)
+        );
     }
 
     #[test]
@@ -701,7 +703,7 @@ mod test {
             flags: PrefixInfoFlags::ON_LINK | PrefixInfoFlags::ADDRCONF,
             valid_lifetime: Duration::from_secs(900),
             preferred_lifetime: Duration::from_secs(1000),
-            prefix: Ipv6Address::new(0xfe80, 0, 0, 0, 0, 0, 0, 1)
+            prefix: Ipv6Address::new(0xfe80, 0, 0, 0, 0, 0, 0, 1),
         });
         let mut opt = NdiscOption::new_unchecked(&mut bytes);
         repr.emit(&mut opt);
@@ -711,6 +713,9 @@ mod test {
     #[test]
     fn test_repr_parse_mtu() {
         let bytes = [0x05, 0x01, 0x00, 0x00, 0x00, 0x00, 0x05, 0xdc];
-        assert_eq!(Repr::parse(&NdiscOption::new_unchecked(&bytes)), Ok(Repr::Mtu(1500)));
+        assert_eq!(
+            Repr::parse(&NdiscOption::new_unchecked(&bytes)),
+            Ok(Repr::Mtu(1500))
+        );
     }
 }

+ 12 - 9
src/wire/pretty_print.rs

@@ -37,7 +37,7 @@ use core::marker::PhantomData;
 #[cfg_attr(feature = "defmt", derive(defmt::Format))]
 pub struct PrettyIndent {
     prefix: &'static str,
-    level:  usize
+    level: usize,
 }
 
 impl PrettyIndent {
@@ -72,24 +72,27 @@ pub trait PrettyPrint {
     ///
     /// `pretty_print` accepts a buffer and not a packet wrapper because the packet might
     /// be truncated, and so it might not be possible to create the packet wrapper.
-    fn pretty_print(buffer: &dyn AsRef<[u8]>, fmt: &mut fmt::Formatter,
-                    indent: &mut PrettyIndent) -> fmt::Result;
+    fn pretty_print(
+        buffer: &dyn AsRef<[u8]>,
+        fmt: &mut fmt::Formatter,
+        indent: &mut PrettyIndent,
+    ) -> fmt::Result;
 }
 
 /// Wrapper for using a `PrettyPrint` where a `Display` is expected.
 pub struct PrettyPrinter<'a, T: PrettyPrint> {
-    prefix:  &'static str,
-    buffer:  &'a dyn AsRef<[u8]>,
-    phantom: PhantomData<T>
+    prefix: &'static str,
+    buffer: &'a dyn AsRef<[u8]>,
+    phantom: PhantomData<T>,
 }
 
 impl<'a, T: PrettyPrint> PrettyPrinter<'a, T> {
     /// Format the listing with the recorded parameters when Display::fmt is called.
     pub fn new(prefix: &'static str, buffer: &'a dyn AsRef<[u8]>) -> PrettyPrinter<'a, T> {
         PrettyPrinter {
-            prefix:  prefix,
-            buffer:  buffer,
-            phantom: PhantomData
+            prefix: prefix,
+            buffer: buffer,
+            phantom: PhantomData,
         }
     }
 }

+ 313 - 235
src/wire/tcp.rs

@@ -1,10 +1,10 @@
-use core::{i32, ops, cmp, fmt};
 use byteorder::{ByteOrder, NetworkEndian};
+use core::{cmp, fmt, i32, ops};
 
-use crate::{Error, Result};
 use crate::phy::ChecksumCapabilities;
-use crate::wire::{IpProtocol, IpAddress};
 use crate::wire::ip::checksum;
+use crate::wire::{IpAddress, IpProtocol};
+use crate::{Error, Result};
 
 /// A TCP sequence number.
 ///
@@ -70,7 +70,7 @@ impl cmp::PartialOrd for SeqNumber {
 #[derive(Debug, PartialEq, Clone)]
 #[cfg_attr(feature = "defmt", derive(defmt::Format))]
 pub struct Packet<T: AsRef<[u8]>> {
-    buffer: T
+    buffer: T,
 }
 
 mod field {
@@ -80,12 +80,12 @@ mod field {
 
     pub const SRC_PORT: Field = 0..2;
     pub const DST_PORT: Field = 2..4;
-    pub const SEQ_NUM:  Field = 4..8;
-    pub const ACK_NUM:  Field = 8..12;
-    pub const FLAGS:    Field = 12..14;
+    pub const SEQ_NUM: Field = 4..8;
+    pub const ACK_NUM: Field = 8..12;
+    pub const FLAGS: Field = 12..14;
     pub const WIN_SIZE: Field = 14..16;
     pub const CHECKSUM: Field = 16..18;
-    pub const URGENT:   Field = 18..20;
+    pub const URGENT: Field = 18..20;
 
     pub fn OPTIONS(length: u8) -> Field {
         URGENT.end..(length as usize)
@@ -99,14 +99,14 @@ mod field {
     pub const FLG_URG: u16 = 0x020;
     pub const FLG_ECE: u16 = 0x040;
     pub const FLG_CWR: u16 = 0x080;
-    pub const FLG_NS:  u16 = 0x100;
+    pub const FLG_NS: u16 = 0x100;
 
     pub const OPT_END: u8 = 0x00;
     pub const OPT_NOP: u8 = 0x01;
     pub const OPT_MSS: u8 = 0x02;
-    pub const OPT_WS:  u8 = 0x03;
+    pub const OPT_WS: u8 = 0x03;
     pub const OPT_SACKPERM: u8 = 0x04;
-    pub const OPT_SACKRNG:  u8 = 0x05;
+    pub const OPT_SACKRNG: u8 = 0x05;
 }
 
 pub const HEADER_LEN: usize = field::URGENT.end;
@@ -289,8 +289,12 @@ impl<T: AsRef<[u8]>> Packet<T> {
     pub fn segment_len(&self) -> usize {
         let data = self.buffer.as_ref();
         let mut length = data.len() - self.header_len() as usize;
-        if self.syn() { length += 1 }
-        if self.fin() { length += 1 }
+        if self.syn() {
+            length += 1
+        }
+        if self.fin() {
+            length += 1
+        }
         length
     }
 
@@ -333,13 +337,14 @@ impl<T: AsRef<[u8]>> Packet<T> {
     /// # Fuzzing
     /// This function always returns `true` when fuzzing.
     pub fn verify_checksum(&self, src_addr: &IpAddress, dst_addr: &IpAddress) -> bool {
-        if cfg!(fuzzing) { return true }
+        if cfg!(fuzzing) {
+            return true;
+        }
 
         let data = self.buffer.as_ref();
         checksum::combine(&[
-            checksum::pseudo_header(src_addr, dst_addr, IpProtocol::Tcp,
-                                    data.len() as u32),
-            checksum::data(data)
+            checksum::pseudo_header(src_addr, dst_addr, IpProtocol::Tcp, data.len() as u32),
+            checksum::data(data),
         ]) == !0
     }
 }
@@ -405,7 +410,11 @@ impl<T: AsRef<[u8]> + AsMut<[u8]>> Packet<T> {
     pub fn set_fin(&mut self, value: bool) {
         let data = self.buffer.as_mut();
         let raw = NetworkEndian::read_u16(&data[field::FLAGS]);
-        let raw = if value { raw | field::FLG_FIN } else { raw & !field::FLG_FIN };
+        let raw = if value {
+            raw | field::FLG_FIN
+        } else {
+            raw & !field::FLG_FIN
+        };
         NetworkEndian::write_u16(&mut data[field::FLAGS], raw)
     }
 
@@ -414,7 +423,11 @@ impl<T: AsRef<[u8]> + AsMut<[u8]>> Packet<T> {
     pub fn set_syn(&mut self, value: bool) {
         let data = self.buffer.as_mut();
         let raw = NetworkEndian::read_u16(&data[field::FLAGS]);
-        let raw = if value { raw | field::FLG_SYN } else { raw & !field::FLG_SYN };
+        let raw = if value {
+            raw | field::FLG_SYN
+        } else {
+            raw & !field::FLG_SYN
+        };
         NetworkEndian::write_u16(&mut data[field::FLAGS], raw)
     }
 
@@ -423,7 +436,11 @@ impl<T: AsRef<[u8]> + AsMut<[u8]>> Packet<T> {
     pub fn set_rst(&mut self, value: bool) {
         let data = self.buffer.as_mut();
         let raw = NetworkEndian::read_u16(&data[field::FLAGS]);
-        let raw = if value { raw | field::FLG_RST } else { raw & !field::FLG_RST };
+        let raw = if value {
+            raw | field::FLG_RST
+        } else {
+            raw & !field::FLG_RST
+        };
         NetworkEndian::write_u16(&mut data[field::FLAGS], raw)
     }
 
@@ -432,7 +449,11 @@ impl<T: AsRef<[u8]> + AsMut<[u8]>> Packet<T> {
     pub fn set_psh(&mut self, value: bool) {
         let data = self.buffer.as_mut();
         let raw = NetworkEndian::read_u16(&data[field::FLAGS]);
-        let raw = if value { raw | field::FLG_PSH } else { raw & !field::FLG_PSH };
+        let raw = if value {
+            raw | field::FLG_PSH
+        } else {
+            raw & !field::FLG_PSH
+        };
         NetworkEndian::write_u16(&mut data[field::FLAGS], raw)
     }
 
@@ -441,7 +462,11 @@ impl<T: AsRef<[u8]> + AsMut<[u8]>> Packet<T> {
     pub fn set_ack(&mut self, value: bool) {
         let data = self.buffer.as_mut();
         let raw = NetworkEndian::read_u16(&data[field::FLAGS]);
-        let raw = if value { raw | field::FLG_ACK } else { raw & !field::FLG_ACK };
+        let raw = if value {
+            raw | field::FLG_ACK
+        } else {
+            raw & !field::FLG_ACK
+        };
         NetworkEndian::write_u16(&mut data[field::FLAGS], raw)
     }
 
@@ -450,7 +475,11 @@ impl<T: AsRef<[u8]> + AsMut<[u8]>> Packet<T> {
     pub fn set_urg(&mut self, value: bool) {
         let data = self.buffer.as_mut();
         let raw = NetworkEndian::read_u16(&data[field::FLAGS]);
-        let raw = if value { raw | field::FLG_URG } else { raw & !field::FLG_URG };
+        let raw = if value {
+            raw | field::FLG_URG
+        } else {
+            raw & !field::FLG_URG
+        };
         NetworkEndian::write_u16(&mut data[field::FLAGS], raw)
     }
 
@@ -459,7 +488,11 @@ impl<T: AsRef<[u8]> + AsMut<[u8]>> Packet<T> {
     pub fn set_ece(&mut self, value: bool) {
         let data = self.buffer.as_mut();
         let raw = NetworkEndian::read_u16(&data[field::FLAGS]);
-        let raw = if value { raw | field::FLG_ECE } else { raw & !field::FLG_ECE };
+        let raw = if value {
+            raw | field::FLG_ECE
+        } else {
+            raw & !field::FLG_ECE
+        };
         NetworkEndian::write_u16(&mut data[field::FLAGS], raw)
     }
 
@@ -468,7 +501,11 @@ impl<T: AsRef<[u8]> + AsMut<[u8]>> Packet<T> {
     pub fn set_cwr(&mut self, value: bool) {
         let data = self.buffer.as_mut();
         let raw = NetworkEndian::read_u16(&data[field::FLAGS]);
-        let raw = if value { raw | field::FLG_CWR } else { raw & !field::FLG_CWR };
+        let raw = if value {
+            raw | field::FLG_CWR
+        } else {
+            raw & !field::FLG_CWR
+        };
         NetworkEndian::write_u16(&mut data[field::FLAGS], raw)
     }
 
@@ -477,7 +514,11 @@ impl<T: AsRef<[u8]> + AsMut<[u8]>> Packet<T> {
     pub fn set_ns(&mut self, value: bool) {
         let data = self.buffer.as_mut();
         let raw = NetworkEndian::read_u16(&data[field::FLAGS]);
-        let raw = if value { raw | field::FLG_NS } else { raw & !field::FLG_NS };
+        let raw = if value {
+            raw | field::FLG_NS
+        } else {
+            raw & !field::FLG_NS
+        };
         NetworkEndian::write_u16(&mut data[field::FLAGS], raw)
     }
 
@@ -521,9 +562,8 @@ impl<T: AsRef<[u8]> + AsMut<[u8]>> Packet<T> {
         let checksum = {
             let data = self.buffer.as_ref();
             !checksum::combine(&[
-                checksum::pseudo_header(src_addr, dst_addr, IpProtocol::Tcp,
-                                        data.len() as u32),
-                checksum::data(data)
+                checksum::pseudo_header(src_addr, dst_addr, IpProtocol::Tcp, data.len() as u32),
+                checksum::data(data),
             ])
         };
         self.set_checksum(checksum)
@@ -562,7 +602,7 @@ pub enum TcpOption<'a> {
     WindowScale(u8),
     SackPermitted,
     SackRange([Option<(u32, u32)>; 3]),
-    Unknown { kind: u8, data: &'a [u8] }
+    Unknown { kind: u8, data: &'a [u8] },
 }
 
 impl<'a> TcpOption<'a> {
@@ -581,24 +621,18 @@ impl<'a> TcpOption<'a> {
                 length = *buffer.get(1).ok_or(Error::Truncated)? as usize;
                 let data = buffer.get(2..length).ok_or(Error::Truncated)?;
                 match (kind, length) {
-                    (field::OPT_END, _) |
-                    (field::OPT_NOP, _) =>
-                        unreachable!(),
-                    (field::OPT_MSS, 4) =>
-                        option = TcpOption::MaxSegmentSize(NetworkEndian::read_u16(data)),
-                    (field::OPT_MSS, _) =>
-                        return Err(Error::Malformed),
-                    (field::OPT_WS, 3) =>
-                        option = TcpOption::WindowScale(data[0]),
-                    (field::OPT_WS, _) =>
-                        return Err(Error::Malformed),
-                    (field::OPT_SACKPERM, 2) =>
-                        option = TcpOption::SackPermitted,
-                    (field::OPT_SACKPERM, _) =>
-                        return Err(Error::Malformed),
+                    (field::OPT_END, _) | (field::OPT_NOP, _) => unreachable!(),
+                    (field::OPT_MSS, 4) => {
+                        option = TcpOption::MaxSegmentSize(NetworkEndian::read_u16(data))
+                    }
+                    (field::OPT_MSS, _) => return Err(Error::Malformed),
+                    (field::OPT_WS, 3) => option = TcpOption::WindowScale(data[0]),
+                    (field::OPT_WS, _) => return Err(Error::Malformed),
+                    (field::OPT_SACKPERM, 2) => option = TcpOption::SackPermitted,
+                    (field::OPT_SACKPERM, _) => return Err(Error::Malformed),
                     (field::OPT_SACKRNG, n) => {
-                        if n < 10 || (n-2) % 8 != 0 {
-                            return Err(Error::Malformed)
+                        if n < 10 || (n - 2) % 8 != 0 {
+                            return Err(Error::Malformed);
                         }
                         if n > 26 {
                             // It's possible for a remote to send 4 SACK blocks, but extremely rare.
@@ -622,19 +656,16 @@ impl<'a> TcpOption<'a> {
                             *nmut = if left < data.len() {
                                 let mid = left + 4;
                                 let right = mid + 4;
-                                let range_left = NetworkEndian::read_u32(
-                                    &data[left..mid]);
-                                let range_right = NetworkEndian::read_u32(
-                                    &data[mid..right]);
+                                let range_left = NetworkEndian::read_u32(&data[left..mid]);
+                                let range_right = NetworkEndian::read_u32(&data[mid..right]);
                                 Some((range_left, range_right))
                             } else {
                                 None
                             };
                         });
                         option = TcpOption::SackRange(sack_ranges);
-                    },
-                    (_, _) =>
-                        option = TcpOption::Unknown { kind, data }
+                    }
+                    (_, _) => option = TcpOption::Unknown { kind, data },
                 }
             }
         }
@@ -649,7 +680,7 @@ impl<'a> TcpOption<'a> {
             TcpOption::WindowScale(_) => 3,
             TcpOption::SackPermitted => 2,
             TcpOption::SackRange(s) => s.iter().filter(|s| s.is_some()).count() * 8 + 2,
-            TcpOption::Unknown { data, .. } => 2 + data.len()
+            TcpOption::Unknown { data, .. } => 2 + data.len(),
         }
     }
 
@@ -657,23 +688,21 @@ impl<'a> TcpOption<'a> {
         let length;
         match *self {
             TcpOption::EndOfList => {
-                length    = 1;
+                length = 1;
                 // There may be padding space which also should be initialized.
                 for p in buffer.iter_mut() {
                     *p = field::OPT_END;
                 }
             }
             TcpOption::NoOperation => {
-                length    = 1;
+                length = 1;
                 buffer[0] = field::OPT_NOP;
             }
             _ => {
-                length    = self.buffer_len();
+                length = self.buffer_len();
                 buffer[1] = length as u8;
                 match self {
-                    &TcpOption::EndOfList |
-                    &TcpOption::NoOperation =>
-                        unreachable!(),
+                    &TcpOption::EndOfList | &TcpOption::NoOperation => unreachable!(),
                     &TcpOption::MaxSegmentSize(value) => {
                         buffer[0] = field::OPT_MSS;
                         NetworkEndian::write_u16(&mut buffer[2..], value)
@@ -687,14 +716,21 @@ impl<'a> TcpOption<'a> {
                     }
                     &TcpOption::SackRange(slice) => {
                         buffer[0] = field::OPT_SACKRNG;
-                        slice.iter().filter(|s| s.is_some()).enumerate().for_each(|(i, s)| {
-                            let (first, second) = *s.as_ref().unwrap();
-                            let pos = i * 8 + 2;
-                            NetworkEndian::write_u32(&mut buffer[pos..], first);
-                            NetworkEndian::write_u32(&mut buffer[pos+4..], second);
-                        });
+                        slice
+                            .iter()
+                            .filter(|s| s.is_some())
+                            .enumerate()
+                            .for_each(|(i, s)| {
+                                let (first, second) = *s.as_ref().unwrap();
+                                let pos = i * 8 + 2;
+                                NetworkEndian::write_u32(&mut buffer[pos..], first);
+                                NetworkEndian::write_u32(&mut buffer[pos + 4..], second);
+                            });
                     }
-                    &TcpOption::Unknown { kind, data: provided } => {
+                    &TcpOption::Unknown {
+                        kind,
+                        data: provided,
+                    } => {
                         buffer[0] = kind;
                         buffer[2..].copy_from_slice(provided)
                     }
@@ -713,7 +749,7 @@ pub enum Control {
     Psh,
     Syn,
     Fin,
-    Rst
+    Rst,
 }
 
 #[allow(clippy::len_without_is_empty)]
@@ -721,8 +757,8 @@ impl Control {
     /// Return the length of a control flag, in terms of sequence space.
     pub fn len(self) -> usize {
         match self {
-            Control::Syn | Control::Fin  => 1,
-            _ => 0
+            Control::Syn | Control::Fin => 1,
+            _ => 0,
         }
     }
 
@@ -730,7 +766,7 @@ impl Control {
     pub fn quash_psh(self) -> Control {
         match self {
             Control::Psh => Control::None,
-            _ => self
+            _ => self,
         }
     }
 }
@@ -739,46 +775,54 @@ impl Control {
 #[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,
-    pub control:      Control,
-    pub seq_number:   SeqNumber,
-    pub ack_number:   Option<SeqNumber>,
-    pub window_len:   u16,
+    pub src_port: u16,
+    pub dst_port: u16,
+    pub control: Control,
+    pub seq_number: SeqNumber,
+    pub ack_number: Option<SeqNumber>,
+    pub window_len: u16,
     pub window_scale: Option<u8>,
     pub max_seg_size: Option<u16>,
     pub sack_permitted: bool,
-    pub sack_ranges:  [Option<(u32, u32)>; 3],
-    pub payload:      &'a [u8]
+    pub sack_ranges: [Option<(u32, u32)>; 3],
+    pub payload: &'a [u8],
 }
 
 impl<'a> Repr<'a> {
     /// Parse a Transmission Control Protocol packet and return a high-level representation.
-    pub fn parse<T>(packet: &Packet<&'a T>, src_addr: &IpAddress, dst_addr: &IpAddress,
-                    checksum_caps: &ChecksumCapabilities) -> Result<Repr<'a>>
-            where T: AsRef<[u8]> + ?Sized {
+    pub fn parse<T>(
+        packet: &Packet<&'a T>,
+        src_addr: &IpAddress,
+        dst_addr: &IpAddress,
+        checksum_caps: &ChecksumCapabilities,
+    ) -> Result<Repr<'a>>
+    where
+        T: AsRef<[u8]> + ?Sized,
+    {
         // Source and destination ports must be present.
-        if packet.src_port() == 0 { return Err(Error::Malformed) }
-        if packet.dst_port() == 0 { return Err(Error::Malformed) }
+        if packet.src_port() == 0 {
+            return Err(Error::Malformed);
+        }
+        if packet.dst_port() == 0 {
+            return Err(Error::Malformed);
+        }
         // Valid checksum is expected.
         if checksum_caps.tcp.rx() && !packet.verify_checksum(src_addr, dst_addr) {
-            return Err(Error::Checksum)
+            return Err(Error::Checksum);
         }
 
-        let control =
-            match (packet.syn(), packet.fin(), packet.rst(), packet.psh()) {
-                (false, false, false, false) => Control::None,
-                (false, false, false, true)  => Control::Psh,
-                (true,  false, false, _)     => Control::Syn,
-                (false, true,  false, _)     => Control::Fin,
-                (false, false, true , _)     => Control::Rst,
-                _ => return Err(Error::Malformed)
-            };
-        let ack_number =
-            match packet.ack() {
-                true  => Some(packet.ack_number()),
-                false => None
-            };
+        let control = match (packet.syn(), packet.fin(), packet.rst(), packet.psh()) {
+            (false, false, false, false) => Control::None,
+            (false, false, false, true) => Control::Psh,
+            (true, false, false, _) => Control::Syn,
+            (false, true, false, _) => Control::Fin,
+            (false, false, true, _) => Control::Rst,
+            _ => return Err(Error::Malformed),
+        };
+        let ack_number = match packet.ack() {
+            true => Some(packet.ack_number()),
+            false => None,
+        };
         // The PSH flag is ignored.
         // The URG flag and the urgent field is ignored. This behavior is standards-compliant,
         // however, most deployed systems (e.g. Linux) are *not* standards-compliant, and would
@@ -794,41 +838,44 @@ impl<'a> Repr<'a> {
             match option {
                 TcpOption::EndOfList => break,
                 TcpOption::NoOperation => (),
-                TcpOption::MaxSegmentSize(value) =>
-                    max_seg_size = Some(value),
+                TcpOption::MaxSegmentSize(value) => max_seg_size = Some(value),
                 TcpOption::WindowScale(value) => {
                     // RFC 1323: Thus, the shift count must be limited to 14 (which allows windows
                     // of 2**30 = 1 Gbyte). If a Window Scale option is received with a shift.cnt
                     // value exceeding 14, the TCP should log the error but use 14 instead of the
                     // specified value.
                     window_scale = if value > 14 {
-                        net_debug!("{}:{}:{}:{}: parsed window scaling factor >14, setting to 14", src_addr, packet.src_port(), dst_addr, packet.dst_port());
+                        net_debug!(
+                            "{}:{}:{}:{}: parsed window scaling factor >14, setting to 14",
+                            src_addr,
+                            packet.src_port(),
+                            dst_addr,
+                            packet.dst_port()
+                        );
                         Some(14)
                     } else {
                         Some(value)
                     };
-                },
-                TcpOption::SackPermitted =>
-                    sack_permitted = true,
-                TcpOption::SackRange(slice) =>
-                    sack_ranges = slice,
+                }
+                TcpOption::SackPermitted => sack_permitted = true,
+                TcpOption::SackRange(slice) => sack_ranges = slice,
                 _ => (),
             }
             options = next_options;
         }
 
         Ok(Repr {
-            src_port:     packet.src_port(),
-            dst_port:     packet.dst_port(),
-            control:      control,
-            seq_number:   packet.seq_number(),
-            ack_number:   ack_number,
-            window_len:   packet.window_len(),
+            src_port: packet.src_port(),
+            dst_port: packet.dst_port(),
+            control: control,
+            seq_number: packet.seq_number(),
+            ack_number: ack_number,
+            window_len: packet.window_len(),
             window_scale: window_scale,
             max_seg_size: max_seg_size,
             sack_permitted: sack_permitted,
-            sack_ranges:   sack_ranges,
-            payload:      packet.payload()
+            sack_ranges: sack_ranges,
+            payload: packet.payload(),
         })
     }
 
@@ -847,9 +894,11 @@ impl<'a> Repr<'a> {
         if self.sack_permitted {
             length += 2;
         }
-        let sack_range_len: usize = self.sack_ranges.iter().map(
-            |o| o.map(|_| 8).unwrap_or(0)
-            ).sum();
+        let sack_range_len: usize = self
+            .sack_ranges
+            .iter()
+            .map(|o| o.map(|_| 8).unwrap_or(0))
+            .sum();
         if sack_range_len > 0 {
             length += sack_range_len + 2;
         }
@@ -865,9 +914,15 @@ impl<'a> Repr<'a> {
     }
 
     /// Emit a high-level representation into a Transmission Control Protocol packet.
-    pub fn emit<T>(&self, packet: &mut Packet<&mut T>, src_addr: &IpAddress, dst_addr: &IpAddress,
-                   checksum_caps: &ChecksumCapabilities)
-            where T: AsRef<[u8]> + AsMut<[u8]> + ?Sized {
+    pub fn emit<T>(
+        &self,
+        packet: &mut Packet<&mut T>,
+        src_addr: &IpAddress,
+        dst_addr: &IpAddress,
+        checksum_caps: &ChecksumCapabilities,
+    ) where
+        T: AsRef<[u8]> + AsMut<[u8]> + ?Sized,
+    {
         packet.set_src_port(self.src_port);
         packet.set_dst_port(self.dst_port);
         packet.set_seq_number(self.seq_number);
@@ -877,24 +932,28 @@ impl<'a> Repr<'a> {
         packet.clear_flags();
         match self.control {
             Control::None => (),
-            Control::Psh  => packet.set_psh(true),
-            Control::Syn  => packet.set_syn(true),
-            Control::Fin  => packet.set_fin(true),
-            Control::Rst  => packet.set_rst(true)
+            Control::Psh => packet.set_psh(true),
+            Control::Syn => packet.set_syn(true),
+            Control::Fin => packet.set_fin(true),
+            Control::Rst => packet.set_rst(true),
         }
         packet.set_ack(self.ack_number.is_some());
         {
             let mut options = packet.options_mut();
             if let Some(value) = self.max_seg_size {
-                let tmp = options; options = TcpOption::MaxSegmentSize(value).emit(tmp);
+                let tmp = options;
+                options = TcpOption::MaxSegmentSize(value).emit(tmp);
             }
             if let Some(value) = self.window_scale {
-                let tmp = options; options = TcpOption::WindowScale(value).emit(tmp);
+                let tmp = options;
+                options = TcpOption::WindowScale(value).emit(tmp);
             }
             if self.sack_permitted {
-                let tmp = options; options = TcpOption::SackPermitted.emit(tmp);
+                let tmp = options;
+                options = TcpOption::SackPermitted.emit(tmp);
             } else if self.ack_number.is_some() && self.sack_ranges.iter().any(|s| s.is_some()) {
-                let tmp = options; options = TcpOption::SackRange(self.sack_ranges).emit(tmp);
+                let tmp = options;
+                options = TcpOption::SackRange(self.sack_ranges).emit(tmp);
             }
 
             if !options.is_empty() {
@@ -922,8 +981,8 @@ impl<'a> Repr<'a> {
     pub fn is_empty(&self) -> bool {
         match self.control {
             _ if !self.payload.is_empty() => false,
-            Control::Syn  | Control::Fin | Control::Rst => false,
-            Control::None | Control::Psh => true
+            Control::Syn | Control::Fin | Control::Rst => false,
+            Control::None | Control::Psh => true,
         }
     }
 }
@@ -931,15 +990,28 @@ impl<'a> Repr<'a> {
 impl<'a, T: AsRef<[u8]> + ?Sized> fmt::Display for Packet<&'a T> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         // Cannot use Repr::parse because we don't have the IP addresses.
-        write!(f, "TCP src={} dst={}",
-               self.src_port(), self.dst_port())?;
-        if self.syn() { write!(f, " syn")? }
-        if self.fin() { write!(f, " fin")? }
-        if self.rst() { write!(f, " rst")? }
-        if self.psh() { write!(f, " psh")? }
-        if self.ece() { write!(f, " ece")? }
-        if self.cwr() { write!(f, " cwr")? }
-        if self.ns()  { write!(f, " ns" )? }
+        write!(f, "TCP src={} dst={}", self.src_port(), self.dst_port())?;
+        if self.syn() {
+            write!(f, " syn")?
+        }
+        if self.fin() {
+            write!(f, " fin")?
+        }
+        if self.rst() {
+            write!(f, " rst")?
+        }
+        if self.psh() {
+            write!(f, " psh")?
+        }
+        if self.ece() {
+            write!(f, " ece")?
+        }
+        if self.cwr() {
+            write!(f, " cwr")?
+        }
+        if self.ns() {
+            write!(f, " ns")?
+        }
         write!(f, " seq={}", self.seq_number())?;
         if self.ack() {
             write!(f, " ack={}", self.ack_number())?;
@@ -952,24 +1024,18 @@ impl<'a, T: AsRef<[u8]> + ?Sized> fmt::Display for Packet<&'a T> {
 
         let mut options = self.options();
         while !options.is_empty() {
-            let (next_options, option) =
-                match TcpOption::parse(options) {
-                    Ok(res) => res,
-                    Err(err) => return write!(f, " ({})", err)
-                };
+            let (next_options, option) = match TcpOption::parse(options) {
+                Ok(res) => res,
+                Err(err) => return write!(f, " ({})", err),
+            };
             match option {
                 TcpOption::EndOfList => break,
                 TcpOption::NoOperation => (),
-                TcpOption::MaxSegmentSize(value) =>
-                    write!(f, " mss={}", value)?,
-                TcpOption::WindowScale(value) =>
-                    write!(f, " ws={}", value)?,
-                TcpOption::SackPermitted =>
-                    write!(f, " sACK")?,
-                TcpOption::SackRange(slice) =>
-                    write!(f, " sACKr{:?}", slice)?, // debug print conveniently includes the []s
-                TcpOption::Unknown { kind, .. } =>
-                    write!(f, " opt({})", kind)?,
+                TcpOption::MaxSegmentSize(value) => write!(f, " mss={}", value)?,
+                TcpOption::WindowScale(value) => write!(f, " ws={}", value)?,
+                TcpOption::SackPermitted => write!(f, " sACK")?,
+                TcpOption::SackRange(slice) => write!(f, " sACKr{:?}", slice)?, // debug print conveniently includes the []s
+                TcpOption::Unknown { kind, .. } => write!(f, " opt({})", kind)?,
             }
             options = next_options;
         }
@@ -979,14 +1045,13 @@ impl<'a, T: AsRef<[u8]> + ?Sized> fmt::Display for Packet<&'a T> {
 
 impl<'a> fmt::Display for Repr<'a> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        write!(f, "TCP src={} dst={}",
-               self.src_port, self.dst_port)?;
+        write!(f, "TCP src={} dst={}", self.src_port, self.dst_port)?;
         match self.control {
             Control::Syn => write!(f, " syn")?,
             Control::Fin => write!(f, " fin")?,
             Control::Rst => write!(f, " rst")?,
             Control::Psh => write!(f, " psh")?,
-            Control::None => ()
+            Control::None => (),
         }
         write!(f, " seq={}", self.seq_number)?;
         if let Some(ack_number) = self.ack_number {
@@ -1001,23 +1066,26 @@ impl<'a> fmt::Display for Repr<'a> {
     }
 }
 
-use crate::wire::pretty_print::{PrettyPrint, PrettyIndent};
+use crate::wire::pretty_print::{PrettyIndent, PrettyPrint};
 
 impl<T: AsRef<[u8]>> PrettyPrint for Packet<T> {
-    fn pretty_print(buffer: &dyn AsRef<[u8]>, f: &mut fmt::Formatter,
-                    indent: &mut PrettyIndent) -> fmt::Result {
+    fn pretty_print(
+        buffer: &dyn AsRef<[u8]>,
+        f: &mut fmt::Formatter,
+        indent: &mut PrettyIndent,
+    ) -> fmt::Result {
         match Packet::new_checked(buffer) {
-            Err(err)   => write!(f, "{}({})", indent, err),
-            Ok(packet) => write!(f, "{}{}", indent, packet)
+            Err(err) => write!(f, "{}({})", indent, err),
+            Ok(packet) => write!(f, "{}{}", indent, packet),
         }
     }
 }
 
 #[cfg(test)]
 mod test {
+    use super::*;
     #[cfg(feature = "proto-ipv4")]
     use crate::wire::Ipv4Address;
-    use super::*;
 
     #[cfg(feature = "proto-ipv4")]
     const SRC_ADDR: Ipv4Address = Ipv4Address([192, 168, 1, 1]);
@@ -1025,22 +1093,16 @@ mod test {
     const DST_ADDR: Ipv4Address = Ipv4Address([192, 168, 1, 2]);
 
     #[cfg(feature = "proto-ipv4")]
-    static PACKET_BYTES: [u8; 28] =
-        [0xbf, 0x00, 0x00, 0x50,
-         0x01, 0x23, 0x45, 0x67,
-         0x89, 0xab, 0xcd, 0xef,
-         0x60, 0x35, 0x01, 0x23,
-         0x01, 0xb6, 0x02, 0x01,
-         0x03, 0x03, 0x0c, 0x01,
-         0xaa, 0x00, 0x00, 0xff];
+    static PACKET_BYTES: [u8; 28] = [
+        0xbf, 0x00, 0x00, 0x50, 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0x60, 0x35, 0x01,
+        0x23, 0x01, 0xb6, 0x02, 0x01, 0x03, 0x03, 0x0c, 0x01, 0xaa, 0x00, 0x00, 0xff,
+    ];
 
     #[cfg(feature = "proto-ipv4")]
-    static OPTION_BYTES: [u8; 4] =
-        [0x03, 0x03, 0x0c, 0x01];
+    static OPTION_BYTES: [u8; 4] = [0x03, 0x03, 0x0c, 0x01];
 
     #[cfg(feature = "proto-ipv4")]
-    static PAYLOAD_BYTES: [u8; 4] =
-        [0xaa, 0x00, 0x00, 0xff];
+    static PAYLOAD_BYTES: [u8; 4] = [0xaa, 0x00, 0x00, 0xff];
 
     #[test]
     #[cfg(feature = "proto-ipv4")]
@@ -1062,7 +1124,10 @@ mod test {
         assert_eq!(packet.checksum(), 0x01b6);
         assert_eq!(packet.options(), &OPTION_BYTES[..]);
         assert_eq!(packet.payload(), &PAYLOAD_BYTES[..]);
-        assert_eq!(packet.verify_checksum(&SRC_ADDR.into(), &DST_ADDR.into()), true);
+        assert_eq!(
+            packet.verify_checksum(&SRC_ADDR.into(), &DST_ADDR.into()),
+            true
+        );
     }
 
     #[test]
@@ -1107,28 +1172,25 @@ mod test {
     }
 
     #[cfg(feature = "proto-ipv4")]
-    static SYN_PACKET_BYTES: [u8; 24] =
-        [0xbf, 0x00, 0x00, 0x50,
-         0x01, 0x23, 0x45, 0x67,
-         0x00, 0x00, 0x00, 0x00,
-         0x50, 0x02, 0x01, 0x23,
-         0x7a, 0x8d, 0x00, 0x00,
-         0xaa, 0x00, 0x00, 0xff];
+    static SYN_PACKET_BYTES: [u8; 24] = [
+        0xbf, 0x00, 0x00, 0x50, 0x01, 0x23, 0x45, 0x67, 0x00, 0x00, 0x00, 0x00, 0x50, 0x02, 0x01,
+        0x23, 0x7a, 0x8d, 0x00, 0x00, 0xaa, 0x00, 0x00, 0xff,
+    ];
 
     #[cfg(feature = "proto-ipv4")]
     fn packet_repr() -> Repr<'static> {
         Repr {
-            src_port:     48896,
-            dst_port:     80,
-            seq_number:   SeqNumber(0x01234567),
-            ack_number:   None,
-            window_len:   0x0123,
+            src_port: 48896,
+            dst_port: 80,
+            seq_number: SeqNumber(0x01234567),
+            ack_number: None,
+            window_len: 0x0123,
             window_scale: None,
-            control:      Control::Syn,
+            control: Control::Syn,
             max_seg_size: None,
             sack_permitted: false,
-            sack_ranges:  [None, None, None],
-            payload:      &PAYLOAD_BYTES
+            sack_ranges: [None, None, None],
+            payload: &PAYLOAD_BYTES,
         }
     }
 
@@ -1136,7 +1198,13 @@ mod test {
     #[cfg(feature = "proto-ipv4")]
     fn test_parse() {
         let packet = Packet::new_unchecked(&SYN_PACKET_BYTES[..]);
-        let repr = Repr::parse(&packet, &SRC_ADDR.into(), &DST_ADDR.into(), &ChecksumCapabilities::default()).unwrap();
+        let repr = Repr::parse(
+            &packet,
+            &SRC_ADDR.into(),
+            &DST_ADDR.into(),
+            &ChecksumCapabilities::default(),
+        )
+        .unwrap();
         assert_eq!(repr, packet_repr());
     }
 
@@ -1146,7 +1214,12 @@ mod test {
         let repr = packet_repr();
         let mut bytes = vec![0xa5; repr.buffer_len()];
         let mut packet = Packet::new_unchecked(&mut bytes);
-        repr.emit(&mut packet, &SRC_ADDR.into(), &DST_ADDR.into(), &ChecksumCapabilities::default());
+        repr.emit(
+            &mut packet,
+            &SRC_ADDR.into(),
+            &DST_ADDR.into(),
+            &ChecksumCapabilities::default(),
+        );
         assert_eq!(&packet.into_inner()[..], &SYN_PACKET_BYTES[..]);
     }
 
@@ -1159,57 +1232,62 @@ mod test {
     }
 
     macro_rules! assert_option_parses {
-        ($opt:expr, $data:expr) => ({
+        ($opt:expr, $data:expr) => {{
             assert_eq!(TcpOption::parse($data), Ok((&[][..], $opt)));
             let buffer = &mut [0; 40][..$opt.buffer_len()];
             assert_eq!($opt.emit(buffer), &mut []);
             assert_eq!(&*buffer, $data);
-        })
+        }};
     }
 
     #[test]
     fn test_tcp_options() {
-        assert_option_parses!(TcpOption::EndOfList,
-                              &[0x00]);
-        assert_option_parses!(TcpOption::NoOperation,
-                              &[0x01]);
-        assert_option_parses!(TcpOption::MaxSegmentSize(1500),
-                              &[0x02, 0x04, 0x05, 0xdc]);
-        assert_option_parses!(TcpOption::WindowScale(12),
-                              &[0x03, 0x03, 0x0c]);
-        assert_option_parses!(TcpOption::SackPermitted,
-                              &[0x4, 0x02]);
-        assert_option_parses!(TcpOption::SackRange([Some((500, 1500)), None, None]),
-                              &[0x05, 0x0a,
-                                0x00, 0x00, 0x01, 0xf4, 0x00, 0x00, 0x05, 0xdc]);
-        assert_option_parses!(TcpOption::SackRange([Some((875, 1225)), Some((1500, 2500)), None]),
-                              &[0x05, 0x12,
-                                0x00, 0x00, 0x03, 0x6b, 0x00, 0x00, 0x04, 0xc9,
-                                0x00, 0x00, 0x05, 0xdc, 0x00, 0x00, 0x09, 0xc4]);
-        assert_option_parses!(TcpOption::SackRange([Some((875000, 1225000)),
-                                                    Some((1500000, 2500000)),
-                                                    Some((876543210, 876654320))]),
-                              &[0x05, 0x1a,
-                                0x00, 0x0d, 0x59, 0xf8, 0x00, 0x12, 0xb1, 0x28,
-                                0x00, 0x16, 0xe3, 0x60, 0x00, 0x26, 0x25, 0xa0,
-                                0x34, 0x3e, 0xfc, 0xea, 0x34, 0x40, 0xae, 0xf0]);
-        assert_option_parses!(TcpOption::Unknown { kind: 12, data: &[1, 2, 3][..] },
-                              &[0x0c, 0x05, 0x01, 0x02, 0x03])
+        assert_option_parses!(TcpOption::EndOfList, &[0x00]);
+        assert_option_parses!(TcpOption::NoOperation, &[0x01]);
+        assert_option_parses!(TcpOption::MaxSegmentSize(1500), &[0x02, 0x04, 0x05, 0xdc]);
+        assert_option_parses!(TcpOption::WindowScale(12), &[0x03, 0x03, 0x0c]);
+        assert_option_parses!(TcpOption::SackPermitted, &[0x4, 0x02]);
+        assert_option_parses!(
+            TcpOption::SackRange([Some((500, 1500)), None, None]),
+            &[0x05, 0x0a, 0x00, 0x00, 0x01, 0xf4, 0x00, 0x00, 0x05, 0xdc]
+        );
+        assert_option_parses!(
+            TcpOption::SackRange([Some((875, 1225)), Some((1500, 2500)), None]),
+            &[
+                0x05, 0x12, 0x00, 0x00, 0x03, 0x6b, 0x00, 0x00, 0x04, 0xc9, 0x00, 0x00, 0x05, 0xdc,
+                0x00, 0x00, 0x09, 0xc4
+            ]
+        );
+        assert_option_parses!(
+            TcpOption::SackRange([
+                Some((875000, 1225000)),
+                Some((1500000, 2500000)),
+                Some((876543210, 876654320))
+            ]),
+            &[
+                0x05, 0x1a, 0x00, 0x0d, 0x59, 0xf8, 0x00, 0x12, 0xb1, 0x28, 0x00, 0x16, 0xe3, 0x60,
+                0x00, 0x26, 0x25, 0xa0, 0x34, 0x3e, 0xfc, 0xea, 0x34, 0x40, 0xae, 0xf0
+            ]
+        );
+        assert_option_parses!(
+            TcpOption::Unknown {
+                kind: 12,
+                data: &[1, 2, 3][..]
+            },
+            &[0x0c, 0x05, 0x01, 0x02, 0x03]
+        )
     }
 
     #[test]
     fn test_malformed_tcp_options() {
-        assert_eq!(TcpOption::parse(&[]),
-                   Err(Error::Truncated));
-        assert_eq!(TcpOption::parse(&[0xc]),
-                   Err(Error::Truncated));
-        assert_eq!(TcpOption::parse(&[0xc, 0x05, 0x01, 0x02]),
-                   Err(Error::Truncated));
-        assert_eq!(TcpOption::parse(&[0xc, 0x01]),
-                   Err(Error::Truncated));
-        assert_eq!(TcpOption::parse(&[0x2, 0x02]),
-                   Err(Error::Malformed));
-        assert_eq!(TcpOption::parse(&[0x3, 0x02]),
-                   Err(Error::Malformed));
+        assert_eq!(TcpOption::parse(&[]), Err(Error::Truncated));
+        assert_eq!(TcpOption::parse(&[0xc]), Err(Error::Truncated));
+        assert_eq!(
+            TcpOption::parse(&[0xc, 0x05, 0x01, 0x02]),
+            Err(Error::Truncated)
+        );
+        assert_eq!(TcpOption::parse(&[0xc, 0x01]), Err(Error::Truncated));
+        assert_eq!(TcpOption::parse(&[0x2, 0x02]), Err(Error::Malformed));
+        assert_eq!(TcpOption::parse(&[0x3, 0x02]), Err(Error::Malformed));
     }
 }

+ 86 - 55
src/wire/udp.rs

@@ -1,16 +1,16 @@
-use core::fmt;
 use byteorder::{ByteOrder, NetworkEndian};
+use core::fmt;
 
-use crate::{Error, Result};
 use crate::phy::ChecksumCapabilities;
-use crate::wire::{IpProtocol, IpAddress};
 use crate::wire::ip::checksum;
+use crate::wire::{IpAddress, IpProtocol};
+use crate::{Error, Result};
 
 /// 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<T: AsRef<[u8]>> {
-    buffer: T
+    buffer: T,
 }
 
 mod field {
@@ -20,7 +20,7 @@ mod field {
 
     pub const SRC_PORT: Field = 0..2;
     pub const DST_PORT: Field = 2..4;
-    pub const LENGTH:   Field = 4..6;
+    pub const LENGTH: Field = 4..6;
     pub const CHECKSUM: Field = 6..8;
 
     pub fn PAYLOAD(length: u16) -> Field {
@@ -113,13 +113,14 @@ impl<T: AsRef<[u8]>> Packet<T> {
     /// # Fuzzing
     /// This function always returns `true` when fuzzing.
     pub fn verify_checksum(&self, src_addr: &IpAddress, dst_addr: &IpAddress) -> bool {
-        if cfg!(fuzzing) { return true }
+        if cfg!(fuzzing) {
+            return true;
+        }
 
         let data = self.buffer.as_ref();
         checksum::combine(&[
-            checksum::pseudo_header(src_addr, dst_addr, IpProtocol::Udp,
-                                    self.len() as u32),
-            checksum::data(&data[..self.len() as usize])
+            checksum::pseudo_header(src_addr, dst_addr, IpProtocol::Udp, self.len() as u32),
+            checksum::data(&data[..self.len() as usize]),
         ]) == !0
     }
 }
@@ -173,9 +174,8 @@ impl<T: AsRef<[u8]> + AsMut<[u8]>> Packet<T> {
         let checksum = {
             let data = self.buffer.as_ref();
             !checksum::combine(&[
-                checksum::pseudo_header(src_addr, dst_addr, IpProtocol::Udp,
-                                        self.len() as u32),
-                checksum::data(&data[..self.len() as usize])
+                checksum::pseudo_header(src_addr, dst_addr, IpProtocol::Udp, self.len() as u32),
+                checksum::data(&data[..self.len() as usize]),
             ])
         };
         // UDP checksum value of 0 means no checksum; if the checksum really is zero,
@@ -210,21 +210,26 @@ pub struct Repr {
 
 impl Repr {
     /// Parse an User Datagram Protocol packet and return a high-level representation.
-    pub fn parse<T>(packet: &Packet<&T>, src_addr: &IpAddress, dst_addr: &IpAddress,
-                    checksum_caps: &ChecksumCapabilities) -> Result<Repr>
-            where T: AsRef<[u8]> + ?Sized {
+    pub fn parse<T>(
+        packet: &Packet<&T>,
+        src_addr: &IpAddress,
+        dst_addr: &IpAddress,
+        checksum_caps: &ChecksumCapabilities,
+    ) -> Result<Repr>
+    where
+        T: AsRef<[u8]> + ?Sized,
+    {
         // Destination port cannot be omitted (but source port can be).
-        if packet.dst_port() == 0 { return Err(Error::Malformed) }
+        if packet.dst_port() == 0 {
+            return Err(Error::Malformed);
+        }
         // Valid checksum is expected...
         if checksum_caps.udp.rx() && !packet.verify_checksum(src_addr, dst_addr) {
             match (src_addr, dst_addr) {
                 // ... except on UDP-over-IPv4, where it can be omitted.
                 #[cfg(feature = "proto-ipv4")]
-                (&IpAddress::Ipv4(_), &IpAddress::Ipv4(_))
-                    if packet.checksum() == 0 => (),
-                _ => {
-                    return Err(Error::Checksum)
-                }
+                (&IpAddress::Ipv4(_), &IpAddress::Ipv4(_)) if packet.checksum() == 0 => (),
+                _ => return Err(Error::Checksum),
             }
         }
 
@@ -240,13 +245,17 @@ impl Repr {
     }
 
     /// Emit a high-level representation into an User Datagram Protocol packet.
-    pub fn emit<T: ?Sized>(&self, packet: &mut Packet<&mut T>,
-                           src_addr: &IpAddress,
-                           dst_addr: &IpAddress,
-                           payload_len: usize,
-                           emit_payload: impl FnOnce(&mut [u8]),
-                           checksum_caps: &ChecksumCapabilities)
-            where T: AsRef<[u8]> + AsMut<[u8]> {
+    pub fn emit<T: ?Sized>(
+        &self,
+        packet: &mut Packet<&mut T>,
+        src_addr: &IpAddress,
+        dst_addr: &IpAddress,
+        payload_len: usize,
+        emit_payload: impl FnOnce(&mut [u8]),
+        checksum_caps: &ChecksumCapabilities,
+    ) where
+        T: AsRef<[u8]> + AsMut<[u8]>,
+    {
         packet.set_src_port(self.src_port);
         packet.set_dst_port(self.dst_port);
         packet.set_len((HEADER_LEN + payload_len) as u16);
@@ -265,8 +274,13 @@ impl Repr {
 impl<'a, T: AsRef<[u8]> + ?Sized> fmt::Display for Packet<&'a T> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         // Cannot use Repr::parse because we don't have the IP addresses.
-        write!(f, "UDP src={} dst={} len={}",
-               self.src_port(), self.dst_port(), self.payload().len())
+        write!(
+            f,
+            "UDP src={} dst={} len={}",
+            self.src_port(),
+            self.dst_port(),
+            self.payload().len()
+        )
     }
 }
 
@@ -276,23 +290,26 @@ impl fmt::Display for Repr {
     }
 }
 
-use crate::wire::pretty_print::{PrettyPrint, PrettyIndent};
+use crate::wire::pretty_print::{PrettyIndent, PrettyPrint};
 
 impl<T: AsRef<[u8]>> PrettyPrint for Packet<T> {
-    fn pretty_print(buffer: &dyn AsRef<[u8]>, f: &mut fmt::Formatter,
-                    indent: &mut PrettyIndent) -> fmt::Result {
+    fn pretty_print(
+        buffer: &dyn AsRef<[u8]>,
+        f: &mut fmt::Formatter,
+        indent: &mut PrettyIndent,
+    ) -> fmt::Result {
         match Packet::new_checked(buffer) {
-            Err(err)   => write!(f, "{}({})", indent, err),
-            Ok(packet) => write!(f, "{}{}", indent, packet)
+            Err(err) => write!(f, "{}({})", indent, err),
+            Ok(packet) => write!(f, "{}{}", indent, packet),
         }
     }
 }
 
 #[cfg(test)]
 mod test {
+    use super::*;
     #[cfg(feature = "proto-ipv4")]
     use crate::wire::Ipv4Address;
-    use super::*;
 
     #[cfg(feature = "proto-ipv4")]
     const SRC_ADDR: Ipv4Address = Ipv4Address([192, 168, 1, 1]);
@@ -300,20 +317,17 @@ mod test {
     const DST_ADDR: Ipv4Address = Ipv4Address([192, 168, 1, 2]);
 
     #[cfg(feature = "proto-ipv4")]
-    static PACKET_BYTES: [u8; 12] =
-        [0xbf, 0x00, 0x00, 0x35,
-         0x00, 0x0c, 0x12, 0x4d,
-         0xaa, 0x00, 0x00, 0xff];
+    static PACKET_BYTES: [u8; 12] = [
+        0xbf, 0x00, 0x00, 0x35, 0x00, 0x0c, 0x12, 0x4d, 0xaa, 0x00, 0x00, 0xff,
+    ];
 
     #[cfg(feature = "proto-ipv4")]
-    static NO_CHECKSUM_PACKET: [u8; 12] =
-        [0xbf, 0x00, 0x00, 0x35,
-         0x00, 0x0c, 0x00, 0x00,
-         0xaa, 0x00, 0x00, 0xff];
+    static NO_CHECKSUM_PACKET: [u8; 12] = [
+        0xbf, 0x00, 0x00, 0x35, 0x00, 0x0c, 0x00, 0x00, 0xaa, 0x00, 0x00, 0xff,
+    ];
 
     #[cfg(feature = "proto-ipv4")]
-    static PAYLOAD_BYTES: [u8; 4] =
-        [0xaa, 0x00, 0x00, 0xff];
+    static PAYLOAD_BYTES: [u8; 4] = [0xaa, 0x00, 0x00, 0xff];
 
     #[test]
     #[cfg(feature = "proto-ipv4")]
@@ -324,7 +338,10 @@ mod test {
         assert_eq!(packet.len(), 12);
         assert_eq!(packet.checksum(), 0x124d);
         assert_eq!(packet.payload(), &PAYLOAD_BYTES[..]);
-        assert_eq!(packet.verify_checksum(&SRC_ADDR.into(), &DST_ADDR.into()), true);
+        assert_eq!(
+            packet.verify_checksum(&SRC_ADDR.into(), &DST_ADDR.into()),
+            true
+        );
     }
 
     #[test]
@@ -373,8 +390,13 @@ mod test {
     #[cfg(feature = "proto-ipv4")]
     fn test_parse() {
         let packet = Packet::new_unchecked(&PACKET_BYTES[..]);
-        let repr = Repr::parse(&packet, &SRC_ADDR.into(), &DST_ADDR.into(),
-                               &ChecksumCapabilities::default()).unwrap();
+        let repr = Repr::parse(
+            &packet,
+            &SRC_ADDR.into(),
+            &DST_ADDR.into(),
+            &ChecksumCapabilities::default(),
+        )
+        .unwrap();
         assert_eq!(repr, packet_repr());
     }
 
@@ -384,10 +406,14 @@ mod test {
         let repr = packet_repr();
         let mut bytes = vec![0xa5; repr.header_len() + PAYLOAD_BYTES.len()];
         let mut packet = Packet::new_unchecked(&mut bytes);
-        repr.emit(&mut packet, &SRC_ADDR.into(), &DST_ADDR.into(),
-                  PAYLOAD_BYTES.len(),
-                  |payload| payload.copy_from_slice(&PAYLOAD_BYTES),
-                  &ChecksumCapabilities::default());
+        repr.emit(
+            &mut packet,
+            &SRC_ADDR.into(),
+            &DST_ADDR.into(),
+            PAYLOAD_BYTES.len(),
+            |payload| payload.copy_from_slice(&PAYLOAD_BYTES),
+            &ChecksumCapabilities::default(),
+        );
         assert_eq!(&packet.into_inner()[..], &PACKET_BYTES[..]);
     }
 
@@ -395,8 +421,13 @@ mod test {
     #[cfg(feature = "proto-ipv4")]
     fn test_checksum_omitted() {
         let packet = Packet::new_unchecked(&NO_CHECKSUM_PACKET[..]);
-        let repr = Repr::parse(&packet, &SRC_ADDR.into(), &DST_ADDR.into(),
-                               &ChecksumCapabilities::default()).unwrap();
+        let repr = Repr::parse(
+            &packet,
+            &SRC_ADDR.into(),
+            &DST_ADDR.into(),
+            &ChecksumCapabilities::default(),
+        )
+        .unwrap();
         assert_eq!(repr, packet_repr());
     }
 }

+ 28 - 19
utils/packet2pcap.rs

@@ -1,15 +1,18 @@
+use getopts::Options;
+use smoltcp::phy::{PcapLinkType, PcapSink};
+use smoltcp::time::Instant;
 use std::cell::RefCell;
+use std::env;
+use std::fs::File;
 use std::io::{self, Read, Write};
 use std::path::Path;
-use std::fs::File;
-use std::env;
 use std::process::exit;
-use smoltcp::phy::{PcapLinkType, PcapSink};
-use smoltcp::time::Instant;
-use getopts::Options;
 
-fn convert(packet_filename: &Path, pcap_filename: &Path, link_type: PcapLinkType)
-          -> io::Result<()> {
+fn convert(
+    packet_filename: &Path,
+    pcap_filename: &Path,
+    link_type: PcapLinkType,
+) -> io::Result<()> {
     let mut packet_file = File::open(packet_filename)?;
     let mut packet = Vec::new();
     packet_file.read_to_end(&mut packet)?;
@@ -35,31 +38,37 @@ fn main() {
 
     let mut opts = Options::new();
     opts.optflag("h", "help", "print this help menu");
-    opts.optopt("t", "link-type", "set link type (one of: ethernet ip)", "TYPE");
+    opts.optopt(
+        "t",
+        "link-type",
+        "set link type (one of: ethernet ip)",
+        "TYPE",
+    );
 
     let matches = match opts.parse(&args[1..]) {
         Ok(m) => m,
         Err(e) => {
             eprintln!("{}", e);
-            return
+            return;
         }
     };
 
-    let link_type =
-        match matches.opt_str("t").as_ref().map(|s| &s[..]) {
-            Some("ethernet") => Some(PcapLinkType::Ethernet),
-            Some("ip") => Some(PcapLinkType::Ip),
-            _ => None
-        };
+    let link_type = match matches.opt_str("t").as_ref().map(|s| &s[..]) {
+        Some("ethernet") => Some(PcapLinkType::Ethernet),
+        Some("ip") => Some(PcapLinkType::Ip),
+        _ => None,
+    };
 
     if matches.opt_present("h") || matches.free.len() != 2 || link_type.is_none() {
         print_usage(&program, opts);
-        return
+        return;
     }
 
-    match convert(Path::new(&matches.free[0]),
-                  Path::new(&matches.free[1]),
-                  link_type.unwrap()) {
+    match convert(
+        Path::new(&matches.free[0]),
+        Path::new(&matches.free[1]),
+        link_type.unwrap(),
+    ) {
         Ok(()) => (),
         Err(e) => {
             eprintln!("Cannot convert packet to pcap: {}", e);

Some files were not shown because too many files changed in this diff