avro 0.3.4.1 → 0.3.4.2
raw patch · 4 files changed
+96/−26 lines, 4 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
Files
- avro.cabal +3/−2
- src/Data/Avro/Decode.hs +14/−13
- src/Data/Avro/Decode/Lazy.hs +14/−11
- test/Avro/Decode/Lazy/ContainerSpec.hs +65/−0
avro.cabal view
@@ -2,10 +2,10 @@ -- -- see: https://github.com/sol/hpack ----- hash: 0af56f5e0a9d8bce12730d5834259529fad0458a9efdf3d8127c1f3ac4e921cb+-- hash: 307ace222c16e9660fc8fd8f1d3b126a4254daea39bb616b93782a86b81d73b0 name: avro-version: 0.3.4.1+version: 0.3.4.2 synopsis: Avro serialization support for Haskell description: Avro serialization and deserialization support for Haskell category: Data@@ -120,6 +120,7 @@ Avro.Codec.NestedSpec Avro.Codec.TextSpec Avro.Codec.ZigZagSpec+ Avro.Decode.Lazy.ContainerSpec Avro.Decode.Lazy.ValuesSpec Avro.Deconflict.Reader Avro.Deconflict.Writer
src/Data/Avro/Decode.hs view
@@ -69,19 +69,20 @@ (containedSchema,) <$> getBlocks (schemaToGet containedSchema) syncBytes decompress where getBlocks :: Get a -> BL.ByteString -> (BL.ByteString -> Get BL.ByteString) -> Get [[a]]- getBlocks getValue sync decompress =- do nrObj <- sFromIntegral =<< getLong- nrBytes <- getLong- bytes <- decompress =<< G.getLazyByteString nrBytes- r <- case runGetOrFail (replicateM nrObj getValue) bytes of- Right (_,_,x) -> return x- Left (_,_,s) -> fail s- marker <- G.getLazyByteString nrSyncBytes- when (marker /= sync) (fail "Invalid marker, does not match sync bytes.")- e <- G.isEmpty- if e- then return [r]- else (r :) <$> getBlocks getValue sync decompress+ getBlocks getValue sync decompress = do+ isEmpty <- G.isEmpty+ if isEmpty+ then return []+ else do+ nrObj <- sFromIntegral =<< getLong+ nrBytes <- getLong+ bytes <- decompress =<< G.getLazyByteString nrBytes+ r <- case runGetOrFail (replicateM nrObj getValue) bytes of+ Right (_,_,x) -> return x+ Left (_,_,s) -> fail s+ marker <- G.getLazyByteString nrSyncBytes+ when (marker /= sync) (fail "Invalid marker, does not match sync bytes.")+ (r :) <$> getBlocks getValue sync decompress getCodec :: Monad m => Maybe BL.ByteString -> m (BL.ByteString -> m BL.ByteString) getCodec code | Just "null" <- code =
src/Data/Avro/Decode/Lazy.hs view
@@ -141,7 +141,8 @@ -> Either String (Schema, [[T.LazyValue Type]]) getContainerValuesWith schemaToGet bs = case runGetOrFail getAvro bs of- Left (bs', _, err) -> Left err+ Left (bs', _, err) ->+ Left err Right (bs', _, ContainerHeader {..}) -> Right (containedSchema, snd $ getBlocks (schemaToGet containedSchema) syncBytes bs' decompress) where@@ -164,16 +165,18 @@ -> (BL.ByteString -> Get BL.ByteString) -- ^ how to decompress -> (BL.ByteString, [[T.LazyValue Type]]) getBlocks getValue sync bs decompress =- case runGetOrFail (getRawBlock decompress) bs of- Left (bs', _, err) -> (bs', [[T.Error err]])- Right (bs', _, (nrObj, bytes)) ->- let (_, vs) = consumeN (fromIntegral nrObj) getValue bytes- in case checkMarker sync bs' of- Left err -> (bs', [[T.Error err]])- Right bs'' | BL.null bs'' -> (bs'', [vs])- Right bs'' ->- let (rest, vs') = getBlocks getValue sync bs'' decompress- in (rest, vs : vs')+ if BL.null bs+ then (bs, [])+ else case runGetOrFail (getRawBlock decompress) bs of+ Left (bs', _, err) -> (bs', [[T.Error err]])+ Right (bs', _, (nrObj, bytes)) ->+ let (_, vs) = consumeN (fromIntegral nrObj) getValue bytes+ in case checkMarker sync bs' of+ Left err -> (bs', [[T.Error err]])+ Right bs'' | BL.null bs'' -> (bs'', [vs])+ Right bs'' ->+ let (rest, vs') = getBlocks getValue sync bs'' decompress+ in (rest, vs : vs') decodeGet :: GetAvro a => (a -> T.LazyValue Type) -> BL.ByteString -> (BL.ByteString, T.LazyValue Type) decodeGet f bs =
+ test/Avro/Decode/Lazy/ContainerSpec.hs view
@@ -0,0 +1,65 @@+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TemplateHaskell #-}+module Avro.Decode.Lazy.ContainerSpec+where++import Data.Avro as A+import Data.Avro.Decode.Lazy as DL+import Data.Avro.Decode.Lazy.Convert as TC+import Data.Avro.Deriving+import Data.Either (isLeft)+import Data.List (unfoldr)+import Data.Semigroup ((<>))+import Data.Text (pack)++import Test.Hspec++{-# ANN module ("HLint: ignore Redundant do" :: String) #-}++deriveAvro "test/data/small.avsc"++spec :: Spec+spec = describe "Avro.Decode.Lazy.ContainerSpec" $ do++ it "should decode empty container" $+ encodeThenDecode ([] :: [[Endpoint]]) >>= (`shouldBe` [])++ it "should decode container with one block" $ do+ let msg = mkEndpoint 1+ res <- encodeThenDecode [[msg]]+ sequence res `shouldBe` Right [msg]++ it "should decode container with empty blocks" $ do+ let msg = mkEndpoint 1+ res <- encodeThenDecode [[msg], [], []]+ sequence res `shouldBe` Right [msg]++ it "should decode container with empty blocks in between" $ do+ let (msg1, msg2) = (mkEndpoint 1, mkEndpoint 2)+ res <- encodeThenDecode [[msg1], [], [], [msg2]]+ sequence res `shouldBe` Right [msg1, msg2]++ it "should decode container with multiple blocks" $ do+ let msgs = mkEndpoint <$> [1..10]+ let chunks = chunksOf 4 msgs+ res <- encodeThenDecode chunks+ sequence res `shouldBe` Right msgs++encodeThenDecode :: (FromAvro a, ToAvro a) => [[a]] -> IO [Either String a]+encodeThenDecode as =+ DL.decodeContainer <$> A.encodeContainer as++mkEndpoint :: Int -> Endpoint+mkEndpoint i =+ Endpoint+ { endpointIps = ["192.168.1." <> pack (show i), "127.0.0." <> pack (show i)]+ , endpointPorts = [PortRange 1 10, PortRange 11 20]+ , endpointOpaque = Opaque "16-b-long-string"+ , endpointCorrelation = Opaque "opaq-correlation"+ , endpointTag = Left (fromIntegral i)+ }++chunksOf :: Int -> [a] -> [[a]]+chunksOf n = takeWhile (not.null) . unfoldr (Just . splitAt n)