diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,30 @@
+Copyright (c)2010, Ozgun Ataman
+
+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 Ozgun Ataman 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.markdown b/README.markdown
new file mode 100644
--- /dev/null
+++ b/README.markdown
@@ -0,0 +1,75 @@
+# README
+
+## CSV Files and Haskell
+
+CSV files are the de-facto standard in many cases of data transfer,
+particularly when dealing with enterprise application or disparate database
+systems.
+
+While there are a number of csv libraries in Haskell, at the time of this
+project's start in 2010, there wasn't one that provided all of the following:
+
+* Full flexibility in quote characters, separators, input/output
+* Constant space operation
+* Robust parsing and error resiliency
+* Fast operation
+* Convenient interface that supports a variety of use cases
+
+This library is an attempt to close these gaps.
+
+
+## This package
+
+csv-conduit is a conduits based CSV parsing library that is easy to
+use, flexible and fast. Furthermore, it provides ways to use
+constant-space during operation, which is absolutely critical in many
+real world use cases.
+
+
+### Introduction
+
+* The CSVeable typeclass implements the key operations.
+* CSVeable is parameterized on both a stream type and a target CSV row type.
+* There are 2 basic row types and they implement *exactly* the same operations,
+  so you can chose the right one for the job at hand:
+  - type MapRow t = Map t t
+  - type Row t = [t]
+* You basically use the Conduits defined in this library to do the
+  parsing from a CSV stream and rendering back into a CSV stream.
+* Use the full flexibility and modularity of conduits for sources and sinks.
+
+### Speed
+
+While fast operation is of concern, I have so far cared more about correct
+operation and a flexible API. Please let me know if you notice any performance
+regressions or optimization opportunities.
+
+
+### Usage Examples
+
+#### Example 1: Basic Operation 
+
+    {-# LANGUAGE OverloadedStrings #-}
+
+    import Data.Conduit.Text
+    import Data.Conduit.Binary
+    import Data.Conduit
+    import Data.CSV.Conduit
+    
+    -- Let's simply stream from a file, parse the CSV, reserialize it
+    -- and push back into another file.
+    test :: IO ()
+    test = runResourceT $ 
+      sourceFile "test/BigFile.csv" $= 
+      decode utf8 $=
+      (intoCSV defCSVSettings 
+        :: forall m. MonadResource m => Conduit Text m (MapRow Text)) $= 
+      fromCSV defCSVSettings $=
+      encode utf8 $$
+      sinkFile "test/BigFileOut.csv"
+
+
+and we are done. 
+
+
+
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/csv-conduit.cabal b/csv-conduit.cabal
new file mode 100644
--- /dev/null
+++ b/csv-conduit.cabal
@@ -0,0 +1,86 @@
+Name:                csv-conduit
+Version:             0.1
+Synopsis:            A flexible, fast, conduit-based CSV parser library for Haskell.  
+Homepage:            http://github.com/ozataman/csv-conduit
+License:             BSD3
+License-file:        LICENSE
+Author:              Ozgun Ataman 
+Maintainer:          Ozgun Ataman <ozataman@gmail.com>
+Category:            Data
+Build-type:          Simple
+Cabal-version:       >=1.6
+Description:
+
+  CSV files are the de-facto standard in many situations involving data transfer,
+  particularly when dealing with enterprise application or disparate database
+  systems.
+
+  .
+
+  While there are a number of CSV libraries in Haskell, at the time of this
+  project's start in 2010, there wasn't one that provided all of the following:
+
+  .
+
+  * Full flexibility in quote characters, separators, input/output
+  .
+  * Constant space operation
+  .
+  * Robust parsing, correctness and error resiliency
+  .
+  * Convenient interface that supports a variety of use cases
+  .
+  * Fast operation
+  .
+
+  This library is an attempt to close these gaps. Please note that
+  this library started its life based on the enumerator package and
+  has recently been ported to work with conduits instead. In the
+  process, it has been greatly simplified thanks to the modular nature
+  of the conduits library.
+
+  . 
+  
+  Following the port to conduits, the library has also gained the
+  ability to parameterize on the stream type and work both with
+  ByteString and Text.
+
+  .
+
+  For more documentation and examples, check out the README at:
+  .
+
+  <http://github.com/ozataman/csv-conduit>
+  .
+  
+
+extra-source-files:
+  README.markdown
+  test/csv-enumerator-test.cabal
+  test/test.csv
+  test/Test.hs
+
+Library
+  hs-source-dirs: src
+  Exposed-modules:     
+      Data.CSV.Conduit
+      Data.CSV.Conduit.Parser.ByteString
+      Data.CSV.Conduit.Parser.Text
+  Other-modules:
+      Data.CSV.Conduit.Types
+  build-depends:
+      attoparsec >= 0.10
+    , attoparsec-conduit
+    , conduit == 0.4.*
+    , base >= 4 && < 5
+    , containers >= 0.3
+    , directory
+    , bytestring
+    , text
+    , transformers >= 0.2
+    , safe
+    , unix-compat >= 0.2.1.1
+    , monad-control
+  extensions:
+    ScopedTypeVariables
+  ghc-options: -funbox-strict-fields
diff --git a/src/Data/CSV/Conduit.hs b/src/Data/CSV/Conduit.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/CSV/Conduit.hs
@@ -0,0 +1,231 @@
+{-# LANGUAGE OverloadedStrings, BangPatterns #-}
+{-# LANGUAGE PackageImports #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE RankNTypes #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE TypeSynonymInstances, FlexibleInstances #-}
+
+module Data.CSV.Conduit
+    ( CSVeable (..)
+    , CSVSettings (..)
+    , defCSVSettings
+    , MapRow
+    , Row
+    -- * Convenience Functions
+    , readCSVFile
+    , mapCSVFile
+    ) where
+
+-------------------------------------------------------------------------------
+import           Control.Applicative        hiding (many)
+import           Control.Exception          (bracket, SomeException)
+import           Control.Monad              (mzero, mplus, foldM, when, liftM)
+import           Control.Monad.IO.Class     (liftIO, MonadIO)
+import           Control.Monad.Trans.Control
+import           Data.Attoparsec            as P hiding (take)
+import qualified Data.Attoparsec.Char8      as C8
+import qualified Data.ByteString            as B
+import           Data.ByteString.Char8      (ByteString)
+import qualified Data.ByteString.Char8      as B8
+import           Data.ByteString.Internal   (c2w)
+import           Data.Conduit as C
+import           Data.Conduit.Attoparsec
+import           Data.Conduit.Binary (sourceFile, sinkFile)
+import qualified Data.Conduit.List as C
+import           Data.Conduit.Text
+import qualified Data.Map                   as M
+import           Data.String
+import           Data.Text (Text)
+import qualified Data.Text as T
+import qualified Data.Text.Encoding as T
+import           Data.Word                  (Word8)
+import           Safe                       (headMay)
+import           System.Directory
+import           System.PosixCompat.Files   (getFileStatus, fileSize)
+-------------------------------------------------------------------------------
+import qualified Data.CSV.Conduit.Parser.ByteString as BSP
+import qualified Data.CSV.Conduit.Parser.Text as TP
+import           Data.CSV.Conduit.Types
+-------------------------------------------------------------------------------
+
+
+-------------------------------------------------------------------------------
+-- | Represents types 'r' that can be converted from an underlying
+-- stream of type 's'.
+--
+-- Example processing using MapRow Text isntance:
+--
+-- @
+-- test :: IO ()
+-- test = runResourceT $ 
+--   sourceFile "test/BigFile.csv" $= 
+--   decode utf8 $=
+--   intoCSV defCSVSettings $=
+--   myMapRowProcessingConduit $=
+--   fromCSV defCSVSettings $=
+--   encode utf8 $$
+--   sinkFile "test/BigFileOut.csv"
+-- @
+class CSVeable s r where
+
+  -----------------------------------------------------------------------------
+  -- | Convert a CSV row into strict ByteString equivalent.
+  rowToStr :: CSVSettings -> r -> s
+
+  -----------------------------------------------------------------------------
+  -- | Turn a stream of 's' into a stream of CSV row type
+  intoCSV :: MonadResource m => CSVSettings -> Conduit s m r
+
+  -----------------------------------------------------------------------------
+  -- | Turn a stream of CSV row type back into a stream of 's'
+  fromCSV :: MonadResource m => CSVSettings -> Conduit r m s
+
+
+------------------------------------------------------------------------------
+-- | 'Row' instance using 'ByteString'
+instance CSVeable ByteString (Row ByteString) where
+  rowToStr s !r = 
+    let 
+      sep = B.pack [c2w (csvOutputColSep s)] 
+      wrapField !f = case (csvOutputQuoteChar s) of
+        Just !x -> x `B8.cons` escape x f `B8.snoc` x
+        otherwise -> f
+      escape c str = B8.intercalate (B8.pack [c,c]) $ B8.split c str
+    in B.intercalate sep . map wrapField $ r
+
+  intoCSV set = intoCSVRow (BSP.row set)
+  fromCSV set = fromCSVRow set
+
+
+------------------------------------------------------------------------------
+-- | 'Row' instance using 'Text'
+instance CSVeable Text (Row Text) where
+  rowToStr s !r = 
+    let 
+      sep = T.pack [(csvOutputColSep s)] 
+      wrapField !f = case (csvOutputQuoteChar s) of
+        Just !x -> x `T.cons` escape x f `T.snoc` x
+        otherwise -> f
+      escape c str = T.intercalate (T.pack [c,c]) $ T.split (== c) str
+    in T.intercalate sep . map wrapField $ r
+
+  intoCSV set = intoCSVRow (TP.row set)
+  fromCSV set = fromCSVRow set
+
+
+-------------------------------------------------------------------------------
+-- | 'Row' instance using 'Text' based on 'ByteString' stream
+instance CSVeable ByteString (Row Text) where
+    rowToStr s r = T.encodeUtf8 $ rowToStr s r
+    intoCSV set = intoCSV set =$= C.map (map T.decodeUtf8)
+    fromCSV set = fromCSV set =$= C.map T.encodeUtf8
+
+
+
+-------------------------------------------------------------------------------
+fromCSVRow set = conduitState init push close
+  where
+    init = ()
+    push st r = return $ StateProducing st [rowToStr set r, "\n"]
+    close _ = return []
+
+
+-------------------------------------------------------------------------------
+intoCSVRow p = parser =$= puller
+  where
+    parser = sequenceSink () seqSink
+    seqSink _ = do
+      p <- sinkParser p
+      return $ Emit () [p]
+    puller = do
+      inc <- await
+      case inc of
+        Nothing -> return ()
+        Just i ->
+          case i of
+            Just i' -> yield i' >> puller
+            Nothing -> puller
+
+
+
+-------------------------------------------------------------------------------
+-- | Generic 'MapRow' instance; any stream type with a 'Row' instance
+-- automatically gets a 'MapRow' instance.
+instance (CSVeable s (Row s'), Ord s', IsString s) => CSVeable s (MapRow s') where
+  rowToStr s r = rowToStr s . M.elems $ r
+  intoCSV set = intoCSVMap set
+  fromCSV set = fromCSVMap set
+
+
+-------------------------------------------------------------------------------
+intoCSVMap set = intoCSV set =$= converter
+  where
+    converter = conduitState Nothing push close 
+      where
+        push Nothing row = 
+          case row of
+            [] -> return $ StateProducing Nothing []
+            xs -> return $ StateProducing (Just xs) []
+        push st@(Just hs) row = return $ StateProducing st [toMapCSV hs row]
+        toMapCSV !headers !fs = M.fromList $ zip headers fs
+        close _ = return []
+
+
+-------------------------------------------------------------------------------
+fromCSVMap set = conduitState False push close
+  where
+    push False r = return $ StateProducing True 
+                   [rowToStr set (M.keys r), "\n", rowToStr set (M.elems r), "\n"]
+    push True r = return $ StateProducing True
+                   [rowToStr set (M.elems r), "\n"]
+    close _ = return []
+
+
+
+                          ---------------------------
+                          -- Convenience Functions --
+                          ---------------------------
+
+
+-------------------------------------------------------------------------------
+-- | Read the entire contents of a CSV file into memory
+readCSVFile set fp = runResourceT $ sourceFile fp $= intoCSV set $$ C.consume
+
+
+-------------------------------------------------------------------------------
+-- | Map over the rows of a CSV file. Don't be scared by the type
+-- signature, this can just run in IO.
+mapCSVFile 
+    :: (MonadIO m, MonadUnsafeIO m, MonadThrow m, 
+        MonadBaseControl IO m, CSVeable ByteString a, CSVeable ByteString b) 
+    => CSVSettings 
+    -- ^ Settings to use both for input and output
+    -> (a -> b) 
+    -- ^ A mapping function
+    -> FilePath 
+    -- ^ Input file
+    -> FilePath 
+    -- ^ Output file
+    -> m ()
+mapCSVFile set f fi fo = runResourceT $
+    sourceFile fi $=
+    intoCSV set $=
+    C.map f $=
+    fromCSV set $$
+    sinkFile fo
+
+
+                               -----------------
+                               -- Simple Test --
+                               -----------------
+
+
+test :: IO ()
+test = runResourceT $ 
+  sourceFile "test/BigFile.csv" $= 
+  decode utf8 $=
+  (intoCSV defCSVSettings 
+    :: forall m. MonadResource m => Conduit Text m (MapRow Text)) $= 
+  fromCSV defCSVSettings $=
+  encode utf8 $$
+  sinkFile "test/BigFileOut.csv"
diff --git a/src/Data/CSV/Conduit/Parser/ByteString.hs b/src/Data/CSV/Conduit/Parser/ByteString.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/CSV/Conduit/Parser/ByteString.hs
@@ -0,0 +1,100 @@
+{-| 
+
+  This module exports the underlying Attoparsec row parser. This is helpful if
+  you want to do some ad-hoc CSV string parsing.
+
+-}
+
+module Data.CSV.Conduit.Parser.ByteString
+    ( parseCSV
+    , parseRow
+    , row
+    , csv
+    ) where
+
+-------------------------------------------------------------------------------
+import           Control.Applicative
+import           Control.Monad (mzero, mplus, foldM, when, liftM)
+import           Control.Monad.IO.Class (liftIO, MonadIO)
+import           Data.Attoparsec as P hiding (take)
+import qualified Data.Attoparsec.Char8 as C8
+import qualified Data.ByteString as B
+import           Data.ByteString.Char8 (ByteString)
+import qualified Data.ByteString.Char8 as B8
+import           Data.ByteString.Internal (c2w)
+import qualified Data.Map as M
+import           Data.Word (Word8)
+-------------------------------------------------------------------------------
+import           Data.CSV.Conduit.Types
+
+
+------------------------------------------------------------------------------
+-- | Try to parse given string as CSV
+parseCSV :: CSVSettings -> ByteString -> Either String [Row ByteString]
+parseCSV s = parseOnly $ csv s
+
+
+------------------------------------------------------------------------------
+-- | Try to parse given string as 'Row ByteString'
+parseRow :: CSVSettings -> ByteString -> Either String (Maybe (Row ByteString))
+parseRow s = parseOnly $ row s
+
+
+------------------------------------------------------------------------------
+-- | Parse CSV
+csv :: CSVSettings -> Parser [Row ByteString]
+csv s = do
+  r <- row s
+  end <- atEnd
+  case end of
+    True -> case r of
+      Just x -> return [x]
+      Nothing -> return []
+    False -> do
+      rest <- csv s
+      return $ case r of
+        Just x -> x : rest
+        Nothing -> rest
+
+
+------------------------------------------------------------------------------
+-- | Parse a CSV row
+row :: CSVSettings -> Parser (Maybe (Row ByteString))
+row csvs = csvrow csvs <|> badrow
+
+
+badrow :: Parser (Maybe (Row ByteString))
+badrow = P.takeWhile (not . C8.isEndOfLine) *> 
+         (C8.endOfLine <|> C8.endOfInput) *> return Nothing
+
+csvrow :: CSVSettings -> Parser (Maybe (Row ByteString))
+csvrow c = 
+  let rowbody = (quotedField' <|> (field c)) `sepBy` C8.char (csvSep c)
+      properrow = rowbody <* (C8.endOfLine <|> P.endOfInput)
+      quotedField' = case csvQuoteChar c of
+          Nothing -> mzero
+          Just q' -> try (quotedField q')
+  in do
+    res <- properrow
+    return $ Just res
+
+field :: CSVSettings -> Parser ByteString
+field s = P.takeWhile (isFieldChar s) 
+
+isFieldChar s = notInClass xs'
+  where xs = csvSep s : "\n\r"
+        xs' = case csvQuoteChar s of 
+          Nothing -> xs
+          Just x -> x : xs
+
+quotedField :: Char -> Parser ByteString
+quotedField c = 
+  let quoted = string dbl *> return c
+      dbl = B8.pack [c,c]
+  in do
+  C8.char c 
+  f <- many (C8.notChar c <|> quoted)
+  C8.char c 
+  return $ B8.pack f
+
+
diff --git a/src/Data/CSV/Conduit/Parser/Text.hs b/src/Data/CSV/Conduit/Parser/Text.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/CSV/Conduit/Parser/Text.hs
@@ -0,0 +1,99 @@
+{-| 
+
+  This module exports the underlying Attoparsec row parser. This is helpful if
+  you want to do some ad-hoc CSV string parsing.
+
+-}
+
+module Data.CSV.Conduit.Parser.Text
+    ( parseCSV
+    , parseRow
+    , row
+    , csv
+    ) where
+
+-------------------------------------------------------------------------------
+import           Control.Applicative
+import           Control.Monad (mzero, mplus, foldM, when, liftM)
+import           Control.Monad.IO.Class (liftIO, MonadIO)
+import           Data.Attoparsec.Text as P hiding (take)
+import qualified Data.Attoparsec.Text as T
+import qualified Data.Map as M
+import           Data.Text (Text)
+import qualified Data.Text as T
+import           Data.Word (Word8)
+-------------------------------------------------------------------------------
+import           Data.CSV.Conduit.Types
+-------------------------------------------------------------------------------
+
+
+------------------------------------------------------------------------------
+-- | Try to parse given string as CSV
+parseCSV :: CSVSettings -> Text -> Either String [Row Text]
+parseCSV s = parseOnly $ csv s
+
+
+------------------------------------------------------------------------------
+-- | Try to parse given string as 'Row Text'
+parseRow :: CSVSettings -> Text -> Either String (Maybe (Row Text))
+parseRow s = parseOnly $ row s
+
+
+------------------------------------------------------------------------------
+-- | Parse CSV
+csv :: CSVSettings -> Parser [Row Text]
+csv s = do
+  r <- row s
+  end <- atEnd
+  case end of
+    True -> case r of
+      Just x -> return [x]
+      Nothing -> return []
+    False -> do
+      rest <- csv s
+      return $ case r of
+        Just x -> x : rest
+        Nothing -> rest
+
+
+------------------------------------------------------------------------------
+-- | Parse a CSV row
+row :: CSVSettings -> Parser (Maybe (Row Text))
+row csvs = csvrow csvs <|> badrow
+
+
+badrow :: Parser (Maybe (Row Text))
+badrow = P.takeWhile (not . T.isEndOfLine) *> 
+         (T.endOfLine <|> T.endOfInput) *> return Nothing
+
+csvrow :: CSVSettings -> Parser (Maybe (Row Text))
+csvrow c = 
+  let rowbody = (quotedField' <|> (field c)) `sepBy` T.char (csvSep c)
+      properrow = rowbody <* (T.endOfLine <|> P.endOfInput)
+      quotedField' = case csvQuoteChar c of
+          Nothing -> mzero
+          Just q' -> try (quotedField q')
+  in do
+    res <- properrow
+    return $ Just res
+
+field :: CSVSettings -> Parser Text
+field s = P.takeWhile (isFieldChar s) 
+
+isFieldChar s = notInClass xs'
+  where xs = csvSep s : "\n\r"
+        xs' = case csvQuoteChar s of 
+          Nothing -> xs
+          Just x -> x : xs
+
+quotedField :: Char -> Parser Text
+quotedField c = 
+  let quoted = string dbl *> return c
+      dbl = T.pack [c,c]
+  in do
+  T.char c 
+  f <- many (T.notChar c <|> quoted)
+  T.char c 
+  return $ T.pack f
+
+
diff --git a/src/Data/CSV/Conduit/Types.hs b/src/Data/CSV/Conduit/Types.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/CSV/Conduit/Types.hs
@@ -0,0 +1,60 @@
+{-# LANGUAGE OverloadedStrings, BangPatterns #-}
+{-# LANGUAGE PackageImports #-}
+{-# LANGUAGE TypeSynonymInstances #-}
+
+module Data.CSV.Conduit.Types where
+
+-------------------------------------------------------------------------------
+import qualified Data.ByteString as B
+import Data.Text (Text)
+import qualified Data.Map as M
+-------------------------------------------------------------------------------
+
+
+-------------------------------------------------------------------------------
+-- | Settings for a CSV file. This library is intended to be flexible
+-- and offer a way to process the majority of text data files out
+-- there.
+data CSVSettings = CSVS
+  { 
+    -- | Separator character to be used in between fields
+    csvSep :: !Char          
+
+    -- | Quote character that may sometimes be present around fields.
+    -- If 'Nothing' is given, the library will never expect quotation
+    -- even if it is present.
+  , csvQuoteChar :: !(Maybe Char)
+  
+    -- | Quote character that should be used in the output.
+  , csvOutputQuoteChar :: !(Maybe Char)
+  
+    -- | Field separator that should be used in the output.
+  , csvOutputColSep :: !Char
+  } deriving (Read, Show, Eq)
+
+
+
+-------------------------------------------------------------------------------
+-- | Default settings for a CSV file. 
+--
+-- > csvSep = ','
+-- > csvQuoteChar = Just '"'
+-- > csvOutputQuoteChar = Just '"'
+-- > csvOutputColSep = ','
+--
+defCSVSettings :: CSVSettings
+defCSVSettings = CSVS
+  { csvSep = ','
+  , csvQuoteChar = Just '"'
+  , csvOutputQuoteChar = Just '"'
+  , csvOutputColSep = ','
+  } 
+
+
+-------------------------------------------------------------------------------
+-- | A 'Row' is just a list of fields
+type Row a = [a]
+
+-------------------------------------------------------------------------------
+-- | A 'MapRow' is a dictionary based on 'Data.Map'
+type MapRow a = M.Map a a
diff --git a/test/Test.hs b/test/Test.hs
new file mode 100644
--- /dev/null
+++ b/test/Test.hs
@@ -0,0 +1,57 @@
+
+module Main where
+
+import qualified Data.ByteString.Char8 as B
+import Data.Map ((!))
+import System.Directory
+
+import Test.Framework (defaultMain, testGroup)
+import Test.Framework.Providers.HUnit
+import Test.Framework.Providers.QuickCheck2 (testProperty)
+
+import Test.QuickCheck
+import Test.HUnit
+
+
+import Data.CSV.Enumerator
+
+
+main = defaultMain tests
+
+tests = [ testGroup "Basic Ops" baseTests ]
+
+
+baseTests = [
+    testCase "mapping with id works" test_identityMap
+  , testCase "simple parsing works" test_simpleParse
+  ]
+
+
+test_identityMap = do
+  Right r <- mapCSVFile "test.csv" csvSettings f "testOut.csv"
+  3 @=? r
+  f1 <- readFile "test.csv"
+  f2 <- readFile "testOut.csv"
+  f1 @=? f2
+  removeFile "testOut.csv"
+  where 
+    f :: MapRow -> [MapRow]
+    f = return
+
+
+test_simpleParse = do
+  Right (d :: [MapRow]) <- readCSVFile csvSettings "test.csv" 
+  mapM_ assertRow d
+  where
+    assertRow r = v3 @=? (v1 + v2)
+      where v1 = readBS $ r ! "Col2"
+            v2 = readBS $ r ! "Col3" 
+            v3 = readBS $ r ! "Sum" 
+
+
+csvSettings = 
+  defCSVSettings { csvQuoteChar = Just '`'
+                 , csvOutputQuoteChar = Just '`' }
+
+
+readBS = read . B.unpack
diff --git a/test/csv-enumerator-test.cabal b/test/csv-enumerator-test.cabal
new file mode 100644
--- /dev/null
+++ b/test/csv-enumerator-test.cabal
@@ -0,0 +1,69 @@
+Name:                csv-enumerator-test
+Version:             0.8.2
+Synopsis:            A flexible, fast, enumerator-based CSV parser library for Haskell.  
+Homepage:            http://github.com/ozataman/csv-enumerator
+License:             BSD3
+License-file:        LICENSE
+Author:              Ozgun Ataman 
+Maintainer:          Ozgun Ataman <ozataman@gmail.com>
+Category:            Data
+Build-type:          Simple
+Cabal-version:       >=1.2
+
+extra-source-files:
+  README.markdown
+
+Executable test
+  main-is: Test.hs
+  hs-source-dirs: ./ ../src
+  Other-modules:
+      Data.CSV.Enumerator.Types
+      Data.CSV.Enumerator
+  build-depends:
+      attoparsec >= 0.8 && < 0.10
+    , attoparsec-enumerator >= 0.2.0.3
+    , base >= 4 && < 5
+    , containers >= 0.3
+    , directory
+    , bytestring
+    , enumerator >= 0.4.5 && < 0.5
+    , transformers >= 0.2
+    , safe
+    , unix-compat >= 0.2.1.1
+    , test-framework
+    , test-framework-quickcheck2
+    , test-framework-hunit
+    , QuickCheck >= 2
+    , HUnit >= 1.2
+  extensions:
+    ScopedTypeVariables
+    OverloadedStrings
+
+
+Executable bench
+  main-is: Bench.hs
+  hs-source-dirs: ./ ../src
+  Other-modules:
+      Data.CSV.Enumerator.Types
+      Data.CSV.Enumerator
+  build-depends:
+      attoparsec >= 0.8 && < 0.10
+    , attoparsec-enumerator >= 0.2.0.3
+    , base >= 4 && < 5
+    , containers >= 0.3
+    , directory
+    , bytestring
+    , enumerator >= 0.4.5 && < 0.5
+    , transformers >= 0.2
+    , safe
+    , unix-compat >= 0.2.1.1
+    , test-framework
+    , test-framework-quickcheck2
+    , test-framework-hunit
+    , QuickCheck >= 2
+    , HUnit >= 1.2
+  extensions:
+    ScopedTypeVariables
+    OverloadedStrings
+  ghc-options: -rtsopts 
+  ghc-prof-options: -rtsopts -caf-all -auto-all    
diff --git a/test/test.csv b/test/test.csv
new file mode 100644
--- /dev/null
+++ b/test/test.csv
@@ -0,0 +1,4 @@
+`Col1`,`Col2`,`Col3`,`Sum`
+`A`,`2`,`3`,`5`
+`B`,`3`,`4`,`7`
+`Field using the quote char ``this is the in-quoted value```,`4`,`5`,`9`
