Compare commits
12
Commits
d27eb91952
...
dev
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
af4066d3db | ||
|
|
3bc1be9eb9 | ||
|
|
d99862b3f4 | ||
|
|
22b6942900 | ||
|
|
c1e9fb7b8e | ||
|
|
82085eaaf9 | ||
|
|
493b7dd9d4 | ||
|
|
723f046ea4 | ||
|
|
bb970e4f42 | ||
|
|
1b20188dfc | ||
|
|
886f991ee3 | ||
|
|
659b817252 |
@@ -1,3 +1,5 @@
|
||||
# Changelog for csv-sip
|
||||
|
||||
## Unreleased changes
|
||||
- changed the types of encodeCSV and encodeRawCSV to make them more generic
|
||||
- slight re-structuring of documentation
|
||||
|
||||
@@ -14,5 +14,8 @@ General Public License for more details.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
## Important Note
|
||||
This library is not yet ready for release. As such, all code should be considered to be unstable and subject to change at any time.
|
||||
## Executive Summary
|
||||
This library allows for reading and writing to and from CSV files in a streaming manner. Files can be read and written to on a row-by-row basis allowing larger files to be worked with, since the whole file doesn't have to be loaded to manipulate it. It is based on the [conduit](https://hackage.haskell.org/package/conduit] library.
|
||||
|
||||
## Pull Requests
|
||||
Please make pull requests to the `dev` branch.
|
||||
|
||||
+5
-3
@@ -5,10 +5,12 @@ cabal-version: 2.2
|
||||
-- see: https://github.com/sol/hpack
|
||||
|
||||
name: csv-sip
|
||||
version: 0.0.0
|
||||
synopsis: extracts data from a CSV file
|
||||
description: extracts data from a CSV file - see README.md for more details
|
||||
version: 0.1.0
|
||||
synopsis: CSV streaming library
|
||||
description: CSV streaming library - see README.md for more details
|
||||
category: Data
|
||||
homepage: https://codeberg.org/jlamothe/csv-sip
|
||||
bug-reports: https://codeberg.org/jlamothe/csv-sip/issues
|
||||
author: Jonathan Lamothe
|
||||
maintainer: jonathan@jlamothe.net
|
||||
copyright: (C) 2022 Jonathan Lamothe
|
||||
|
||||
+5
-3
@@ -1,5 +1,5 @@
|
||||
name: csv-sip
|
||||
version: 0.0.0
|
||||
version: 0.1.0
|
||||
license: GPL-3.0-or-later
|
||||
author: "Jonathan Lamothe"
|
||||
maintainer: "jonathan@jlamothe.net"
|
||||
@@ -10,13 +10,15 @@ extra-source-files:
|
||||
- ChangeLog.md
|
||||
|
||||
# Metadata used when publishing your package
|
||||
synopsis: extracts data from a CSV file
|
||||
synopsis: CSV streaming library
|
||||
category: Data
|
||||
|
||||
# To avoid duplicated efforts in documentation and dealing with the
|
||||
# complications of embedding Haddock markup inside cabal files, it is
|
||||
# common to point users to the README.md file.
|
||||
description: extracts data from a CSV file - see README.md for more details
|
||||
description: CSV streaming library - see README.md for more details
|
||||
homepage: https://codeberg.org/jlamothe/csv-sip
|
||||
bug-reports: https://codeberg.org/jlamothe/csv-sip/issues
|
||||
|
||||
ghc-options:
|
||||
- -Wall
|
||||
|
||||
+46
-30
@@ -35,20 +35,26 @@ module Data.CSV.Sip (
|
||||
-- ** Write an entire CSV file
|
||||
writeCSV,
|
||||
writeRawCSV,
|
||||
writeCSVFromStream,
|
||||
writeRawCSVFromStream,
|
||||
-- * Conduits
|
||||
-- ** Encoding
|
||||
-- ** Producers
|
||||
readFromCSV,
|
||||
readFromCSVRaw,
|
||||
encodeCSV,
|
||||
encodeRawCSV,
|
||||
-- ** Consumers
|
||||
writeToCSV,
|
||||
writeToCSVRaw,
|
||||
-- ** Transformers
|
||||
-- *** Encoding
|
||||
encodeRows,
|
||||
encodeRawRows,
|
||||
-- ** Decoding
|
||||
-- *** Decoding
|
||||
labelFields,
|
||||
decodeRows,
|
||||
decodeRawRows,
|
||||
decodeUTF8,
|
||||
toBytes,
|
||||
-- * Helper Functions
|
||||
decodeUTF8,
|
||||
) where
|
||||
|
||||
import Conduit
|
||||
@@ -127,34 +133,28 @@ writeRawCSV
|
||||
-> m ()
|
||||
writeRawCSV file csv = runConduit $ encodeRawCSV csv .| sinkFile file
|
||||
|
||||
-- | Write a CSV file from a stream of Text-based rows
|
||||
writeCSVFromStream
|
||||
-- | reads a stream of Text-based rows from a CSV file
|
||||
readFromCSV
|
||||
:: MonadResource m
|
||||
=> FilePath
|
||||
-- ^ the path to the file to write to
|
||||
-> ConduitT () [T.Text] m ()
|
||||
-- ^ the source conduit
|
||||
-> m ()
|
||||
writeCSVFromStream file src = runConduit $
|
||||
src .| encodeRows .| sinkFile file
|
||||
-- ^ the path to the CSV file to read from
|
||||
-> ConduitT i [T.Text] m ()
|
||||
readFromCSV file = sourceFile file .| decodeRows
|
||||
|
||||
-- | Write a CSV file from a stream of ByteString-based rows
|
||||
writeRawCSVFromStream
|
||||
-- | reads a stream of ByteString-based rows from a CSV file
|
||||
readFromCSVRaw
|
||||
:: MonadResource m
|
||||
=> FilePath
|
||||
-- ^ the path to the file to write to
|
||||
-> ConduitT () [BS.ByteString] m ()
|
||||
-- ^ the source conduit
|
||||
-> m ()
|
||||
writeRawCSVFromStream file src = runConduit $
|
||||
src .| encodeRawRows .| sinkFile file
|
||||
-- ^ the path to the CSV file to read from
|
||||
-> ConduitT i [BS.ByteString] m ()
|
||||
readFromCSVRaw file = sourceFile file .| decodeRawRows
|
||||
|
||||
-- | encode an entire CSV file
|
||||
encodeCSV
|
||||
:: Monad m
|
||||
=> [[T.Text]]
|
||||
-- ^ the data being encoded, organized into rows and fields
|
||||
-> ConduitT () BS.ByteString m ()
|
||||
-> ConduitT o BS.ByteString m ()
|
||||
encodeCSV csv = sourceList csv .| encodeRows
|
||||
|
||||
-- | encode an entire CSV file
|
||||
@@ -162,9 +162,25 @@ encodeRawCSV
|
||||
:: Monad m
|
||||
=> [[BS.ByteString]]
|
||||
-- ^ the data being encoded, organized into rows and fields
|
||||
-> ConduitT () BS.ByteString m ()
|
||||
-> ConduitT o BS.ByteString m ()
|
||||
encodeRawCSV csv = sourceList csv .| encodeRawRows
|
||||
|
||||
-- | Writes a stream of Text-based rows to a CSV file
|
||||
writeToCSV
|
||||
:: MonadResource m
|
||||
=> FilePath
|
||||
-- ^ the path to the CSV file to write to
|
||||
-> ConduitT [T.Text] o m ()
|
||||
writeToCSV file = encodeRows .| sinkFile file
|
||||
|
||||
-- | Writes a stream of ByteString-based rows to a CSV file
|
||||
writeToCSVRaw
|
||||
:: MonadResource m
|
||||
=> FilePath
|
||||
-- ^ the path to the CSV file to write to
|
||||
-> ConduitT [BS.ByteString] o m ()
|
||||
writeToCSVRaw file = encodeRawRows .| sinkFile file
|
||||
|
||||
-- | encode a CSV stream row by row, each element in the list read
|
||||
-- represents a field, with the entire list representing a row
|
||||
encodeRows :: Monad m => ConduitT [T.Text] BS.ByteString m ()
|
||||
@@ -196,13 +212,7 @@ decodeRows = decodeRawRows .| mapC (map $ fromMaybe "" . decodeUTF8)
|
||||
decodeRawRows :: Monad m => ConduitT BS.ByteString [BS.ByteString] m ()
|
||||
decodeRawRows = toBytes .| evalStateT decodeLoop newDecodeState
|
||||
|
||||
-- | decode a raw ByteString into Text (if possible)
|
||||
decodeUTF8 :: BS.ByteString -> Maybe T.Text
|
||||
decodeUTF8 bs = case decodeUtf8' bs of
|
||||
Left _ -> Nothing
|
||||
Right txt -> Just txt
|
||||
|
||||
-- | convert a stream to ByteStrings to a string of bytes
|
||||
-- | convert a stream to ByteStrings to a stream of bytes
|
||||
toBytes :: Monad m => ConduitT BS.ByteString Word8 m ()
|
||||
toBytes = await >>= \case
|
||||
Just bs -> do
|
||||
@@ -211,6 +221,12 @@ toBytes = await >>= \case
|
||||
toBytes
|
||||
Nothing -> return ()
|
||||
|
||||
-- | decode a raw ByteString into Text (if possible)
|
||||
decodeUTF8 :: BS.ByteString -> Maybe T.Text
|
||||
decodeUTF8 bs = case decodeUtf8' bs of
|
||||
Left _ -> Nothing
|
||||
Right txt -> Just txt
|
||||
|
||||
-- Internal
|
||||
|
||||
data DecodeState = DecodeState
|
||||
|
||||
@@ -40,8 +40,8 @@ spec = describe "Data.CSV.Sip" $ do
|
||||
labelFieldsSpec
|
||||
decodeRowsSpec
|
||||
decodeRawRowsSpec
|
||||
decodeUTF8Spec
|
||||
toBytesSpec
|
||||
decodeUTF8Spec
|
||||
|
||||
encodeCSVSpec :: Spec
|
||||
encodeCSVSpec = describe "encodeCSV" $ do
|
||||
@@ -327,6 +327,14 @@ decodeRawRowsSpec = describe "decodeRawRows" $ mapM_
|
||||
, ["baz", "quux"]
|
||||
]
|
||||
|
||||
toBytesSpec :: Spec
|
||||
toBytesSpec = describe "toBytes" $ let
|
||||
input = ["ab", "cd"]
|
||||
expected = map (fromIntegral . ord) "abcd"
|
||||
in it ("should be " ++ show expected) $ do
|
||||
result <- runConduit $ sourceList input .| toBytes .| consume
|
||||
result `shouldBe` expected
|
||||
|
||||
decodeUTF8Spec :: Spec
|
||||
decodeUTF8Spec = describe "decodeUTF8" $ mapM_
|
||||
( \(label, input, expected) -> context label $
|
||||
@@ -341,12 +349,4 @@ decodeUTF8Spec = describe "decodeUTF8" $ mapM_
|
||||
, ( "blank", "", Just "" )
|
||||
]
|
||||
|
||||
toBytesSpec :: Spec
|
||||
toBytesSpec = describe "toBytes" $ let
|
||||
input = ["ab", "cd"]
|
||||
expected = map (fromIntegral . ord) "abcd"
|
||||
in it ("should be " ++ show expected) $ do
|
||||
result <- runConduit $ sourceList input .| toBytes .| consume
|
||||
result `shouldBe` expected
|
||||
|
||||
--jl
|
||||
|
||||
Reference in New Issue
Block a user