binary-generic-combinators 0.4.3.0 → 0.4.4.0
raw patch · 4 files changed
+66/−4 lines, 4 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
+ Data.Binary.Combinators: data MatchASCII (ctx :: Symbol) (ascii :: Symbol)
+ Data.Binary.Combinators: instance (GHC.TypeLits.KnownSymbol ctx, GHC.TypeLits.KnownSymbol ascii) => Data.Binary.Class.Binary (Data.Binary.Combinators.MatchASCII ctx ascii)
+ Data.Binary.Combinators: instance (GHC.TypeLits.KnownSymbol ctx, GHC.TypeLits.KnownSymbol ascii) => Test.QuickCheck.Arbitrary.Arbitrary (Data.Binary.Combinators.MatchASCII ctx ascii)
+ Data.Binary.Combinators: instance GHC.Classes.Eq (Data.Binary.Combinators.MatchASCII s ns)
+ Data.Binary.Combinators: instance GHC.Classes.Ord (Data.Binary.Combinators.MatchASCII s ns)
+ Data.Binary.Combinators: instance GHC.Show.Show (Data.Binary.Combinators.MatchASCII ctx ascii)
+ Data.Binary.Combinators: matchASCII :: (KnownSymbol ctx, KnownSymbol ascii) => MatchASCII ctx ascii
Files
- ChangeLog.md +5/−0
- binary-generic-combinators.cabal +3/−3
- src/Data/Binary/Combinators.hs +47/−0
- test/Spec.hs +11/−1
ChangeLog.md view
@@ -1,5 +1,10 @@ # Changelog for binary-generic-combinators +## v0.4.4.0++- Add `MatchASCII` helper.+- Minor documentation improvements.+ ## v0.4.3.0 - Add `LE` newtype wrapper for little endian (de)serialization.
binary-generic-combinators.cabal view
@@ -1,13 +1,13 @@ cabal-version: 1.12 --- This file has been generated from package.yaml by hpack version 0.33.0.+-- This file has been generated from package.yaml by hpack version 0.34.4. -- -- see: https://github.com/sol/hpack ----- hash: 3a3c919e506e259e384c033410599dd1b6c49127ebccec2c46eae9bdab9401d8+-- hash: 5538ed4321c0204d5b35f264f98d0eb44d34283505bd06a5c140744f0f59dd64 name: binary-generic-combinators-version: 0.4.3.0+version: 0.4.4.0 synopsis: Combinators and utilities to make Generic-based deriving of Binary easier and more expressive description: Please see the README on GitHub at <https://github.com/0xd34df00d/binary-generic-combinators#readme> category: Data, Parsing
src/Data/Binary/Combinators.hs view
@@ -25,9 +25,15 @@ , CountedBy(..) , SkipCount(..) , SkipByte(..)+ , MatchBytes , matchBytes+ , MatchByte++, MatchASCII+, matchASCII+ , LE(..) ) where @@ -36,6 +42,7 @@ import Data.Binary import Data.Binary.Get import Data.Binary.Put+import Data.Char import Data.Functor import Data.Int import Data.Kind@@ -134,6 +141,9 @@ -- if they are equal to @[ 0xd3, 0x4d, 0xf0, 0x0d ]@ respectively, or fails otherwise. -- -- Serializing this type produces the @bytes@.+-- To easily create a value of this type, use the 'matchBytes' helper.+--+-- See also 'MatchASCII'. data MatchBytes (ctx :: Symbol) (bytes :: [Nat]) :: Type where ConsumeNil :: MatchBytes ctx '[] ConsumeCons :: KnownNat n => Proxy n -> MatchBytes ctx ns -> MatchBytes ctx (n ': ns)@@ -185,6 +195,43 @@ -- | An alias for 'MatchBytes' when you only need to match a single byte. type MatchByte ctx byte = MatchBytes ctx '[ byte ]+++-- | @MatchASCII ctx ascii@ ensures that the subsequent bytes in the input stream match the ASCII characters @ascii@.+--+-- Serializing this type producers the @ascii@.+-- To easily create a value of this type, use the 'matchASCII' helper.+--+-- See also 'MatchBytes'.+data MatchASCII (ctx :: Symbol) (ascii :: Symbol) where+ ConsumeASCII :: KnownSymbol ascii => MatchASCII ctx ascii++deriving instance Eq (MatchASCII s ns)+deriving instance Ord (MatchASCII s ns)++toBytes :: forall ctx ascii. MatchASCII ctx ascii -> [Word8]+toBytes ConsumeASCII = map (fromIntegral . ord) $ symbolVal (Proxy :: Proxy ascii)++instance (KnownSymbol ctx, KnownSymbol ascii) => Binary (MatchASCII ctx ascii) where+ get = do bytes <- replicateM (length expected) get+ when (bytes /= expected) $ fail $ "Unexpected bytes " <> show bytes+ <> " (or, as ASCII, `" <> (chr . fromIntegral <$> bytes) <> "`)"+ <> " when parsing" <> symbolVal (Proxy :: Proxy ctx)+ pure resSing+ where+ resSing = ConsumeASCII+ expected = toBytes resSing+ put = mapM_ put . toBytes++instance Show (MatchASCII ctx ascii) where+ show ConsumeASCII = "Marker [ " <> symbolVal (Proxy :: Proxy ascii) <> " ]"++instance (KnownSymbol ctx, KnownSymbol ascii) => Arbitrary (MatchASCII ctx ascii) where+ arbitrary = pure matchASCII++-- | Produce the (singleton) value of type 'MatchASCII' @ctx ascii@.+matchASCII :: (KnownSymbol ctx, KnownSymbol ascii) => MatchASCII ctx ascii+matchASCII = ConsumeASCII -- | An @a@ serialized in little endian byte order.
test/Spec.hs view
@@ -1,5 +1,5 @@ {-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE DerivingVia, DeriveGeneric #-}+{-# LANGUAGE DerivingVia, DeriveGeneric, DeriveAnyClass #-} {-# LANGUAGE DataKinds #-} import Data.Binary@@ -50,6 +50,13 @@ deriving (Show, Eq, Generic) deriving Binary via Alternatively ComplexType +newtype WithBytesMarker = WithBytesMarker (MatchBytes "test context" [ 113, 111, 105, 102 ])+ deriving (Show, Eq, Generic)+ deriving anyclass Binary+newtype WithASCIIMarker = WithASCIIMarker (MatchASCII "test context" "qoif")+ deriving (Show, Eq, Generic)+ deriving anyclass Binary+ instance Arbitrary ComplexType where arbitrary = genericArbitrary shrink = genericShrink@@ -80,6 +87,9 @@ it "decoding Word16" $ property $ \(n :: Word16) -> getLE (decode $ encode n) `shouldBe` swapBytes n it "decoding Word32" $ property $ \(n :: Word32) -> getLE (decode $ encode n) `shouldBe` swapBytes n it "decoding Word64" $ property $ \(n :: Word64) -> getLE (decode $ encode n) `shouldBe` swapBytes n+ describe "MatchASCII" $ do+ it "matches MatchBytes when encoding" $ decode (encode $ WithASCIIMarker matchASCII) `shouldBe` WithBytesMarker matchBytes+ it "matches MatchBytes when decoding" $ decode (encode $ WithBytesMarker matchBytes) `shouldBe` WithASCIIMarker matchASCII swapBytes :: Bytes a => a -> a swapBytes n = case targetByteOrder of