diff --git a/.gitignore b/.gitignore
new file mode 100644
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,17 @@
+dist
+dist-newstyle
+.ghc.environment.*
+cabal.project.local
+
+# Profiler outputs and formatted reports:
+*.prof
+*.hp
+*.aux
+*.ps
+
+.hspec
+.hspec-failures
+
+# Code coverage:
+.hpc
+*.tix
diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,4 @@
+
+# 0.1.0.0
+
+First release
diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,20 @@
+Copyright (c) 2019 Ian Denhardt
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/README.md b/README.md
new file mode 100644
--- /dev/null
+++ b/README.md
@@ -0,0 +1,8 @@
+This is a Haskell package for working with flat arrays of fixed-size
+numeric values in a format that is independent of host CPU endianness
+(or word size).  This means that you can manipulate the array in memory,
+and then just write it out to disk or the network when finished -- no
+marshalling step.
+
+The types exposed by this package can be used with the `vector` package;
+they implement the type classes provided by that package.
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/src/big-endian/Internal/Endianness.hs b/src/big-endian/Internal/Endianness.hs
new file mode 100644
--- /dev/null
+++ b/src/big-endian/Internal/Endianness.hs
@@ -0,0 +1,7 @@
+module Internal.Endianness (to, from) where
+
+import Data.Vector.Endian.Class
+
+from, to :: Endian a => a -> a
+from = fromBE
+to = toBE
diff --git a/src/endian-common/Data/Vector/Endian/Class.hs b/src/endian-common/Data/Vector/Endian/Class.hs
new file mode 100644
--- /dev/null
+++ b/src/endian-common/Data/Vector/Endian/Class.hs
@@ -0,0 +1,34 @@
+module Data.Vector.Endian.Class where
+
+import System.Endian
+import Zhp
+
+class Endian a where
+    fromLE :: a -> a
+    toLE :: a -> a
+    fromBE :: a -> a
+    toBE :: a -> a
+
+instance Endian Word8 where
+    fromLE = id
+    toLE = id
+    fromBE = id
+    toBE = id
+
+instance Endian Word16 where
+    fromLE = fromLE16
+    toLE = toLE16
+    fromBE = fromBE16
+    toBE = toBE16
+
+instance Endian Word32 where
+    fromLE = fromLE32
+    toLE = toLE32
+    fromBE = fromBE32
+    toBE = toBE32
+
+instance Endian Word64 where
+    fromLE = fromLE64
+    toLE = toLE64
+    fromBE = fromBE64
+    toBE = toBE64
diff --git a/src/little-endian/Internal/Endianness.hs b/src/little-endian/Internal/Endianness.hs
new file mode 100644
--- /dev/null
+++ b/src/little-endian/Internal/Endianness.hs
@@ -0,0 +1,7 @@
+module Internal.Endianness (to, from) where
+
+import Data.Vector.Endian.Class
+
+from, to :: Endian a => a -> a
+from = fromLE
+to = toLE
diff --git a/src/vector-endian-indef/Data/Vector/Endian.hs b/src/vector-endian-indef/Data/Vector/Endian.hs
new file mode 100644
--- /dev/null
+++ b/src/vector-endian-indef/Data/Vector/Endian.hs
@@ -0,0 +1,69 @@
+module Data.Vector.Endian
+    ( MVector
+    , Vector
+
+    -- * Accessors
+    -- ** Length information
+    , length
+    , null
+    -- ** Indexing
+    , (!)
+    , (!?)
+    , head
+    , last
+    , unsafeIndex
+    , unsafeHead
+    , unsafeLast
+    -- ** Monadic indexing
+    , indexM
+    , headM
+    , lastM
+    , unsafeIndexM
+    , unsafeHeadM
+    , unsafeLastM
+    -- ** Extracting subvectors (slicing)
+    , slice
+    , init
+    , tail
+    , take
+    , drop
+    , splitAt
+    , unsafeSlice
+    , unsafeInit
+    , unsafeTail
+    , unsafeTake
+    , unsafeDrop
+    -- * Construction
+    -- ** Initialisation
+    , empty
+    , singleton
+    , replicate
+    , generate
+    , iterateN
+    -- ** Monadic initialisation
+    , replicateM
+    , generateM
+    , iterateNM
+    , create
+    , createT
+    -- ** Unfolding
+    , unfoldr
+    , unfoldrN
+    , unfoldrM
+    , unfoldrNM
+    , constructN
+    , constructrN
+    -- ** Enumeration
+    , enumFromN
+    , enumFromStepN
+    , enumFromTo
+    , enumFromThenTo
+    -- * Raw pointers
+    , unsafeFromForeignPtr
+    , unsafeFromForeignPtr0
+    , unsafeToForeignPtr
+    , unsafeToForeignPtr0
+    , unsafeWith
+    ) where
+
+import Internal.Vector
diff --git a/src/vector-endian-indef/Data/Vector/Endian/Mutable.hs b/src/vector-endian-indef/Data/Vector/Endian/Mutable.hs
new file mode 100644
--- /dev/null
+++ b/src/vector-endian-indef/Data/Vector/Endian/Mutable.hs
@@ -0,0 +1,3 @@
+module Data.Vector.Endian.Mutable(MVector) where
+
+import Internal.Vector
diff --git a/src/vector-endian-indef/Internal/Endianness.hsig b/src/vector-endian-indef/Internal/Endianness.hsig
new file mode 100644
--- /dev/null
+++ b/src/vector-endian-indef/Internal/Endianness.hsig
@@ -0,0 +1,5 @@
+signature Internal.Endianness where
+
+import Data.Vector.Endian.Class (Endian)
+
+from, to :: Endian a => a -> a
diff --git a/src/vector-endian-indef/Internal/Vector.hs b/src/vector-endian-indef/Internal/Vector.hs
new file mode 100644
--- /dev/null
+++ b/src/vector-endian-indef/Internal/Vector.hs
@@ -0,0 +1,278 @@
+{-# LANGUAGE BangPatterns               #-}
+{-# LANGUAGE FlexibleInstances          #-}
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
+{-# LANGUAGE MultiParamTypeClasses      #-}
+{-# LANGUAGE RankNTypes                 #-}
+{-# LANGUAGE TypeFamilies               #-}
+{-# LANGUAGE UndecidableInstances       #-}
+module Internal.Vector where
+
+import Zhp hiding (empty)
+
+import Data.Vector.Endian.Class (Endian)
+import Internal.Endianness      (from, to)
+import Text.Read                (Read(..))
+
+import Control.DeepSeq      (NFData)
+import Control.Monad.ST     (ST)
+import Data.Traversable     (Traversable)
+import Data.Vector.Storable (Storable)
+import Foreign.ForeignPtr   (ForeignPtr)
+import Foreign.Ptr          (Ptr)
+import GHC.Exts             (IsList(..))
+
+import qualified Data.Vector.Generic          as GV
+import qualified Data.Vector.Generic.Mutable  as GMV
+import qualified Data.Vector.Storable         as SV
+import qualified Data.Vector.Storable.Mutable as SMV
+
+newtype MVector s a = MVector (SMV.MVector s a)
+    deriving(NFData)
+
+newtype Vector a = Vector (SV.Vector a)
+    deriving(Eq, NFData, Semigroup, Monoid)
+
+instance (Storable a, Endian a) => IsList (Vector a) where
+    type Item (Vector a) = a
+
+    fromList = Vector . fromList . map to
+    fromListN len = Vector . fromListN len . map to
+    toList (Vector v) = map from $ SV.toList v
+
+instance (Show a, SV.Storable a, Endian a) => Show (Vector a) where
+    show (Vector v) = show $ SV.map from v
+
+instance (Read a, SV.Storable a, Endian a) => Read (Vector a) where
+    -- Read in the storable vector, then convert all of the elemnents to
+    -- the storage format we need.
+    readPrec = Vector . SV.map to <$> readPrec
+
+type instance GV.Mutable Vector = MVector
+
+instance (SV.Storable a, Endian a) => GMV.MVector MVector a where
+    -- These are all trivial wrappers around the underlying vector.
+    basicLength (MVector v) = GMV.basicLength v
+    basicUnsafeSlice i len (MVector v) = MVector (GMV.basicUnsafeSlice i len v)
+    basicOverlaps (MVector l) (MVector r) = GMV.basicOverlaps l r
+    basicUnsafeNew = fmap MVector . GMV.basicUnsafeNew
+    basicInitialize (MVector v) = GMV.basicInitialize v
+    basicClear (MVector v) = GMV.basicClear v
+    basicUnsafeCopy (MVector l) (MVector r) = GMV.basicUnsafeCopy l r
+    basicUnsafeMove (MVector l) (MVector r) = GMV.basicUnsafeMove l r
+    basicUnsafeGrow (MVector v) i = MVector <$> GMV.basicUnsafeGrow v i
+
+    -- These have to do endianness conversion:
+    basicUnsafeReplicate !i !e = GMV.basicUnsafeReplicate i $! to e
+    basicUnsafeRead (MVector v) i = from <$> GMV.basicUnsafeRead v i
+    basicUnsafeWrite (MVector v) i e = GMV.basicUnsafeWrite v i $! to e
+    basicSet (MVector v) e = GMV.basicSet v $! to e
+
+instance (SV.Storable a, Endian a) => GV.Vector Vector a where
+    -- boring wrappers:
+    basicUnsafeFreeze (MVector v) = Vector <$> GV.basicUnsafeFreeze v
+    basicUnsafeThaw (Vector v) = MVector <$> GV.basicUnsafeThaw v
+    basicLength (Vector v) = GV.basicLength v
+    basicUnsafeSlice i len (Vector v) = Vector (GV.basicUnsafeSlice i len v)
+    basicUnsafeCopy (MVector mv) (Vector v) = GV.basicUnsafeCopy mv v
+    elemseq (Vector v) x y = GV.elemseq v x y
+
+    -- need to do endianness conversion:
+    basicUnsafeIndexM (Vector v) i = from <$!> GV.basicUnsafeIndexM v i
+
+---------------
+-- Accessors --
+---------------
+
+
+-- Length information
+---------------------
+
+length :: (Storable a, Endian a) => Vector a -> Int
+length (Vector v) = SV.length v
+
+null :: (Storable a, Endian a) => Vector a -> Bool
+null (Vector v) = SV.null v
+
+-- Indexing
+-----------
+
+(!) :: (Storable a, Endian a) => Vector a -> Int -> a
+(!) (Vector v) i = from $! v SV.! i
+
+(!?) :: (Storable a, Endian a) => Vector a -> Int -> Maybe a
+Vector v !? i = from <$!> v SV.!? i
+
+head :: (Storable a, Endian a) => Vector a -> a
+head (Vector v) = from $! SV.head v
+
+last :: (Storable a, Endian a) => Vector a -> a
+last (Vector v) = from $! SV.last v
+
+unsafeIndex :: (Storable a, Endian a) => Vector a -> Int -> a
+unsafeIndex (Vector v) i = from $! SV.unsafeIndex v i
+
+unsafeHead :: (Storable a, Endian a) => Vector a -> a
+unsafeHead (Vector v) = from $! SV.unsafeHead v
+
+unsafeLast :: (Storable a, Endian a) => Vector a -> a
+unsafeLast (Vector v) = from $! SV.unsafeLast v
+
+-- Monadic indexing
+-------------------
+
+indexM :: (Storable a, Endian a, Monad m) => Vector a -> Int -> m a
+indexM (Vector v) i = from <$!> SV.indexM v i
+
+headM :: (Storable a, Endian a, Monad m) => Vector a -> m a
+headM (Vector v) = from <$!> SV.headM v
+
+lastM :: (Storable a, Endian a, Monad m) => Vector a -> m a
+lastM (Vector v) = from <$!> SV.lastM v
+
+unsafeIndexM :: (Storable a, Endian a, Monad m) => Vector a -> Int -> m a
+unsafeIndexM (Vector v) i = from <$!> SV.unsafeIndexM v i
+
+unsafeHeadM :: (Storable a, Endian a, Monad m) => Vector a -> m a
+unsafeHeadM (Vector v) = from <$!> SV.unsafeHeadM v
+
+unsafeLastM :: (Storable a, Endian a, Monad m) => Vector a -> m a
+unsafeLastM (Vector v) = from <$!> SV.unsafeLastM v
+
+-- Extracting subvectors (slicing)
+----------------------------------
+
+slice :: (Storable a, Endian a) => Int -> Int -> Vector a -> Vector a
+slice i len (Vector v) = Vector (SV.slice i len v)
+
+init :: (Storable a, Endian a) => Vector a -> Vector a
+init (Vector v) = Vector (SV.init v)
+
+tail :: (Storable a, Endian a) => Vector a -> Vector a
+tail (Vector v) = Vector (SV.tail v)
+
+take :: (Storable a, Endian a) => Int -> Vector a -> Vector a
+take count (Vector v) = Vector (SV.take count v)
+
+drop :: (Storable a, Endian a) => Int -> Vector a -> Vector a
+drop count (Vector v) = Vector (SV.drop count v)
+
+splitAt :: (Storable a, Endian a) => Int -> Vector a -> (Vector a, Vector a)
+splitAt i (Vector v) =
+    let (l, r) = SV.splitAt i v
+    in (Vector l, Vector r)
+
+unsafeSlice :: (Storable a, Endian a) => Int -> Int -> Vector a -> Vector a
+unsafeSlice i len (Vector v) = Vector (SV.unsafeSlice i len v)
+
+unsafeInit :: (Storable a, Endian a) => Vector a -> Vector a
+unsafeInit (Vector v) = Vector (SV.unsafeInit v)
+
+unsafeTail :: (Storable a, Endian a) => Vector a -> Vector a
+unsafeTail (Vector v) = Vector (SV.unsafeTail v)
+
+unsafeTake :: (Storable a, Endian a) => Int -> Vector a -> Vector a
+unsafeTake count (Vector v) = Vector (SV.unsafeTake count v)
+
+unsafeDrop :: (Storable a, Endian a) => Int -> Vector a -> Vector a
+unsafeDrop count (Vector v) = Vector (SV.unsafeDrop count v)
+
+---------------
+-- Construction
+---------------
+
+-- Initialisation
+-----------------
+
+empty :: (Storable a, Endian a) => Vector a
+empty = Vector SV.empty
+
+singleton :: (Storable a, Endian a) => a -> Vector a
+singleton value = Vector (SV.singleton (to value))
+
+replicate :: (Storable a, Endian a) => Int -> a -> Vector a
+replicate count value = Vector (SV.replicate count (to value))
+
+generate :: (Storable a, Endian a) => Int -> (Int -> a) -> Vector a
+generate count f = Vector (SV.generate count (to . f))
+
+iterateN :: (Storable a, Endian a) => Int -> (a -> a) -> a -> Vector a
+iterateN count f orig = Vector (SV.iterateN count (to . f . from) (to orig))
+
+-- Monadic Initialisation
+-------------------------
+
+replicateM :: (Monad m, Storable a, Endian a) => Int -> m a -> m (Vector a)
+replicateM count m = Vector <$> SV.replicateM count (to <$> m)
+
+generateM :: (Monad m, Storable a, Endian a) => Int -> (Int -> m a) -> m (Vector a)
+generateM count m = Vector <$> SV.generateM count (fmap to . m)
+
+iterateNM :: (Monad m, Storable a, Endian a) => Int -> (a -> m a) -> a -> m (Vector a)
+iterateNM count m orig = Vector <$> SV.iterateNM count (fmap to . m . from) orig
+
+create :: (Storable a, Endian a) => (forall s. ST s (MVector s a)) -> Vector a
+create = GV.create
+
+createT :: (Traversable f, Storable a, Endian a)
+    => (forall s. ST s (f (MVector s a))) -> f (Vector a)
+createT = GV.createT
+
+-- Unfolding
+------------
+
+unfoldr :: (Storable a, Endian a) => (b -> Maybe (a, b)) -> b -> Vector a
+unfoldr = GV.unfoldr
+
+unfoldrN :: (Storable a, Endian a) => Int -> (b -> Maybe (a, b)) -> b -> Vector a
+unfoldrN = GV.unfoldrN
+
+unfoldrM :: (Monad m, Storable a, Endian a) => (b -> m (Maybe (a, b))) -> b -> m (Vector a)
+unfoldrM = GV.unfoldrM
+
+unfoldrNM :: (Monad m, Storable a, Endian a) => Int -> (b -> m (Maybe (a, b))) -> b -> m (Vector a)
+unfoldrNM = GV.unfoldrNM
+
+constructN :: (Storable a, Endian a) => Int -> (Vector a -> a) -> Vector a
+constructN = GV.constructN
+
+constructrN :: (Storable a, Endian a) => Int -> (Vector a -> a) -> Vector a
+constructrN = GV.constructrN
+
+-- Enumeration
+--------------
+enumFromN :: (Storable a, Endian a, Num a) => a -> Int -> Vector a
+enumFromN = GV.enumFromN
+
+enumFromStepN :: (Storable a, Endian a, Num a) => a -> a -> Int -> Vector a
+enumFromStepN = GV.enumFromStepN
+
+enumFromTo :: (Storable a, Endian a, Enum a) => a -> a -> Vector a
+enumFromTo = GV.enumFromTo
+
+enumFromThenTo :: (Storable a, Endian a, Enum a) => a -> a -> a -> Vector a
+enumFromThenTo = GV.enumFromThenTo
+
+---------------
+-- Raw pointers
+---------------
+
+unsafeFromForeignPtr :: (SV.Storable a, Endian a)
+    => ForeignPtr a -> Int -> Int -> Vector a
+unsafeFromForeignPtr p off len = Vector $ SV.unsafeFromForeignPtr p off len
+
+unsafeFromForeignPtr0 :: (SV.Storable a, Endian a)
+    => ForeignPtr a -> Int -> Vector a
+unsafeFromForeignPtr0 p len = Vector $ SV.unsafeFromForeignPtr0 p len
+
+unsafeToForeignPtr :: (SV.Storable a, Endian a)
+    => Vector a -> (ForeignPtr a, Int, Int)
+unsafeToForeignPtr (Vector v) = SV.unsafeToForeignPtr v
+
+unsafeToForeignPtr0 :: (SV.Storable a, Endian a)
+    => Vector a -> (ForeignPtr a, Int)
+unsafeToForeignPtr0 (Vector v) = SV.unsafeToForeignPtr0 v
+
+-- | Like 'SV.unsafeWith', but note well: the pointer will point to the value
+-- in its *wire format*, which may not match the host cpu endianness.
+unsafeWith :: (SV.Storable a, Endian a) => Vector a -> (Ptr a -> IO b) -> IO b
+unsafeWith (Vector v) = SV.unsafeWith v
diff --git a/vector-endian.cabal b/vector-endian.cabal
new file mode 100644
--- /dev/null
+++ b/vector-endian.cabal
@@ -0,0 +1,101 @@
+cabal-version:       2.2
+name:                vector-endian
+version:             0.1.0.0
+synopsis:            Storable vectors with cpu-independent representation.
+description:
+  This package exposes data types that implement the type classes from the
+  vector package, but the vectors have an in-memory representation that
+  is independent of the host's CPU.
+  .
+  This makes the data stored within them suitable for storage or transmission
+  over a network, and they can be converted to bytestrings without copying.
+homepage:            https://git.zenhack.net/zenhack/haskell-vector-endian
+license:             MIT
+license-file:        LICENSE
+author:              Ian Denhardt
+maintainer:          ian@zenhack.net
+copyright:           2019 Ian Denhardt
+category:            Data, Data Structures
+
+build-type:          Simple
+extra-source-files:
+    CHANGELOG.md
+  , README.md
+  , .gitignore
+
+source-repository head
+  type:     git
+  branch:   master
+  location: https://git.zenhack.net/zenhack/haskell-vector-endian
+
+common shared-opts
+  default-extensions:
+      NoImplicitPrelude
+    , OverloadedStrings
+  build-depends:
+      base ^>=4.12
+    , zenhack-prelude ^>=0.1
+    , cpu ^>=0.1.2
+    , vector ^>=0.12.0
+    , deepseq ^>=1.4.4
+  ghc-options:
+    -Wall
+  default-language:    Haskell2010
+
+library endian-common
+  import: shared-opts
+  exposed-modules: Data.Vector.Endian.Class
+  hs-source-dirs: src/endian-common
+
+library little-endian
+  import: shared-opts
+  build-depends: endian-common
+  exposed-modules: Internal.Endianness
+  hs-source-dirs: src/little-endian
+
+library big-endian
+  import: shared-opts
+  build-depends: endian-common
+  exposed-modules: Internal.Endianness
+  hs-source-dirs: src/big-endian
+
+library vector-endian-indef
+  import: shared-opts
+  exposed-modules:
+      Data.Vector.Endian
+    , Data.Vector.Endian.Mutable
+  other-modules:
+    Internal.Vector
+  build-depends:
+    endian-common
+  signatures:
+    Internal.Endianness
+  hs-source-dirs: src/vector-endian-indef
+
+library vector-endian-little
+  import: shared-opts
+  build-depends: vector-endian-indef, little-endian
+  reexported-modules:
+      Data.Vector.Endian as Data.Vector.Endian.Little
+    , Data.Vector.Endian.Mutable as Data.Vector.Endian.Little.Mutable
+
+library vector-endian-big
+  import: shared-opts
+  build-depends: vector-endian-indef, big-endian
+  reexported-modules:
+      Data.Vector.Endian as Data.Vector.Endian.Big
+    , Data.Vector.Endian.Mutable as Data.Vector.Endian.Big.Mutable
+
+library
+  import: shared-opts
+  build-depends:
+      endian-common
+    , vector-endian-big
+    , vector-endian-little
+  reexported-modules:
+      Data.Vector.Endian.Class as Data.Vector.Endian
+    , Data.Vector.Endian.Little
+    , Data.Vector.Endian.Little.Mutable
+    , Data.Vector.Endian.Big
+    , Data.Vector.Endian.Big.Mutable
+  hs-source-dirs:      src
