Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use specific builder functions for encoding. #187

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 12 additions & 11 deletions src/Data/Csv/Conversion.hs
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ import qualified Control.Monad.Fail as Fail
import Data.Attoparsec.ByteString.Char8 (double)
import qualified Data.Attoparsec.ByteString.Char8 as A8
import qualified Data.ByteString as B
import qualified Data.ByteString.Builder as Builder
import qualified Data.ByteString.Char8 as B8
import qualified Data.ByteString.Lazy as L
#if MIN_VERSION_bytestring(0,10,4)
Expand Down Expand Up @@ -885,7 +886,7 @@ instance FromField Int where

-- | Uses decimal encoding with optional sign.
instance ToField Int where
toField = decimal
toField = viaBuilder . Builder.intDec
{-# INLINE toField #-}

-- | Accepts a signed decimal number. Ignores whitespace.
Expand All @@ -895,7 +896,7 @@ instance FromField Integer where

-- | Uses decimal encoding with optional sign.
instance ToField Integer where
toField = decimal
toField = viaBuilder . Builder.integerDec
{-# INLINE toField #-}

-- | Accepts a signed decimal number. Ignores whitespace.
Expand All @@ -905,7 +906,7 @@ instance FromField Int8 where

-- | Uses decimal encoding with optional sign.
instance ToField Int8 where
toField = decimal
toField = viaBuilder . Builder.int8Dec
{-# INLINE toField #-}

-- | Accepts a signed decimal number. Ignores whitespace.
Expand All @@ -915,7 +916,7 @@ instance FromField Int16 where

-- | Uses decimal encoding with optional sign.
instance ToField Int16 where
toField = decimal
toField = viaBuilder . Builder.int16Dec
{-# INLINE toField #-}

-- | Accepts a signed decimal number. Ignores whitespace.
Expand All @@ -925,7 +926,7 @@ instance FromField Int32 where

-- | Uses decimal encoding with optional sign.
instance ToField Int32 where
toField = decimal
toField = viaBuilder . Builder.int32Dec
{-# INLINE toField #-}

-- | Accepts a signed decimal number. Ignores whitespace.
Expand All @@ -935,7 +936,7 @@ instance FromField Int64 where

-- | Uses decimal encoding with optional sign.
instance ToField Int64 where
toField = decimal
toField = viaBuilder . Builder.int64Dec
{-# INLINE toField #-}

-- | Accepts an unsigned decimal number. Ignores whitespace.
Expand All @@ -945,7 +946,7 @@ instance FromField Word where

-- | Uses decimal encoding.
instance ToField Word where
toField = decimal
toField = viaBuilder . Builder.wordDec
{-# INLINE toField #-}

-- | Accepts an unsigned decimal number. Ignores whitespace.
Expand All @@ -969,7 +970,7 @@ instance FromField Word8 where

-- | Uses decimal encoding.
instance ToField Word8 where
toField = decimal
toField = viaBuilder . Builder.word8Dec
{-# INLINE toField #-}

-- | Accepts an unsigned decimal number. Ignores whitespace.
Expand All @@ -979,7 +980,7 @@ instance FromField Word16 where

-- | Uses decimal encoding.
instance ToField Word16 where
toField = decimal
toField = viaBuilder . Builder.word16Dec
{-# INLINE toField #-}

-- | Accepts an unsigned decimal number. Ignores whitespace.
Expand All @@ -989,7 +990,7 @@ instance FromField Word32 where

-- | Uses decimal encoding.
instance ToField Word32 where
toField = decimal
toField = viaBuilder . Builder.word32Dec
{-# INLINE toField #-}

-- | Accepts an unsigned decimal number. Ignores whitespace.
Expand All @@ -999,7 +1000,7 @@ instance FromField Word64 where

-- | Uses decimal encoding.
instance ToField Word64 where
toField = decimal
toField = viaBuilder . Builder.word64Dec
{-# INLINE toField #-}

instance FromField B.ByteString where
Expand Down
43 changes: 7 additions & 36 deletions src/Data/Csv/Conversion/Internal.hs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ module Data.Csv.Conversion.Internal
( decimal
, scientific
, realFloat
, viaBuilder
, formatBoundedSigned
) where

import Data.ByteString.Builder (Builder, toLazyByteString, word8, char8,
Expand All @@ -12,7 +14,6 @@ import Data.Array.Base (unsafeAt)
import Data.Array.IArray
import qualified Data.ByteString as B
import Data.Char (ord)
import Data.Int
import qualified Data.Monoid as Mon
import Data.Scientific (Scientific)
import Data.Word
Expand All @@ -29,26 +30,6 @@ decimal = toStrict . toLazyByteString . formatDecimal
-- TODO: Add an optimized version for Integer.

formatDecimal :: Integral a => a -> Builder
{-# RULES "formatDecimal/Int" formatDecimal = formatBoundedSigned
:: Int -> Builder #-}
{-# RULES "formatDecimal/Int8" formatDecimal = formatBoundedSigned
:: Int8 -> Builder #-}
{-# RULES "formatDecimal/Int16" formatDecimal = formatBoundedSigned
:: Int16 -> Builder #-}
{-# RULES "formatDecimal/Int32" formatDecimal = formatBoundedSigned
:: Int32 -> Builder #-}
{-# RULES "formatDecimal/Int64" formatDecimal = formatBoundedSigned
:: Int64 -> Builder #-}
{-# RULES "formatDecimal/Word" formatDecimal = formatPositive
:: Word -> Builder #-}
{-# RULES "formatDecimal/Word8" formatDecimal = formatPositive
:: Word8 -> Builder #-}
{-# RULES "formatDecimal/Word16" formatDecimal = formatPositive
:: Word16 -> Builder #-}
{-# RULES "formatDecimal/Word32" formatDecimal = formatPositive
:: Word32 -> Builder #-}
{-# RULES "formatDecimal/Word64" formatDecimal = formatPositive
:: Word64 -> Builder #-}
{-# NOINLINE formatDecimal #-}
formatDecimal i
| i < 0 = minus Mon.<>
Expand All @@ -58,11 +39,6 @@ formatDecimal i
| otherwise = formatPositive i

formatBoundedSigned :: (Integral a, Bounded a) => a -> Builder
{-# SPECIALIZE formatBoundedSigned :: Int -> Builder #-}
{-# SPECIALIZE formatBoundedSigned :: Int8 -> Builder #-}
{-# SPECIALIZE formatBoundedSigned :: Int16 -> Builder #-}
{-# SPECIALIZE formatBoundedSigned :: Int32 -> Builder #-}
{-# SPECIALIZE formatBoundedSigned :: Int64 -> Builder #-}
formatBoundedSigned i
| i < 0 = minus Mon.<>
if i == minBound
Expand All @@ -71,16 +47,6 @@ formatBoundedSigned i
| otherwise = formatPositive i

formatPositive :: Integral a => a -> Builder
{-# SPECIALIZE formatPositive :: Int -> Builder #-}
{-# SPECIALIZE formatPositive :: Int8 -> Builder #-}
{-# SPECIALIZE formatPositive :: Int16 -> Builder #-}
{-# SPECIALIZE formatPositive :: Int32 -> Builder #-}
{-# SPECIALIZE formatPositive :: Int64 -> Builder #-}
{-# SPECIALIZE formatPositive :: Word -> Builder #-}
{-# SPECIALIZE formatPositive :: Word8 -> Builder #-}
{-# SPECIALIZE formatPositive :: Word16 -> Builder #-}
{-# SPECIALIZE formatPositive :: Word32 -> Builder #-}
{-# SPECIALIZE formatPositive :: Word64 -> Builder #-}
formatPositive = go
where go n | n < 10 = digit n
| otherwise = go (n `quot` 10) Mon.<> digit (n `rem` 10)
Expand Down Expand Up @@ -297,3 +263,8 @@ i2d i = fromIntegral (ord '0' + i)
-- | Word8 list rendering
word8s :: [Word8] -> Builder
word8s = BP.primMapListFixed BP.word8

-- | Helper function that build strict bytestring via a provided builder.
viaBuilder :: Builder -> B.ByteString
viaBuilder = toStrict . toLazyByteString
{-# INLINE viaBuilder #-}