    -- | DNS message decoders.
    --
    -- When in doubt, use the 'decodeAt' or 'decodeManyAt' functions, which
    -- correctly handle /circle-arithmetic/ DNS timestamps, e.g., in @RRSIG@
    -- resource records.  The 'decode', and 'decodeMany' functions are only
    -- appropriate in pure contexts when the current time is not available, and
    -- @RRSIG@ records are not expected or desired.
    --
    -- The 'decodeMany' and 'decodeManyAt' functions decode a buffer holding one or
    -- more messages, each preceded by 16-bit length in network byte order.  This
    -- encoding is generally only appropriate for DNS TCP, and because TCP does not
    -- preserve message boundaries, the decode is prepared to return a trailing
    -- message fragment to be completed and retried when more input arrives from
    -- network.
    --
    module Network.DNS.Decode (
        -- * Decoding a single DNS message
        decodeAt
      , decode
        -- * Decoding multple length-encoded DNS messages,
        -- e.g., from TCP traffic.
      , decodeManyAt
      , decodeMany
      ) where

    import qualified Data.ByteString as B

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

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

    -- | Decode an input buffer containing a single encoded DNS message.  If the
    -- input buffer has excess content beyond the end of the message an error is
    -- returned.  DNS /circle-arithmetic/ timestamps (e.g. in RRSIG records) are
    -- interpreted at the supplied epoch time.
    --
    decodeAt :: Int64                      -- ^ current epoch time
             -> ByteString                 -- ^ encoded input buffer
             -> Either DNSError DNSMessage -- ^ decoded message or error
    decodeAt :: Int64 -> ByteString -> Either DNSError DNSMessage
    decodeAt t :: Int64
    t bs :: ByteString
    bs = (DNSMessage, PState) -> DNSMessage
    forall a b. (a, b) -> a
    fst ((DNSMessage, PState) -> DNSMessage)
    -> Either DNSError (DNSMessage, PState)
    -> Either DNSError DNSMessage
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Int64
    -> SGet DNSMessage
    -> ByteString
    -> Either DNSError (DNSMessage, PState)
    forall a.
    Int64 -> SGet a -> ByteString -> Either DNSError (a, PState)
    runSGetAt Int64
    t (Int -> SGet DNSMessage -> SGet DNSMessage
    forall a. Int -> SGet a -> SGet a
    fitSGet (ByteString -> Int
    B.length ByteString
    bs) SGet DNSMessage
    getResponse) ByteString
    bs

    -- | Decode an input buffer containing a single encoded DNS message.  If the
    -- input buffer has excess content beyond the end of the message an error is
    -- returned.  DNS /circle-arithmetic/ timestamps (e.g. in RRSIG records) are
    -- interpreted based on a nominal time in the year 2073 chosen to maximize
    -- the time range for which this gives correct translations of 32-bit epoch
    -- times to absolute 64-bit epoch times.  This will yield incorrect results
    -- starting circa 2141.
    --
    decode :: ByteString                 -- ^ encoded input buffer
           -> Either DNSError DNSMessage -- ^ decoded message or error
    decode :: ByteString -> Either DNSError DNSMessage
    decode bs :: ByteString
    bs = (DNSMessage, PState) -> DNSMessage
    forall a b. (a, b) -> a
    fst ((DNSMessage, PState) -> DNSMessage)
    -> Either DNSError (DNSMessage, PState)
    -> Either DNSError DNSMessage
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> SGet DNSMessage
    -> ByteString -> Either DNSError (DNSMessage, PState)
    forall a. SGet a -> ByteString -> Either DNSError (a, PState)
    runSGet (Int -> SGet DNSMessage -> SGet DNSMessage
    forall a. Int -> SGet a -> SGet a
    fitSGet (ByteString -> Int
    B.length ByteString
    bs) SGet DNSMessage
    getResponse) ByteString
    bs

    -- | Decode a buffer containing multiple encoded DNS messages each preceded by
    -- a 16-bit length in network byte order.  Any left-over bytes of a partial
    -- message after the last complete message are returned as the second element
    -- of the result tuple.  DNS /circle-arithmetic/ timestamps (e.g. in RRSIG
    -- records) are interpreted at the supplied epoch time.
    --
    decodeManyAt :: Int64      -- ^ current epoch time
                 -> ByteString -- ^ encoded input buffer
                 -> Either DNSError ([DNSMessage], ByteString)
                               -- ^ decoded messages and left-over partial message
                               -- or error if any complete message fails to parse.
    decodeManyAt :: Int64 -> ByteString -> Either DNSError ([DNSMessage], ByteString)
    decodeManyAt t :: Int64
    t bs :: ByteString
    bs = (ByteString -> Either DNSError DNSMessage)
    -> ByteString -> Either DNSError ([DNSMessage], ByteString)
    decodeMParse (Int64 -> ByteString -> Either DNSError DNSMessage
    decodeAt Int64
    t) ByteString
    bs

    -- | Decode a buffer containing multiple encoded DNS messages each preceded by
    -- a 16-bit length in network byte order.  Any left-over bytes of a partial
    -- message after the last complete message are returned as the second element
    -- of the result tuple.  DNS /circle-arithmetic/ timestamps (e.g. in RRSIG
    -- records) are interpreted based on a nominal time in the year 2078 chosen to
    -- give correct dates for DNS timestamps over a 136 year time range from the
    -- date the root zone was signed on the 15th of July 2010 until the 21st of
    -- August in 2146.  Outside this date range the output is off by some non-zero
    -- multiple 2\^32 seconds.
    --
    decodeMany :: ByteString -- ^ encoded input buffer
               -> Either DNSError ([DNSMessage], ByteString)
                             -- ^ decoded messages and left-over partial message
                             -- or error if any complete message fails to parse.
    decodeMany :: ByteString -> Either DNSError ([DNSMessage], ByteString)
    decodeMany bs :: ByteString
    bs = (ByteString -> Either DNSError DNSMessage)
    -> ByteString -> Either DNSError ([DNSMessage], ByteString)
    decodeMParse ByteString -> Either DNSError DNSMessage
    decode ByteString
    bs

    -- | Decode multiple messages using the given parser.
    --
    decodeMParse :: (ByteString -> Either DNSError DNSMessage)
                    -- ^ message decoder
                 -> ByteString
                    -- ^ enoded input buffer
                 -> Either DNSError ([DNSMessage], ByteString)
                    -- ^ decoded messages and left-over partial message
                    -- or error if any complete message fails to parse.
    decodeMParse :: (ByteString -> Either DNSError DNSMessage)
    -> ByteString -> Either DNSError ([DNSMessage], ByteString)
    decodeMParse decoder :: ByteString -> Either DNSError DNSMessage
    decoder bs :: ByteString
    bs = do
        ((bss :: [ByteString]
    bss, _), leftovers :: ByteString
    leftovers) <- SGet [ByteString]
    -> ByteString
    -> Either DNSError (([ByteString], PState), ByteString)
    forall a.
    SGet a -> ByteString -> Either DNSError ((a, PState), ByteString)
    runSGetWithLeftovers SGet [ByteString]
    lengthEncoded ByteString
    bs
        [DNSMessage]
    msgs <- (ByteString -> Either DNSError DNSMessage)
    -> [ByteString] -> Either DNSError [DNSMessage]
    forall (t :: * -> *) (m :: * -> *) a b.
    (Traversable t, Monad m) =>
    (a -> m b) -> t a -> m (t b)
    mapM ByteString -> Either DNSError DNSMessage
    decoder [ByteString]
    bss
        ([DNSMessage], ByteString)
    -> Either DNSError ([DNSMessage], ByteString)
    forall (m :: * -> *) a. Monad m => a -> m a
    return ([DNSMessage]
    msgs, ByteString
    leftovers)
      where
        -- Read a list of length-encoded bytestrings
        lengthEncoded :: SGet [ByteString]
        lengthEncoded :: SGet [ByteString]
    lengthEncoded = StateT PState (Parser ByteString) ByteString -> SGet [ByteString]
    forall (f :: * -> *) a. Alternative f => f a -> f [a]
    many (StateT PState (Parser ByteString) ByteString -> SGet [ByteString])
    -> StateT PState (Parser ByteString) ByteString
    -> SGet [ByteString]
    forall a b. (a -> b) -> a -> b
    $ SGet Int
    getInt16 SGet Int
    -> (Int -> StateT PState (Parser ByteString) ByteString)
    -> StateT PState (Parser ByteString) ByteString
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= Int -> StateT PState (Parser ByteString) ByteString
    getNByteString