lib: Make generic FilePack of any encodable type
This commit is contained in:
parent
505f8e66af
commit
6c5f0b513c
2 changed files with 56 additions and 31 deletions
|
|
@ -73,3 +73,9 @@ instance Encode Word32 where
|
|||
|
||||
instance Encode FileMode where
|
||||
encode (CMode mode) = encode mode
|
||||
|
||||
instance (Encode a, Encode b) => Encode (a, b) where
|
||||
encode (a, b) = encodeWithSize a <> encodeWithSize b
|
||||
|
||||
instance {-# OVERLAPPABLE #-} Encode a => Encode [a] where
|
||||
encode = foldMap encodeWithSize
|
||||
|
|
|
|||
|
|
@ -1,42 +1,61 @@
|
|||
{-# LANGUAGE ImpredicativeTypes #-}
|
||||
{-# LANGUAGE RecordWildCards #-}
|
||||
|
||||
module FilePack.FileData where
|
||||
|
||||
import Data.ByteString (ByteString)
|
||||
import Data.Text
|
||||
|
||||
import Data.Text (Text)
|
||||
import System.Posix.Types (FileMode)
|
||||
|
||||
import Data.ByteString.Base64 qualified as B64
|
||||
import Data.ByteString.Char8 qualified as BC
|
||||
import GHC.Natural (Natural)
|
||||
import System.Posix.Types (CMode (..), FileMode)
|
||||
import Text.Read (readEither)
|
||||
import Data.Word (Word32)
|
||||
import FilePack.Encode (Encode (encode, encodeWithSize))
|
||||
|
||||
import FilePack.Encode ()
|
||||
data FileData a = FileData
|
||||
{ fileName :: Text
|
||||
, fileSize :: Word32
|
||||
, filePermissions :: FileMode
|
||||
, fileData :: a
|
||||
}
|
||||
deriving (Eq, Read, Show)
|
||||
|
||||
data FileData = FileData
|
||||
{ fileName :: Text
|
||||
, fileSize :: Natural
|
||||
, filePermissions :: FileMode
|
||||
, fileData :: ByteString
|
||||
}
|
||||
deriving (Eq, Read, Show)
|
||||
instance Encode a => Encode (FileData a) where
|
||||
encode FileData{..} =
|
||||
mconcat
|
||||
[ encodeWithSize fileName
|
||||
, encodeWithSize fileSize
|
||||
, encodeWithSize filePermissions
|
||||
, encodeWithSize fileData
|
||||
]
|
||||
|
||||
newtype FilePack = FilePack {getPackedFiles :: [FileData]}
|
||||
deriving (Eq, Read, Show)
|
||||
data Packable = forall a. Encode a => Packable {getPackable :: a}
|
||||
|
||||
{- | @packFiles@ takes a FilePack and encodes it into a serialized form.
|
||||
instance Encode Packable where
|
||||
encode (Packable a) = encode a
|
||||
|
||||
>>> import Data.Text qualified as T
|
||||
>>> import Data.ByteString qualified as BS
|
||||
>>> import System.Posix.Files (stdFileMode)
|
||||
>>> let sampleFileData = FileData{fileName=T.pack "foo.txt", fileSize = 1024, filePermissions = stdFileMode, fileData = BS.empty}
|
||||
>>> let sampleFilePack = FilePack [sampleFileData]
|
||||
>>> (Right sampleFilePack) == (unpackFiles . packFiles $ sampleFilePack)
|
||||
True
|
||||
-}
|
||||
packFiles :: FilePack -> ByteString
|
||||
packFiles = B64.encode . BC.pack . show
|
||||
newtype FilePack = FilePack [Packable]
|
||||
|
||||
instance Encode FilePack where
|
||||
encode (FilePack ps) = encode ps
|
||||
|
||||
infixr 6 .:
|
||||
(.:) :: Encode a => FileData a -> FilePack -> FilePack
|
||||
(.:) = addFileDataToPack
|
||||
|
||||
-- | @addFileDataToPack@ takes an encodeable FileData and adds it to a FilePack.
|
||||
--
|
||||
-- >>> import Data.ByteString qualified as BS
|
||||
-- >>> d = FileData{fileName = pack "a", fileSize = 4, filePermissions = 0644, fileData = "foo"}
|
||||
-- >>> BS.length $ encode d
|
||||
-- 28
|
||||
addFileDataToPack :: Encode a => FileData a -> FilePack -> FilePack
|
||||
addFileDataToPack a (FilePack as) = FilePack (Packable a : as)
|
||||
|
||||
-- | @packFiles@ takes a FilePack and encodes it into a serialized form.
|
||||
--
|
||||
-- packFiles :: FilePack -> ByteString
|
||||
-- packFiles = B64.encode . encode
|
||||
|
||||
-- | @unpackFiles@ tries to recover a FilePack from its serialized form.
|
||||
unpackFiles :: ByteString -> Either String FilePack
|
||||
unpackFiles serializedData =
|
||||
B64.decode serializedData >>= readEither . BC.unpack
|
||||
-- unpackFiles :: ByteString -> Either String FilePack
|
||||
-- unpackFiles serializedData =
|
||||
-- B64.decode serializedData >>= readEither . BC.unpack
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue