network-anonymous-i2p-0.9.0: src/Network/Anonymous/I2P/Protocol/Parser/Ast.hs
-- | Abstract syntax tree used by the 'Parser', including helper functions
-- for traversing the tree.
--
-- __Warning__: This function is used internally by 'Network.Anonymous.I2P'
-- and using these functions directly is unsupported. The
-- interface of these functions might change at any time without
-- prior notice.
--
module Network.Anonymous.I2P.Protocol.Parser.Ast where
import qualified Data.Attoparsec.ByteString as Atto
import qualified Data.ByteString as BS
-- | A token is a key and can maybe have an associated value
data Token =
Token BS.ByteString (Maybe BS.ByteString)
deriving (Show, Eq)
-- | A line is just a sequence of tokens -- the 'Parser' ends the chain
-- when a newline is received.
type Line = [Token]
-- | Returns true if the key was found
key :: BS.ByteString -- ^ The key to look for
-> [Token] -- ^ Tokens to consider
-> Bool -- ^ Result
key _ [] = False -- Key was not found
key k1 (Token k2 _:xs) = (k1 == k2) || key k1 xs -- If keys match, return true, otherwise enter recursion
-- | Looks up a key and returns the value if found
value :: BS.ByteString -- ^ Key to look for
-> [Token] -- ^ Tokens to consider
-> Maybe BS.ByteString -- ^ The value if the key was found
value _ [] = Nothing -- Key not found!
value k1 (Token k2 v:xs) = if k1 == k2 -- This assumes keys are unique
then v -- This returns the value of the key, if any value is associated
else value k1 xs -- Otherwise we continue our quest (in recursion)
-- | Retrieves value, and applies it to an Attoparsec parser
valueAs :: Atto.Parser a
-> BS.ByteString
-> [Token]
-> Maybe a
valueAs p k xs =
let parseValue bs =
case Atto.parseOnly p bs of
Left _ -> Nothing
Right r -> Just r
in case value k xs of
Nothing -> Nothing
Just v -> parseValue v