content: {-# LANGUAGE RecordWildCards #-}
  {-# LANGUAGE PatternSynonyms #-}
  
  module Hans.Udp.Packet where
  
  import Data.Serialize (Get,getWord16be,label,Putter,Put,putWord16be)
  import Data.Word (Word16)
  
  
  -- Udp Ports -------------------------------------------------------------------
  
  type UdpPort = Word16
  
  getUdpPort :: Get UdpPort
  getUdpPort  = getWord16be
  {-# INLINE getUdpPort #-}
  
  putUdpPort :: Putter UdpPort
  putUdpPort  = putWord16be
  {-# INLINE putUdpPort #-}
  
  
  -- Udp Header ------------------------------------------------------------------
  
  data UdpHeader = UdpHeader { udpSourcePort :: {-# UNPACK #-} !UdpPort
                             , udpDestPort   :: {-# UNPACK #-} !UdpPort
                             , udpChecksum   :: {-# UNPACK #-} !Word16
                             } deriving (Eq,Show)
  
  emptyUdpHeader :: UdpHeader
  emptyUdpHeader  = UdpHeader { udpSourcePort = 0
                              , udpDestPort   = 0
                              , udpChecksum   = 0 }
  
  udpHeaderSize :: Int
  udpHeaderSize  = 8
  
  -- | Parse out a @UdpHeader@, and the size of the payload.
  getUdpHeader :: Get (UdpHeader,Int)
  getUdpHeader  = label "UDP Header" $
    do udpSourcePort <- getUdpPort
       udpDestPort   <- getUdpPort
       len           <- getWord16be
       udpChecksum   <- getWord16be
       return (UdpHeader { .. },fromIntegral len - udpHeaderSize)
  
  -- | Render a @UdpHeader@.
  putUdpHeader :: UdpHeader -> Int -> Put
  putUdpHeader UdpHeader { .. } bodyLen =
    do putUdpPort  udpSourcePort
       putUdpPort  udpDestPort
       putWord16be (fromIntegral (bodyLen + udpHeaderSize))
       putWord16be 0
  