Data.FileEmbed

file-embed-0.0.16.0: Use Template Haskell to embed file contents directly.

Safe Haskell | None
Language | Haskell2010

Data.FileEmbed

Contents

- Embed at compile time
- Embed as a IsString
- Inject into an executable
- Relative path manipulation
- Internal

Description

This module uses template Haskell. Following is a simplified explanation of usage for those unfamiliar with calling Template Haskell functions.

The function `embedFile` in this modules embeds a file into the executable that you can use it at runtime. A file is represented as a `ByteString`. However, as you can see below, the type signature indicates a value of type `Q Exp` will be returned. In order to convert this into a `ByteString`, you must use Template Haskell syntax, e.g.:

    $(embedFile "myfile.txt")

This expression will have type `ByteString`. Be certain to enable the TemplateHaskell language extension, usually by adding the following to the top of your module:

    {-# LANGUAGE TemplateHaskell #-}

Synopsis

- embedFile :: FilePath -> Q Exp
- embedFileRelative :: FilePath -> Q Exp
- embedFileIfExists :: FilePath -> Q Exp
- embedOneFileOf :: [FilePath] -> Q Exp
- embedDir :: FilePath -> Q Exp
- embedDirListing :: FilePath -> Q Exp
- getDir :: FilePath -> IO [(FilePath, ByteString)]
- embedStringFile :: FilePath -> Q Exp
- embedOneStringFileOf :: [FilePath] -> Q Exp
- dummySpace :: Int -> Q Exp
- dummySpaceWith :: ByteString -> Int -> Q Exp
- inject :: ByteString -> ByteString -> Maybe ByteString
- injectFile :: ByteString -> FilePath -> FilePath -> IO ()
- injectWith :: ByteString -> ByteString -> ByteString -> Maybe ByteString
- injectFileWith :: ByteString -> ByteString -> FilePath -> FilePath -> IO ()
- makeRelativeToProject :: FilePath -> Q FilePath
- makeRelativeToLocationPredicate :: (FilePath -> Bool) -> FilePath -> Q FilePath
- stringToBs :: String -> ByteString
- bsToExp :: ByteString -> Q Exp
- strToExp :: String -> Q Exp

# Embed at compile time

embedFile :: FilePath -> Q Exp #

Embed a single file in your source code.

    import qualified Data.ByteString

    myFile :: Data.ByteString.ByteString
    myFile = $(embedFile "dirName/fileName")

embedFileRelative :: FilePath -> Q Exp #

Embed a single file in your source code. Unlike `embedFile`, path is given relative to project root. @since 0.0.16.0

embedFileIfExists :: FilePath -> Q Exp #

Maybe embed a single file in your source code depending on whether or not file exists.

Warning: When a build is compiled with the file missing, a recompile when the file exists might not trigger an embed of the file. You might try to fix this by doing a clean build.

    import qualified Data.ByteString

    maybeMyFile :: Maybe Data.ByteString.ByteString
    maybeMyFile = $(embedFileIfExists "dirName/fileName")

Since: 0.0.14.0

embedOneFileOf :: [FilePath] -> Q Exp #

Embed a single existing file in your source code out of list a list of paths supplied.

    import qualified Data.ByteString

    myFile :: Data.ByteString.ByteString
    myFile = $(embedOneFileOf [ "dirName/fileName", "src/dirName/fileName" ])

embedDir :: FilePath -> Q Exp #

Embed a directory recursively in your source code.

    import qualified Data.ByteString

    myDir :: [(FilePath, Data.ByteString.ByteString)]
    myDir = $(embedDir "dirName")

embedDirListing :: FilePath -> Q Exp #

Embed a directory listing recursively in your source code.

    myFiles :: [FilePath]
    myFiles = $(embedDirListing "dirName")

Since: 0.0.11

getDir :: FilePath -> IO [(FilePath, ByteString)] #

Get a directory tree in the IO monad.

This is the workhorse of `embedDir`

# Embed as a IsString

embedStringFile :: FilePath -> Q Exp #

Embed a single file in your source code.

    import Data.String

    myFile :: IsString a => a
    myFile = $(embedStringFile "dirName/fileName")

Since 0.0.9

embedOneStringFileOf :: [FilePath] -> Q Exp #

Embed a single existing string file in your source code out of list a list of paths supplied.

Since 0.0.9

# Inject into an executable

The inject system allows arbitrary content to be embedded inside a Haskell executable, post compilation. Typically, file-embed allows you to read some contents from the file system at compile time and embed them inside your executable. Consider a case, instead, where you would want to embed these contents after compilation. Two real-world examples are:

- You would like to embed a hash of the executable itself, for sanity checking in a network protocol. (Obviously the hash will change after you embed the hash.)
- You want to create a self-contained web server that has a set of content, but will need to update the content on machines that do not have access to GHC.

The typical workflow use:

- Use `dummySpace` or `dummySpaceWith` to create some empty space in your executable
- Use `injectFile` or `injectFileWith` from a separate utility to modify that executable to have the updated content.

The reason for the `With`-variant of the functions is for cases where you wish to inject multiple different kinds of content, and therefore need control over the magic key. If you know for certain that there will only be one dummy space available, you can use the non-`With` variants.

dummySpace :: Int -> Q Exp #

Allocate the given number of bytes in the generate executable. That space can be filled up with the `inject` and `injectFile` functions.

dummySpaceWith :: ByteString -> Int -> Q Exp #

Like `dummySpace`, but takes a postfix for the magic string. In order for this to work, the same postfix must be used by `inject` / `injectFile`. This allows an executable to have multiple `ByteString`s injected into it, without encountering collisions.

Since 0.0.8

inject #

Arguments

:: ByteString | bs to inject
-> ByteString | original BS containing dummy
-> Maybe ByteString | new BS, or Nothing if there is insufficient dummy space

Inject some raw data inside a `ByteString` containing empty, dummy space (allocated with `dummySpace`). Typically, the original `ByteString` is an executable read from the filesystem.

injectFile #

Arguments

:: ByteString | bs to inject
-> FilePath | template file
-> FilePath | output file
-> IO () |

Same as `inject`, but instead of performing the injecting in memory, read the contents from the filesystem and write back to a different file on the filesystem.

injectWith #

Arguments

:: ByteString | postfix of magic string
-> ByteString | bs to inject
-> ByteString | original BS containing dummy
-> Maybe ByteString | new BS, or Nothing if there is insufficient dummy space

Like `inject`, but takes a postfix for the magic string.

Since 0.0.8

injectFileWith #

Arguments

:: ByteString | postfix of magic string
-> ByteString | bs to inject
-> FilePath | template file
-> FilePath | output file
-> IO () |

Like `injectFile`, but takes a postfix for the magic string.

Since 0.0.8

# Relative path manipulation

makeRelativeToProject :: FilePath -> Q FilePath #

Take a relative file path and attach it to the root of the current project.

The idea here is that, when building with Stack, the build will always be executed with a current working directory of the root of the project (where your .cabal file is located). However, if you load up multiple projects with `stack ghci`, the working directory may be something else entirely.

This function looks at the source location of the Haskell file calling it, finds the first parent directory with a .cabal file, and uses that as the root directory for fixing the relative path.

    $(makeRelativeToProject "data/foo.txt" >>= embedFile)

Since: 0.0.10

makeRelativeToLocationPredicate :: (FilePath -> Bool) -> FilePath -> Q FilePath #

Take a predicate to infer the project root and a relative file path, the given file path is then attached to the inferred project root

This function looks at the source location of the Haskell file calling it, finds the first parent directory with a file matching the given predicate, and uses that as the root directory for fixing the relative path.

    $(makeRelativeToLocationPredicate ((==) ".cabal" . takeExtension) "data/foo.txt" >>= embedFile)

Since: 0.0.15.0

# Internal

stringToBs :: String -> ByteString #

bsToExp :: ByteString -> Q Exp #

strToExp :: String -> Q Exp #