module FP.API.Convert
(encodeFpco
,decodeFpco
,validFileName
,validateFilePath)
where
import Control.Monad
import Data.Aeson
import Data.Aeson.Types (parseEither)
import Data.ByteString (ByteString)
import qualified Data.ByteString.Char8 as BS
import Data.Data
import Data.Generics.Aliases
import qualified Data.Text as Text
import Fay.Convert (encodeFay, decodeFay)
import qualified FP.API as API
import FP.API.ModuleName
import Prelude
encodeFpco :: GenericQ Value
encodeFpco = encodeFay $ \f -> (f
`extQ` (int :: Integer -> Value))
where
int = Number . fromIntegral
decodeFpco :: Data a => Value -> Either String a
decodeFpco = decodeFay $ \value r -> r
`extR` parseInteger value
`extR` (validateEncFileName =<< normalDecode value)
`extR` (either (Left . Text.unpack) Right . checkModuleName =<< normalDecode value)
normalDecode :: Data a => Value -> Either String a
normalDecode = decodeFay (\_ r' -> r')
validateEncFileName :: API.EncFileName -> Either String API.EncFileName
validateEncFileName
= fmap API.encFileNameFromByteString
. validateFilePath
. API.unFileName
. API.unEncFileName
validateFilePath :: ByteString -> Either String ByteString
validateFilePath path =
case filter (not . BS.null) $ BS.splitWith (`elem` ['\\', '/']) $ BS.filter (/= '\NUL') path of
[] -> Left "Invalid filepath: Empty"
components -> Right $ BS.intercalate "/" components
validFileName :: ByteString -> Either String API.FileName
validFileName = fmap API.FileName . validateFilePath
parseInteger :: Value -> Either String Integer
parseInteger = parseEither parseJSON