file-embed 0.0.3.1 → 0.0.4
raw patch · 2 files changed
+62/−3 lines, 2 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
+ Data.FileEmbed: dummySpace :: Int -> Q Exp
+ Data.FileEmbed: inject :: ByteString -> ByteString -> Maybe ByteString
+ Data.FileEmbed: injectFile :: ByteString -> FilePath -> FilePath -> IO ()
Files
- Data/FileEmbed.hs +61/−2
- file-embed.cabal +1/−1
Data/FileEmbed.hs view
@@ -1,13 +1,18 @@ {-# LANGUAGE TemplateHaskell #-} module Data.FileEmbed- ( embedFile+ ( -- * Embed at compile time+ embedFile , embedDir , getDir+ -- * Inject into an executable+ , dummySpace+ , inject+ , injectFile ) where import Language.Haskell.TH (runQ, Exp (AppE, ListE, LitE, TupE),- Lit (StringL),+ Lit (StringL, StringPrimL, IntegerL), Q, runIO) import System.Directory (doesDirectoryExist, doesFileExist,@@ -18,6 +23,8 @@ import Control.Arrow ((&&&), second, first) import Control.Applicative ((<$>)) import Data.Monoid (mappend)+import Data.ByteString.Unsafe (unsafePackAddressLen)+import System.IO.Unsafe (unsafePerformIO) -- | Embed a single file in your source code. --@@ -78,3 +85,55 @@ liftPair2 :: Monad m => (a, m b) -> m (a, b) liftPair2 (a, b) = b >>= \b' -> return (a, b')++magic = concat ["fe", "MS"]+sizeLen = 20++getInner :: B.ByteString -> B.ByteString+getInner b =+ let (sizeBS, rest) = B.splitAt sizeLen $ B.drop (length magic) b+ in case reads $ B8.unpack sizeBS of+ (i, _):_ -> B.take i rest+ [] -> error "Data.FileEmbed (getInner): Your dummy space has been corrupted."++padSize :: Int -> String+padSize i =+ let s = show i+ in replicate (sizeLen - length s) '0' ++ s++dummySpace :: Int -> Q Exp+dummySpace space = do+ let size = padSize space+ let start = magic ++ size+ let chars = LitE $ StringPrimL $ start ++ replicate space '0'+ let len = LitE $ IntegerL $ fromIntegral $ length start + space+ upi <- [|unsafePerformIO|]+ pack <- [|unsafePackAddressLen|]+ getInner' <- [|getInner|]+ return $ getInner' `AppE` (upi `AppE` (pack `AppE` len `AppE` chars))++inject :: B.ByteString -- ^ bs to inject+ -> B.ByteString -- ^ original BS containing dummy+ -> Maybe B.ByteString -- ^ new BS, or Nothing if there is insufficient dummy space+inject toInj orig =+ if toInjL > size+ then Nothing+ else Just $ B.concat [before, B8.pack magic, B8.pack $ padSize toInjL, toInj, B8.pack $ replicate (size - toInjL) '0', after]+ where+ toInjL = B.length toInj+ (before, rest) = B.breakSubstring (B8.pack magic) orig+ (sizeBS, rest') = B.splitAt sizeLen $ B.drop (length magic) rest+ size = case reads $ B8.unpack sizeBS of+ (i, _):_ -> i+ [] -> error $ "Data.FileEmbed (inject): Your dummy space has been corrupted. Size is: " ++ show sizeBS+ (dummy, after) = B.splitAt size rest'++injectFile :: B.ByteString+ -> FilePath -- ^ template file+ -> FilePath -- ^ output file+ -> IO ()+injectFile inj srcFP dstFP = do+ src <- B.readFile srcFP+ case inject inj src of+ Nothing -> error "Insufficient dummy space"+ Just dst -> B.writeFile dstFP dst
file-embed.cabal view
@@ -1,5 +1,5 @@ name: file-embed-version: 0.0.3.1+version: 0.0.4 license: BSD3 license-file: LICENSE author: Michael Snoyman <michael@snoyman.com>