{-# LANGUAGE RecordWildCards   #-}
{-# LANGUAGE OverloadedStrings #-}

module Nix.NarInfo.Parser
  ( -- * Parser
    parseNarInfo
  , parseNarInfoWith
  ) where

import Data.Set (Set)
import Data.Text (Text)
import Data.Attoparsec.Text (Parser)
import Nix.NarInfo.Types

import qualified Control.Applicative
import qualified Data.Char
import qualified Data.Set
import qualified Data.Text
import qualified Data.Attoparsec.Text

parseNarInfo :: Parser (NarInfo FilePath Text Text)
parseNarInfo :: Parser (NarInfo FilePath Text Text)
parseNarInfo = forall fp txt hash.
Ord fp =>
(Bool -> Parser fp)
-> Parser txt -> Parser hash -> Parser (NarInfo fp txt hash)
parseNarInfoWith forall {p}. p -> Parser Text FilePath
pathParse Parser Text
textParse Parser Text
hashParse
  where
    textParse :: Parser Text
textParse = (Char -> Bool) -> Parser Text
Data.Attoparsec.Text.takeWhile1 (Bool -> Bool
not forall b c a. (b -> c) -> (a -> b) -> a -> c
. Char -> Bool
Data.Char.isSpace)
    pathParse :: p -> Parser Text FilePath
pathParse p
_hasPrefix = Text -> FilePath
Data.Text.unpack forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser Text
textParse
    hashParse :: Parser Text
hashParse = Parser Text
textParse

parseNarInfoWith :: (Ord fp)
                 => (Bool -> Parser fp) -- True when path prefix is present
                 -> Parser txt
                 -> Parser hash
                 -> Parser (NarInfo fp txt hash)
parseNarInfoWith :: forall fp txt hash.
Ord fp =>
(Bool -> Parser fp)
-> Parser txt -> Parser hash -> Parser (NarInfo fp txt hash)
parseNarInfoWith Bool -> Parser fp
pathParser Parser txt
textParser Parser hash
hashParser = do
  fp
storePath   <- Text -> Parser fp
keyPath Text
"StorePath"
  txt
url         <- Text -> Parser txt
key     Text
"URL"
  txt
compression <- Text -> Parser txt
key     Text
"Compression"
  hash
fileHash    <- Text -> Parser hash
keyHash Text
"FileHash"
  Integer
fileSize    <- forall {b}. Integral b => Text -> Parser Text b
keyNum  Text
"FileSize"
  hash
narHash     <- Text -> Parser hash
keyHash Text
"NarHash"
  Integer
narSize     <- forall {b}. Integral b => Text -> Parser Text b
keyNum  Text
"NarSize"

  Set fp
references  <- forall a. Ord a => [a] -> Set a
Data.Set.fromList forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (forall {b}. Text -> Parser Text b -> Parser Text b
parseKey Text
"References" forall a b. (a -> b) -> a -> b
$
    (Bool -> Parser fp
pathParser Bool
False) forall (f :: * -> *) a s. Alternative f => f a -> f s -> f [a]
`Data.Attoparsec.Text.sepBy` Char -> Parser Char
Data.Attoparsec.Text.char Char
' ')

  Maybe txt
deriver     <- Text -> Parser Text (Maybe txt)
optKey Text
"Deriver"
  Maybe txt
system      <- Text -> Parser Text (Maybe txt)
optKey Text
"System"
  Maybe txt
sig         <- Text -> Parser Text (Maybe txt)
optKey Text
"Sig"
  Maybe txt
ca          <- Text -> Parser Text (Maybe txt)
optKey Text
"Ca"

  forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ NarInfo {fp
txt
hash
Integer
Maybe txt
Set fp
ca :: Maybe txt
sig :: Maybe txt
system :: Maybe txt
deriver :: Maybe txt
references :: Set fp
narSize :: Integer
narHash :: hash
fileSize :: Integer
fileHash :: hash
compression :: txt
url :: txt
storePath :: fp
ca :: Maybe txt
sig :: Maybe txt
system :: Maybe txt
deriver :: Maybe txt
references :: Set fp
narSize :: Integer
narHash :: hash
fileSize :: Integer
fileHash :: hash
compression :: txt
url :: txt
storePath :: fp
..}
  where
    parseKey :: Text -> Parser Text b -> Parser Text b
parseKey Text
key Parser Text b
parser = do
      Text -> Parser Text
Data.Attoparsec.Text.string Text
key
      Text -> Parser Text
Data.Attoparsec.Text.string Text
": "
      b
out <- Parser Text b
parser
      Char -> Parser Char
Data.Attoparsec.Text.char Char
'\n'
      forall (m :: * -> *) a. Monad m => a -> m a
return b
out

    key :: Text -> Parser txt
key = forall a b c. (a -> b -> c) -> b -> a -> c
flip forall {b}. Text -> Parser Text b -> Parser Text b
parseKey Parser txt
textParser
    optKey :: Text -> Parser Text (Maybe txt)
optKey = forall (f :: * -> *) a. Alternative f => f a -> f (Maybe a)
Control.Applicative.optional forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Parser txt
key
    keyNum :: Text -> Parser Text b
keyNum Text
x = forall {b}. Text -> Parser Text b -> Parser Text b
parseKey Text
x forall a. Integral a => Parser a
Data.Attoparsec.Text.decimal
    keyPath :: Text -> Parser fp
keyPath Text
x = forall {b}. Text -> Parser Text b -> Parser Text b
parseKey Text
x (Bool -> Parser fp
pathParser Bool
True)
    keyHash :: Text -> Parser hash
keyHash Text
x = forall {b}. Text -> Parser Text b -> Parser Text b
parseKey Text
x Parser hash
hashParser