[rustack] wire::ipv4: Use wire::util::packet

Change-Id: I73f5cf6b5117e4e37bd52a9110992750222bc53f
diff --git a/bin/recovery-netstack/src/wire/ipv4.rs b/bin/recovery-netstack/src/wire/ipv4.rs
index 6ad77c4..9ac3a15 100644
--- a/bin/recovery-netstack/src/wire/ipv4.rs
+++ b/bin/recovery-netstack/src/wire/ipv4.rs
@@ -3,10 +3,12 @@
 // found in the LICENSE file.
 
 use byteorder::{BigEndian, ByteOrder};
-use zerocopy::{AsBytes, ByteSlice, FromBytes, LayoutVerified};
+use zerocopy::{AsBytes, ByteSlice, FromBytes, Unaligned};
 
 use ip::{Ipv4Addr, Ipv4Option};
-use wire::util::{Checksum, Options, PacketFormat};
+use wire::util::packet;
+use wire::util::packet::{PacketWithOptions, PacketWithOptionsParseErr};
+use wire::util::{Checksum, OptionParseErr, Options, PacketFormat};
 
 use self::options::Ipv4OptionImpl;
 
@@ -35,6 +37,7 @@
 
 unsafe impl FromBytes for HeaderPrefix {}
 unsafe impl AsBytes for HeaderPrefix {}
+unsafe impl Unaligned for HeaderPrefix {}
 
 impl HeaderPrefix {
     fn version(&self) -> u8 {
@@ -46,144 +49,155 @@
     }
 }
 
+impl packet::Header for HeaderPrefix {
+    type Error = ();
+
+    fn total_packet_len(&self) -> Result<Option<usize>, ()> {
+        Ok(Some(BigEndian::read_u16(&self.total_len[..]) as usize))
+    }
+}
+
+impl packet::HeaderPrefix for HeaderPrefix {
+    fn total_header_len(&self) -> Result<usize, ()> {
+        Ok(self.ihl() as usize * 4)
+    }
+}
+
 /// An IPv4 packet.
 ///
 /// An `Ipv4Packet` shares its underlying memory with the byte slice it was
 /// parsed from or serialized to, meaning that no copying or extra allocation is
 /// necessary.
-pub struct Ipv4Packet<B> {
-    hdr_prefix: LayoutVerified<B, HeaderPrefix>,
-    options: Options<B, Ipv4OptionImpl>,
-    body: B,
-}
+// pub struct Ipv4Packet<B> {
+//     hdr_prefix: LayoutVerified<B, HeaderPrefix>,
+//     options: Options<B, Ipv4OptionImpl>,
+//     body: B,
+// }
+
+pub struct Ipv4Packet<B>(PacketWithOptions<B, HeaderPrefix, Options<B, Ipv4OptionImpl>>);
 
 impl<B> PacketFormat for Ipv4Packet<B> {
     const MAX_HEADER_BYTES: usize = 60;
     const MAX_FOOTER_BYTES: usize = 0;
 }
 
