packages feed

cassava 0.1.0.0 → 0.1.0.1

raw patch · 5 files changed

+74/−17 lines, 5 filesPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

API changes (from Hackage documentation)

- Data.Csv.Parser: field :: Parser Field
+ Data.Csv.Parser: field :: Word8 -> Parser Field
- Data.Csv.Parser: name :: Parser Field
+ Data.Csv.Parser: name :: Word8 -> Parser Field

Files

Data/Csv/Parser.hs view
@@ -80,12 +80,12 @@ -- | Parse a header, including the terminating line separator. header :: Word8  -- ^ Field delimiter        -> AL.Parser Header-header delim = V.fromList <$> name `sepBy1` (A.word8 delim) <* endOfLine+header !delim = V.fromList <$> name delim `sepBy1` (A.word8 delim) <* endOfLine  -- | Parse a header name. Header names have the same format as regular -- 'field's.-name :: AL.Parser Field  -- TODO: Create Name type alias-name = field+name :: Word8 -> AL.Parser Field  -- TODO: Create Name type alias+name !delim = field delim  removeBlankLines :: [Record] -> [Record] removeBlankLines = filter (not . blankLine)@@ -98,19 +98,19 @@ -- this parser. record :: Word8  -- ^ Field delimiter        -> AL.Parser Record-record !delim = V.fromList <$> field `sepBy1` (A.word8 delim)+record !delim = V.fromList <$> field delim `sepBy1` (A.word8 delim) {-# INLINE record #-}  -- | Parse a field. The field may be in either the escaped or -- non-escaped format. The return value is unescaped.-field :: AL.Parser Field-field = do+field :: Word8 -> AL.Parser Field+field !delim = do     mb <- A.peekWord8     -- We purposely don't use <|> as we want to commit to the first     -- choice if we see a double quote.     case mb of         Just b | b == doubleQuote -> escapedField-        _                         -> unescapedField+        _                         -> unescapedField delim  escapedField :: AL.Parser S.ByteString escapedField = do@@ -127,11 +127,11 @@             Left err -> fail err         else return s -unescapedField :: AL.Parser S.ByteString-unescapedField = A.takeWhile (\ c -> c /= doubleQuote &&-                                     c /= newline &&-                                     c /= commaB &&-                                     c /= cr)+unescapedField :: Word8 -> AL.Parser S.ByteString+unescapedField !delim = A.takeWhile (\ c -> c /= doubleQuote &&+                                            c /= newline &&+                                            c /= delim &&+                                            c /= cr)  dquote :: AL.Parser Char dquote = char '"'@@ -151,8 +151,7 @@       then return (acc `mappend` fromByteString h)       else rest -doubleQuote, newline, commaB, cr :: Word8+doubleQuote, newline, cr :: Word8 doubleQuote = 34 newline = 10-commaB = 44 cr = 13
cassava.cabal view
@@ -1,10 +1,10 @@ Name:                cassava-Version:             0.1.0.0+Version:             0.1.0.1 Synopsis:            A CSV parsing and encoding library Description:   A CSV parsing and encoding library optimized for ease of use and high   performance.-Homepage:            https://github.com/tibbe/sea+Homepage:            https://github.com/tibbe/cassava License:             BSD3 License-file:        LICENSE Bug-reports:         https://github.com/tibbe/cassava/issues@@ -16,6 +16,7 @@ Category:            Text, Web, CSV Build-type:          Simple Cabal-version:       >=1.8+Extra-source-files:  examples/*.hs   Library
+ examples/IndexBasedDecode.hs view
@@ -0,0 +1,13 @@+{-# LANGUAGE ScopedTypeVariables #-}++import qualified Data.ByteString.Lazy as BL+import Data.Csv+import qualified Data.Vector as V++main :: IO ()+main = do+    csvData <- BL.readFile "salaries.csv"+    case decode csvData of+        Left err -> putStrLn err+        Right v -> V.forM_ v $ \ (name, salary :: Int) ->+            putStrLn $ name ++ " earns " ++ show salary ++ " dollars"
+ examples/NamedBasedDecode.hs view
@@ -0,0 +1,22 @@+{-# LANGUAGE OverloadedStrings #-}++import Control.Applicative+import qualified Data.ByteString.Lazy as BL+import Data.Csv+import qualified Data.Vector as V++data Person = Person+    { name   :: String+    , salary :: Int+    }++instance FromNamedRecord Person where+    parseNamedRecord r = Person <$> r .: "name" <*> r .: "salary"++main :: IO ()+main = do+    csvData <- BL.readFile "salaries.csv"+    case decodeByName csvData of+        Left err -> putStrLn err+        Right (_, v) -> V.forM_ v $ \ p ->+            putStrLn $ name p ++ " earns " ++ show (salary p) ++ " dollars"
tests/UnitTests.hs view
@@ -27,7 +27,15 @@ -- Parse tests  decodesAs :: BL.ByteString -> [[B.ByteString]] -> Assertion-decodesAs input expected = case decode input of+decodesAs input expected = assertResult input expected $ decode input++decodesWithAs :: DecodeOptions -> BL.ByteString -> [[B.ByteString]] -> Assertion+decodesWithAs opts input expected =+    assertResult input expected $ decodeWith opts input++assertResult :: BL.ByteString -> [[B.ByteString]]+             -> Either String (V.Vector (V.Vector B.ByteString)) -> Assertion+assertResult input expected res = case res of     Right r  -> V.fromList (map V.fromList expected) @=? r     Left err -> assertFailure $                 "      input: " ++ show (BL8.unpack input) ++ "\n" ++@@ -37,6 +45,10 @@ encodesAs input expected =     encode (V.fromList (map V.fromList input)) @?= expected +encodesWithAs :: EncodeOptions -> [[B.ByteString]] -> BL.ByteString -> Assertion+encodesWithAs opts input expected =+    encodeWith opts (V.fromList (map V.fromList input)) @?= expected+ namedEncodesAs :: [B.ByteString] -> [[(B.ByteString, B.ByteString)]]                -> BL.ByteString -> Assertion namedEncodesAs hdr input expected =@@ -79,6 +91,10 @@       , ("twoRecords",   [["abc"], ["def"]], "abc\r\ndef\r\n")       , ("newline",      [["abc\ndef"]],     "\"abc\ndef\"\r\n")       ]+    , testGroup "encodeWith"+      [ testCase "tab-delim" $ encodesWithAs (defEnc { encDelimiter = 9 })+        [["1", "2"]] "1\t2\r\n"+      ]     , testGroup "decode" $ map decodeTest       [ ("simple",       "a,b,c\n",        [["a", "b", "c"]])       , ("crlf",         "a,b\r\nc,d\r\n", [["a", "b"], ["c", "d"]])@@ -87,12 +103,18 @@          [["a", "b", "c"], ["d", "e", "f"]])       , ("leadingSpace", " a,  b,   c\n",  [[" a", "  b", "   c"]])       ] ++ [testCase "rfc4180" testRfc4180]+    , testGroup "decodeWith"+      [ testCase "tab-delim" $ decodesWithAs (defDec { decDelimiter = 9 })+        "1\t2" [["1", "2"]]+      ]     ]   where     encodeTest (name, input, expected) =         testCase name $ input `encodesAs` expected     decodeTest (name, input, expected) =         testCase name $ input `decodesAs` expected+    defEnc = defaultEncodeOptions+    defDec = defaultDecodeOptions  nameBasedTests :: [TF.Test] nameBasedTests =