Source

AttoBencode / src / Data / AttoBencode / Parser.hs

-- |
-- Module: Data.AttoBencode.Parser
-- Copyright: Florian Hartwig
-- License: BSD3
-- Maintainer: Florian Hartwig <florian.j.hartwig@gmail.com>
-- Stability: experimental
-- Portability: GHC

{-# LANGUAGE BangPatterns #-}
module Data.AttoBencode.Parser 
    ( decode
    , bValue
    ) where

import Data.AttoBencode.Types
import Prelude hiding (take)
import Data.Attoparsec (maybeResult, parse, Parser)
import Data.Attoparsec.Char8 (char, decimal, signed, take)
import Control.Applicative (many, (<$>), (<|>), (*>), (<*))
import Data.Map (fromList)
import qualified Data.ByteString as B

-- | Deserialise a bencoded ByteString.
-- If parsing or conversion fails, Nothing is returned.
decode :: (FromBencode a) => B.ByteString -> Maybe a
decode bs = maybeResult (parse bValue bs) >>= fromBencode

-- | Parser for Bencode values
bValue :: Parser BValue
bValue = stringParser <|> intParser <|> listParser <|> dictParser

bsParser :: Parser B.ByteString
bsParser =
 do l <- decimal
    _ <-char ':'
    take l
{-# INLINE bsParser #-}

stringParser :: Parser BValue
stringParser = BString <$> bsParser

intParser :: Parser BValue
intParser = BInt <$> (char 'i' *> signed decimal <* char 'e')

listParser :: Parser BValue
listParser = BList <$> (char 'l' *> many bValue <* char 'e')

pairParser :: Parser (B.ByteString, BValue)
pairParser = 
 do !key <- bsParser
    !value <- bValue
    return (key, value)

dictParser :: Parser BValue
dictParser = 
 do _ <- char 'd'
    !pairs <- many pairParser
    _ <- char 'e'
    return $ BDict $ fromList pairs -- TODO: fromAscList?
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.