-- | Decoders for DNS.
module Network.DNS.Decode (
    -- * Decoder
    decode
  , decodeMany
    -- ** Decoder for Each Part
  , decodeResourceRecord
  , decodeDNSHeader
  , decodeDNSFlags
  , decodeDomain
  , decodeMailbox
  ) where

import Network.DNS.Decode.Internal
import Network.DNS.Imports
import Network.DNS.StateBinary
import Network.DNS.Types

----------------------------------------------------------------

-- | Decoding DNS query or response.

decode :: ByteString -> Either DNSError DNSMessage
decode bs = fst <$> runSGet getResponse bs

-- | Parse many length-encoded DNS records, for example, from TCP traffic.

decodeMany :: ByteString -> Either DNSError ([DNSMessage], ByteString)
decodeMany bs = do
    ((bss, _), leftovers) <- runSGetWithLeftovers lengthEncoded bs
    msgs <- mapM decode bss
    return (msgs, leftovers)
  where
    -- Read a list of length-encoded lazy bytestrings
    lengthEncoded :: SGet [ByteString]
    lengthEncoded = many $ do
      len <- getInt16
      getNByteString len

-- | Decoding DNS flags.
decodeDNSFlags :: ByteString -> Either DNSError DNSFlags
decodeDNSFlags bs = fst <$> runSGet getDNSFlags bs

-- | Decoding DNS header.
decodeDNSHeader :: ByteString -> Either DNSError DNSHeader
decodeDNSHeader bs = fst <$> runSGet getHeader bs

-- | Decoding domain.
decodeDomain :: ByteString -> Either DNSError Domain
decodeDomain bs = fst <$> runSGet getDomain bs

-- | Decoding mailbox.
decodeMailbox :: ByteString -> Either DNSError Mailbox
decodeMailbox bs = fst <$> runSGet getMailbox bs

-- | Decoding resource record.
decodeResourceRecord :: ByteString -> Either DNSError ResourceRecord
decodeResourceRecord bs = fst <$> runSGet getResourceRecord bs