+pub enum Ipv4ParseErr {
+    Packet(PacketWithOptionsParseErr<(), OptionParseErr<()>>),
+    Version,
+    Checksum,
+}
+
 impl<B: ByteSlice> Ipv4Packet<B> {
     /// Parse an IPv4 packet.
     ///
     /// `parse` parses `bytes` as an IPv4 packet and validates the checksum.
     #[cfg_attr(feature = "clippy", allow(needless_pass_by_value))]
-    pub fn parse(bytes: B) -> Result<Ipv4Packet<B>, ()> {
+    pub fn parse(bytes: B) -> Result<Ipv4Packet<B>, Ipv4ParseErr> {
         // See for details: https://en.wikipedia.org/wiki/IPv4#Header
 
-        let total_len = bytes.len();
-        let (hdr_prefix, rest) =
-            LayoutVerified::<B, HeaderPrefix>::new_from_prefix(bytes).ok_or(())?;
-        let hdr_bytes = (hdr_prefix.ihl() * 4) as usize;
-        if hdr_bytes > total_len {
-            return Err(());
-        }
-        let (options, body) = rest.split_at(hdr_bytes - HEADER_PREFIX_SIZE);
-        let options = Options::parse(options).map_err(|_| ())?;
-        let packet = Ipv4Packet {
-            hdr_prefix,
-            options,
-            body,
-        };
-        if packet.hdr_prefix.version() != 4 {
-            return Err(());
+        let packet: PacketWithOptions<B, HeaderPrefix, _> =
+            PacketWithOptions::parse(bytes).map_err(Ipv4ParseErr::Packet)?;
+        let packet = Ipv4Packet(packet);
+        if packet.0.header_prefix().version() != 4 {
+            return Err(Ipv4ParseErr::Version);
         }
         if packet.compute_header_checksum() != 0 {
-            return Err(());
+            return Err(Ipv4ParseErr::Checksum);
         }
 
         Ok(packet)
     }
 
     pub fn iter_options<'a>(&'a self) -> impl 'a + Iterator<Item = Ipv4Option> {
-        self.options.iter()
+        self.0.options().iter()
     }
 }
 
 impl<B: ByteSlice> Ipv4Packet<B> {
     fn compute_header_checksum(&self) -> u16 {
         let mut c = Checksum::new();
-        c.add_bytes(self.hdr_prefix.bytes());
-        c.add_bytes(self.options.bytes());
+        c.add_bytes(self.0.header_prefix_bytes());
+        c.add_bytes(self.0.options().bytes());
         c.sum()
     }
 
     pub fn body(&self) -> &[u8] {
-        &self.body
+        self.0.body()
     }
 
     pub fn version(&self) -> u8 {
-        self.hdr_prefix.version()
+        self.0.header_prefix().version()
     }
 
     pub fn ihl(&self) -> u8 {
-        self.hdr_prefix.ihl()
+        self.0.header_prefix().ihl()
     }
 
     pub fn dscp(&self) -> u8 {
-        self.hdr_prefix.dscp_ecn >> 2
+        self.0.header_prefix().dscp_ecn >> 2
     }
 
     pub fn ecn(&self) -> u8 {
-        self.hdr_prefix.dscp_ecn & 3
+        self.0.header_prefix().dscp_ecn & 3
     }
 
     pub fn total_length(&self) -> u16 {
-        BigEndian::read_u16(&self.hdr_prefix.total_len)
+        BigEndian::read_u16(&self.0.header_prefix().total_len)
     }
 
     pub fn id(&self) -> u16 {
-        BigEndian::read_u16(&self.hdr_prefix.id)
+        BigEndian::read_u16(&self.0.header_prefix().id)
     }
 
     pub fn flags(&self) -> u8 {
-        self.hdr_prefix.flags_frag_off[0] >> 5
+        self.0.header_prefix().flags_frag_off[0] >> 5
     }
 
     pub fn fragment_offset(&self) -> u16 {
-        ((u16::from(self.hdr_prefix.flags_frag_off[0] & 0x1F)) << 8)
-            | u16::from(self.hdr_prefix.flags_frag_off[1])
+        ((u16::from(self.0.header_prefix().flags_frag_off[0] & 0x1F)) << 8)
+            | u16::from(self.0.header_prefix().flags_frag_off[1])
     }
 
     pub fn ttl(&self) -> u8 {
-        self.hdr_prefix.ttl
+        self.0.header_prefix().ttl
     }
 
     pub fn proto(&self) -> u8 {
-        self.hdr_prefix.proto
+        self.0.header_prefix().proto
     }
 
     pub fn hdr_checksum(&self) -> u16 {
-        BigEndian::read_u16(&self.hdr_prefix.hdr_checksum)
+        BigEndian::read_u16(&self.0.header_prefix().hdr_checksum)
     }
 
     pub fn src_ip(&self) -> Ipv4Addr {
-        Ipv4Addr::new(self.hdr_prefix.src_ip)
+        Ipv4Addr::new(self.0.header_prefix().src_ip)
     }
 
     pub fn dst_ip(&self) -> Ipv4Addr {
-        Ipv4Addr::new(self.hdr_prefix.dst_ip)
+        Ipv4Addr::new(self.0.header_prefix().dst_ip)
     }
 }
 
 impl<'a> Ipv4Packet<&'a mut [u8]> {
     pub fn set_id(&mut self, id: u16) {
-        BigEndian::write_u16(&mut self.hdr_prefix.id, id);
+        BigEndian::write_u16(&mut self.0.header_prefix_mut().id, id);
     }
 
     pub fn set_ttl(&mut self, ttl: u8) {
-        self.hdr_prefix.ttl = ttl;
+        self.0.header_prefix_mut().ttl = ttl;
     }
 
     pub fn set_proto(&mut self, proto: u8) {
-        self.hdr_prefix.proto = proto;
+        self.0.header_prefix_mut().proto = proto;
     }
 
     pub fn set_src_ip(&mut self, src_ip: Ipv4Addr) {
-        self.hdr_prefix.src_ip = src_ip.ipv4_bytes();
+        self.0.header_prefix_mut().src_ip = src_ip.ipv4_bytes();
     }
 
     pub fn set_dst_ip(&mut self, dst_ip: Ipv4Addr) {
-        self.hdr_prefix.dst_ip = dst_ip.ipv4_bytes();
+        self.0.header_prefix_mut().dst_ip = dst_ip.ipv4_bytes();
     }
 
     /// Compute and set the header checksum.
@@ -191,9 +205,9 @@
     /// Compute the header checksum from the current header state, and set it in
     /// the header.
     pub fn set_checksum(&mut self) {
-        self.hdr_prefix.hdr_checksum = [0, 0];
+        self.0.header_prefix_mut().hdr_checksum = [0, 0];
         let c = self.compute_header_checksum();
-        BigEndian::write_u16(&mut self.hdr_prefix.hdr_checksum, c);
+        BigEndian::write_u16(&mut self.0.header_prefix_mut().hdr_checksum, c);
     }
 }