content: {-# LANGUAGE OverloadedStrings #-}
  {-# LANGUAGE RecordWildCards   #-}
  -- |Routines for parsing and rendering the default directories included in this
  -- binary.
  module Tor.DataFormat.DefaultDirectory(
           DefaultDirectory(..)
         , parseDefaultDirectory
         )
   where
  
  import Data.Attoparsec.ByteString
  import Data.ByteString(ByteString)
  import Data.Word
  import Tor.DataFormat.Helpers
  
  -- |A default directory for pulling consensus and other data.
  data DefaultDirectory = DefaultDirectory {
         ddirNickname    :: String
       , ddirIsBridge    :: Bool
       , ddirAddress     :: String
       , ddirOnionPort   :: Word16
       , ddirDirPort     :: Word16
       , ddirV3Ident     :: Maybe ByteString
       , ddirFingerprint :: ByteString
       }
   deriving (Show)
  
  -- FIXME: Make this handle partial input
  -- |Parse a directory structure.
  parseDefaultDirectory :: ByteString -> Either String DefaultDirectory
  parseDefaultDirectory bstr =
    case parse defaultDirectory bstr of
      Fail _ _ err -> Left err
      Partial _    -> Left "Incomplete default directory!"
      Done _   res -> Right res
  
  defaultDirectory :: Parser DefaultDirectory
  defaultDirectory =
    do ddirNickname               <- nickname
       _                          <- sp
       _                          <- string "orport="
       ddirOnionPort              <- port False
       _                          <- sp
       ddirV3Ident                <- option Nothing $ do res <- v3Ident
                                                         _   <- sp
                                                         return (Just res)
       ddirIsBridge               <- option False $ do _ <- string "bridge "
                                                       return True
       (ddirAddress, ddirDirPort) <- addrPort
       ddirFingerprint            <- fingerprint
       return DefaultDirectory{..}
  
  v3Ident :: Parser ByteString
  v3Ident =
    do _ <- string "v3ident="
       hexDigest
  
  addrPort :: Parser (String, Word16)
  addrPort =
    do a <- ip4
       _ <- char8 ':'
       p <- port False
       return (a, p)
  
  fingerprint :: Parser ByteString
  fingerprint =
    do parts <- count 10 (sp >> toString `fmap` count 4 hexDigit)
       return (readHex (concat parts))
  
  