packages feed

cborg-json 0.2.1.0 → 0.2.2.0

raw patch · 4 files changed

+123/−13 lines, 4 filesdep +bytestringdep +cborg-jsondep +criteriondep ~aesondep ~basedep ~cborgPVP ok

version bump matches the API change (PVP)

Dependencies added: bytestring, cborg-json, criterion, deepseq, directory, process, zlib

Dependency ranges changed: aeson, base, cborg

API changes (from Hackage documentation)

Files

ChangeLog.md view
@@ -1,5 +1,14 @@ # Revision history for cborg-json -## 0.1.0.0  -- YYYY-mm-dd+## 0.2.2.0  -- 2019-12-29++* Use `replicateM` to significantly speed up decoding. Now faster than Aeson!++* Add support for decoding half-precision and single-precision floating-point+  numbers.++* Version bumps and support for GHC 8.8++## 0.1.0.0  -- 2017-08-01  * First version. Released on an unsuspecting world.
+ bench/Main.hs view
@@ -0,0 +1,67 @@+module Main (main) where++import qualified Data.ByteString.Lazy   as LBS+import qualified Codec.Compression.GZip as GZip+import           Control.Monad (unless)+import           System.Directory (doesFileExist)+import           System.Process   (callProcess)++import           Codec.CBOR.JSON (encodeValue, decodeValue)+import           Codec.CBOR.Read (deserialiseFromBytes)+import           Codec.CBOR.Write (toLazyByteString, toStrictByteString)++import           Criterion.Main+                   ( defaultMain, Benchmark, bgroup, bench, env, nf, whnf )+import qualified Data.Aeson as Aeson (Value, decode, encode)+++dataFile :: FilePath+dataFile = "bench/data.json.gz"++dataFileURL :: FilePath+dataFileURL = "https://raw.githubusercontent.com/well-typed/cborg/master/cborg-json/bench/data.json.gz"++fetchLargeJSON :: IO ()+fetchLargeJSON = do+    exists <- doesFileExist dataFile+    unless exists $ do+      putStrLn $ "Fetching bechmark data file from " ++ dataFileURL+      callProcess "curl" [dataFileURL, "--output", dataFile]++loadLargeJSONBytes :: IO LBS.ByteString+loadLargeJSONBytes = do+    fetchLargeJSON+    fmap GZip.decompress (LBS.readFile dataFile)++loadLargeJSON :: IO Aeson.Value+loadLargeJSON = do+    bytes <- loadLargeJSONBytes+    let Just json = Aeson.decode bytes+    return json++loadLargeCBORBytes :: IO LBS.ByteString+loadLargeCBORBytes =+    fmap (toLazyByteString . encodeValue) loadLargeJSON++main :: IO ()+main = defaultMain benchmarks++benchmarks :: [Benchmark]+benchmarks =+    [ bgroup "Decode"+        [ env loadLargeJSONBytes $ \largeJSONBytes ->+          bench "JSON" (whnf (Aeson.decode :: LBS.ByteString -> Maybe Aeson.Value) largeJSONBytes)++        , env loadLargeCBORBytes $ \largeCBORBytes ->+          bench "CBOR" (whnf (deserialiseFromBytes (decodeValue False)) largeCBORBytes)++        , env loadLargeCBORBytes $ \largeCBORBytes ->+          bench "CBOR lenient" (whnf (deserialiseFromBytes (decodeValue True)) largeCBORBytes)+        ]+    , env loadLargeJSON $ \largeJSON ->+      bgroup "Encode"+        [ bench "JSON" (nf Aeson.encode largeJSON)+        , bench "CBOR" (nf (toLazyByteString . encodeValue) largeJSON)+        , bench "CBOR strict" (whnf (toStrictByteString . encodeValue) largeJSON)+        ]+    ]
cborg-json.cabal view
@@ -1,5 +1,5 @@ name:                cborg-json-version:             0.2.1.0+version:             0.2.2.0 synopsis:            A library for encoding JSON as CBOR description:         This package implements the bijection between JSON and                      CBOR defined in the CBOR specification, RFC 7049.@@ -16,12 +16,14 @@ build-type:          Simple extra-source-files:  ChangeLog.md cabal-version:       >=1.10+tested-with:+  GHC == 7.8.4, GHC == 7.10.3, GHC == 8.0.2, GHC == 8.2.2, GHC == 8.4.4, GHC == 8.6.5, GHC==8.8.1  library   exposed-modules:     Codec.CBOR.JSON   ghc-options:         -Wall   build-depends:-    base >=4.7 && <4.13,+    base >=4.7 && < 4.14,     aeson >=0.7 && <1.5,     aeson-pretty >=0.8 && <0.9,     unordered-containers >=0.2 && <0.3,@@ -33,4 +35,29 @@   default-language:    Haskell2010    if impl(ghc >= 8.0)-    ghc-options: -Wcompat -Wnoncanonical-monad-instances -Wnoncanonical-monadfail-instances+    ghc-options: -Wcompat -Wnoncanonical-monad-instances++++benchmark bench+  type:              exitcode-stdio-1.0+  hs-source-dirs:    bench+  main-is:           Main.hs++  default-language:  Haskell2010+  ghc-options:+    -Wall -rtsopts -fno-cse -fno-ignore-asserts -fno-warn-orphans -O2++  other-modules:++  build-depends:+    base                    >= 4.6     && < 5.0,+    cborg                                      ,+    cborg-json                                 ,+    aeson                                      ,+    bytestring              >= 0.10.4  && < 0.11,+    criterion               >= 1.0     && < 1.6,+    deepseq                 >= 1.0     && < 1.5,+    directory,+    process,+    zlib                    >= 0.5     && < 0.7
src/Codec/CBOR/JSON.hs view
@@ -7,7 +7,7 @@  import           Data.Monoid import           Control.Applicative-import           Prelude+import           Prelude hiding (decodeFloat)  import           Codec.CBOR.Encoding import           Codec.CBOR.Decoding@@ -49,13 +49,15 @@       TypeNInt    -> decodeNumberIntegral       TypeNInt64  -> decodeNumberIntegral       TypeInteger -> decodeNumberIntegral+      TypeFloat16 -> decodeNumberFloat16+      TypeFloat32 -> decodeNumberFloating       TypeFloat64 -> decodeNumberFloating       TypeBool    -> Bool   <$> decodeBool       TypeNull    -> Null   <$  decodeNull       TypeString  -> String <$> decodeString -      TypeListLen      -> decodeListLen >>= flip (decodeListN lenient) []-      TypeListLenIndef -> decodeListLenIndef >> (decodeListIndef lenient) []+      TypeListLen      -> decodeListLen >>= decodeListN lenient+      TypeListLenIndef -> decodeListLenIndef >> decodeListIndef lenient []       TypeMapLen       -> decodeMapLen >>= flip (decodeMapN lenient) HM.empty        _           -> fail $ "unexpected CBOR token type for a JSON value: "@@ -67,12 +69,17 @@ decodeNumberFloating :: Decoder s Value decodeNumberFloating = Number . Scientific.fromFloatDigits <$> decodeDouble -decodeListN :: Bool -> Int -> [Value] -> Decoder s Value-decodeListN !lenient !n acc =-    case n of-      0 -> return $! Array (V.fromList (reverse acc))-      _ -> do !t <- decodeValue lenient-              decodeListN lenient (n-1) (t : acc)+decodeNumberFloat16 :: Decoder s Value+decodeNumberFloat16 = do+    f <- decodeFloat+    if isNaN f || isInfinite f+        then return Null+        else return $ Number (Scientific.fromFloatDigits f)++decodeListN :: Bool -> Int -> Decoder s Value+decodeListN !lenient !n = do+  vec <- V.replicateM n (decodeValue lenient) +  return $! Array vec  decodeListIndef :: Bool -> [Value] -> Decoder s Value decodeListIndef !lenient acc = do