diff --git a/.ghc.environment.x86_64-darwin-8.6.3 b/.ghc.environment.x86_64-darwin-8.6.3
new file mode 100644
--- /dev/null
+++ b/.ghc.environment.x86_64-darwin-8.6.3
@@ -0,0 +1,15 @@
+-- This is a GHC environment file written by cabal. This means you can
+-- run ghc or ghci and get the environment of the project as a whole.
+-- But you still need to use cabal repl $target to get the environment
+-- of specific components (libs, exes, tests etc) because each one can
+-- have its own source dirs, cpp flags etc.
+-- 
+clear-package-db
+global-package-db
+package-db /Users/benselfridge/.cabal/store/ghc-8.6.3/package.db
+package-db dist-newstyle/packagedb/ghc-8.6.3
+package-id bv-embed-0.1.0-inplace
+package-id base-4.12.0.0
+package-id ghc-prim-0.5.3
+package-id rts
+package-id integer-gmp-1.0.2.0
diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,5 @@
+# Revision history for bv-embed
+
+## 0.1.0.0 -- YYYY-mm-dd
+
+* First version. Released on an unsuspecting world.
diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,30 @@
+Copyright (c) 2019, Ben Selfridge
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+
+    * Neither the name of Ben Selfridge nor the names of other
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/README.md b/README.md
new file mode 100644
--- /dev/null
+++ b/README.md
@@ -0,0 +1,1 @@
+bv-embed - Define embeddings of small bit vectors into larger ones
diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,2 @@
+import Distribution.Simple
+main = defaultMain
diff --git a/bv-embed.cabal b/bv-embed.cabal
new file mode 100644
--- /dev/null
+++ b/bv-embed.cabal
@@ -0,0 +1,26 @@
+cabal-version:       2.4
+-- Initial package description 'bv-embed.cabal' generated by 'cabal init'.
+--   For further documentation, see http://haskell.org/cabal/users-guide/
+
+name:                bv-embed
+version:             0.1.0
+synopsis:            Define embeddings of small bit vectors into larger ones
+description:         Data structures for defining embeddings of small bit vectors
+                     into larger ones. Functions that perform the embedding and
+                     extracting.
+-- bug-reports:
+license:             BSD-3-Clause
+license-file:        LICENSE
+author:              Ben Selfridge
+maintainer:          benselfridge@galois.com
+-- copyright:
+category:            Data
+extra-source-files:  CHANGELOG.md
+
+library
+  exposed-modules:   Data.BitVector.Embed
+  -- other-modules:
+  -- other-extensions:
+  build-depends:       base >=4.6 && <5
+  hs-source-dirs:      src
+  default-language:    Haskell2010
diff --git a/src/Data/BitVector/Embed.hs b/src/Data/BitVector/Embed.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/BitVector/Embed.hs
@@ -0,0 +1,57 @@
+
+{-|
+Module      : Data.BitVector.Embed
+Copyright   : (c) Galois Inc. 2018
+License     : BSD-3
+Maintainer  : benselfridge@galois.com
+Stability   : experimental
+Portability : portable
+
+This module exports types and functions for defining how a small bit vector is
+embedded into a larger one.
+
+-}
+
+module Data.BitVector.Embed
+  ( BitEmbedding
+  , fromList
+  , bitEmbed
+  , bitExtract
+  ) where
+
+import qualified Data.Bits as B
+
+-- | Defines a mapping from each bit of a small bit vector into a larger one.
+newtype BitEmbedding = BitEmbedding [Int]
+  deriving (Eq, Ord, Show)
+
+-- | Construct a `BitEmbedding` from a list, where the length of the list is the same
+-- as the width of the "small" bit vector we are embedding into the larger one. The
+-- nth element of the list tells us at which bit index in the target to embed bit n
+-- of the source.
+fromList :: [Int] -> BitEmbedding
+fromList = BitEmbedding
+
+-- | Embed a smaller bit vector into a larger one using a `BitEmbedding`.
+--
+-- >>> bitEmbed (fromList [4,5,7] 7 0)
+-- 176
+bitEmbed :: (B.Bits src, B.Bits tgt) => BitEmbedding -> src -> tgt -> tgt
+bitEmbed (BitEmbedding []) _ tgt = tgt
+bitEmbed (BitEmbedding (bit:rst)) src tgt =
+  bitEmbed (BitEmbedding rst) (src `B.shiftR` 1) (tgt B..|. bitMask)
+  where bitMask = if B.testBit src 0
+                  then B.bit bit
+                  else B.zeroBits
+
+-- | Extract a smaller bit vector from a larger one using a `BitEmbedding`.
+--
+-- >>> bitExtract (fromList [4,5,7] 7 0) 176
+-- 7
+bitExtract :: (B.Bits src, B.Bits tgt) => BitEmbedding -> tgt -> src
+bitExtract (BitEmbedding []) _ = B.zeroBits
+bitExtract (BitEmbedding (bit:rst)) tgt =
+  (bitExtract (BitEmbedding rst) tgt `B.shiftL` 1) B..|. bitMask
+  where bitMask = if B.testBit tgt bit
+                  then B.bit 0
+                  else B.zeroBits
