data-embed-0.1.0.0: Embed files and other binary blobs inside executables without Template Haskell.

Safe HaskellNone
LanguageHaskell2010

Data.Embed.File

Contents

Description

Readingwriting bundles of embedded files and other data fromto executables.

A bundle has three parts: the static header, which identifies a string of bytes as a bundle using a particular version of the format and gives the size of the dynamic header; the dynamic header which describes all files and directories contained in the bundle; and the data part, where the data for all files is located. All words are stored in little endian format.

The static header comprises the last bundleHeaderStaticSize bytes of the file, with the dynamic header coming immediately before, and the data section coming immediately before the dynamic header.

The dynamic header is stored as a tuple of the number of files in the bundle (Word32), and the . Each file is stored as a triple of the file's UTF-8 encoded path, its offset from the start of the data section, and its size. The path is prepended with a Word32 giving its length in bytes; the offset is given as a Word32 and the size is given as a Word32.

The layout of the bundle format is given in the following table:

[file data]

[files] * hdrNumFiles
  pathLen       : Word32
  path          : pathLen * Word8
  offset        : Word64
  size          : Word32

[static header]
  hdrDataOffset : Word64
  hdrNumFiles   : Word32
  hdrDynSize    : Word32
  hdrVersion    : Word8
  "BNDLLDNB"    : Word64

The included embedtool program offers a command line interface for manipulating and inspecting bundles.

Synopsis

Documentation

data Bundle Source

A handle to a file bundle. Bundle handles are obtained using openBundle or withBundle and start out as open. That is, files may be read from them. An open bundle contains an open file handle to the bundle's backing file, ensuring that the file data will not disappear from under it. When a bundle becomes unreachable, its corresponding file handle is closed by the bundle's associated finalizer.

However, as finalizers are not guaranteed to run promptly - or even at all - bundles may also be closed before becoming unreachable using closeBundle. If you expect to perform other operations on a bundle's backing file, you should always close the bundle manually first.

Reading bundles

hasBundle :: FilePath -> IO Bool Source

Does the given file contain a bundle or not?

openBundle :: FilePath -> IO (Either String Bundle) Source

Open a file bundle. The bundle will keep an open handle to its backing file. The handle will be closed when the bundle is garbage collected. Use closeBundle to close the handle before the

withBundle :: FilePath -> (Bundle -> IO a) -> IO (Either String a) Source

Perform a computation over a bundle, returning an error if either the computation failed or the bundle could not be loaded. The bundle is always closed before this function returns, regardless of whether an error occurred.

closeBundle :: Bundle -> IO () Source

Close a bundle before it becomes unreachable. After a bundle is closed, any read operations performed on it will fail as though the requested file could not be found. Subsequent close operations on it will have no effect.

readBundleFile :: Bundle -> FilePath -> IO (Either String ByteString) Source

Read a file from a previously opened bundle. Will fail of the given path is not found within the bundle, or if the bundle is no longer alive, i.e. it has been closed using closeBundle.

readBundle :: Serialize a => Bundle -> FilePath -> IO (Either String a) Source

Like readBundleFile, but attempts to decode the file's contents into an appropriate Haskell value.

listBundleFiles :: Bundle -> [FilePath] Source

List all files in the given bundle. Will succeed even on closed bundles.

Creating bundles

data File Source

A file to be included in a bundle. May be either the path to a file on disk or an actual (path, data) pair.

If a file path refers to a directory, all non-dotfile files and subdirectories of that directory will be included in the bundle. File paths also have a strip number: the number of leading directories to strip from file names when adding them to a bundle. For instance, adding File 1 "foo/bar" to a bundle will add the file foo/bar, under the name bar within the bundle.

If a file name would "disappear" entirely due to stripping, for instance when stripping two directories from foo/bar, bar will "disappear" entirely and so will be silently ignored.

Instances

appendBundle :: FilePath -> [File] -> IO () Source

Write a bundle to a file. If the given file already has a bundle, the new bundle will be written *after* the old one. The old bundle will thus still be present in the file, but only the new one will be recognized by openBundle and friends.

eraseBundle :: FilePath -> IO () Source

Remove a bundle from an existing file. Does nothing if the given file does not have a bundle. The given file is *not* removed, even if it only contains the bundle.

replaceBundle :: FilePath -> [File] -> IO () Source

Replace the bundle currently attached to the given file. Equivalent to appendBundle if the given file does not already have a bundle attached.