    {-# LANGUAGE FlexibleContexts, OverloadedStrings #-}

    -- | Module    : Network.MPD.Commands.Parse
    -- Copyright   : (c) Ben Sinclair 2005-2009, Joachim Fasting 2010
    -- License     : MIT (see LICENSE)
    -- Maintainer  : Joachim Fasting <joachifm@fastmail.fm>
    -- Stability   : alpha
    --
    -- Parsers for MPD data types.

    module Network.MPD.Commands.Parse where

    import           Network.MPD.Commands.Types

    import           Control.Monad
    import           Control.Monad.Except
    import           Data.Maybe (fromMaybe)

    import           Network.MPD.Util

    import           Data.ByteString.Char8 (ByteString)
    import qualified Data.ByteString.UTF8 as UTF8

    -- | Builds a 'Count' instance from an assoc. list.
    parseCount :: [ByteString] -> Either String Count
    parseCount :: [ByteString] -> Either String Count
    parseCount = (Count -> (ByteString, ByteString) -> Either String Count)
    -> Count -> [(ByteString, ByteString)] -> Either String Count
    forall (t :: * -> *) (m :: * -> *) b a.
    (Foldable t, Monad m) =>
    (b -> a -> m b) -> b -> t a -> m b
    foldM Count -> (ByteString, ByteString) -> Either String Count
    f Count
    forall a. Default a => a
    def ([(ByteString, ByteString)] -> Either String Count)
    -> ([ByteString] -> [(ByteString, ByteString)])
    -> [ByteString]
    -> Either String Count
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . [ByteString] -> [(ByteString, ByteString)]
    toAssocList
            where f :: Count -> (ByteString, ByteString) -> Either String Count
                  f :: Count -> (ByteString, ByteString) -> Either String Count
    f Count
    a (ByteString
    "songs", ByteString
    x)    = Count -> Either String Count
    forall a. a -> Either String a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (Count -> Either String Count) -> Count -> Either String Count
    forall a b. (a -> b) -> a -> b
    $ (ByteString -> Maybe Seconds)
    -> (Seconds -> Count) -> Count -> ByteString -> Count
    forall a b.
    (ByteString -> Maybe a) -> (a -> b) -> b -> ByteString -> b
    parse ByteString -> Maybe Seconds
    forall a. (Read a, Integral a) => ByteString -> Maybe a
    parseNum
                                        (\Seconds
    x' -> Count
    a { cSongs = x'}) Count
    a ByteString
    x
                  f Count
    a (ByteString
    "playtime", ByteString
    x) = Count -> Either String Count
    forall a. a -> Either String a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (Count -> Either String Count) -> Count -> Either String Count
    forall a b. (a -> b) -> a -> b
    $ (ByteString -> Maybe Seconds)
    -> (Seconds -> Count) -> Count -> ByteString -> Count
    forall a b.
    (ByteString -> Maybe a) -> (a -> b) -> b -> ByteString -> b
    parse ByteString -> Maybe Seconds
    forall a. (Read a, Integral a) => ByteString -> Maybe a
    parseNum
                                        (\Seconds
    x' -> Count
    a { cPlaytime = x' }) Count
    a ByteString
    x
                  f Count
    _ (ByteString, ByteString)
    x               = String -> Either String Count
    forall a b. a -> Either a b
    Left (String -> Either String Count) -> String -> Either String Count
    forall a b. (a -> b) -> a -> b
    $ (ByteString, ByteString) -> String
    forall a. Show a => a -> String
    show (ByteString, ByteString)
    x

    -- | Builds a list of 'Device' instances from an assoc. list
    parseOutputs :: [ByteString] -> Either String [Device]
    parseOutputs :: [ByteString] -> Either String [Device]
    parseOutputs = ([(ByteString, ByteString)] -> Either String Device)
    -> [[(ByteString, ByteString)]] -> Either String [Device]
    forall (t :: * -> *) (m :: * -> *) a b.
    (Traversable t, Monad m) =>
    (a -> m b) -> t a -> m (t b)
    forall (m :: * -> *) a b. Monad m => (a -> m b) -> [a] -> m [b]
    mapM ((Device -> (ByteString, ByteString) -> Either String Device)
    -> Device -> [(ByteString, ByteString)] -> Either String Device
    forall (t :: * -> *) (m :: * -> *) b a.
    (Foldable t, Monad m) =>
    (b -> a -> m b) -> b -> t a -> m b
    foldM Device -> (ByteString, ByteString) -> Either String Device
    forall {a}.
    (Eq a, IsString a, Show a) =>
    Device -> (a, ByteString) -> Either String Device
    f Device
    forall a. Default a => a
    def)
                 ([[(ByteString, ByteString)]] -> Either String [Device])
    -> ([ByteString] -> [[(ByteString, ByteString)]])
    -> [ByteString]
    -> Either String [Device]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . [ByteString]
    -> [(ByteString, ByteString)] -> [[(ByteString, ByteString)]]
    splitGroups [ByteString
    "outputid"]
                 ([(ByteString, ByteString)] -> [[(ByteString, ByteString)]])
    -> ([ByteString] -> [(ByteString, ByteString)])
    -> [ByteString]
    -> [[(ByteString, ByteString)]]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . [ByteString] -> [(ByteString, ByteString)]
    toAssocList
        where f :: Device -> (a, ByteString) -> Either String Device
    f Device
    a (a
    "outputid", ByteString
    x)      = Device -> Either String Device
    forall a. a -> Either String a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (Device -> Either String Device) -> Device -> Either String Device
    forall a b. (a -> b) -> a -> b
    $ (ByteString -> Maybe Int)
    -> (Int -> Device) -> Device -> ByteString -> Device
    forall a b.
    (ByteString -> Maybe a) -> (a -> b) -> b -> ByteString -> b
    parse ByteString -> Maybe Int
    forall a. (Read a, Integral a) => ByteString -> Maybe a
    parseNum
                                         (\Int
    x' -> Device
    a { dOutputID = x' }) Device
    a ByteString
    x
              f Device
    a (a
    "outputname", ByteString
    x)    = Device -> Either String Device
    forall a. a -> Either String a
    forall (m :: * -> *) a. Monad m => a -> m a
    return Device
    a { dOutputName = UTF8.toString x }
              f Device
    a (a
    "outputenabled", ByteString
    x) = Device -> Either String Device
    forall a. a -> Either String a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (Device -> Either String Device) -> Device -> Either String Device
    forall a b. (a -> b) -> a -> b
    $ (ByteString -> Maybe Bool)
    -> (Bool -> Device) -> Device -> ByteString -> Device
    forall a b.
    (ByteString -> Maybe a) -> (a -> b) -> b -> ByteString -> b
    parse ByteString -> Maybe Bool
    parseBool
                                         (\Bool
    x' -> Device
    a { dOutputEnabled = x'}) Device
    a ByteString
    x
              f Device
    _ (a, ByteString)
    x                    = String -> Either String Device
    forall a b. a -> Either a b
    Left (String -> Either String Device) -> String -> Either String Device
    forall a b. (a -> b) -> a -> b
    $ (a, ByteString) -> String
    forall a. Show a => a -> String
    show (a, ByteString)
    x

    -- | Builds a 'Stats' instance from an assoc. list.
    parseStats :: [ByteString] -> Either String Stats
    parseStats :: [ByteString] -> Either String Stats
    parseStats = (Stats -> (ByteString, ByteString) -> Either String Stats)
    -> Stats -> [(ByteString, ByteString)] -> Either String Stats
    forall (t :: * -> *) (m :: * -> *) b a.
    (Foldable t, Monad m) =>
    (b -> a -> m b) -> b -> t a -> m b
    foldM Stats -> (ByteString, ByteString) -> Either String Stats
    forall {a}.
    (Eq a, IsString a, Show a) =>
    Stats -> (a, ByteString) -> Either String Stats
    f Stats
    forall a. Default a => a
    def ([(ByteString, ByteString)] -> Either String Stats)
    -> ([ByteString] -> [(ByteString, ByteString)])
    -> [ByteString]
    -> Either String Stats
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . [ByteString] -> [(ByteString, ByteString)]
    toAssocList
        where
            f :: Stats -> (a, ByteString) -> Either String Stats
    f Stats
    a (a
    "artists", ByteString
    x)     = Stats -> Either String Stats
    forall a. a -> Either String a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (Stats -> Either String Stats) -> Stats -> Either String Stats
    forall a b. (a -> b) -> a -> b
    $ (ByteString -> Maybe Seconds)
    -> (Seconds -> Stats) -> Stats -> ByteString -> Stats
    forall a b.
    (ByteString -> Maybe a) -> (a -> b) -> b -> ByteString -> b
    parse ByteString -> Maybe Seconds
    forall a. (Read a, Integral a) => ByteString -> Maybe a
    parseNum
                                     (\Seconds
    x' -> Stats
    a { stsArtists  = x' }) Stats
    a ByteString
    x
            f Stats
    a (a
    "albums", ByteString
    x)      = Stats -> Either String Stats
    forall a. a -> Either String a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (Stats -> Either String Stats) -> Stats -> Either String Stats
    forall a b. (a -> b) -> a -> b
    $ (ByteString -> Maybe Seconds)
    -> (Seconds -> Stats) -> Stats -> ByteString -> Stats
    forall a b.
    (ByteString -> Maybe a) -> (a -> b) -> b -> ByteString -> b
    parse ByteString -> Maybe Seconds
    forall a. (Read a, Integral a) => ByteString -> Maybe a
    parseNum
                                     (\Seconds
    x' -> Stats
    a { stsAlbums   = x' }) Stats
    a ByteString
    x
            f Stats
    a (a
    "songs", ByteString
    x)       = Stats -> Either String Stats
    forall a. a -> Either String a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (Stats -> Either String Stats) -> Stats -> Either String Stats
    forall a b. (a -> b) -> a -> b
    $ (ByteString -> Maybe Seconds)
    -> (Seconds -> Stats) -> Stats -> ByteString -> Stats
    forall a b.
    (ByteString -> Maybe a) -> (a -> b) -> b -> ByteString -> b
    parse ByteString -> Maybe Seconds
    forall a. (Read a, Integral a) => ByteString -> Maybe a
    parseNum
                                     (\Seconds
    x' -> Stats
    a { stsSongs    = x' }) Stats
    a ByteString
    x
            f Stats
    a (a
    "uptime", ByteString
    x)      = Stats -> Either String Stats
    forall a. a -> Either String a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (Stats -> Either String Stats) -> Stats -> Either String Stats
    forall a b. (a -> b) -> a -> b
    $ (ByteString -> Maybe Seconds)
    -> (Seconds -> Stats) -> Stats -> ByteString -> Stats
    forall a b.
    (ByteString -> Maybe a) -> (a -> b) -> b -> ByteString -> b
    parse ByteString -> Maybe Seconds
    forall a. (Read a, Integral a) => ByteString -> Maybe a
    parseNum
                                     (\Seconds
    x' -> Stats
    a { stsUptime   = x' }) Stats
    a ByteString
    x
            f Stats
    a (a
    "playtime", ByteString
    x)    = Stats -> Either String Stats
    forall a. a -> Either String a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (Stats -> Either String Stats) -> Stats -> Either String Stats
    forall a b. (a -> b) -> a -> b
    $ (ByteString -> Maybe Seconds)
    -> (Seconds -> Stats) -> Stats -> ByteString -> Stats
    forall a b.
    (ByteString -> Maybe a) -> (a -> b) -> b -> ByteString -> b
    parse ByteString -> Maybe Seconds
    forall a. (Read a, Integral a) => ByteString -> Maybe a
    parseNum
                                     (\Seconds
    x' -> Stats
    a { stsPlaytime = x' }) Stats
    a ByteString
    x
            f Stats
    a (a
    "db_playtime", ByteString
    x) = Stats -> Either String Stats
    forall a. a -> Either String a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (Stats -> Either String Stats) -> Stats -> Either String Stats
    forall a b. (a -> b) -> a -> b
    $ (ByteString -> Maybe Seconds)
    -> (Seconds -> Stats) -> Stats -> ByteString -> Stats
    forall a b.
    (ByteString -> Maybe a) -> (a -> b) -> b -> ByteString -> b
    parse ByteString -> Maybe Seconds
    forall a. (Read a, Integral a) => ByteString -> Maybe a
    parseNum
                                     (\Seconds
    x' -> Stats
    a { stsDbPlaytime = x' }) Stats
    a ByteString
    x
            f Stats
    a (a
    "db_update", ByteString
    x)   = Stats -> Either String Stats
    forall a. a -> Either String a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (Stats -> Either String Stats) -> Stats -> Either String Stats
    forall a b. (a -> b) -> a -> b
    $ (ByteString -> Maybe Seconds)
    -> (Seconds -> Stats) -> Stats -> ByteString -> Stats
    forall a b.
    (ByteString -> Maybe a) -> (a -> b) -> b -> ByteString -> b
    parse ByteString -> Maybe Seconds
    forall a. (Read a, Integral a) => ByteString -> Maybe a
    parseNum
                                     (\Seconds
    x' -> Stats
    a { stsDbUpdate = x' }) Stats
    a ByteString
    x
            f Stats
    _ (a, ByteString)
    x = String -> Either String Stats
    forall a b. a -> Either a b
    Left (String -> Either String Stats) -> String -> Either String Stats
    forall a b. (a -> b) -> a -> b
    $ (a, ByteString) -> String
    forall a. Show a => a -> String
    show (a, ByteString)
    x

    parseMaybeSong :: [ByteString] -> Either String (Maybe Song)
    parseMaybeSong :: [ByteString] -> Either String (Maybe Song)
    parseMaybeSong [ByteString]
    xs | [ByteString] -> Bool
    forall a. [a] -> Bool
    forall (t :: * -> *) a. Foldable t => t a -> Bool
    null [ByteString]
    xs   = Maybe Song -> Either String (Maybe Song)
    forall a b. b -> Either a b
    Right Maybe Song
    forall a. Maybe a
    Nothing
                      | Bool
    otherwise = Song -> Maybe Song
    forall a. a -> Maybe a
    Just (Song -> Maybe Song)
    -> Either String Song -> Either String (Maybe Song)
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> ([(ByteString, ByteString)] -> Either String Song
    parseSong ([(ByteString, ByteString)] -> Either String Song)
    -> ([ByteString] -> [(ByteString, ByteString)])
    -> [ByteString]
    -> Either String Song
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . [ByteString] -> [(ByteString, ByteString)]
    toAssocList) [ByteString]
    xs

    -- | Builds a 'Song' instance from an assoc. list.
    parseSong :: [(ByteString, ByteString)] -> Either String Song
    parseSong :: [(ByteString, ByteString)] -> Either String Song
    parseSong [(ByteString, ByteString)]
    xs = case [(ByteString, ByteString)]
    xs of
        (ByteString
    "file", ByteString
    path):[(ByteString, ByteString)]
    ys -> (Song -> (ByteString, ByteString) -> Either String Song)
    -> Song -> [(ByteString, ByteString)] -> Either String Song
    forall (t :: * -> *) (m :: * -> *) b a.
    (Foldable t, Monad m) =>
    (b -> a -> m b) -> b -> t a -> m b
    foldM Song -> (ByteString, ByteString) -> Either String Song
    f (Path -> Song
    defaultSong (ByteString -> Path
    Path ByteString
    path)) [(ByteString, ByteString)]
    ys
        [(ByteString, ByteString)]
    _ -> String -> Either String Song
    forall a b. a -> Either a b
    Left String
    "Got a song without a file path! This indicates a bug in either libmpd-haskell or MPD itself!"

        where
            f :: Song -> (ByteString, ByteString) -> Either String Song
            f :: Song -> (ByteString, ByteString) -> Either String Song
    f Song
    s (ByteString
    "Last-Modified", ByteString
    v) =
                Song -> Either String Song
    forall a. a -> Either String a
    forall (m :: * -> *) a. Monad m => a -> m a
    return Song
    s { sgLastModified = parseIso8601 v }
            f Song
    s (ByteString
    "Time", ByteString
    v) =
                Song -> Either String Song
    forall a. a -> Either String a
    forall (m :: * -> *) a. Monad m => a -> m a
    return Song
    s { sgLength = fromMaybe 0 $ parseNum v }
            f Song
    s (ByteString
    "Id", ByteString
    v) =
                Song -> Either String Song
    forall a. a -> Either String a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (Song -> Either String Song) -> Song -> Either String Song
    forall a b. (a -> b) -> a -> b
    $ (ByteString -> Maybe Int)
    -> (Int -> Song) -> Song -> ByteString -> Song
    forall a b.
    (ByteString -> Maybe a) -> (a -> b) -> b -> ByteString -> b
    parse ByteString -> Maybe Int
    forall a. (Read a, Integral a) => ByteString -> Maybe a
    parseNum (\Int
    v' -> Song
    s { sgId = Just $ Id v' }) Song
    s ByteString
    v
            f Song
    s (ByteString
    "Pos", ByteString
    v) =
                Either String Song
    -> (Int -> Either String Song) -> Maybe Int -> Either String Song
    forall b a. b -> (a -> b) -> Maybe a -> b
    maybe (Song -> Either String Song
    forall a. a -> Either String a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (Song -> Either String Song) -> Song -> Either String Song
    forall a b. (a -> b) -> a -> b
    $ (ByteString -> Maybe Int)
    -> (Int -> Song) -> Song -> ByteString -> Song
    forall a b.
    (ByteString -> Maybe a) -> (a -> b) -> b -> ByteString -> b
    parse ByteString -> Maybe Int
    forall a. (Read a, Integral a) => ByteString -> Maybe a
    parseNum
                                      (\Int
    v' -> Song
    s { sgIndex = Just v' }) Song
    s ByteString
    v)
                      (Either String Song -> Int -> Either String Song
    forall a b. a -> b -> a
    const (Either String Song -> Int -> Either String Song)
    -> Either String Song -> Int -> Either String Song
    forall a b. (a -> b) -> a -> b
    $ Song -> Either String Song
    forall a. a -> Either String a
    forall (m :: * -> *) a. Monad m => a -> m a
    return Song
    s)
                      (Song -> Maybe Int
    sgIndex Song
    s)
            f Song
    s (ByteString
    k, ByteString
    v) = Song -> Either String Song
    forall a. a -> Either String a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (Song -> Either String Song)
    -> (Maybe Metadata -> Song) -> Maybe Metadata -> Either String Song
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Song -> (Metadata -> Song) -> Maybe Metadata -> Song
    forall b a. b -> (a -> b) -> Maybe a -> b
    maybe Song
    s (\Metadata
    m -> Metadata -> Value -> Song -> Song
    sgAddTag Metadata
    m (ByteString -> Value
    Value ByteString
    v) Song
    s) (Maybe Metadata -> Either String Song)
    -> Maybe Metadata -> Either String Song
    forall a b. (a -> b) -> a -> b
    $
                         ByteString -> Maybe Metadata
    forall {a}. (Eq a, IsString a) => a -> Maybe Metadata
    readMeta ByteString
    k

            -- Custom-made Read instance
            readMeta :: a -> Maybe Metadata
    readMeta a
    "Artist" = Metadata -> Maybe Metadata
    forall a. a -> Maybe a
    Just Metadata
    Artist
            readMeta a
    "ArtistSort" = Metadata -> Maybe Metadata
    forall a. a -> Maybe a
    Just Metadata
    ArtistSort
            readMeta a
    "Album" = Metadata -> Maybe Metadata
    forall a. a -> Maybe a
    Just Metadata
    Album
            readMeta a
    "AlbumSort" = Metadata -> Maybe Metadata
    forall a. a -> Maybe a
    Just Metadata
    AlbumSort
            readMeta a
    "AlbumArtist" = Metadata -> Maybe Metadata
    forall a. a -> Maybe a
    Just Metadata
    AlbumArtist
            readMeta a
    "AlbumArtistSort" = Metadata -> Maybe Metadata
    forall a. a -> Maybe a
    Just Metadata
    AlbumArtistSort
            readMeta a
    "Title" = Metadata -> Maybe Metadata
    forall a. a -> Maybe a
    Just Metadata
    Title
            readMeta a
    "Track" = Metadata -> Maybe Metadata
    forall a. a -> Maybe a
    Just Metadata
    Track
            readMeta a
    "Name" = Metadata -> Maybe Metadata
    forall a. a -> Maybe a
    Just Metadata
    Name
            readMeta a
    "Genre" = Metadata -> Maybe Metadata
    forall a. a -> Maybe a
    Just Metadata
    Genre
            readMeta a
    "Date" = Metadata -> Maybe Metadata
    forall a. a -> Maybe a
    Just Metadata
    Date
            readMeta a
    "OriginalDate" = Metadata -> Maybe Metadata
    forall a. a -> Maybe a
    Just Metadata
    OriginalDate
            readMeta a
    "Composer" = Metadata -> Maybe Metadata
    forall a. a -> Maybe a
    Just Metadata
    Composer
            readMeta a
    "Performer" = Metadata -> Maybe Metadata
    forall a. a -> Maybe a
    Just Metadata
    Performer
            readMeta a
    "Conductor" = Metadata -> Maybe Metadata
    forall a. a -> Maybe a
    Just Metadata
    Conductor
            readMeta a
    "Work" = Metadata -> Maybe Metadata
    forall a. a -> Maybe a
    Just Metadata
    Work
            readMeta a
    "Grouping" = Metadata -> Maybe Metadata
    forall a. a -> Maybe a
    Just Metadata
    Grouping
            readMeta a
    "Comment" = Metadata -> Maybe Metadata
    forall a. a -> Maybe a
    Just Metadata
    Comment
            readMeta a
    "Disc" = Metadata -> Maybe Metadata
    forall a. a -> Maybe a
    Just Metadata
    Disc
            readMeta a
    "Label" = Metadata -> Maybe Metadata
    forall a. a -> Maybe a
    Just Metadata
    Label
            readMeta a
    "MUSICBRAINZ_ARTISTID" = Metadata -> Maybe Metadata
    forall a. a -> Maybe a
    Just Metadata
    MUSICBRAINZ_ARTISTID
            readMeta a
    "MUSICBRAINZ_ALBUMID" = Metadata -> Maybe Metadata
    forall a. a -> Maybe a
    Just Metadata
    MUSICBRAINZ_ALBUMID
            readMeta a
    "MUSICBRAINZ_ALBUMARTISTID" = Metadata -> Maybe Metadata
    forall a. a -> Maybe a
    Just Metadata
    MUSICBRAINZ_ALBUMARTISTID
            readMeta a
    "MUSICBRAINZ_TRACKID" = Metadata -> Maybe Metadata
    forall a. a -> Maybe a
    Just Metadata
    MUSICBRAINZ_TRACKID
            readMeta a
    "MUSICBRAINZ_RELEASETRACKID" = Metadata -> Maybe Metadata
    forall a. a -> Maybe a
    Just Metadata
    MUSICBRAINZ_RELEASETRACKID
            readMeta a
    "MUSICBRAINZ_WORKID" = Metadata -> Maybe Metadata
    forall a. a -> Maybe a
    Just Metadata
    MUSICBRAINZ_WORKID
            readMeta a
    _ = Maybe Metadata
    forall a. Maybe a
    Nothing

    -- | A helper that runs a parser on a string and, depending on the
    -- outcome, either returns the result of some command applied to the
    -- result, or a default value. Used when building structures.
    parse :: (ByteString -> Maybe a) -> (a -> b) -> b -> ByteString -> b
    parse :: forall a b.
    (ByteString -> Maybe a) -> (a -> b) -> b -> ByteString -> b
    parse ByteString -> Maybe a
    parser a -> b
    f b
    x = b -> (a -> b) -> Maybe a -> b
    forall b a. b -> (a -> b) -> Maybe a -> b
    maybe b
    x a -> b
    f (Maybe a -> b) -> (ByteString -> Maybe a) -> ByteString -> b
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . ByteString -> Maybe a
    parser

    -- | A helper for running a parser returning Maybe on a pair of strings.
    -- Returns Just if both strings where parsed successfully, Nothing otherwise.
    pair :: (ByteString -> Maybe a) -> (ByteString, ByteString) -> Maybe (a, a)
    pair :: forall a.
    (ByteString -> Maybe a) -> (ByteString, ByteString) -> Maybe (a, a)
    pair ByteString -> Maybe a
    p (ByteString
    x, ByteString
    y) = case (ByteString -> Maybe a
    p ByteString
    x, ByteString -> Maybe a
    p ByteString
    y) of
                        (Just a
    a, Just a
    b) -> (a, a) -> Maybe (a, a)
    forall a. a -> Maybe a
    Just (a
    a, a
    b)
                        (Maybe a, Maybe a)
    _                -> Maybe (a, a)
    forall a. Maybe a
    Nothing