diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,27 @@
+Copyright (c) 2010, Gregory Collins
+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 Gregory Collins nor the names of its 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 HOLDER 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/Setup.lhs b/Setup.lhs
new file mode 100644
--- /dev/null
+++ b/Setup.lhs
@@ -0,0 +1,4 @@
+#!/usr/bin/env runhaskell
+
+> import Distribution.Simple
+> main = defaultMain
diff --git a/attoparsec-iteratee.cabal b/attoparsec-iteratee.cabal
new file mode 100644
--- /dev/null
+++ b/attoparsec-iteratee.cabal
@@ -0,0 +1,35 @@
+name:           attoparsec-iteratee
+version:        0.1
+synopsis:       An adapter to convert attoparsec Parsers into blazing-fast Iteratees
+description:
+  An adapter to convert attoparsec Parsers into blazing-fast Iteratees
+license:        BSD3
+license-file:   LICENSE
+author:         Gregory Collins
+maintainer:     greg@gregorycollins.net
+build-type:     Simple
+cabal-version:  >= 1.6
+homepage:       http://github.com/gregorycollins
+category:       Data
+
+
+Library
+  hs-source-dirs: src
+
+  exposed-modules:
+    Data.Attoparsec.Iteratee
+
+  build-depends:
+    attoparsec >= 0.8 && < 0.9,
+    base >= 4 && < 5,
+    bytestring,
+    iteratee >= 0.3.1 && <0.4,
+    monads-fd,
+    transformers
+
+  ghc-options: -Wall -fwarn-tabs -funbox-strict-fields -O2
+
+
+source-repository head
+  type:     git
+  location: git://github.com/gregorycollins/attoparsec-iteratee.git
diff --git a/src/Data/Attoparsec/Iteratee.hs b/src/Data/Attoparsec/Iteratee.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Attoparsec/Iteratee.hs
@@ -0,0 +1,73 @@
+module Data.Attoparsec.Iteratee
+  ( parserToIteratee ) where
+
+
+------------------------------------------------------------------------------
+import qualified Data.Attoparsec as Atto
+import           Data.Attoparsec hiding (many, Result(..))
+import           Data.ByteString (ByteString)
+import qualified Data.ByteString as S
+import qualified Data.ByteString.Lazy as L
+import           Data.Iteratee
+import           Data.Iteratee.WrappedByteString
+import           Data.Word
+------------------------------------------------------------------------------
+
+type Stream         = StreamG WrappedByteString Word8
+type IterV      m   = IterGV WrappedByteString Word8 m
+
+
+parserToIteratee :: (Monad m) =>
+                    Parser a
+                 -> IterateeG WrappedByteString Word8 m a
+parserToIteratee p = IterateeG $ f (\s -> parse p s)
+  where
+    f :: (Monad m) =>
+         (ByteString -> Atto.Result a)
+      -> Stream
+      -> m (IterV m a)
+    f k (EOF Nothing)  = finalChunk $ k S.empty
+    f _ (EOF (Just e)) = reportError e
+    f k (Chunk s)      = let s' = S.concat $ L.toChunks $ fromWrap s
+                         in if S.null s'
+                             then return $ Cont (IterateeG $ f k) Nothing
+                             else chunk s' k
+
+
+    finalChunk :: (Monad m) => Atto.Result a -> m (IterV m a)
+    finalChunk (Atto.Fail _ _ m) =
+        return $ Cont (error $ show m)
+                      (Just $ Err m)
+
+    finalChunk (Atto.Done rest r) =
+        return $ Done r (Chunk $ toWrap $ L.fromChunks [rest])
+
+    finalChunk (Atto.Partial _) =
+        return $ Cont (error "parser did not produce a value")
+                      (Just $ Err "parser did not produce a value")
+
+    reportError e = return $ Cont (error $ show e) (Just e)
+
+    chunk :: (Monad m) =>
+             ByteString
+          -> (ByteString -> Atto.Result a)
+          -> m (IterV m a)
+    chunk s k = do
+        let r = k s
+        case r of
+          (Atto.Fail _ _ m) -> return $
+                             Cont (throwErr (Err m)) (Just $ Err m)
+          (Atto.Done rest x) -> return $ Done x (Chunk $ toWrap $ L.fromChunks [rest])
+          (Atto.Partial z) -> return $
+                              Cont (IterateeG $ f z) Nothing
+
+
+-- | lazy bytestring -> wrapped bytestring
+toWrap :: L.ByteString -> WrappedByteString Word8
+toWrap = WrapBS . S.concat . L.toChunks
+{-# INLINE toWrap #-}
+
+-- | wrapped bytestring -> lazy bytestring
+fromWrap :: WrappedByteString Word8 -> L.ByteString
+fromWrap = L.fromChunks . (:[]) . unWrap
+{-# INLINE fromWrap #-}
