serialise 0.2.0.0 → 0.2.1.0
raw patch · 20 files changed
+180/−2434 lines, 20 filesdep +semigroupsdep −base16-bytestringdep −base64-bytestringdep −scientificdep ~QuickCheckdep ~aesondep ~binaryPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
Dependencies added: semigroups
Dependencies removed: base16-bytestring, base64-bytestring, scientific
Dependency ranges changed: QuickCheck, aeson, binary, containers, criterion, primitive, store, tasty, tasty-hunit, tasty-quickcheck, time
API changes (from Hackage documentation)
- Codec.Serialise.Class: instance (Codec.Serialise.Class.GSerialiseProd f, Codec.Serialise.Class.GSerialiseProd g) => Codec.Serialise.Class.GSerialiseDecode (f GHC.Generics.:*: g)
- Codec.Serialise.Class: instance (Codec.Serialise.Class.GSerialiseProd f, Codec.Serialise.Class.GSerialiseProd g) => Codec.Serialise.Class.GSerialiseEncode (f GHC.Generics.:*: g)
- Codec.Serialise.Class: instance (Codec.Serialise.Class.GSerialiseProd f, Codec.Serialise.Class.GSerialiseProd g) => Codec.Serialise.Class.GSerialiseProd (f GHC.Generics.:*: g)
- Codec.Serialise.Class: instance (Codec.Serialise.Class.GSerialiseSum f, Codec.Serialise.Class.GSerialiseSum g) => Codec.Serialise.Class.GSerialiseDecode (f GHC.Generics.:+: g)
- Codec.Serialise.Class: instance (Codec.Serialise.Class.GSerialiseSum f, Codec.Serialise.Class.GSerialiseSum g) => Codec.Serialise.Class.GSerialiseEncode (f GHC.Generics.:+: g)
- Codec.Serialise.Class: instance (Codec.Serialise.Class.GSerialiseSum f, Codec.Serialise.Class.GSerialiseSum g) => Codec.Serialise.Class.GSerialiseSum (f GHC.Generics.:+: g)
- Codec.Serialise.Class: instance (GHC.Classes.Ord a, Codec.Serialise.Class.Serialise a) => Codec.Serialise.Class.Serialise (Data.Set.Base.Set a)
- Codec.Serialise.Class: instance (GHC.Classes.Ord k, Codec.Serialise.Class.Serialise k, Codec.Serialise.Class.Serialise v) => Codec.Serialise.Class.Serialise (Data.Map.Base.Map k v)
- Codec.Serialise.Class: instance (i ~ GHC.Generics.C, Codec.Serialise.Class.GSerialiseProd f) => Codec.Serialise.Class.GSerialiseSum (GHC.Generics.M1 i c f)
- Codec.Serialise.Class: instance (i ~ GHC.Generics.S, Codec.Serialise.Class.GSerialiseProd f) => Codec.Serialise.Class.GSerialiseProd (GHC.Generics.M1 i c f)
- Codec.Serialise.Class: instance Codec.Serialise.Class.GSerialiseDecode a => Codec.Serialise.Class.GSerialiseDecode (GHC.Generics.M1 i c a)
- Codec.Serialise.Class: instance Codec.Serialise.Class.GSerialiseEncode a => Codec.Serialise.Class.GSerialiseEncode (GHC.Generics.M1 i c a)
- Codec.Serialise.Class: instance Codec.Serialise.Class.Serialise Data.IntSet.Base.IntSet
- Codec.Serialise.Class: instance Codec.Serialise.Class.Serialise Data.Monoid.All
- Codec.Serialise.Class: instance Codec.Serialise.Class.Serialise Data.Monoid.Any
- Codec.Serialise.Class: instance Codec.Serialise.Class.Serialise Data.Time.Clock.UTC.UTCTime
- Codec.Serialise.Class: instance Codec.Serialise.Class.Serialise Data.Typeable.Internal.TypeRep
- Codec.Serialise.Class: instance Codec.Serialise.Class.Serialise a => Codec.Serialise.Class.Serialise (Data.IntMap.Base.IntMap a)
- Codec.Serialise.Class: instance Codec.Serialise.Class.Serialise a => Codec.Serialise.Class.Serialise (Data.List.NonEmpty.NonEmpty a)
- Codec.Serialise.Class: instance Codec.Serialise.Class.Serialise a => Codec.Serialise.Class.Serialise (Data.Monoid.Dual a)
- Codec.Serialise.Class: instance Codec.Serialise.Class.Serialise a => Codec.Serialise.Class.Serialise (Data.Monoid.Product a)
- Codec.Serialise.Class: instance Codec.Serialise.Class.Serialise a => Codec.Serialise.Class.Serialise (Data.Monoid.Sum a)
- Codec.Serialise.Class: instance Codec.Serialise.Class.Serialise a => Codec.Serialise.Class.Serialise (Data.Sequence.Seq a)
- Codec.Serialise.Class: instance forall k (f :: k -> *) (a :: k). Codec.Serialise.Class.Serialise (f a) => Codec.Serialise.Class.Serialise (Data.Monoid.Alt f a)
+ Codec.Serialise.Class: instance (GHC.Classes.Ord a, Codec.Serialise.Class.Serialise a) => Codec.Serialise.Class.Serialise (Data.Set.Internal.Set a)
+ Codec.Serialise.Class: instance (GHC.Classes.Ord k, Codec.Serialise.Class.Serialise k, Codec.Serialise.Class.Serialise v) => Codec.Serialise.Class.Serialise (Data.Map.Internal.Map k v)
+ Codec.Serialise.Class: instance Codec.Serialise.Class.Serialise Data.IntSet.Internal.IntSet
+ Codec.Serialise.Class: instance Codec.Serialise.Class.Serialise Data.Semigroup.Internal.All
+ Codec.Serialise.Class: instance Codec.Serialise.Class.Serialise Data.Semigroup.Internal.Any
+ Codec.Serialise.Class: instance Codec.Serialise.Class.Serialise Data.Time.Clock.Internal.UTCTime.UTCTime
+ Codec.Serialise.Class: instance Codec.Serialise.Class.Serialise Data.Typeable.Internal.SomeTypeRep
+ Codec.Serialise.Class: instance Codec.Serialise.Class.Serialise GHC.Types.KindRep
+ Codec.Serialise.Class: instance Codec.Serialise.Class.Serialise GHC.Types.RuntimeRep
+ Codec.Serialise.Class: instance Codec.Serialise.Class.Serialise GHC.Types.TypeLitSort
+ Codec.Serialise.Class: instance Codec.Serialise.Class.Serialise GHC.Types.VecCount
+ Codec.Serialise.Class: instance Codec.Serialise.Class.Serialise GHC.Types.VecElem
+ Codec.Serialise.Class: instance Codec.Serialise.Class.Serialise a => Codec.Serialise.Class.Serialise (Data.IntMap.Internal.IntMap a)
+ Codec.Serialise.Class: instance Codec.Serialise.Class.Serialise a => Codec.Serialise.Class.Serialise (Data.Semigroup.Internal.Dual a)
+ Codec.Serialise.Class: instance Codec.Serialise.Class.Serialise a => Codec.Serialise.Class.Serialise (Data.Semigroup.Internal.Product a)
+ Codec.Serialise.Class: instance Codec.Serialise.Class.Serialise a => Codec.Serialise.Class.Serialise (Data.Semigroup.Internal.Sum a)
+ Codec.Serialise.Class: instance Codec.Serialise.Class.Serialise a => Codec.Serialise.Class.Serialise (Data.Sequence.Internal.Seq a)
+ Codec.Serialise.Class: instance Codec.Serialise.Class.Serialise a => Codec.Serialise.Class.Serialise (GHC.Base.NonEmpty a)
+ Codec.Serialise.Class: instance forall k (a :: k -> *) i (c :: GHC.Generics.Meta). Codec.Serialise.Class.GSerialiseDecode a => Codec.Serialise.Class.GSerialiseDecode (GHC.Generics.M1 i c a)
+ Codec.Serialise.Class: instance forall k (a :: k -> *) i (c :: GHC.Generics.Meta). Codec.Serialise.Class.GSerialiseEncode a => Codec.Serialise.Class.GSerialiseEncode (GHC.Generics.M1 i c a)
+ Codec.Serialise.Class: instance forall k (a :: k). Data.Typeable.Internal.Typeable a => Codec.Serialise.Class.Serialise (Data.Typeable.Internal.TypeRep a)
+ Codec.Serialise.Class: instance forall k (f :: k -> *) (a :: k). Codec.Serialise.Class.Serialise (f a) => Codec.Serialise.Class.Serialise (Data.Semigroup.Internal.Alt f a)
+ Codec.Serialise.Class: instance forall k (f :: k -> *) (g :: k -> *). (Codec.Serialise.Class.GSerialiseProd f, Codec.Serialise.Class.GSerialiseProd g) => Codec.Serialise.Class.GSerialiseDecode (f GHC.Generics.:*: g)
+ Codec.Serialise.Class: instance forall k (f :: k -> *) (g :: k -> *). (Codec.Serialise.Class.GSerialiseProd f, Codec.Serialise.Class.GSerialiseProd g) => Codec.Serialise.Class.GSerialiseEncode (f GHC.Generics.:*: g)
+ Codec.Serialise.Class: instance forall k (f :: k -> *) (g :: k -> *). (Codec.Serialise.Class.GSerialiseProd f, Codec.Serialise.Class.GSerialiseProd g) => Codec.Serialise.Class.GSerialiseProd (f GHC.Generics.:*: g)
+ Codec.Serialise.Class: instance forall k (f :: k -> *) (g :: k -> *). (Codec.Serialise.Class.GSerialiseSum f, Codec.Serialise.Class.GSerialiseSum g) => Codec.Serialise.Class.GSerialiseDecode (f GHC.Generics.:+: g)
+ Codec.Serialise.Class: instance forall k (f :: k -> *) (g :: k -> *). (Codec.Serialise.Class.GSerialiseSum f, Codec.Serialise.Class.GSerialiseSum g) => Codec.Serialise.Class.GSerialiseEncode (f GHC.Generics.:+: g)
+ Codec.Serialise.Class: instance forall k (f :: k -> *) (g :: k -> *). (Codec.Serialise.Class.GSerialiseSum f, Codec.Serialise.Class.GSerialiseSum g) => Codec.Serialise.Class.GSerialiseSum (f GHC.Generics.:+: g)
+ Codec.Serialise.Class: instance forall k i (f :: k -> *) (c :: GHC.Generics.Meta). (i ~ GHC.Generics.C, Codec.Serialise.Class.GSerialiseProd f) => Codec.Serialise.Class.GSerialiseSum (GHC.Generics.M1 i c f)
+ Codec.Serialise.Class: instance forall k i (f :: k -> *) (c :: GHC.Generics.Meta). (i ~ GHC.Generics.S, Codec.Serialise.Class.GSerialiseProd f) => Codec.Serialise.Class.GSerialiseProd (GHC.Generics.M1 i c f)
+ Codec.Serialise.Decoding: ConsumeByteArrayCanonical :: ByteArray -> ST s DecodeAction s a -> DecodeAction s a
+ Codec.Serialise.Decoding: ConsumeBytesCanonical :: ByteString -> ST s DecodeAction s a -> DecodeAction s a
+ Codec.Serialise.Decoding: ConsumeStringCanonical :: Text -> ST s DecodeAction s a -> DecodeAction s a
+ Codec.Serialise.Decoding: ConsumeUtf8ByteArrayCanonical :: ByteArray -> ST s DecodeAction s a -> DecodeAction s a
- Codec.Serialise: Done :: ~ByteString -> {-# UNPACK #-} ~ByteOffset -> a -> IDecode s a
+ Codec.Serialise: Done :: !ByteString -> {-# UNPACK #-} !ByteOffset -> a -> IDecode s a
- Codec.Serialise: Fail :: ~ByteString -> {-# UNPACK #-} ~ByteOffset -> DeserialiseFailure -> IDecode s a
+ Codec.Serialise: Fail :: !ByteString -> {-# UNPACK #-} !ByteOffset -> DeserialiseFailure -> IDecode s a
- Codec.Serialise: Partial :: (Maybe ByteString -> ST s (IDecode s a)) -> IDecode s a
+ Codec.Serialise: Partial :: Maybe ByteString -> ST s IDecode s a -> IDecode s a
- Codec.Serialise: class Serialise a where encode = gencode . from decode = to <$> gdecode encodeList = defaultEncodeList decodeList = defaultDecodeList
+ Codec.Serialise: class Serialise a
- Codec.Serialise: data DeserialiseFailure :: *
+ Codec.Serialise: data DeserialiseFailure
- Codec.Serialise: data IDecode s a :: * -> * -> *
+ Codec.Serialise: data IDecode s a
- Codec.Serialise.Class: class Serialise a where encode = gencode . from decode = to <$> gdecode encodeList = defaultEncodeList decodeList = defaultDecodeList
+ Codec.Serialise.Class: class Serialise a
- Codec.Serialise.Decoding: ConsumeBool :: (Bool -> ST s (DecodeAction s a)) -> DecodeAction s a
+ Codec.Serialise.Decoding: ConsumeBool :: Bool -> ST s DecodeAction s a -> DecodeAction s a
- Codec.Serialise.Decoding: ConsumeBreakOr :: (Bool -> ST s (DecodeAction s a)) -> DecodeAction s a
+ Codec.Serialise.Decoding: ConsumeBreakOr :: Bool -> ST s DecodeAction s a -> DecodeAction s a
- Codec.Serialise.Decoding: ConsumeByteArray :: (ByteArray -> ST s (DecodeAction s a)) -> DecodeAction s a
+ Codec.Serialise.Decoding: ConsumeByteArray :: ByteArray -> ST s DecodeAction s a -> DecodeAction s a
- Codec.Serialise.Decoding: ConsumeBytes :: (ByteString -> ST s (DecodeAction s a)) -> DecodeAction s a
+ Codec.Serialise.Decoding: ConsumeBytes :: ByteString -> ST s DecodeAction s a -> DecodeAction s a
- Codec.Serialise.Decoding: ConsumeBytesIndef :: ST s (DecodeAction s a) -> DecodeAction s a
+ Codec.Serialise.Decoding: ConsumeBytesIndef :: ST s DecodeAction s a -> DecodeAction s a
- Codec.Serialise.Decoding: ConsumeDouble :: (Double# -> ST s (DecodeAction s a)) -> DecodeAction s a
+ Codec.Serialise.Decoding: ConsumeDouble :: Double# -> ST s DecodeAction s a -> DecodeAction s a
- Codec.Serialise.Decoding: ConsumeDoubleCanonical :: (Double# -> ST s (DecodeAction s a)) -> DecodeAction s a
+ Codec.Serialise.Decoding: ConsumeDoubleCanonical :: Double# -> ST s DecodeAction s a -> DecodeAction s a
- Codec.Serialise.Decoding: ConsumeFloat :: (Float# -> ST s (DecodeAction s a)) -> DecodeAction s a
+ Codec.Serialise.Decoding: ConsumeFloat :: Float# -> ST s DecodeAction s a -> DecodeAction s a
- Codec.Serialise.Decoding: ConsumeFloat16Canonical :: (Float# -> ST s (DecodeAction s a)) -> DecodeAction s a
+ Codec.Serialise.Decoding: ConsumeFloat16Canonical :: Float# -> ST s DecodeAction s a -> DecodeAction s a
- Codec.Serialise.Decoding: ConsumeFloatCanonical :: (Float# -> ST s (DecodeAction s a)) -> DecodeAction s a
+ Codec.Serialise.Decoding: ConsumeFloatCanonical :: Float# -> ST s DecodeAction s a -> DecodeAction s a
- Codec.Serialise.Decoding: ConsumeInt :: (Int# -> ST s (DecodeAction s a)) -> DecodeAction s a
+ Codec.Serialise.Decoding: ConsumeInt :: Int# -> ST s DecodeAction s a -> DecodeAction s a
- Codec.Serialise.Decoding: ConsumeInt16 :: (Int# -> ST s (DecodeAction s a)) -> DecodeAction s a
+ Codec.Serialise.Decoding: ConsumeInt16 :: Int# -> ST s DecodeAction s a -> DecodeAction s a
- Codec.Serialise.Decoding: ConsumeInt16Canonical :: (Int# -> ST s (DecodeAction s a)) -> DecodeAction s a
+ Codec.Serialise.Decoding: ConsumeInt16Canonical :: Int# -> ST s DecodeAction s a -> DecodeAction s a
- Codec.Serialise.Decoding: ConsumeInt32 :: (Int# -> ST s (DecodeAction s a)) -> DecodeAction s a
+ Codec.Serialise.Decoding: ConsumeInt32 :: Int# -> ST s DecodeAction s a -> DecodeAction s a
- Codec.Serialise.Decoding: ConsumeInt32Canonical :: (Int# -> ST s (DecodeAction s a)) -> DecodeAction s a
+ Codec.Serialise.Decoding: ConsumeInt32Canonical :: Int# -> ST s DecodeAction s a -> DecodeAction s a
- Codec.Serialise.Decoding: ConsumeInt8 :: (Int# -> ST s (DecodeAction s a)) -> DecodeAction s a
+ Codec.Serialise.Decoding: ConsumeInt8 :: Int# -> ST s DecodeAction s a -> DecodeAction s a
- Codec.Serialise.Decoding: ConsumeInt8Canonical :: (Int# -> ST s (DecodeAction s a)) -> DecodeAction s a
+ Codec.Serialise.Decoding: ConsumeInt8Canonical :: Int# -> ST s DecodeAction s a -> DecodeAction s a
- Codec.Serialise.Decoding: ConsumeIntCanonical :: (Int# -> ST s (DecodeAction s a)) -> DecodeAction s a
+ Codec.Serialise.Decoding: ConsumeIntCanonical :: Int# -> ST s DecodeAction s a -> DecodeAction s a
- Codec.Serialise.Decoding: ConsumeInteger :: (Integer -> ST s (DecodeAction s a)) -> DecodeAction s a
+ Codec.Serialise.Decoding: ConsumeInteger :: Integer -> ST s DecodeAction s a -> DecodeAction s a
- Codec.Serialise.Decoding: ConsumeIntegerCanonical :: (Integer -> ST s (DecodeAction s a)) -> DecodeAction s a
+ Codec.Serialise.Decoding: ConsumeIntegerCanonical :: Integer -> ST s DecodeAction s a -> DecodeAction s a
- Codec.Serialise.Decoding: ConsumeListLen :: (Int# -> ST s (DecodeAction s a)) -> DecodeAction s a
+ Codec.Serialise.Decoding: ConsumeListLen :: Int# -> ST s DecodeAction s a -> DecodeAction s a
- Codec.Serialise.Decoding: ConsumeListLenCanonical :: (Int# -> ST s (DecodeAction s a)) -> DecodeAction s a
+ Codec.Serialise.Decoding: ConsumeListLenCanonical :: Int# -> ST s DecodeAction s a -> DecodeAction s a
- Codec.Serialise.Decoding: ConsumeListLenIndef :: ST s (DecodeAction s a) -> DecodeAction s a
+ Codec.Serialise.Decoding: ConsumeListLenIndef :: ST s DecodeAction s a -> DecodeAction s a
- Codec.Serialise.Decoding: ConsumeListLenOrIndef :: (Int# -> ST s (DecodeAction s a)) -> DecodeAction s a
+ Codec.Serialise.Decoding: ConsumeListLenOrIndef :: Int# -> ST s DecodeAction s a -> DecodeAction s a
- Codec.Serialise.Decoding: ConsumeMapLen :: (Int# -> ST s (DecodeAction s a)) -> DecodeAction s a
+ Codec.Serialise.Decoding: ConsumeMapLen :: Int# -> ST s DecodeAction s a -> DecodeAction s a
- Codec.Serialise.Decoding: ConsumeMapLenCanonical :: (Int# -> ST s (DecodeAction s a)) -> DecodeAction s a
+ Codec.Serialise.Decoding: ConsumeMapLenCanonical :: Int# -> ST s DecodeAction s a -> DecodeAction s a
- Codec.Serialise.Decoding: ConsumeMapLenIndef :: ST s (DecodeAction s a) -> DecodeAction s a
+ Codec.Serialise.Decoding: ConsumeMapLenIndef :: ST s DecodeAction s a -> DecodeAction s a
- Codec.Serialise.Decoding: ConsumeMapLenOrIndef :: (Int# -> ST s (DecodeAction s a)) -> DecodeAction s a
+ Codec.Serialise.Decoding: ConsumeMapLenOrIndef :: Int# -> ST s DecodeAction s a -> DecodeAction s a
- Codec.Serialise.Decoding: ConsumeNegWord :: (Word# -> ST s (DecodeAction s a)) -> DecodeAction s a
+ Codec.Serialise.Decoding: ConsumeNegWord :: Word# -> ST s DecodeAction s a -> DecodeAction s a
- Codec.Serialise.Decoding: ConsumeNegWordCanonical :: (Word# -> ST s (DecodeAction s a)) -> DecodeAction s a
+ Codec.Serialise.Decoding: ConsumeNegWordCanonical :: Word# -> ST s DecodeAction s a -> DecodeAction s a
- Codec.Serialise.Decoding: ConsumeNull :: ST s (DecodeAction s a) -> DecodeAction s a
+ Codec.Serialise.Decoding: ConsumeNull :: ST s DecodeAction s a -> DecodeAction s a
- Codec.Serialise.Decoding: ConsumeSimple :: (Word# -> ST s (DecodeAction s a)) -> DecodeAction s a
+ Codec.Serialise.Decoding: ConsumeSimple :: Word# -> ST s DecodeAction s a -> DecodeAction s a
- Codec.Serialise.Decoding: ConsumeSimpleCanonical :: (Word# -> ST s (DecodeAction s a)) -> DecodeAction s a
+ Codec.Serialise.Decoding: ConsumeSimpleCanonical :: Word# -> ST s DecodeAction s a -> DecodeAction s a
- Codec.Serialise.Decoding: ConsumeString :: (Text -> ST s (DecodeAction s a)) -> DecodeAction s a
+ Codec.Serialise.Decoding: ConsumeString :: Text -> ST s DecodeAction s a -> DecodeAction s a
- Codec.Serialise.Decoding: ConsumeStringIndef :: ST s (DecodeAction s a) -> DecodeAction s a
+ Codec.Serialise.Decoding: ConsumeStringIndef :: ST s DecodeAction s a -> DecodeAction s a
- Codec.Serialise.Decoding: ConsumeTag :: (Word# -> ST s (DecodeAction s a)) -> DecodeAction s a
+ Codec.Serialise.Decoding: ConsumeTag :: Word# -> ST s DecodeAction s a -> DecodeAction s a
- Codec.Serialise.Decoding: ConsumeTagCanonical :: (Word# -> ST s (DecodeAction s a)) -> DecodeAction s a
+ Codec.Serialise.Decoding: ConsumeTagCanonical :: Word# -> ST s DecodeAction s a -> DecodeAction s a
- Codec.Serialise.Decoding: ConsumeUtf8ByteArray :: (ByteArray -> ST s (DecodeAction s a)) -> DecodeAction s a
+ Codec.Serialise.Decoding: ConsumeUtf8ByteArray :: ByteArray -> ST s DecodeAction s a -> DecodeAction s a
- Codec.Serialise.Decoding: ConsumeWord :: (Word# -> ST s (DecodeAction s a)) -> DecodeAction s a
+ Codec.Serialise.Decoding: ConsumeWord :: Word# -> ST s DecodeAction s a -> DecodeAction s a
- Codec.Serialise.Decoding: ConsumeWord16 :: (Word# -> ST s (DecodeAction s a)) -> DecodeAction s a
+ Codec.Serialise.Decoding: ConsumeWord16 :: Word# -> ST s DecodeAction s a -> DecodeAction s a
- Codec.Serialise.Decoding: ConsumeWord16Canonical :: (Word# -> ST s (DecodeAction s a)) -> DecodeAction s a
+ Codec.Serialise.Decoding: ConsumeWord16Canonical :: Word# -> ST s DecodeAction s a -> DecodeAction s a
- Codec.Serialise.Decoding: ConsumeWord32 :: (Word# -> ST s (DecodeAction s a)) -> DecodeAction s a
+ Codec.Serialise.Decoding: ConsumeWord32 :: Word# -> ST s DecodeAction s a -> DecodeAction s a
- Codec.Serialise.Decoding: ConsumeWord32Canonical :: (Word# -> ST s (DecodeAction s a)) -> DecodeAction s a
+ Codec.Serialise.Decoding: ConsumeWord32Canonical :: Word# -> ST s DecodeAction s a -> DecodeAction s a
- Codec.Serialise.Decoding: ConsumeWord8 :: (Word# -> ST s (DecodeAction s a)) -> DecodeAction s a
+ Codec.Serialise.Decoding: ConsumeWord8 :: Word# -> ST s DecodeAction s a -> DecodeAction s a
- Codec.Serialise.Decoding: ConsumeWord8Canonical :: (Word# -> ST s (DecodeAction s a)) -> DecodeAction s a
+ Codec.Serialise.Decoding: ConsumeWord8Canonical :: Word# -> ST s DecodeAction s a -> DecodeAction s a
- Codec.Serialise.Decoding: ConsumeWordCanonical :: (Word# -> ST s (DecodeAction s a)) -> DecodeAction s a
+ Codec.Serialise.Decoding: ConsumeWordCanonical :: Word# -> ST s DecodeAction s a -> DecodeAction s a
- Codec.Serialise.Decoding: PeekAvailable :: (Int# -> ST s (DecodeAction s a)) -> DecodeAction s a
+ Codec.Serialise.Decoding: PeekAvailable :: Int# -> ST s DecodeAction s a -> DecodeAction s a
- Codec.Serialise.Decoding: PeekTokenType :: (TokenType -> ST s (DecodeAction s a)) -> DecodeAction s a
+ Codec.Serialise.Decoding: PeekTokenType :: TokenType -> ST s DecodeAction s a -> DecodeAction s a
- Codec.Serialise.Decoding: data DecodeAction s a :: * -> * -> *
+ Codec.Serialise.Decoding: data DecodeAction s a
- Codec.Serialise.Decoding: data Decoder s a :: * -> * -> *
+ Codec.Serialise.Decoding: data Decoder s a
- Codec.Serialise.Decoding: data TokenType :: *
+ Codec.Serialise.Decoding: data TokenType
- Codec.Serialise.Decoding: decodeBool :: Decoder s Bool
+ Codec.Serialise.Decoding: decodeBool :: () => Decoder s Bool
- Codec.Serialise.Decoding: decodeBreakOr :: Decoder s Bool
+ Codec.Serialise.Decoding: decodeBreakOr :: () => Decoder s Bool
- Codec.Serialise.Decoding: decodeByteArray :: Decoder s ByteArray
+ Codec.Serialise.Decoding: decodeByteArray :: () => Decoder s ByteArray
- Codec.Serialise.Decoding: decodeBytes :: Decoder s ByteString
+ Codec.Serialise.Decoding: decodeBytes :: () => Decoder s ByteString
- Codec.Serialise.Decoding: decodeBytesIndef :: Decoder s ()
+ Codec.Serialise.Decoding: decodeBytesIndef :: () => Decoder s ()
- Codec.Serialise.Decoding: decodeDouble :: Decoder s Double
+ Codec.Serialise.Decoding: decodeDouble :: () => Decoder s Double
- Codec.Serialise.Decoding: decodeFloat :: Decoder s Float
+ Codec.Serialise.Decoding: decodeFloat :: () => Decoder s Float
- Codec.Serialise.Decoding: decodeInt :: Decoder s Int
+ Codec.Serialise.Decoding: decodeInt :: () => Decoder s Int
- Codec.Serialise.Decoding: decodeInt16 :: Decoder s Int16
+ Codec.Serialise.Decoding: decodeInt16 :: () => Decoder s Int16
- Codec.Serialise.Decoding: decodeInt32 :: Decoder s Int32
+ Codec.Serialise.Decoding: decodeInt32 :: () => Decoder s Int32
- Codec.Serialise.Decoding: decodeInt64 :: Decoder s Int64
+ Codec.Serialise.Decoding: decodeInt64 :: () => Decoder s Int64
- Codec.Serialise.Decoding: decodeInt8 :: Decoder s Int8
+ Codec.Serialise.Decoding: decodeInt8 :: () => Decoder s Int8
- Codec.Serialise.Decoding: decodeInteger :: Decoder s Integer
+ Codec.Serialise.Decoding: decodeInteger :: () => Decoder s Integer
- Codec.Serialise.Decoding: decodeListLen :: Decoder s Int
+ Codec.Serialise.Decoding: decodeListLen :: () => Decoder s Int
- Codec.Serialise.Decoding: decodeListLenIndef :: Decoder s ()
+ Codec.Serialise.Decoding: decodeListLenIndef :: () => Decoder s ()
- Codec.Serialise.Decoding: decodeListLenOf :: Int -> Decoder s ()
+ Codec.Serialise.Decoding: decodeListLenOf :: () => Int -> Decoder s ()
- Codec.Serialise.Decoding: decodeListLenOrIndef :: Decoder s (Maybe Int)
+ Codec.Serialise.Decoding: decodeListLenOrIndef :: () => Decoder s Maybe Int
- Codec.Serialise.Decoding: decodeMapLen :: Decoder s Int
+ Codec.Serialise.Decoding: decodeMapLen :: () => Decoder s Int
- Codec.Serialise.Decoding: decodeMapLenIndef :: Decoder s ()
+ Codec.Serialise.Decoding: decodeMapLenIndef :: () => Decoder s ()
- Codec.Serialise.Decoding: decodeMapLenOrIndef :: Decoder s (Maybe Int)
+ Codec.Serialise.Decoding: decodeMapLenOrIndef :: () => Decoder s Maybe Int
- Codec.Serialise.Decoding: decodeNegWord :: Decoder s Word
+ Codec.Serialise.Decoding: decodeNegWord :: () => Decoder s Word
- Codec.Serialise.Decoding: decodeNegWord64 :: Decoder s Word64
+ Codec.Serialise.Decoding: decodeNegWord64 :: () => Decoder s Word64
- Codec.Serialise.Decoding: decodeNull :: Decoder s ()
+ Codec.Serialise.Decoding: decodeNull :: () => Decoder s ()
- Codec.Serialise.Decoding: decodeSequenceLenIndef :: (r -> a -> r) -> r -> (r -> r') -> Decoder s a -> Decoder s r'
+ Codec.Serialise.Decoding: decodeSequenceLenIndef :: () => r -> a -> r -> r -> r -> r' -> Decoder s a -> Decoder s r'
- Codec.Serialise.Decoding: decodeSequenceLenN :: (r -> a -> r) -> r -> (r -> r') -> Int -> Decoder s a -> Decoder s r'
+ Codec.Serialise.Decoding: decodeSequenceLenN :: () => r -> a -> r -> r -> r -> r' -> Int -> Decoder s a -> Decoder s r'
- Codec.Serialise.Decoding: decodeSimple :: Decoder s Word8
+ Codec.Serialise.Decoding: decodeSimple :: () => Decoder s Word8
- Codec.Serialise.Decoding: decodeString :: Decoder s Text
+ Codec.Serialise.Decoding: decodeString :: () => Decoder s Text
- Codec.Serialise.Decoding: decodeStringIndef :: Decoder s ()
+ Codec.Serialise.Decoding: decodeStringIndef :: () => Decoder s ()
- Codec.Serialise.Decoding: decodeTag :: Decoder s Word
+ Codec.Serialise.Decoding: decodeTag :: () => Decoder s Word
- Codec.Serialise.Decoding: decodeTag64 :: Decoder s Word64
+ Codec.Serialise.Decoding: decodeTag64 :: () => Decoder s Word64
- Codec.Serialise.Decoding: decodeUtf8ByteArray :: Decoder s ByteArray
+ Codec.Serialise.Decoding: decodeUtf8ByteArray :: () => Decoder s ByteArray
- Codec.Serialise.Decoding: decodeWord :: Decoder s Word
+ Codec.Serialise.Decoding: decodeWord :: () => Decoder s Word
- Codec.Serialise.Decoding: decodeWord16 :: Decoder s Word16
+ Codec.Serialise.Decoding: decodeWord16 :: () => Decoder s Word16
- Codec.Serialise.Decoding: decodeWord32 :: Decoder s Word32
+ Codec.Serialise.Decoding: decodeWord32 :: () => Decoder s Word32
- Codec.Serialise.Decoding: decodeWord64 :: Decoder s Word64
+ Codec.Serialise.Decoding: decodeWord64 :: () => Decoder s Word64
- Codec.Serialise.Decoding: decodeWord8 :: Decoder s Word8
+ Codec.Serialise.Decoding: decodeWord8 :: () => Decoder s Word8
- Codec.Serialise.Decoding: decodeWordOf :: Word -> Decoder s ()
+ Codec.Serialise.Decoding: decodeWordOf :: () => Word -> Decoder s ()
- Codec.Serialise.Decoding: getDecodeAction :: Decoder s a -> ST s (DecodeAction s a)
+ Codec.Serialise.Decoding: getDecodeAction :: () => Decoder s a -> ST s DecodeAction s a
- Codec.Serialise.Decoding: peekAvailable :: Decoder s Int
+ Codec.Serialise.Decoding: peekAvailable :: () => Decoder s Int
- Codec.Serialise.Decoding: peekTokenType :: Decoder s TokenType
+ Codec.Serialise.Decoding: peekTokenType :: () => Decoder s TokenType
- Codec.Serialise.Encoding: Encoding :: (Tokens -> Tokens) -> Encoding
+ Codec.Serialise.Encoding: Encoding :: Tokens -> Tokens -> Encoding
- Codec.Serialise.Encoding: TkBool :: ~Bool -> Tokens -> Tokens
+ Codec.Serialise.Encoding: TkBool :: !Bool -> Tokens -> Tokens
- Codec.Serialise.Encoding: TkByteArray :: {-# UNPACK #-} ~SlicedByteArray -> Tokens -> Tokens
+ Codec.Serialise.Encoding: TkByteArray :: {-# UNPACK #-} !SlicedByteArray -> Tokens -> Tokens
- Codec.Serialise.Encoding: TkBytes :: {-# UNPACK #-} ~ByteString -> Tokens -> Tokens
+ Codec.Serialise.Encoding: TkBytes :: {-# UNPACK #-} !ByteString -> Tokens -> Tokens
- Codec.Serialise.Encoding: TkFloat16 :: {-# UNPACK #-} ~Float -> Tokens -> Tokens
+ Codec.Serialise.Encoding: TkFloat16 :: {-# UNPACK #-} !Float -> Tokens -> Tokens
- Codec.Serialise.Encoding: TkFloat32 :: {-# UNPACK #-} ~Float -> Tokens -> Tokens
+ Codec.Serialise.Encoding: TkFloat32 :: {-# UNPACK #-} !Float -> Tokens -> Tokens
- Codec.Serialise.Encoding: TkFloat64 :: {-# UNPACK #-} ~Double -> Tokens -> Tokens
+ Codec.Serialise.Encoding: TkFloat64 :: {-# UNPACK #-} !Double -> Tokens -> Tokens
- Codec.Serialise.Encoding: TkInt :: {-# UNPACK #-} ~Int -> Tokens -> Tokens
+ Codec.Serialise.Encoding: TkInt :: {-# UNPACK #-} !Int -> Tokens -> Tokens
- Codec.Serialise.Encoding: TkInt64 :: {-# UNPACK #-} ~Int64 -> Tokens -> Tokens
+ Codec.Serialise.Encoding: TkInt64 :: {-# UNPACK #-} !Int64 -> Tokens -> Tokens
- Codec.Serialise.Encoding: TkInteger :: ~Integer -> Tokens -> Tokens
+ Codec.Serialise.Encoding: TkInteger :: !Integer -> Tokens -> Tokens
- Codec.Serialise.Encoding: TkListLen :: {-# UNPACK #-} ~Word -> Tokens -> Tokens
+ Codec.Serialise.Encoding: TkListLen :: {-# UNPACK #-} !Word -> Tokens -> Tokens
- Codec.Serialise.Encoding: TkMapLen :: {-# UNPACK #-} ~Word -> Tokens -> Tokens
+ Codec.Serialise.Encoding: TkMapLen :: {-# UNPACK #-} !Word -> Tokens -> Tokens
- Codec.Serialise.Encoding: TkSimple :: {-# UNPACK #-} ~Word8 -> Tokens -> Tokens
+ Codec.Serialise.Encoding: TkSimple :: {-# UNPACK #-} !Word8 -> Tokens -> Tokens
- Codec.Serialise.Encoding: TkString :: {-# UNPACK #-} ~Text -> Tokens -> Tokens
+ Codec.Serialise.Encoding: TkString :: {-# UNPACK #-} !Text -> Tokens -> Tokens
- Codec.Serialise.Encoding: TkTag :: {-# UNPACK #-} ~Word -> Tokens -> Tokens
+ Codec.Serialise.Encoding: TkTag :: {-# UNPACK #-} !Word -> Tokens -> Tokens
- Codec.Serialise.Encoding: TkTag64 :: {-# UNPACK #-} ~Word64 -> Tokens -> Tokens
+ Codec.Serialise.Encoding: TkTag64 :: {-# UNPACK #-} !Word64 -> Tokens -> Tokens
- Codec.Serialise.Encoding: TkUtf8ByteArray :: {-# UNPACK #-} ~SlicedByteArray -> Tokens -> Tokens
+ Codec.Serialise.Encoding: TkUtf8ByteArray :: {-# UNPACK #-} !SlicedByteArray -> Tokens -> Tokens
- Codec.Serialise.Encoding: TkWord :: {-# UNPACK #-} ~Word -> Tokens -> Tokens
+ Codec.Serialise.Encoding: TkWord :: {-# UNPACK #-} !Word -> Tokens -> Tokens
- Codec.Serialise.Encoding: TkWord64 :: {-# UNPACK #-} ~Word64 -> Tokens -> Tokens
+ Codec.Serialise.Encoding: TkWord64 :: {-# UNPACK #-} !Word64 -> Tokens -> Tokens
- Codec.Serialise.Encoding: data Tokens :: *
+ Codec.Serialise.Encoding: data Tokens
- Codec.Serialise.Encoding: newtype Encoding :: *
+ Codec.Serialise.Encoding: newtype Encoding
Files
- ChangeLog.md +14/−1
- bench/instances/Instances/Float.hs +25/−0
- bench/instances/Main.hs +3/−1
- bench/micro/Micro/CBOR.hs +4/−1
- bench/versus/Macro/CBOR.hs +4/−1
- bench/versus/Macro/DeepSeq.hs +4/−0
- bench/versus/Macro/Load.hs +62/−10
- serialise.cabal +33/−46
- src/Codec/Serialise/Tutorial.hs +5/−5
- tests/Main.hs +3/−6
- tests/Tests/CBOR.hs +0/−297
- tests/Tests/Negative.hs +5/−0
- tests/Tests/Orphanage.hs +3/−1
- tests/Tests/Reference.hs +0/−293
- tests/Tests/Reference/Implementation.hs +0/−1070
- tests/Tests/Regress.hs +1/−3
- tests/Tests/Regress/FlatTerm.hs +0/−47
- tests/Tests/Serialise.hs +14/−1
- tests/test-vectors/README.md +0/−27
- tests/test-vectors/appendix_a.json +0/−624
ChangeLog.md view
@@ -1,5 +1,18 @@ # Revision history for serialise -## 0.1.0.0 -- YYYY-mm-dd+## 0.2.1.0 -- 2018-10-11++* Bounds bumps and GHC 8.6 compatibility++## 0.2.0.0 -- 2017-11-30++* Improved robustness in presence of invalid UTF-8 strings++* Add encoders and decoders for `ByteArray`++* Export `GSerialiseProd(..) and GSerialiseSum(..)`+++## 0.1.0.0 -- 2017-06-28 * First version. Released on an unsuspecting world.
+ bench/instances/Instances/Float.hs view
@@ -0,0 +1,25 @@+{-# LANGUAGE ScopedTypeVariables #-}++module Instances.Float+ ( benchmarks -- :: [Benchmark]+ ) where++import Criterion.Main+import Codec.Serialise+import Control.DeepSeq (force)+import qualified Data.ByteString.Lazy as BSL++benchmarks :: [Benchmark]+benchmarks =+ [ bench "serialise Float" (whnf (BSL.length . serialise) fakesF)+ , bench "deserialise Float" (nf (deserialise :: BSL.ByteString -> [Float]) serialF)+ , bench "serialise Double" (whnf (BSL.length . serialise) fakesD)+ , bench "deserialise Double" (nf (deserialise :: BSL.ByteString -> [Double]) serialD)+ ]+ where+ fakesF = force (replicate 100 (3.14159 :: Float))+ fakesD = force (replicate 100 (3.14159 :: Double))++ serialF = force (serialise fakesF)+ serialD = force (serialise fakesD)+
bench/instances/Main.hs view
@@ -4,6 +4,7 @@ import Criterion.Main (bgroup, defaultMain) +import qualified Instances.Float as Float import qualified Instances.Integer as Integer import qualified Instances.Time as Time import qualified Instances.Vector as Vector@@ -12,7 +13,8 @@ main :: IO () main = defaultMain- [ bgroup "integer" Integer.benchmarks+ [ bgroup "float" Float.benchmarks+ , bgroup "integer" Integer.benchmarks , bgroup "time" Time.benchmarks , bgroup "vector" Vector.benchmarks ]
bench/micro/Micro/CBOR.hs view
@@ -8,7 +8,10 @@ import Codec.Serialise.Encoding import Codec.Serialise.Decoding hiding (DecodeAction(Done, Fail)) import qualified Codec.Serialise as Serialise-import Data.Monoid++#if ! MIN_VERSION_base(4,11,0)+import Data.Monoid+#endif import qualified Data.ByteString.Lazy as BS
bench/versus/Macro/CBOR.hs view
@@ -13,7 +13,10 @@ import Codec.Serialise.Decoding hiding (DecodeAction(Done, Fail)) import Codec.CBOR.Read import Codec.CBOR.Write-import Data.Monoid++#if ! MIN_VERSION_base(4,11,0)+import Data.Monoid+#endif import qualified Data.ByteString.Lazy as BS import qualified Data.ByteString.Builder as BS
bench/versus/Macro/DeepSeq.hs view
@@ -1,9 +1,13 @@+{-# LANGUAGE CPP #-} {-# OPTIONS_GHC -fno-warn-orphans #-} module Macro.DeepSeq where import Macro.Types import Control.DeepSeq+#if MIN_VERSION_deepseq(1,4,3)+ hiding (rnf1, rnf2)+#endif rnf0 :: () rnf1 :: NFData a => a -> ()
bench/versus/Macro/Load.hs view
@@ -9,7 +9,7 @@ import qualified Text.ParserCombinators.ReadP as Parse import qualified Text.PrettyPrint as Disp import qualified Data.Char as Char (isDigit, isAlphaNum, isSpace)-import Text.PrettyPrint hiding (braces)+import Text.PrettyPrint hiding (braces, (<>)) import Data.List import Data.Function (on)@@ -25,11 +25,21 @@ import qualified Codec.Archive.Tar as Tar import qualified Codec.Archive.Tar.Entry as Tar +#if MIN_VERSION_base(4,11,0)+import Prelude hiding ((<>))+#endif+import Data.Semigroup hiding (option)+ #if !MIN_VERSION_base(4,8,0) import Control.Applicative (Applicative(..)) import Data.Monoid hiding ((<>)) #endif +#if !MIN_VERSION_base(4,9,0)+instance Semigroup Doc where+ a <> b = mappend a b+#endif+ readPkgIndex :: BS.ByteString -> Either String [GenericPackageDescription] readPkgIndex = fmap extractCabalFiles . readTarIndex where@@ -2378,7 +2388,13 @@ libExposed = True, libBuildInfo = mempty }- mappend a b = Library {+ mappend = mappendLibrary++instance Semigroup Library where+ a <> b = mappendLibrary a b++mappendLibrary :: Library -> Library -> Library+mappendLibrary a b = Library { exposedModules = combine exposedModules, libExposed = libExposed a && libExposed b, -- so False propagates libBuildInfo = combine libBuildInfo@@ -2394,7 +2410,13 @@ modulePath = mempty, buildInfo = mempty }- mappend a b = Executable{+ mappend = mappendExecutable++instance Semigroup Executable where+ a <> b = mappendExecutable a b++mappendExecutable :: Executable -> Executable -> Executable+mappendExecutable a b = Executable { exeName = combine' exeName, modulePath = combine modulePath, buildInfo = combine buildInfo@@ -2417,8 +2439,13 @@ testBuildInfo = mempty, testEnabled = False }+ mappend = mappendTestSuite - mappend a b = TestSuite {+instance Semigroup TestSuite where+ a <> b = mappendTestSuite a b++mappendTestSuite :: TestSuite -> TestSuite -> TestSuite+mappendTestSuite a b = TestSuite { testName = combine' testName, testInterface = combine testInterface, testBuildInfo = combine testBuildInfo,@@ -2433,9 +2460,15 @@ instance Monoid TestSuiteInterface where mempty = TestSuiteUnsupported (TestTypeUnknown mempty (Version [] []))- mappend a (TestSuiteUnsupported _) = a- mappend _ b = b+ mappend = mappendTestSuiteInterface +instance Semigroup TestSuiteInterface where+ a <> b = mappendTestSuiteInterface a b++mappendTestSuiteInterface :: TestSuiteInterface -> TestSuiteInterface -> TestSuiteInterface+mappendTestSuiteInterface a (TestSuiteUnsupported _) = a+mappendTestSuiteInterface _ b = b+ emptyTestSuite :: TestSuite emptyTestSuite = mempty @@ -2446,8 +2479,10 @@ benchmarkBuildInfo = mempty, benchmarkEnabled = False }+ mappend = mappendBenchmark - mappend a b = Benchmark {+mappendBenchmark :: Benchmark -> Benchmark -> Benchmark+mappendBenchmark a b = Benchmark { benchmarkName = combine' benchmarkName, benchmarkInterface = combine benchmarkInterface, benchmarkBuildInfo = combine benchmarkBuildInfo,@@ -2462,9 +2497,14 @@ instance Monoid BenchmarkInterface where mempty = BenchmarkUnsupported (BenchmarkTypeUnknown mempty (Version [] []))- mappend a (BenchmarkUnsupported _) = a- mappend _ b = b+ mappend = mappendBenchmarkInterface +mappendBenchmarkInterface :: BenchmarkInterface -> BenchmarkInterface -> BenchmarkInterface+mappendBenchmarkInterface a (BenchmarkUnsupported _) = a+mappendBenchmarkInterface _ b = b+++ emptyBenchmark :: Benchmark emptyBenchmark = mempty @@ -2496,7 +2536,10 @@ customFieldsBI = [], targetBuildDepends = [] }- mappend a b = BuildInfo {+ mappend = mappendBuildInfo++mappendBuildInfo :: BuildInfo -> BuildInfo -> BuildInfo+mappendBuildInfo a b = BuildInfo { buildable = buildable a && buildable b, buildTools = combine buildTools, cppOptions = combine cppOptions,@@ -2528,6 +2571,15 @@ combineNub field = nub (combine field) combineMby field = field b `mplus` field a ++instance Semigroup Benchmark where+ a <> b = mappendBenchmark a b++instance Semigroup BenchmarkInterface where+ a <> b = mappendBenchmarkInterface a b++instance Semigroup BuildInfo where+ a <> b = mappendBuildInfo a b -- | Parse a list of fields, given a list of field descriptions, -- a structure to accumulate the parsed fields, and a function
serialise.cabal view
@@ -1,5 +1,5 @@ name: serialise-version: 0.2.0.0+version: 0.2.1.0 synopsis: A binary serialisation library for Haskell values. description: This package (formerly @binary-serialise-cbor@) provides pure, efficient@@ -11,7 +11,7 @@ Representation', or CBOR, specified in RFC 7049. As a result, serialised Haskell values have implicit structure outside of the Haskell program itself, meaning they can be inspected or analyzed- with custom tools.+ without custom tools. . An implementation of the standard bijection between CBOR and JSON is provided by the [cborg-json](/package/cborg-json) package. Also see@@ -31,8 +31,6 @@ build-type: Simple extra-source-files:- tests/test-vectors/appendix_a.json- tests/test-vectors/README.md ChangeLog.md source-repository head@@ -67,9 +65,9 @@ base >= 4.6 && < 5.0, bytestring >= 0.10.4 && < 0.11, cborg == 0.2.*,- containers >= 0.5 && < 0.6,- ghc-prim >= 0.3 && < 0.6,- half >= 0.2.2.3 && < 0.3,+ containers >= 0.5 && < 0.7,+ ghc-prim >= 0.3.1.0 && < 0.6,+ half >= 0.2.2.3 && < 0.4, hashable >= 1.2 && < 2.0, primitive >= 0.5 && < 0.7, text >= 1.1 && < 1.3,@@ -78,7 +76,7 @@ if flag(newtime15) build-depends:- time >= 1.5 && < 1.9+ time >= 1.5 && < 1.10 else build-depends: time >= 1.4 && < 1.5,@@ -97,10 +95,10 @@ default-language: Haskell2010 ghc-options:- -Wall -fno-warn-orphans -threaded -rtsopts "-with-rtsopts=-N"+ -Wall -fno-warn-orphans+ -threaded -rtsopts "-with-rtsopts=-N2" other-modules:- Tests.CBOR Tests.IO Tests.Negative Tests.Orphanage@@ -112,39 +110,25 @@ Tests.Regress.Issue80 Tests.Regress.Issue106 Tests.Regress.Issue135- Tests.Regress.FlatTerm- Tests.Reference- Tests.Reference.Implementation Tests.Deriving Tests.GeneralisedUTF8 build-depends:- array >= 0.4 && < 0.6, base >= 4.6 && < 5.0,- binary >= 0.7 && < 0.10, bytestring >= 0.10.4 && < 0.11, directory >= 1.0 && < 1.4, filepath >= 1.0 && < 1.5,- ghc-prim >= 0.3 && < 0.6, text >= 1.1 && < 1.3,- time >= 1.4 && < 1.9,- containers >= 0.5 && < 0.6,+ time >= 1.4 && < 1.10,+ containers >= 0.5 && < 0.7, unordered-containers >= 0.2 && < 0.3,- hashable >= 1.2 && < 2.0, primitive >= 0.5 && < 0.7, cborg, serialise,-- aeson >= 0.7 && < 1.3,- base64-bytestring >= 1.0 && < 1.1,- base16-bytestring >= 0.1 && < 0.2,- deepseq >= 1.0 && < 1.5,- half >= 0.2.2.3 && < 0.3,- QuickCheck >= 2.9 && < 2.11,- scientific >= 0.3 && < 0.4,- tasty >= 0.11 && < 0.13,- tasty-hunit >= 0.9 && < 0.10,- tasty-quickcheck >= 0.8 && < 0.10,+ QuickCheck >= 2.9 && < 2.13,+ tasty >= 0.11 && < 1.2,+ tasty-hunit >= 0.9 && < 0.11,+ tasty-quickcheck >= 0.8 && < 0.11, quickcheck-instances >= 0.3.12 && < 0.4, vector >= 0.10 && < 0.13 @@ -161,24 +145,25 @@ -Wall -rtsopts -fno-cse -fno-ignore-asserts -fno-warn-orphans other-modules:+ Instances.Float Instances.Integer Instances.Vector Instances.Time build-depends: base >= 4.6 && < 5.0,- binary >= 0.7 && < 0.10,+ binary >= 0.7 && < 0.11, bytestring >= 0.10.4 && < 0.11, vector >= 0.10 && < 0.13, cborg, serialise, deepseq >= 1.0 && < 1.5,- criterion >= 1.0 && < 1.3+ criterion >= 1.0 && < 1.6 if flag(newtime15) build-depends:- time >= 1.5 && < 1.9+ time >= 1.5 && < 1.10 else build-depends: time >= 1.4 && < 1.5,@@ -211,19 +196,20 @@ build-depends: base >= 4.6 && < 5.0,- binary >= 0.7 && < 0.10,+ binary >= 0.7 && < 0.11, bytestring >= 0.10.4 && < 0.11,- ghc-prim >= 0.3 && < 0.6,+ ghc-prim >= 0.3.1.0 && < 0.6, vector >= 0.10 && < 0.13, cborg, serialise, - aeson >= 0.7 && < 1.3,+ aeson >= 0.7 && < 1.5, deepseq >= 1.0 && < 1.5,- criterion >= 1.0 && < 1.3,+ criterion >= 1.0 && < 1.6, cereal >= 0.5.2.0 && < 0.6, cereal-vector >= 0.2 && < 0.3,- store >= 0.4 && < 0.5+ store >= 0.4 && < 0.6,+ semigroups == 0.18.* benchmark versus type: exitcode-stdio-1.0@@ -257,30 +243,31 @@ build-depends: array >= 0.4 && < 0.6, base >= 4.6 && < 5.0,- binary >= 0.7 && < 0.10,+ binary >= 0.7 && < 0.11, bytestring >= 0.10.4 && < 0.11, directory >= 1.0 && < 1.4,- ghc-prim >= 0.3 && < 0.6,+ ghc-prim >= 0.3.1.0 && < 0.6, text >= 1.1 && < 1.3, vector >= 0.10 && < 0.13, cborg, serialise, filepath >= 1.0 && < 1.5,- containers >= 0.5 && < 0.6,+ containers >= 0.5 && < 0.7, deepseq >= 1.0 && < 1.5,- aeson >= 0.7 && < 1.3,+ aeson >= 0.7 && < 1.5, cereal >= 0.5.2.0 && < 0.6,- half >= 0.2.2.3 && < 0.3,+ half >= 0.2.2.3 && < 0.4, tar >= 0.4 && < 0.6, zlib >= 0.5 && < 0.7, pretty >= 1.0 && < 1.2,- criterion >= 1.0 && < 1.3,- store >= 0.4 && < 0.5+ criterion >= 1.0 && < 1.6,+ store >= 0.4 && < 0.6,+ semigroups == 0.18.* if flag(newtime15) build-depends:- time >= 1.5 && < 1.9+ time >= 1.5 && < 1.10 else build-depends: time >= 1.4 && < 1.5,
src/Codec/Serialise/Tutorial.hs view
@@ -270,24 +270,24 @@ > -- HoppingAnimal, SwimmingAnimal cases are unchanged... > encodeAnimal (HoppingAnimal name height) = > encodeListLen 3 <> encodeWord 0 <> encode name <> encode height-> encodeAnimal (WalkingAnimal name speed) =-> encodeListLen 3 <> encodeWord 1 <> encode name <> encode speed+> encodeAnimal (SwimmingAnimal numberOfFins) =+> encodeListLen 2 <> encodeWord 2 <> encode numberOfFins > -- This is new... > encodeAnimal (WalkingAnimal animalName walkingSpeed numberOfFeet) =-> encodeListLen 4 <> encodeWord 3 <> encode animalName <> encode walkingSpeed <> encode numberOfFins+> encodeListLen 4 <> encodeWord 3 <> encode animalName <> encode walkingSpeed <> encode numberOfFeet > > decodeAnimal :: Decoder s Animal > decodeAnimal = do > len <- decodeListLen > tag <- decodeWord > case (len, tag) of-> -- this cases are unchanged...+> -- these cases are unchanged... > (3, 0) -> HoppingAnimal <$> decode <*> decode > (2, 2) -> SwimmingAnimal <$> decode > -- this is new... > (3, 1) -> WalkingAnimal <$> decode <*> decode <*> pure 4 > -- ^ note the default for backwards compat-> (4, 3) -> WalkingAnimal <$> decode <*> decode+> (4, 3) -> WalkingAnimal <$> decode <*> decode <*> decode > _ -> fail "invalid Animal encoding" We can use this same approach to handle field removal and type changes.
tests/Main.hs view
@@ -4,20 +4,17 @@ import Test.Tasty (defaultMain, testGroup) import qualified Tests.IO as IO-import qualified Tests.CBOR as CBOR import qualified Tests.Regress as Regress-import qualified Tests.Reference as Reference import qualified Tests.Serialise as Serialise import qualified Tests.Negative as Negative import qualified Tests.Deriving as Deriving import qualified Tests.GeneralisedUTF8 as GeneralisedUTF8 main :: IO ()-main = Reference.loadTestCases >>= \tcs -> defaultMain $+main =+ defaultMain $ testGroup "CBOR tests"- [ CBOR.testTree tcs- , Reference.testTree tcs- , Serialise.testTree+ [ Serialise.testTree , Serialise.testGenerics , Negative.testTree , IO.testTree
− tests/Tests/CBOR.hs
@@ -1,297 +0,0 @@-{-# LANGUAGE CPP #-}-{-# LANGUAGE NamedFieldPuns #-}-{-# LANGUAGE OverloadedStrings #-}-{-# OPTIONS_GHC -fno-warn-orphans #-}-module Tests.CBOR- ( testTree -- :: TestTree- ) where--import qualified Data.ByteString as BS-import qualified Data.ByteString.Lazy as LBS-import qualified Data.Text as T-import qualified Data.Text.Lazy as LT-import Data.Word-import qualified Numeric.Half as Half--import Codec.CBOR.Term-import Codec.CBOR.Read-import Codec.CBOR.Write--import Test.Tasty-import Test.Tasty.HUnit-import Test.Tasty.QuickCheck--import qualified Tests.Reference.Implementation as RefImpl-import qualified Tests.Reference as TestVector-import Tests.Reference (TestCase(..))--#if !MIN_VERSION_base(4,8,0)-import Control.Applicative-#endif-import Control.Exception (throw)---externalTestCase :: TestCase -> Assertion-externalTestCase TestCase { encoded, decoded = Left expectedJson } = do- let term = deserialise encoded- actualJson = TestVector.termToJson (toRefTerm term)- reencoded = serialise term-- expectedJson `TestVector.equalJson` actualJson- encoded @=? reencoded--externalTestCase TestCase { encoded, decoded = Right expectedDiagnostic } = do- let term = deserialise encoded- actualDiagnostic = RefImpl.diagnosticNotation (toRefTerm term)- reencoded = serialise term-- expectedDiagnostic @=? actualDiagnostic- encoded @=? reencoded--expectedDiagnosticNotation :: String -> [Word8] -> Assertion-expectedDiagnosticNotation expectedDiagnostic encoded = do- let term = deserialise (LBS.pack encoded)- actualDiagnostic = RefImpl.diagnosticNotation (toRefTerm term)-- expectedDiagnostic @=? actualDiagnostic----- | The reference implementation satisfies the roundtrip property for most--- examples (all the ones from Appendix A). It does not satisfy the roundtrip--- property in general however, non-canonical over-long int encodings for--- example.-------encodedRoundtrip :: String -> [Word8] -> Assertion-encodedRoundtrip expectedDiagnostic encoded = do- let term = deserialise (LBS.pack encoded)- reencoded = LBS.unpack (serialise term)-- assertEqual ("for CBOR: " ++ expectedDiagnostic) encoded reencoded--prop_encodeDecodeTermRoundtrip :: Term -> Bool-prop_encodeDecodeTermRoundtrip term =- (deserialise . serialise) term `eqTerm` term--prop_encodeDecodeTermRoundtrip_splits2 :: Term -> Bool-prop_encodeDecodeTermRoundtrip_splits2 term =- and [ deserialise thedata' `eqTerm` term- | let thedata = serialise term- , thedata' <- splits2 thedata ]--prop_encodeDecodeTermRoundtrip_splits3 :: Term -> Bool-prop_encodeDecodeTermRoundtrip_splits3 term =- and [ deserialise thedata' `eqTerm` term- | let thedata = serialise term- , thedata' <- splits3 thedata ]--prop_encodeTermMatchesRefImpl :: RefImpl.Term -> Bool-prop_encodeTermMatchesRefImpl term =- let encoded = serialise (fromRefTerm term)- encoded' = RefImpl.serialise (RefImpl.canonicaliseTerm term)- in encoded == encoded'--prop_encodeTermMatchesRefImpl2 :: Term -> Bool-prop_encodeTermMatchesRefImpl2 term =- let encoded = serialise term- encoded' = RefImpl.serialise (toRefTerm term)- in encoded == encoded'--prop_decodeTermMatchesRefImpl :: RefImpl.Term -> Bool-prop_decodeTermMatchesRefImpl term0 =- let encoded = RefImpl.serialise (RefImpl.canonicaliseTerm term0)- term = RefImpl.deserialise encoded- term' = deserialise encoded- in term' `eqTerm` fromRefTerm term----------------------------------------------------------------------------------splits2 :: LBS.ByteString -> [LBS.ByteString]-splits2 bs = zipWith (\a b -> LBS.fromChunks [a,b]) (BS.inits sbs) (BS.tails sbs)- where- sbs = LBS.toStrict bs--splits3 :: LBS.ByteString -> [LBS.ByteString]-splits3 bs =- [ LBS.fromChunks [a,b,c]- | (a,x) <- zip (BS.inits sbs) (BS.tails sbs)- , (b,c) <- zip (BS.inits x) (BS.tails x) ]- where- sbs = LBS.toStrict bs---serialise :: Term -> LBS.ByteString-serialise = toLazyByteString . encodeTerm--deserialise :: LBS.ByteString -> Term-deserialise = either throw snd . deserialiseFromBytes decodeTerm----------------------------------------------------------------------------------toRefTerm :: Term -> RefImpl.Term-toRefTerm (TInt n)- | n >= 0 = RefImpl.TUInt (RefImpl.toUInt (fromIntegral n))- | otherwise = RefImpl.TNInt (RefImpl.toUInt (fromIntegral (-1 - n)))-toRefTerm (TInteger n) -- = RefImpl.TBigInt n- | n >= 0 && n <= fromIntegral (maxBound :: Word64)- = RefImpl.TUInt (RefImpl.toUInt (fromIntegral n))- | n < 0 && n >= -1 - fromIntegral (maxBound :: Word64)- = RefImpl.TNInt (RefImpl.toUInt (fromIntegral (-1 - n)))- | otherwise = RefImpl.TBigInt n-toRefTerm (TBytes bs) = RefImpl.TBytes (BS.unpack bs)-toRefTerm (TBytesI bs) = RefImpl.TBytess (map BS.unpack (LBS.toChunks bs))-toRefTerm (TString st) = RefImpl.TString (T.unpack st)-toRefTerm (TStringI st) = RefImpl.TStrings (map T.unpack (LT.toChunks st))-toRefTerm (TList ts) = RefImpl.TArray (map toRefTerm ts)-toRefTerm (TListI ts) = RefImpl.TArrayI (map toRefTerm ts)-toRefTerm (TMap ts) = RefImpl.TMap [ (toRefTerm x, toRefTerm y)- | (x,y) <- ts ]-toRefTerm (TMapI ts) = RefImpl.TMapI [ (toRefTerm x, toRefTerm y)- | (x,y) <- ts ]-toRefTerm (TTagged w t) = RefImpl.TTagged (RefImpl.toUInt (fromIntegral w))- (toRefTerm t)-toRefTerm (TBool False) = RefImpl.TFalse-toRefTerm (TBool True) = RefImpl.TTrue-toRefTerm TNull = RefImpl.TNull-toRefTerm (TSimple 23) = RefImpl.TUndef-toRefTerm (TSimple w) = RefImpl.TSimple (fromIntegral w)-toRefTerm (THalf f) = if isNaN f- then RefImpl.TFloat16 RefImpl.canonicalNaN- else RefImpl.TFloat16 (Half.toHalf f)-toRefTerm (TFloat f) = if isNaN f- then RefImpl.TFloat16 RefImpl.canonicalNaN- else RefImpl.TFloat32 f-toRefTerm (TDouble f) = if isNaN f- then RefImpl.TFloat16 RefImpl.canonicalNaN- else RefImpl.TFloat64 f---fromRefTerm :: RefImpl.Term -> Term-fromRefTerm (RefImpl.TUInt u)- | n <= fromIntegral (maxBound :: Int) = TInt (fromIntegral n)- | otherwise = TInteger (fromIntegral n)- where n = RefImpl.fromUInt u--fromRefTerm (RefImpl.TNInt u)- | n <= fromIntegral (maxBound :: Int) = TInt (-1 - fromIntegral n)- | otherwise = TInteger (-1 - fromIntegral n)- where n = RefImpl.fromUInt u--fromRefTerm (RefImpl.TBigInt n) = TInteger n-fromRefTerm (RefImpl.TBytes bs) = TBytes (BS.pack bs)-fromRefTerm (RefImpl.TBytess bs) = TBytesI (LBS.fromChunks (map BS.pack bs))-fromRefTerm (RefImpl.TString st) = TString (T.pack st)-fromRefTerm (RefImpl.TStrings st) = TStringI (LT.fromChunks (map T.pack st))--fromRefTerm (RefImpl.TArray ts) = TList (map fromRefTerm ts)-fromRefTerm (RefImpl.TArrayI ts) = TListI (map fromRefTerm ts)-fromRefTerm (RefImpl.TMap ts) = TMap [ (fromRefTerm x, fromRefTerm y)- | (x,y) <- ts ]-fromRefTerm (RefImpl.TMapI ts) = TMapI [ (fromRefTerm x, fromRefTerm y)- | (x,y) <- ts ]-fromRefTerm (RefImpl.TTagged w t) = TTagged (RefImpl.fromUInt w)- (fromRefTerm t)-fromRefTerm (RefImpl.TFalse) = TBool False-fromRefTerm (RefImpl.TTrue) = TBool True-fromRefTerm RefImpl.TNull = TNull-fromRefTerm RefImpl.TUndef = TSimple 23-fromRefTerm (RefImpl.TSimple w) = TSimple w-fromRefTerm (RefImpl.TFloat16 f) = THalf (Half.fromHalf f)-fromRefTerm (RefImpl.TFloat32 f) = if isNaN f- then THalf (Half.fromHalf RefImpl.canonicalNaN)- else TFloat f-fromRefTerm (RefImpl.TFloat64 f) = if isNaN f- then THalf (Half.fromHalf RefImpl.canonicalNaN)- else TDouble f---- NaNs are so annoying...-eqTerm :: Term -> Term -> Bool-eqTerm (TInt n) (TInteger n') = fromIntegral n == n'-eqTerm (TList ts) (TList ts') = and (zipWith eqTerm ts ts')-eqTerm (TListI ts) (TListI ts') = and (zipWith eqTerm ts ts')-eqTerm (TMap ts) (TMap ts') = and (zipWith eqTermPair ts ts')-eqTerm (TMapI ts) (TMapI ts') = and (zipWith eqTermPair ts ts')-eqTerm (TTagged w t) (TTagged w' t') = w == w' && eqTerm t t'-eqTerm (THalf f) (THalf f') | isNaN f && isNaN f' = True-eqTerm (TFloat f) (TFloat f') | isNaN f && isNaN f' = True-eqTerm (TDouble f) (TDouble f') | isNaN f && isNaN f' = True-eqTerm a b = a == b--eqTermPair :: (Term, Term) -> (Term, Term) -> Bool-eqTermPair (a,b) (a',b') = eqTerm a a' && eqTerm b b'---prop_fromToRefTerm :: RefImpl.Term -> Bool-prop_fromToRefTerm term = toRefTerm (fromRefTerm term)- `RefImpl.eqTerm` RefImpl.canonicaliseTerm term--prop_toFromRefTerm :: Term -> Bool-prop_toFromRefTerm term = fromRefTerm (toRefTerm term) `eqTerm` term--instance Arbitrary Term where- arbitrary = fromRefTerm <$> arbitrary-- shrink (TInt n) = [ TInt n' | n' <- shrink n ]- shrink (TInteger n) = [ TInteger n' | n' <- shrink n ]-- shrink (TBytes ws) = [ TBytes (BS.pack ws') | ws' <- shrink (BS.unpack ws) ]- shrink (TBytesI wss) = [ TBytesI (LBS.fromChunks (map BS.pack wss'))- | wss' <- shrink (map BS.unpack (LBS.toChunks wss)) ]- shrink (TString cs) = [ TString (T.pack cs') | cs' <- shrink (T.unpack cs) ]- shrink (TStringI css) = [ TStringI (LT.fromChunks (map T.pack css'))- | css' <- shrink (map T.unpack (LT.toChunks css)) ]-- shrink (TList xs@[x]) = x : [ TList xs' | xs' <- shrink xs ]- shrink (TList xs) = [ TList xs' | xs' <- shrink xs ]- shrink (TListI xs@[x]) = x : [ TListI xs' | xs' <- shrink xs ]- shrink (TListI xs) = [ TListI xs' | xs' <- shrink xs ]-- shrink (TMap xys@[(x,y)]) = x : y : [ TMap xys' | xys' <- shrink xys ]- shrink (TMap xys) = [ TMap xys' | xys' <- shrink xys ]- shrink (TMapI xys@[(x,y)]) = x : y : [ TMapI xys' | xys' <- shrink xys ]- shrink (TMapI xys) = [ TMapI xys' | xys' <- shrink xys ]-- shrink (TTagged w t) = [ TTagged w' t' | (w', t') <- shrink (w, t)- , not (RefImpl.reservedTag (fromIntegral w')) ]-- shrink (TBool _) = []- shrink TNull = []-- shrink (TSimple w) = [ TSimple w' | w' <- shrink w- , not (RefImpl.reservedSimple (fromIntegral w)) ]- shrink (THalf _f) = []- shrink (TFloat f) = [ TFloat f' | f' <- shrink f ]- shrink (TDouble f) = [ TDouble f' | f' <- shrink f ]------------------------------------------------------------------------------------- TestTree API--testTree :: [TestCase] -> TestTree-testTree testCases =- testGroup "Main implementation"- [ testCase "external test vector" $- mapM_ externalTestCase testCases-- , testCase "internal test vector" $ do- sequence_ [ do expectedDiagnosticNotation d e- encodedRoundtrip d e- | (d,e) <- TestVector.specTestVector ]-- , --localOption (QuickCheckTests 5000) $- localOption (QuickCheckMaxSize 150) $- testGroup "properties"- [ testProperty "from/to reference terms" prop_fromToRefTerm- , testProperty "to/from reference terms" prop_toFromRefTerm- , testProperty "rountrip de/encoding terms" prop_encodeDecodeTermRoundtrip- -- TODO FIXME: need to fix the generation of terms to give- -- better size distribution some get far too big for the- -- splits properties.- , localOption (QuickCheckMaxSize 30) $- testProperty "decoding with all 2-chunks" prop_encodeDecodeTermRoundtrip_splits2- , localOption (QuickCheckMaxSize 20) $- testProperty "decoding with all 3-chunks" prop_encodeDecodeTermRoundtrip_splits3- , testProperty "encode term matches ref impl 1" prop_encodeTermMatchesRefImpl- , testProperty "encode term matches ref impl 2" prop_encodeTermMatchesRefImpl2- , testProperty "decoding term matches ref impl" prop_decodeTermMatchesRefImpl- ]- ]
tests/Tests/Negative.hs view
@@ -1,7 +1,12 @@+{-# LANGUAGE CPP #-} module Tests.Negative ( testTree -- :: TestTree ) where++#if ! MIN_VERSION_base(4,11,0) import Data.Monoid+#endif+ import Data.Version import Test.Tasty
tests/Tests/Orphanage.hs view
@@ -26,7 +26,7 @@ import Test.QuickCheck.Arbitrary import qualified Data.Vector.Primitive as Vector.Primitive-import qualified Data.ByteString.Short as BSS+-- import qualified Data.ByteString.Short as BSS -------------------------------------------------------------------------------- -- QuickCheck Orphans@@ -195,8 +195,10 @@ deriving instance Eq a => Eq (Const a b) #endif +#if !MIN_VERSION_quickcheck_instances(0,3,17) instance Arbitrary BSS.ShortByteString where arbitrary = BSS.pack <$> arbitrary+#endif instance (Vector.Primitive.Prim a, Arbitrary a ) => Arbitrary (Vector.Primitive.Vector a) where
− tests/Tests/Reference.hs
@@ -1,293 +0,0 @@-{-# LANGUAGE NamedFieldPuns #-}-{-# LANGUAGE OverloadedStrings #-}-module Tests.Reference- ( TestCase(..) -- :: *- , termToJson -- ::- , equalJson -- ::- , loadTestCases -- ::- , specTestVector -- ::- , testTree -- :: TestTree- ) where--import Test.Tasty-import Test.Tasty.QuickCheck--import qualified Data.ByteString as BS-import qualified Data.ByteString.Lazy as LBS-import qualified Data.ByteString.Base64 as Base64-import qualified Data.ByteString.Base64.URL as Base64url-import qualified Data.ByteString.Base16 as Base16-import qualified Data.Text as T-import qualified Data.Text.Encoding as T-import qualified Data.Vector as V-import Data.Scientific (fromFloatDigits, toRealFloat)-import Data.Aeson as Aeson-import Control.Applicative-import Control.Monad-import Data.Word-import qualified Numeric.Half as Half--import Test.Tasty.HUnit--import Tests.Reference.Implementation as CBOR---data TestCase = TestCase {- encoded :: !LBS.ByteString,- decoded :: !(Either Aeson.Value String),- roundTrip :: !Bool- }- deriving Show--instance FromJSON TestCase where- parseJSON =- withObject "cbor test" $ \obj -> do- encoded64 <- T.encodeUtf8 <$> obj .: "cbor"- encoded <- either (fail "invalid base64") return $- Base64.decode encoded64- encoded16 <- T.encodeUtf8 <$> obj .: "hex"- let encoded' = fst (Base16.decode encoded16)- when (encoded /= encoded') $- fail "hex and cbor encoding mismatch in input"- roundTrip <- obj .: "roundtrip"- decoded <- Left <$> obj .: "decoded"- <|> Right <$> obj .: "diagnostic"- return $! TestCase {- encoded = LBS.fromStrict encoded,- roundTrip,- decoded- }--loadTestCases :: IO [TestCase]-loadTestCases = do- content <- LBS.readFile "tests/test-vectors/appendix_a.json"- either fail return (Aeson.eitherDecode' content)--externalTestCase :: TestCase -> Assertion-externalTestCase TestCase { encoded, decoded = Left expectedJson } = do- let term = deserialise encoded- actualJson = termToJson term- reencoded = serialise term-- expectedJson `equalJson` actualJson- encoded @=? reencoded--externalTestCase TestCase { encoded, decoded = Right expectedDiagnostic } = do- let term = deserialise encoded- actualDiagnostic = diagnosticNotation term- reencoded = serialise term-- expectedDiagnostic @=? actualDiagnostic- encoded @=? reencoded--equalJson :: Aeson.Value -> Aeson.Value -> Assertion-equalJson (Aeson.Number expected) (Aeson.Number actual)- | toRealFloat expected == promoteDouble (toRealFloat actual)- = return ()- where- -- This is because the expected JSON output is always using double precision- -- where as Aeson's Scientific type preserves the precision of the input.- -- So for tests using Float, we're more precise than the reference values.- promoteDouble :: Float -> Double- promoteDouble = realToFrac--equalJson expected actual = expected @=? actual---termToJson :: CBOR.Term -> Aeson.Value-termToJson (TUInt n) = Aeson.Number (fromIntegral (fromUInt n))-termToJson (TNInt n) = Aeson.Number (-1 - fromIntegral (fromUInt n))-termToJson (TBigInt n) = Aeson.Number (fromIntegral n)-termToJson (TBytes ws) = Aeson.String (bytesToBase64Text ws)-termToJson (TBytess wss) = Aeson.String (bytesToBase64Text (concat wss))-termToJson (TString cs) = Aeson.String (T.pack cs)-termToJson (TStrings css) = Aeson.String (T.pack (concat css))-termToJson (TArray ts) = Aeson.Array (V.fromList (map termToJson ts))-termToJson (TArrayI ts) = Aeson.Array (V.fromList (map termToJson ts))-termToJson (TMap kvs) = Aeson.object [ (T.pack k, termToJson v)- | (TString k,v) <- kvs ]-termToJson (TMapI kvs) = Aeson.object [ (T.pack k, termToJson v)- | (TString k,v) <- kvs ]-termToJson (TTagged _ t) = termToJson t-termToJson TTrue = Aeson.Bool True-termToJson TFalse = Aeson.Bool False-termToJson TNull = Aeson.Null-termToJson TUndef = Aeson.Null -- replacement value-termToJson (TSimple _) = Aeson.Null -- replacement value-termToJson (TFloat16 f) = Aeson.Number (fromFloatDigits (Half.fromHalf f))-termToJson (TFloat32 f) = Aeson.Number (fromFloatDigits f)-termToJson (TFloat64 f) = Aeson.Number (fromFloatDigits f)--bytesToBase64Text :: [Word8] -> T.Text-bytesToBase64Text = T.decodeLatin1 . Base64url.encode . BS.pack--expectedDiagnosticNotation :: String -> [Word8] -> Assertion-expectedDiagnosticNotation expectedDiagnostic encoded = do- let Just (term, []) = runDecoder decodeTerm encoded- actualDiagnostic = diagnosticNotation term-- expectedDiagnostic @=? actualDiagnostic---- | The reference implementation satisfies the roundtrip property for most--- examples (all the ones from Appendix A). It does not satisfy the roundtrip--- property in general however, non-canonical over-long int encodings for--- example.-------encodedRoundtrip :: String -> [Word8] -> Assertion-encodedRoundtrip expectedDiagnostic encoded = do- let Just (term, []) = runDecoder decodeTerm encoded- reencoded = encodeTerm term-- assertEqual ("for CBOR: " ++ expectedDiagnostic) encoded reencoded---- | The examples from the CBOR spec RFC7049 Appendix A.--- The diagnostic notation and encoded bytes.----specTestVector :: [(String, [Word8])]-specTestVector =- [ ("0", [0x00])- , ("1", [0x01])- , ("10", [0x0a])- , ("23", [0x17])- , ("24", [0x18, 0x18])- , ("25", [0x18, 0x19])- , ("100", [0x18, 0x64])- , ("1000", [0x19, 0x03, 0xe8])- , ("1000000", [0x1a, 0x00, 0x0f, 0x42, 0x40])- , ("1000000000000", [0x1b, 0x00, 0x00, 0x00, 0xe8, 0xd4, 0xa5, 0x10, 0x00])-- , ("18446744073709551615", [0x1b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff])- , ("18446744073709551616", [0xc2, 0x49, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00])- , ("-18446744073709551616", [0x3b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff])- , ("-18446744073709551617", [0xc3, 0x49, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00])-- , ("-1", [0x20])- , ("-10", [0x29])- , ("-100", [0x38, 0x63])- , ("-1000", [0x39, 0x03, 0xe7])-- , ("0.0", [0xf9, 0x00, 0x00])- , ("-0.0", [0xf9, 0x80, 0x00])- , ("1.0", [0xf9, 0x3c, 0x00])- , ("1.1", [0xfb, 0x3f, 0xf1, 0x99, 0x99, 0x99, 0x99, 0x99, 0x9a])- , ("1.5", [0xf9, 0x3e, 0x00])- , ("65504.0", [0xf9, 0x7b, 0xff])- , ("100000.0", [0xfa, 0x47, 0xc3, 0x50, 0x00])- , ("3.4028234663852886e38", [0xfa, 0x7f, 0x7f, 0xff, 0xff])- , ("1.0e300", [0xfb, 0x7e, 0x37, 0xe4, 0x3c, 0x88, 0x00, 0x75, 0x9c])- , ("5.960464477539063e-8", [0xf9, 0x00, 0x01])- , ("0.00006103515625", [0xf9, 0x04, 0x00])- , ("-4.0", [0xf9, 0xc4, 0x00])- , ("-4.1", [0xfb, 0xc0, 0x10, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66])-- , ("Infinity", [0xf9, 0x7c, 0x00])- , ("NaN", [0xf9, 0x7e, 0x00])- , ("-Infinity", [0xf9, 0xfc, 0x00])- , ("Infinity", [0xfa, 0x7f, 0x80, 0x00, 0x00])- , ("-Infinity", [0xfa, 0xff, 0x80, 0x00, 0x00])- , ("Infinity", [0xfb, 0x7f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00])- , ("-Infinity", [0xfb, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00])-- , ("false", [0xf4])- , ("true", [0xf5])- , ("null", [0xf6])- , ("undefined", [0xf7])- , ("simple(16)", [0xf0])- , ("simple(24)", [0xf8, 0x18])- , ("simple(255)", [0xf8, 0xff])-- , ("0(\"2013-03-21T20:04:00Z\")",- [0xc0, 0x74, 0x32, 0x30, 0x31, 0x33, 0x2d, 0x30, 0x33, 0x2d, 0x32, 0x31,- 0x54, 0x32, 0x30, 0x3a, 0x30, 0x34, 0x3a, 0x30, 0x30, 0x5a])- , ("1(1363896240)", [0xc1, 0x1a, 0x51, 0x4b, 0x67, 0xb0])- , ("1(1363896240.5)", [0xc1, 0xfb, 0x41, 0xd4, 0x52, 0xd9, 0xec, 0x20, 0x00, 0x00])- , ("23(h'01020304')", [0xd7, 0x44, 0x01, 0x02, 0x03, 0x04])- , ("24(h'6449455446')", [0xd8, 0x18, 0x45, 0x64, 0x49, 0x45, 0x54, 0x46])- , ("32(\"http://www.example.com\")",- [0xd8, 0x20, 0x76, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77,- 0x77, 0x2e, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d])-- , ("h''", [0x40])- , ("h'01020304'", [0x44, 0x01, 0x02, 0x03, 0x04])- , ("\"\"", [0x60])- , ("\"a\"", [0x61, 0x61])- , ("\"IETF\"", [0x64, 0x49, 0x45, 0x54, 0x46])- , ("\"\\\"\\\\\"", [0x62, 0x22, 0x5c])- , ("\"\\252\"", [0x62, 0xc3, 0xbc])- , ("\"\\27700\"", [0x63, 0xe6, 0xb0, 0xb4])- , ("\"\\65873\"", [0x64, 0xf0, 0x90, 0x85, 0x91])-- , ("[]", [0x80])- , ("[1, 2, 3]", [0x83, 0x01, 0x02, 0x03])- , ("[1, [2, 3], [4, 5]]", [0x83, 0x01, 0x82, 0x02, 0x03, 0x82, 0x04, 0x05])- , ("[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25]",- [0x98, 0x19, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a,- 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16,- 0x17, 0x18, 0x18, 0x18, 0x19])-- , ("{}", [0xa0])- , ("{1: 2, 3: 4}", [0xa2, 0x01, 0x02, 0x03, 0x04])- , ("{\"a\": 1, \"b\": [2, 3]}", [0xa2, 0x61, 0x61, 0x01, 0x61, 0x62, 0x82, 0x02, 0x03])- , ("[\"a\", {\"b\": \"c\"}]", [0x82, 0x61, 0x61, 0xa1, 0x61, 0x62, 0x61, 0x63])- , ("{\"a\": \"A\", \"b\": \"B\", \"c\": \"C\", \"d\": \"D\", \"e\": \"E\"}",- [0xa5, 0x61, 0x61, 0x61, 0x41, 0x61, 0x62, 0x61, 0x42, 0x61, 0x63, 0x61,- 0x43, 0x61, 0x64, 0x61, 0x44, 0x61, 0x65, 0x61, 0x45])-- , ("(_ h'0102', h'030405')", [0x5f, 0x42, 0x01, 0x02, 0x43, 0x03, 0x04, 0x05, 0xff])- , ("(_ \"strea\", \"ming\")", [0x7f, 0x65, 0x73, 0x74, 0x72, 0x65, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x67, 0xff])-- , ("[_ ]", [0x9f, 0xff])- , ("[_ 1, [2, 3], [_ 4, 5]]", [0x9f, 0x01, 0x82, 0x02, 0x03, 0x9f, 0x04, 0x05, 0xff, 0xff])- , ("[_ 1, [2, 3], [4, 5]]", [0x9f, 0x01, 0x82, 0x02, 0x03, 0x82, 0x04, 0x05, 0xff])- , ("[1, [2, 3], [_ 4, 5]]", [0x83, 0x01, 0x82, 0x02, 0x03, 0x9f, 0x04, 0x05, 0xff])- , ("[1, [_ 2, 3], [4, 5]]", [0x83, 0x01, 0x9f, 0x02, 0x03, 0xff, 0x82, 0x04, 0x05])- , ("[_ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25]",- [0x9f, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,- 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,- 0x18, 0x18, 0x18, 0x19, 0xff])- , ("{_ \"a\": 1, \"b\": [_ 2, 3]}", [0xbf, 0x61, 0x61, 0x01, 0x61, 0x62, 0x9f, 0x02, 0x03, 0xff, 0xff])-- , ("[\"a\", {_ \"b\": \"c\"}]", [0x82, 0x61, 0x61, 0xbf, 0x61, 0x62, 0x61, 0x63, 0xff])- , ("{_ \"Fun\": true, \"Amt\": -2}", [0xbf, 0x63, 0x46, 0x75, 0x6e, 0xf5, 0x63, 0x41, 0x6d, 0x74, 0x21, 0xff])- ]---- TODO FIXME: test redundant encodings e.g.--- bigint with zero-length bytestring--- bigint with leading zeros--- bigint using indefinate bytestring encoding--- larger than necessary ints, lengths, tags, simple etc------------------------------------------------------------------------------------- TestTree API--testTree :: [TestCase] -> TestTree-testTree testCases =- testGroup "Reference implementation"- [ testCase "external test vector" $- mapM_ externalTestCase testCases-- , testCase "internal test vector" $ do- sequence_ [ do expectedDiagnosticNotation d e- encodedRoundtrip d e- | (d,e) <- specTestVector ]-- , testGroup "properties"- [ testProperty "encoding/decoding initial byte" prop_InitialByte- , testProperty "encoding/decoding additional info" prop_AdditionalInfo- , testProperty "encoding/decoding token header" prop_TokenHeader- , testProperty "encoding/decoding token header 2" prop_TokenHeader2- , testProperty "encoding/decoding tokens" prop_Token- , --localOption (QuickCheckTests 1000) $- localOption (QuickCheckMaxSize 150) $- testProperty "encoding/decoding terms" prop_Term- ]-- , testGroup "internal properties"- [ testProperty "Integer to/from bytes" prop_integerToFromBytes- , testProperty "Word16 to/from network byte order" prop_word16ToFromNet- , testProperty "Word32 to/from network byte order" prop_word32ToFromNet- , testProperty "Word64 to/from network byte order" prop_word64ToFromNet- , testProperty "Numeric.Half to/from Float" prop_halfToFromFloat- ]- ]
− tests/Tests/Reference/Implementation.hs
@@ -1,1070 +0,0 @@-{-# LANGUAGE CPP, BangPatterns, MagicHash, UnboxedTuples, RankNTypes, ScopedTypeVariables #-}-{-# OPTIONS_GHC -fno-warn-orphans #-}--------------------------------------------------------------------------------- |--- Module : Codec.CBOR--- Copyright : 2013 Simon Meier <iridcode@gmail.com>,--- 2013-2014 Duncan Coutts,--- License : BSD3-style (see LICENSE.txt)------ Maintainer : Duncan Coutts--- Stability :--- Portability : portable------ CBOR format support.-----------------------------------------------------------------------------------module Tests.Reference.Implementation (- serialise,- deserialise,-- Term(..),- reservedTag,- reservedSimple,- eqTerm,- canonicaliseTerm,-- UInt(..),- fromUInt,- toUInt,- canonicaliseUInt,-- Decoder,- runDecoder,- testDecode,-- decodeTerm,- decodeTokens,- decodeToken,-- canonicalNaN,-- diagnosticNotation,-- encodeTerm,- encodeToken,-- prop_InitialByte,- prop_AdditionalInfo,- prop_TokenHeader,- prop_TokenHeader2,- prop_Token,- prop_Term,-- -- properties of internal helpers- prop_integerToFromBytes,- prop_word16ToFromNet,- prop_word32ToFromNet,- prop_word64ToFromNet,- prop_halfToFromFloat,-- arbitraryFullRangeIntegral,- ) where---import Data.Bits-import Data.Word-import Data.Int-import Numeric.Half (Half(..))-import qualified Numeric.Half as Half-import Data.List-import Numeric-import GHC.Float (float2Double)-import qualified Data.ByteString as BS-import qualified Data.ByteString.Lazy as LBS-import qualified Data.Text as T-import qualified Data.Text.Encoding as T-import Data.Monoid ((<>))-import Foreign-import System.IO.Unsafe-import Control.Monad (ap)--import Test.QuickCheck.Arbitrary-import Test.QuickCheck.Gen--#if !MIN_VERSION_base(4,8,0)-import Data.Monoid (Monoid(..))-import Control.Applicative-#endif---serialise :: Term -> LBS.ByteString-serialise = LBS.pack . encodeTerm--deserialise :: LBS.ByteString -> Term-deserialise bytes =- case runDecoder decodeTerm (LBS.unpack bytes) of- Just (term, []) -> term- Just _ -> error "ReferenceImpl.deserialise: trailing data"- Nothing -> error "ReferenceImpl.deserialise: decoding failed"-----------------------------------------------------------------------------newtype Decoder a = Decoder { runDecoder :: [Word8] -> Maybe (a, [Word8]) }--instance Functor Decoder where- fmap f a = a >>= return . f--instance Applicative Decoder where- pure = return- (<*>) = ap--instance Monad Decoder where- return x = Decoder (\ws -> Just (x, ws))- d >>= f = Decoder (\ws -> case runDecoder d ws of- Nothing -> Nothing- Just (x, ws') -> runDecoder (f x) ws')- fail _ = Decoder (\_ -> Nothing)--getByte :: Decoder Word8-getByte =- Decoder $ \ws ->- case ws of- w:ws' -> Just (w, ws')- _ -> Nothing--getBytes :: Integral n => n -> Decoder [Word8]-getBytes n =- Decoder $ \ws ->- case genericSplitAt n ws of- (ws', []) | genericLength ws' == n -> Just (ws', [])- | otherwise -> Nothing- (ws', ws'') -> Just (ws', ws'')--eof :: Decoder Bool-eof = Decoder $ \ws -> Just (null ws, ws)--type Encoder a = a -> [Word8]---- The initial byte of each data item contains both information about--- the major type (the high-order 3 bits, described in Section 2.1) and--- additional information (the low-order 5 bits).--data MajorType = MajorType0 | MajorType1 | MajorType2 | MajorType3- | MajorType4 | MajorType5 | MajorType6 | MajorType7- deriving (Show, Eq, Ord, Enum)--instance Arbitrary MajorType where- arbitrary = elements [MajorType0 .. MajorType7]--encodeInitialByte :: MajorType -> Word -> Word8-encodeInitialByte mt ai- | ai < 2^(5 :: Int)- = fromIntegral (fromIntegral (fromEnum mt) `shiftL` 5 .|. ai)-- | otherwise- = error "encodeInitialByte: invalid additional info value"--decodeInitialByte :: Word8 -> (MajorType, Word)-decodeInitialByte ib = ( toEnum $ fromIntegral $ ib `shiftR` 5- , fromIntegral $ ib .&. 0x1f)--prop_InitialByte :: Bool-prop_InitialByte =- and [ (uncurry encodeInitialByte . decodeInitialByte) w8 == w8- | w8 <- [minBound..maxBound] ]---- When the value of the--- additional information is less than 24, it is directly used as a--- small unsigned integer. When it is 24 to 27, the additional bytes--- for a variable-length integer immediately follow; the values 24 to 27--- of the additional information specify that its length is a 1-, 2-,--- 4-, or 8-byte unsigned integer, respectively. Additional information--- value 31 is used for indefinite-length items, described in--- Section 2.2. Additional information values 28 to 30 are reserved for--- future expansion.------ In all additional information values, the resulting integer is--- interpreted depending on the major type. It may represent the actual--- data: for example, in integer types, the resulting integer is used--- for the value itself. It may instead supply length information: for--- example, in byte strings it gives the length of the byte string data--- that follows.--data UInt =- UIntSmall Word- | UInt8 Word8- | UInt16 Word16- | UInt32 Word32- | UInt64 Word64- deriving (Eq, Show)--data AdditionalInformation =- AiValue UInt- | AiIndefLen- | AiReserved Word- deriving (Eq, Show)--instance Arbitrary UInt where- arbitrary =- sized $ \n ->- oneof $ take (1 + n `div` 2)- [ UIntSmall <$> choose (0, 23)- , UInt8 <$> arbitraryBoundedIntegral- , UInt16 <$> arbitraryBoundedIntegral- , UInt32 <$> arbitraryBoundedIntegral- , UInt64 <$> arbitraryBoundedIntegral- ]--instance Arbitrary AdditionalInformation where- arbitrary =- frequency- [ (7, AiValue <$> arbitrary)- , (2, pure AiIndefLen)- , (1, AiReserved <$> choose (28, 30))- ]--decodeAdditionalInfo :: Word -> Decoder AdditionalInformation-decodeAdditionalInfo = dec- where- dec n- | n < 24 = return (AiValue (UIntSmall n))- dec 24 = do w <- getByte- return (AiValue (UInt8 w))- dec 25 = do [w1,w0] <- getBytes (2 :: Int)- let w = word16FromNet w1 w0- return (AiValue (UInt16 w))- dec 26 = do [w3,w2,w1,w0] <- getBytes (4 :: Int)- let w = word32FromNet w3 w2 w1 w0- return (AiValue (UInt32 w))- dec 27 = do [w7,w6,w5,w4,w3,w2,w1,w0] <- getBytes (8 :: Int)- let w = word64FromNet w7 w6 w5 w4 w3 w2 w1 w0- return (AiValue (UInt64 w))- dec 31 = return AiIndefLen- dec n- | n < 31 = return (AiReserved n)- dec _ = fail ""--encodeAdditionalInfo :: AdditionalInformation -> (Word, [Word8])-encodeAdditionalInfo = enc- where- enc (AiValue (UIntSmall n))- | n < 24 = (n, [])- | otherwise = error "invalid UIntSmall value"- enc (AiValue (UInt8 w)) = (24, [w])- enc (AiValue (UInt16 w)) = (25, [w1, w0])- where (w1, w0) = word16ToNet w- enc (AiValue (UInt32 w)) = (26, [w3, w2, w1, w0])- where (w3, w2, w1, w0) = word32ToNet w- enc (AiValue (UInt64 w)) = (27, [w7, w6, w5, w4,- w3, w2, w1, w0])- where (w7, w6, w5, w4,- w3, w2, w1, w0) = word64ToNet w- enc AiIndefLen = (31, [])- enc (AiReserved n)- | n >= 28 && n < 31 = (n, [])- | otherwise = error "invalid AiReserved value"--prop_AdditionalInfo :: AdditionalInformation -> Bool-prop_AdditionalInfo ai =- let (w, ws) = encodeAdditionalInfo ai- Just (ai', _) = runDecoder (decodeAdditionalInfo w) ws- in ai == ai'---data TokenHeader = TokenHeader MajorType AdditionalInformation- deriving (Show, Eq)--instance Arbitrary TokenHeader where- arbitrary = TokenHeader <$> arbitrary <*> arbitrary--decodeTokenHeader :: Decoder TokenHeader-decodeTokenHeader = do- b <- getByte- let (mt, ai) = decodeInitialByte b- ai' <- decodeAdditionalInfo ai- return (TokenHeader mt ai')--encodeTokenHeader :: Encoder TokenHeader-encodeTokenHeader (TokenHeader mt ai) =- let (w, ws) = encodeAdditionalInfo ai- in encodeInitialByte mt w : ws--prop_TokenHeader :: TokenHeader -> Bool-prop_TokenHeader header =- let ws = encodeTokenHeader header- Just (header', _) = runDecoder decodeTokenHeader ws- in header == header'--prop_TokenHeader2 :: Bool-prop_TokenHeader2 =- and [ w8 : extraused == encoded- | w8 <- [minBound..maxBound]- , let extra = [1..8]- Just (header, unused) = runDecoder decodeTokenHeader (w8 : extra)- encoded = encodeTokenHeader header- extraused = take (8 - length unused) extra- ]--data Token =- MT0_UnsignedInt UInt- | MT1_NegativeInt UInt- | MT2_ByteString UInt [Word8]- | MT2_ByteStringIndef- | MT3_String UInt [Word8]- | MT3_StringIndef- | MT4_ArrayLen UInt- | MT4_ArrayLenIndef- | MT5_MapLen UInt- | MT5_MapLenIndef- | MT6_Tag UInt- | MT7_Simple Word8- | MT7_Float16 Half- | MT7_Float32 Float- | MT7_Float64 Double- | MT7_Break- deriving (Show, Eq)--instance Arbitrary Token where- arbitrary =- oneof- [ MT0_UnsignedInt <$> arbitrary- , MT1_NegativeInt <$> arbitrary- , do ws <- arbitrary- MT2_ByteString <$> arbitraryLengthUInt ws <*> pure ws- , pure MT2_ByteStringIndef- , do cs <- arbitrary- let ws = encodeUTF8 cs- MT3_String <$> arbitraryLengthUInt ws <*> pure ws- , pure MT3_StringIndef- , MT4_ArrayLen <$> arbitrary- , pure MT4_ArrayLenIndef- , MT5_MapLen <$> arbitrary- , pure MT5_MapLenIndef- , MT6_Tag <$> arbitrary- , MT7_Simple <$> arbitrary- , MT7_Float16 . getFloatSpecials <$> arbitrary- , MT7_Float32 . getFloatSpecials <$> arbitrary- , MT7_Float64 . getFloatSpecials <$> arbitrary- , pure MT7_Break- ]- where- arbitraryLengthUInt xs =- let n = length xs in- elements $- [ UIntSmall (fromIntegral n) | n < 24 ]- ++ [ UInt8 (fromIntegral n) | n < 255 ]- ++ [ UInt16 (fromIntegral n) | n < 65536 ]- ++ [ UInt32 (fromIntegral n)- , UInt64 (fromIntegral n) ]--testDecode :: [Word8] -> Term-testDecode ws =- case runDecoder decodeTerm ws of- Just (x, []) -> x- _ -> error "testDecode: parse error"--decodeTokens :: Decoder [Token]-decodeTokens = do- done <- eof- if done- then return []- else do tok <- decodeToken- toks <- decodeTokens- return (tok:toks)--decodeToken :: Decoder Token-decodeToken = do- header <- decodeTokenHeader- extra <- getBytes (tokenExtraLen header)- either fail return (packToken header extra)--tokenExtraLen :: TokenHeader -> Word64-tokenExtraLen (TokenHeader MajorType2 (AiValue n)) = fromUInt n -- bytestrings-tokenExtraLen (TokenHeader MajorType3 (AiValue n)) = fromUInt n -- unicode strings-tokenExtraLen _ = 0--packToken :: TokenHeader -> [Word8] -> Either String Token-packToken (TokenHeader mt ai) extra = case (mt, ai) of- -- Major type 0: an unsigned integer. The 5-bit additional information- -- is either the integer itself (for additional information values 0- -- through 23) or the length of additional data.- (MajorType0, AiValue n) -> return (MT0_UnsignedInt n)-- -- Major type 1: a negative integer. The encoding follows the rules- -- for unsigned integers (major type 0), except that the value is- -- then -1 minus the encoded unsigned integer.- (MajorType1, AiValue n) -> return (MT1_NegativeInt n)-- -- Major type 2: a byte string. The string's length in bytes is- -- represented following the rules for positive integers (major type 0).- (MajorType2, AiValue n) -> return (MT2_ByteString n extra)- (MajorType2, AiIndefLen) -> return MT2_ByteStringIndef-- -- Major type 3: a text string, specifically a string of Unicode- -- characters that is encoded as UTF-8 [RFC3629]. The format of this- -- type is identical to that of byte strings (major type 2), that is,- -- as with major type 2, the length gives the number of bytes.- (MajorType3, AiValue n) -> return (MT3_String n extra)- (MajorType3, AiIndefLen) -> return MT3_StringIndef-- -- Major type 4: an array of data items. The array's length follows the- -- rules for byte strings (major type 2), except that the length- -- denotes the number of data items, not the length in bytes that the- -- array takes up.- (MajorType4, AiValue n) -> return (MT4_ArrayLen n)- (MajorType4, AiIndefLen) -> return MT4_ArrayLenIndef-- -- Major type 5: a map of pairs of data items. A map is comprised of- -- pairs of data items, each pair consisting of a key that is- -- immediately followed by a value. The map's length follows the- -- rules for byte strings (major type 2), except that the length- -- denotes the number of pairs, not the length in bytes that the map- -- takes up.- (MajorType5, AiValue n) -> return (MT5_MapLen n)- (MajorType5, AiIndefLen) -> return MT5_MapLenIndef-- -- Major type 6: optional semantic tagging of other major types.- -- The initial bytes of the tag follow the rules for positive integers- -- (major type 0).- (MajorType6, AiValue n) -> return (MT6_Tag n)-- -- Major type 7 is for two types of data: floating-point numbers and- -- "simple values" that do not need any content. Each value of the- -- 5-bit additional information in the initial byte has its own separate- -- meaning, as defined in Table 1.- -- | 0..23 | Simple value (value 0..23) |- -- | 24 | Simple value (value 32..255 in following byte) |- -- | 25 | IEEE 754 Half-Precision Float (16 bits follow) |- -- | 26 | IEEE 754 Single-Precision Float (32 bits follow) |- -- | 27 | IEEE 754 Double-Precision Float (64 bits follow) |- -- | 28-30 | (Unassigned) |- -- | 31 | "break" stop code for indefinite-length items |- (MajorType7, AiValue (UIntSmall w)) -> return (MT7_Simple (fromIntegral w))- (MajorType7, AiValue (UInt8 w)) -> return (MT7_Simple (fromIntegral w))- (MajorType7, AiValue (UInt16 w)) -> return (MT7_Float16 (wordToHalf w))- (MajorType7, AiValue (UInt32 w)) -> return (MT7_Float32 (wordToFloat w))- (MajorType7, AiValue (UInt64 w)) -> return (MT7_Float64 (wordToDouble w))- (MajorType7, AiIndefLen) -> return (MT7_Break)- _ -> fail "invalid token header"---encodeToken :: Encoder Token-encodeToken tok =- let (header, extra) = unpackToken tok- in encodeTokenHeader header ++ extra---unpackToken :: Token -> (TokenHeader, [Word8])-unpackToken tok = (\(mt, ai, ws) -> (TokenHeader mt ai, ws)) $ case tok of- (MT0_UnsignedInt n) -> (MajorType0, AiValue n, [])- (MT1_NegativeInt n) -> (MajorType1, AiValue n, [])- (MT2_ByteString n ws) -> (MajorType2, AiValue n, ws)- MT2_ByteStringIndef -> (MajorType2, AiIndefLen, [])- (MT3_String n ws) -> (MajorType3, AiValue n, ws)- MT3_StringIndef -> (MajorType3, AiIndefLen, [])- (MT4_ArrayLen n) -> (MajorType4, AiValue n, [])- MT4_ArrayLenIndef -> (MajorType4, AiIndefLen, [])- (MT5_MapLen n) -> (MajorType5, AiValue n, [])- MT5_MapLenIndef -> (MajorType5, AiIndefLen, [])- (MT6_Tag n) -> (MajorType6, AiValue n, [])- (MT7_Simple n)- | n <= 23 -> (MajorType7, AiValue (UIntSmall (fromIntegral n)), [])- | otherwise -> (MajorType7, AiValue (UInt8 n), [])- (MT7_Float16 f) -> (MajorType7, AiValue (UInt16 (halfToWord f)), [])- (MT7_Float32 f) -> (MajorType7, AiValue (UInt32 (floatToWord f)), [])- (MT7_Float64 f) -> (MajorType7, AiValue (UInt64 (doubleToWord f)), [])- MT7_Break -> (MajorType7, AiIndefLen, [])---fromUInt :: UInt -> Word64-fromUInt (UIntSmall w) = fromIntegral w-fromUInt (UInt8 w) = fromIntegral w-fromUInt (UInt16 w) = fromIntegral w-fromUInt (UInt32 w) = fromIntegral w-fromUInt (UInt64 w) = fromIntegral w--toUInt :: Word64 -> UInt-toUInt n- | n < 24 = UIntSmall (fromIntegral n)- | n <= fromIntegral (maxBound :: Word8) = UInt8 (fromIntegral n)- | n <= fromIntegral (maxBound :: Word16) = UInt16 (fromIntegral n)- | n <= fromIntegral (maxBound :: Word32) = UInt32 (fromIntegral n)- | otherwise = UInt64 n--lengthUInt :: [a] -> UInt-lengthUInt = toUInt . fromIntegral . length--decodeUTF8 :: [Word8] -> Either String [Char]-decodeUTF8 = either (fail . show) (return . T.unpack) . T.decodeUtf8' . BS.pack--encodeUTF8 :: [Char] -> [Word8]-encodeUTF8 = BS.unpack . T.encodeUtf8 . T.pack--reservedSimple :: Word8 -> Bool-reservedSimple w = w >= 20 && w <= 31--reservedTag :: Word64 -> Bool-reservedTag w = w <= 5--prop_Token :: Token -> Bool-prop_Token token =- let ws = encodeToken token- Just (token', []) = runDecoder decodeToken ws- in token `eqToken` token'---- NaNs are so annoying...-eqToken :: Token -> Token -> Bool-eqToken (MT7_Float16 f) (MT7_Float16 f') | isNaN f && isNaN f' = True-eqToken (MT7_Float32 f) (MT7_Float32 f') | isNaN f && isNaN f' = True-eqToken (MT7_Float64 f) (MT7_Float64 f') | isNaN f && isNaN f' = True-eqToken a b = a == b--data Term = TUInt UInt- | TNInt UInt- | TBigInt Integer- | TBytes [Word8]- | TBytess [[Word8]]- | TString [Char]- | TStrings [[Char]]- | TArray [Term]- | TArrayI [Term]- | TMap [(Term, Term)]- | TMapI [(Term, Term)]- | TTagged UInt Term- | TTrue- | TFalse- | TNull- | TUndef- | TSimple Word8- | TFloat16 Half- | TFloat32 Float- | TFloat64 Double- deriving (Show, Eq)--instance Arbitrary Term where- arbitrary =- frequency- [ (1, TUInt <$> arbitrary)- , (1, TNInt <$> arbitrary)- , (1, TBigInt . getLargeInteger <$> arbitrary)- , (1, TBytes <$> arbitrary)- , (1, TBytess <$> arbitrary)- , (1, TString <$> arbitrary)- , (1, TStrings <$> arbitrary)- , (2, TArray <$> listOfSmaller arbitrary)- , (2, TArrayI <$> listOfSmaller arbitrary)- , (2, TMap <$> listOfSmaller ((,) <$> arbitrary <*> arbitrary))- , (2, TMapI <$> listOfSmaller ((,) <$> arbitrary <*> arbitrary))- , (1, TTagged <$> arbitraryTag <*> sized (\sz -> resize (max 0 (sz-1)) arbitrary))- , (1, pure TFalse)- , (1, pure TTrue)- , (1, pure TNull)- , (1, pure TUndef)- , (1, TSimple <$> arbitrary `suchThat` (not . reservedSimple))- , (1, TFloat16 <$> arbitrary)- , (1, TFloat32 <$> arbitrary)- , (1, TFloat64 <$> arbitrary)- ]- where- listOfSmaller :: Gen a -> Gen [a]- listOfSmaller gen =- sized $ \n -> do- k <- choose (0,n)- vectorOf k (resize (n `div` (k+1)) gen)-- arbitraryTag = arbitrary `suchThat` (not . reservedTag . fromUInt)-- shrink (TUInt n) = [ TUInt n' | n' <- shrink n ]- shrink (TNInt n) = [ TNInt n' | n' <- shrink n ]- shrink (TBigInt n) = [ TBigInt n' | n' <- shrink n ]-- shrink (TBytes ws) = [ TBytes ws' | ws' <- shrink ws ]- shrink (TBytess wss) = [ TBytess wss' | wss' <- shrink wss ]- shrink (TString ws) = [ TString ws' | ws' <- shrink ws ]- shrink (TStrings wss) = [ TStrings wss' | wss' <- shrink wss ]-- shrink (TArray xs@[x]) = x : [ TArray xs' | xs' <- shrink xs ]- shrink (TArray xs) = [ TArray xs' | xs' <- shrink xs ]- shrink (TArrayI xs@[x]) = x : [ TArrayI xs' | xs' <- shrink xs ]- shrink (TArrayI xs) = [ TArrayI xs' | xs' <- shrink xs ]-- shrink (TMap xys@[(x,y)]) = x : y : [ TMap xys' | xys' <- shrink xys ]- shrink (TMap xys) = [ TMap xys' | xys' <- shrink xys ]- shrink (TMapI xys@[(x,y)]) = x : y : [ TMapI xys' | xys' <- shrink xys ]- shrink (TMapI xys) = [ TMapI xys' | xys' <- shrink xys ]-- shrink (TTagged w t) = [ TTagged w' t' | (w', t') <- shrink (w, t)- , not (reservedTag (fromUInt w')) ]-- shrink TFalse = []- shrink TTrue = []- shrink TNull = []- shrink TUndef = []-- shrink (TSimple w) = [ TSimple w' | w' <- shrink w, not (reservedSimple w) ]- shrink (TFloat16 f) = [ TFloat16 f' | f' <- shrink f ]- shrink (TFloat32 f) = [ TFloat32 f' | f' <- shrink f ]- shrink (TFloat64 f) = [ TFloat64 f' | f' <- shrink f ]---decodeTerm :: Decoder Term-decodeTerm = decodeToken >>= decodeTermFrom--decodeTermFrom :: Token -> Decoder Term-decodeTermFrom tk =- case tk of- MT0_UnsignedInt n -> return (TUInt n)- MT1_NegativeInt n -> return (TNInt n)-- MT2_ByteString _ bs -> return (TBytes bs)- MT2_ByteStringIndef -> decodeBytess []-- MT3_String _ ws -> either fail (return . TString) (decodeUTF8 ws)- MT3_StringIndef -> decodeStrings []-- MT4_ArrayLen len -> decodeArrayN (fromUInt len) []- MT4_ArrayLenIndef -> decodeArray []-- MT5_MapLen len -> decodeMapN (fromUInt len) []- MT5_MapLenIndef -> decodeMap []-- MT6_Tag tag -> decodeTagged tag-- MT7_Simple 20 -> return TFalse- MT7_Simple 21 -> return TTrue- MT7_Simple 22 -> return TNull- MT7_Simple 23 -> return TUndef- MT7_Simple w -> return (TSimple w)- MT7_Float16 f -> return (TFloat16 f)- MT7_Float32 f -> return (TFloat32 f)- MT7_Float64 f -> return (TFloat64 f)- MT7_Break -> fail "unexpected"---decodeBytess :: [[Word8]] -> Decoder Term-decodeBytess acc = do- tk <- decodeToken- case tk of- MT7_Break -> return $! TBytess (reverse acc)- MT2_ByteString _ bs -> decodeBytess (bs : acc)- _ -> fail "unexpected"--decodeStrings :: [String] -> Decoder Term-decodeStrings acc = do- tk <- decodeToken- case tk of- MT7_Break -> return $! TStrings (reverse acc)- MT3_String _ ws -> do cs <- either fail return (decodeUTF8 ws)- decodeStrings (cs : acc)- _ -> fail "unexpected"--decodeArrayN :: Word64 -> [Term] -> Decoder Term-decodeArrayN n acc =- case n of- 0 -> return $! TArray (reverse acc)- _ -> do t <- decodeTerm- decodeArrayN (n-1) (t : acc)--decodeArray :: [Term] -> Decoder Term-decodeArray acc = do- tk <- decodeToken- case tk of- MT7_Break -> return $! TArrayI (reverse acc)- _ -> do- tm <- decodeTermFrom tk- decodeArray (tm : acc)--decodeMapN :: Word64 -> [(Term, Term)] -> Decoder Term-decodeMapN n acc =- case n of- 0 -> return $! TMap (reverse acc)- _ -> do- tm <- decodeTerm- tm' <- decodeTerm- decodeMapN (n-1) ((tm, tm') : acc)--decodeMap :: [(Term, Term)] -> Decoder Term-decodeMap acc = do- tk <- decodeToken- case tk of- MT7_Break -> return $! TMapI (reverse acc)- _ -> do- tm <- decodeTermFrom tk- tm' <- decodeTerm- decodeMap ((tm, tm') : acc)--decodeTagged :: UInt -> Decoder Term-decodeTagged tag | fromUInt tag == 2 = do- MT2_ByteString _ bs <- decodeToken- let !n = integerFromBytes bs- return (TBigInt n)-decodeTagged tag | fromUInt tag == 3 = do- MT2_ByteString _ bs <- decodeToken- let !n = integerFromBytes bs- return (TBigInt (-1 - n))-decodeTagged tag = do- tm <- decodeTerm- return (TTagged tag tm)--integerFromBytes :: [Word8] -> Integer-integerFromBytes [] = 0-integerFromBytes (w0:ws0) = go (fromIntegral w0) ws0- where- go !acc [] = acc- go !acc (w:ws) = go (acc `shiftL` 8 + fromIntegral w) ws--integerToBytes :: Integer -> [Word8]-integerToBytes n0- | n0 == 0 = [0]- | n0 < 0 = reverse (go (-n0))- | otherwise = reverse (go n0)- where- go n | n == 0 = []- | otherwise = narrow n : go (n `shiftR` 8)-- narrow :: Integer -> Word8- narrow = fromIntegral--prop_integerToFromBytes :: LargeInteger -> Bool-prop_integerToFromBytes (LargeInteger n)- | n >= 0 =- let ws = integerToBytes n- n' = integerFromBytes ws- in n == n'- | otherwise =- let ws = integerToBytes n- n' = integerFromBytes ws- in n == -n'-----------------------------------------------------------------------------------encodeTerm :: Encoder Term-encodeTerm (TUInt n) = encodeToken (MT0_UnsignedInt n)-encodeTerm (TNInt n) = encodeToken (MT1_NegativeInt n)-encodeTerm (TBigInt n)- | n >= 0 = encodeToken (MT6_Tag (UIntSmall 2))- <> let ws = integerToBytes n- len = lengthUInt ws in- encodeToken (MT2_ByteString len ws)- | otherwise = encodeToken (MT6_Tag (UIntSmall 3))- <> let ws = integerToBytes (-1 - n)- len = lengthUInt ws in- encodeToken (MT2_ByteString len ws)-encodeTerm (TBytes ws) = let len = lengthUInt ws in- encodeToken (MT2_ByteString len ws)-encodeTerm (TBytess wss) = encodeToken MT2_ByteStringIndef- <> mconcat [ encodeToken (MT2_ByteString len ws)- | ws <- wss- , let len = lengthUInt ws ]- <> encodeToken MT7_Break-encodeTerm (TString cs) = let ws = encodeUTF8 cs- len = lengthUInt ws in- encodeToken (MT3_String len ws)-encodeTerm (TStrings css) = encodeToken MT3_StringIndef- <> mconcat [ encodeToken (MT3_String len ws)- | cs <- css- , let ws = encodeUTF8 cs- len = lengthUInt ws ]- <> encodeToken MT7_Break-encodeTerm (TArray ts) = let len = lengthUInt ts in- encodeToken (MT4_ArrayLen len)- <> mconcat (map encodeTerm ts)-encodeTerm (TArrayI ts) = encodeToken MT4_ArrayLenIndef- <> mconcat (map encodeTerm ts)- <> encodeToken MT7_Break-encodeTerm (TMap kvs) = let len = lengthUInt kvs in- encodeToken (MT5_MapLen len)- <> mconcat [ encodeTerm k <> encodeTerm v- | (k,v) <- kvs ]-encodeTerm (TMapI kvs) = encodeToken MT5_MapLenIndef- <> mconcat [ encodeTerm k <> encodeTerm v- | (k,v) <- kvs ]- <> encodeToken MT7_Break-encodeTerm (TTagged tag t) = encodeToken (MT6_Tag tag)- <> encodeTerm t-encodeTerm TFalse = encodeToken (MT7_Simple 20)-encodeTerm TTrue = encodeToken (MT7_Simple 21)-encodeTerm TNull = encodeToken (MT7_Simple 22)-encodeTerm TUndef = encodeToken (MT7_Simple 23)-encodeTerm (TSimple w) = encodeToken (MT7_Simple w)-encodeTerm (TFloat16 f) = encodeToken (MT7_Float16 f)-encodeTerm (TFloat32 f) = encodeToken (MT7_Float32 f)-encodeTerm (TFloat64 f) = encodeToken (MT7_Float64 f)------------------------------------------------------------------------------------prop_Term :: Term -> Bool-prop_Term term =- let ws = encodeTerm term- Just (term', []) = runDecoder decodeTerm ws- in term `eqTerm` term'---- NaNs are so annoying...-eqTerm :: Term -> Term -> Bool-eqTerm (TArray ts) (TArray ts') = and (zipWith eqTerm ts ts')-eqTerm (TArrayI ts) (TArrayI ts') = and (zipWith eqTerm ts ts')-eqTerm (TMap ts) (TMap ts') = and (zipWith eqTermPair ts ts')-eqTerm (TMapI ts) (TMapI ts') = and (zipWith eqTermPair ts ts')-eqTerm (TTagged w t) (TTagged w' t') = w == w' && eqTerm t t'-eqTerm (TFloat16 f) (TFloat16 f') | isNaN f && isNaN f' = True-eqTerm (TFloat32 f) (TFloat32 f') | isNaN f && isNaN f' = True-eqTerm (TFloat64 f) (TFloat64 f') | isNaN f && isNaN f' = True-eqTerm a b = a == b--eqTermPair :: (Term, Term) -> (Term, Term) -> Bool-eqTermPair (a,b) (a',b') = eqTerm a a' && eqTerm b b'--canonicaliseTerm :: Term -> Term-canonicaliseTerm (TUInt n) = TUInt (canonicaliseUInt n)-canonicaliseTerm (TNInt n) = TNInt (canonicaliseUInt n)-canonicaliseTerm (TBigInt n)- | n >= 0 && n <= fromIntegral (maxBound :: Word64)- = TUInt (toUInt (fromIntegral n))- | n < 0 && n >= -1 - fromIntegral (maxBound :: Word64)- = TNInt (toUInt (fromIntegral (-1 - n)))- | otherwise = TBigInt n-canonicaliseTerm (TFloat16 f) = TFloat16 (canonicaliseHalf f)-canonicaliseTerm (TFloat32 f) = if isNaN f- then TFloat16 canonicalNaN- else TFloat32 f-canonicaliseTerm (TFloat64 f) = if isNaN f- then TFloat16 canonicalNaN- else TFloat64 f-canonicaliseTerm (TBytess wss) = TBytess (filter (not . null) wss)-canonicaliseTerm (TStrings css) = TStrings (filter (not . null) css)-canonicaliseTerm (TArray ts) = TArray (map canonicaliseTerm ts)-canonicaliseTerm (TArrayI ts) = TArrayI (map canonicaliseTerm ts)-canonicaliseTerm (TMap ts) = TMap (map canonicaliseTermPair ts)-canonicaliseTerm (TMapI ts) = TMapI (map canonicaliseTermPair ts)-canonicaliseTerm (TTagged tag t) = TTagged (canonicaliseUInt tag) (canonicaliseTerm t)-canonicaliseTerm t = t--canonicaliseUInt :: UInt -> UInt-canonicaliseUInt = toUInt . fromUInt--canonicaliseHalf :: Half -> Half-canonicaliseHalf f- | isNaN f = canonicalNaN- | otherwise = f--canonicaliseTermPair :: (Term, Term) -> (Term, Term)-canonicaliseTermPair (x,y) = (canonicaliseTerm x, canonicaliseTerm y)--canonicalNaN :: Half-canonicalNaN = Half 0x7e00-----------------------------------------------------------------------------------diagnosticNotation :: Term -> String-diagnosticNotation = \t -> showsTerm t ""- where- showsTerm tm = case tm of- TUInt n -> shows (fromUInt n)- TNInt n -> shows (-1 - fromIntegral (fromUInt n) :: Integer)- TBigInt n -> shows n- TBytes bs -> showsBytes bs- TBytess bss -> surround '(' ')' (underscoreSpace . commaSep showsBytes bss)- TString cs -> shows cs- TStrings css -> surround '(' ')' (underscoreSpace . commaSep shows css)- TArray ts -> surround '[' ']' (commaSep showsTerm ts)- TArrayI ts -> surround '[' ']' (underscoreSpace . commaSep showsTerm ts)- TMap ts -> surround '{' '}' (commaSep showsMapElem ts)- TMapI ts -> surround '{' '}' (underscoreSpace . commaSep showsMapElem ts)- TTagged tag t -> shows (fromUInt tag) . surround '(' ')' (showsTerm t)- TTrue -> showString "true"- TFalse -> showString "false"- TNull -> showString "null"- TUndef -> showString "undefined"- TSimple n -> showString "simple" . surround '(' ')' (shows n)- -- convert to float to work around https://github.com/ekmett/half/issues/2- TFloat16 f -> showFloatCompat (float2Double (Half.fromHalf f))- TFloat32 f -> showFloatCompat (float2Double f)- TFloat64 f -> showFloatCompat f-- surround a b x = showChar a . x . showChar b-- commaSpace = showChar ',' . showChar ' '- underscoreSpace = showChar '_' . showChar ' '-- showsMapElem (k,v) = showsTerm k . showChar ':' . showChar ' ' . showsTerm v-- catShows :: (a -> ShowS) -> [a] -> ShowS- catShows f xs = \s -> foldr (\x r -> f x . r) id xs s-- sepShows :: ShowS -> (a -> ShowS) -> [a] -> ShowS- sepShows sep f xs = foldr (.) id (intersperse sep (map f xs))-- commaSep = sepShows commaSpace-- showsBytes :: [Word8] -> ShowS- showsBytes bs = showChar 'h' . showChar '\''- . catShows showFHex bs- . showChar '\''-- showFHex n | n < 16 = showChar '0' . showHex n- | otherwise = showHex n-- showFloatCompat n- | exponent' >= -5 && exponent' <= 15 = showFFloat Nothing n- | otherwise = showEFloat Nothing n- where exponent' = snd (floatToDigits 10 n)---word16FromNet :: Word8 -> Word8 -> Word16-word16FromNet w1 w0 =- fromIntegral w1 `shiftL` (8*1)- .|. fromIntegral w0 `shiftL` (8*0)--word16ToNet :: Word16 -> (Word8, Word8)-word16ToNet w =- ( fromIntegral ((w `shiftR` (8*1)) .&. 0xff)- , fromIntegral ((w `shiftR` (8*0)) .&. 0xff)- )--word32FromNet :: Word8 -> Word8 -> Word8 -> Word8 -> Word32-word32FromNet w3 w2 w1 w0 =- fromIntegral w3 `shiftL` (8*3)- .|. fromIntegral w2 `shiftL` (8*2)- .|. fromIntegral w1 `shiftL` (8*1)- .|. fromIntegral w0 `shiftL` (8*0)--word32ToNet :: Word32 -> (Word8, Word8, Word8, Word8)-word32ToNet w =- ( fromIntegral ((w `shiftR` (8*3)) .&. 0xff)- , fromIntegral ((w `shiftR` (8*2)) .&. 0xff)- , fromIntegral ((w `shiftR` (8*1)) .&. 0xff)- , fromIntegral ((w `shiftR` (8*0)) .&. 0xff)- )--word64FromNet :: Word8 -> Word8 -> Word8 -> Word8 ->- Word8 -> Word8 -> Word8 -> Word8 -> Word64-word64FromNet w7 w6 w5 w4 w3 w2 w1 w0 =- fromIntegral w7 `shiftL` (8*7)- .|. fromIntegral w6 `shiftL` (8*6)- .|. fromIntegral w5 `shiftL` (8*5)- .|. fromIntegral w4 `shiftL` (8*4)- .|. fromIntegral w3 `shiftL` (8*3)- .|. fromIntegral w2 `shiftL` (8*2)- .|. fromIntegral w1 `shiftL` (8*1)- .|. fromIntegral w0 `shiftL` (8*0)--word64ToNet :: Word64 -> (Word8, Word8, Word8, Word8,- Word8, Word8, Word8, Word8)-word64ToNet w =- ( fromIntegral ((w `shiftR` (8*7)) .&. 0xff)- , fromIntegral ((w `shiftR` (8*6)) .&. 0xff)- , fromIntegral ((w `shiftR` (8*5)) .&. 0xff)- , fromIntegral ((w `shiftR` (8*4)) .&. 0xff)- , fromIntegral ((w `shiftR` (8*3)) .&. 0xff)- , fromIntegral ((w `shiftR` (8*2)) .&. 0xff)- , fromIntegral ((w `shiftR` (8*1)) .&. 0xff)- , fromIntegral ((w `shiftR` (8*0)) .&. 0xff)- )--prop_word16ToFromNet :: Word8 -> Word8 -> Bool-prop_word16ToFromNet w1 w0 =- word16ToNet (word16FromNet w1 w0) == (w1, w0)--prop_word32ToFromNet :: Word8 -> Word8 -> Word8 -> Word8 -> Bool-prop_word32ToFromNet w3 w2 w1 w0 =- word32ToNet (word32FromNet w3 w2 w1 w0) == (w3, w2, w1, w0)--prop_word64ToFromNet :: Word8 -> Word8 -> Word8 -> Word8 ->- Word8 -> Word8 -> Word8 -> Word8 -> Bool-prop_word64ToFromNet w7 w6 w5 w4 w3 w2 w1 w0 =- word64ToNet (word64FromNet w7 w6 w5 w4 w3 w2 w1 w0)- == (w7, w6, w5, w4, w3, w2, w1, w0)--wordToHalf :: Word16 -> Half-wordToHalf = Half.Half . fromIntegral--wordToFloat :: Word32 -> Float-wordToFloat = toFloat--wordToDouble :: Word64 -> Double-wordToDouble = toFloat--toFloat :: (Storable word, Storable float) => word -> float-toFloat w =- unsafeDupablePerformIO $ alloca $ \buf -> do- poke (castPtr buf) w- peek buf--halfToWord :: Half -> Word16-halfToWord (Half.Half w) = fromIntegral w--floatToWord :: Float -> Word32-floatToWord = fromFloat--doubleToWord :: Double -> Word64-doubleToWord = fromFloat--fromFloat :: (Storable word, Storable float) => float -> word-fromFloat float =- unsafeDupablePerformIO $ alloca $ \buf -> do- poke (castPtr buf) float- peek buf---- Note: some NaNs do not roundtrip https://github.com/ekmett/half/issues/3--- but all the others had better-prop_halfToFromFloat :: Bool-prop_halfToFromFloat =- all (\w -> roundTrip w || isNaN (Half.Half w)) [minBound..maxBound]- where- roundTrip w =- w == (Half.getHalf . Half.toHalf . Half.fromHalf . Half.Half $ w)--instance Arbitrary Half where- arbitrary = Half.Half . fromIntegral <$> (arbitrary :: Gen Word16)--newtype FloatSpecials n = FloatSpecials { getFloatSpecials :: n }- deriving (Show, Eq)--instance (Arbitrary n, RealFloat n) => Arbitrary (FloatSpecials n) where- arbitrary =- frequency- [ (7, FloatSpecials <$> arbitrary)- , (1, pure (FloatSpecials (1/0)) ) -- +Infinity- , (1, pure (FloatSpecials (0/0)) ) -- NaN- , (1, pure (FloatSpecials (-1/0)) ) -- -Infinity- ]--newtype LargeInteger = LargeInteger { getLargeInteger :: Integer }- deriving (Show, Eq)--instance Arbitrary LargeInteger where- arbitrary =- sized $ \n ->- oneof $ take (1 + n `div` 10)- [ LargeInteger . fromIntegral <$> (arbitrary :: Gen Int8)- , LargeInteger . fromIntegral <$> choose (minBound, maxBound :: Int64)- , LargeInteger . bigger . fromIntegral <$> choose (minBound, maxBound :: Int64)- ]- where- bigger n = n * abs n---arbitraryFullRangeIntegral :: forall a. (Bounded a,-#if MIN_VERSION_base(4,7,0)- FiniteBits a,-#else- Bits a,-#endif- Integral a) => Gen a-arbitraryFullRangeIntegral- | isSigned (undefined :: a)- = let maxBits = bitSize' (undefined :: a) - 1- in sized $ \s ->- let bound = fromIntegral (maxBound :: a)- `shiftR` ((maxBits - s) `max` 0)- in fmap fromInteger $ choose (-bound, bound)-- | otherwise- = let maxBits = bitSize' (undefined :: a)- in sized $ \s ->- let bound = fromIntegral (maxBound :: a)- `shiftR` ((maxBits - s) `max` 0)- in fmap fromInteger $ choose (0, bound)-- where- bitSize' =-#if MIN_VERSION_base(4,7,0)- finiteBitSize-#else- bitSize-#endif-
tests/Tests/Regress.hs view
@@ -9,15 +9,13 @@ import qualified Tests.Regress.Issue80 as Issue80 import qualified Tests.Regress.Issue106 as Issue106 import qualified Tests.Regress.Issue135 as Issue135-import qualified Tests.Regress.FlatTerm as FlatTerm -------------------------------------------------------------------------------- -- Tests and properties testTree :: TestTree testTree = testGroup "Regression tests"- [ FlatTerm.testTree- , Issue13.testTree+ [ Issue13.testTree , Issue67.testTree , Issue80.testTree , Issue106.testTree
− tests/Tests/Regress/FlatTerm.hs
@@ -1,47 +0,0 @@-{-# LANGUAGE CPP #-}-module Tests.Regress.FlatTerm- ( testTree -- :: TestTree- ) where--import Data.Int-#if !MIN_VERSION_base(4,8,0)-import Data.Word-#endif--import Test.Tasty-import Test.Tasty.HUnit--import Codec.CBOR.Encoding-import Codec.CBOR.Decoding-import Codec.CBOR.FlatTerm------------------------------------------------------------------------------------- Tests and properties---- | Test an edge case in the FlatTerm implementation: when encoding a word--- larger than @'maxBound' :: 'Int'@, we store it as an @'Integer'@, and--- need to remember to handle this case when we decode.-largeWordTest :: Either String Word-largeWordTest = fromFlatTerm decodeWord $ toFlatTerm (encodeWord largeWord)--largeWord :: Word-largeWord = fromIntegral (maxBound :: Int) + 1---- | Test an edge case in the FlatTerm implementation: when encoding an--- Int64 that is less than @'minBound' :: 'Int'@, make sure we use an--- @'Integer'@ to store the result, because sticking it into an @'Int'@--- will result in overflow otherwise.-smallInt64Test :: Either String Int64-smallInt64Test = fromFlatTerm decodeInt64 $ toFlatTerm (encodeInt64 smallInt64)--smallInt64 :: Int64-smallInt64 = fromIntegral (minBound :: Int) - 1------------------------------------------------------------------------------------- TestTree API--testTree :: TestTree-testTree = testGroup "FlatTerm regressions"- [ testCase "Decoding of large-ish words" (Right largeWord @=? largeWordTest)- , testCase "Encoding of Int64s on 32bit" (Right smallInt64 @=? smallInt64Test)- ]
tests/Tests/Serialise.hs view
@@ -218,7 +218,7 @@ , mkTest (T :: T CUIntMax) , mkTest (T :: T CClock) , mkTest (T :: T CTime)- , mkTest (T :: T CUSeconds)+ , mkTest (T :: T CUSeconds_) , mkTest (T :: T CSUSeconds) , mkTest (T :: T CFloat) , mkTest (T :: T CDouble)@@ -334,6 +334,19 @@ , testProperty "flat term is valid" (prop_validFlatTerm t) ] +--------------------------------------------------------------------------------+-- Various data types++-- Wrapper for CUSeconds with Arbitrary instance that works on x86_32.+newtype CUSeconds_ = CUSeconds_ CUSeconds+ deriving (Eq, Show, Typeable)++instance Arbitrary CUSeconds_ where+ arbitrary = CUSeconds_ . CUSeconds <$> arbitraryBoundedIntegral++instance Serialise CUSeconds_ where+ encode (CUSeconds_ s) = encode s+ decode = CUSeconds_ <$> decode -------------------------------------------------------------------------------- -- Generic data types
− tests/test-vectors/README.md
@@ -1,27 +0,0 @@-test-vectors-============--This repo collects some simple test vectors in machine-processable form.--appendix_a.json------------------All examples in Appendix A of RFC 7049, encoded as a JSON array.--Each element of the test vector is a map (JSON object) with the keys:--- cbor: a base-64 encoded CBOR data item-- hex: the same CBOR data item in hex encoding-- roundtrip: a boolean that indicates whether a generic CBOR encoder- would _typically_ produce identical CBOR on re-encoding the decoded- data item (your mileage may vary)-- decoded: the decoded data item if it can be represented in JSON-- diagnostic: the representation of the data item in CBOR diagnostic notation, otherwise--To make use of the cases that need diagnostic notation, a diagnostic-notation printer is usually all that is needed: decode the CBOR, print-the decoded data item in diagnostic notation, and compare.--(Note that the diagnostic notation uses full decoration for the-indefinite length byte string, while the decoded indefinite length-text string represented in JSON necessarily doesn't.)
− tests/test-vectors/appendix_a.json
@@ -1,624 +0,0 @@-[- {- "cbor": "AA==",- "hex": "00",- "roundtrip": true,- "decoded": 0- },- {- "cbor": "AQ==",- "hex": "01",- "roundtrip": true,- "decoded": 1- },- {- "cbor": "Cg==",- "hex": "0a",- "roundtrip": true,- "decoded": 10- },- {- "cbor": "Fw==",- "hex": "17",- "roundtrip": true,- "decoded": 23- },- {- "cbor": "GBg=",- "hex": "1818",- "roundtrip": true,- "decoded": 24- },- {- "cbor": "GBk=",- "hex": "1819",- "roundtrip": true,- "decoded": 25- },- {- "cbor": "GGQ=",- "hex": "1864",- "roundtrip": true,- "decoded": 100- },- {- "cbor": "GQPo",- "hex": "1903e8",- "roundtrip": true,- "decoded": 1000- },- {- "cbor": "GgAPQkA=",- "hex": "1a000f4240",- "roundtrip": true,- "decoded": 1000000- },- {- "cbor": "GwAAAOjUpRAA",- "hex": "1b000000e8d4a51000",- "roundtrip": true,- "decoded": 1000000000000- },- {- "cbor": "G///////////",- "hex": "1bffffffffffffffff",- "roundtrip": true,- "decoded": 18446744073709551615- },- {- "cbor": "wkkBAAAAAAAAAAA=",- "hex": "c249010000000000000000",- "roundtrip": true,- "decoded": 18446744073709551616- },- {- "cbor": "O///////////",- "hex": "3bffffffffffffffff",- "roundtrip": true,- "decoded": -18446744073709551616- },- {- "cbor": "w0kBAAAAAAAAAAA=",- "hex": "c349010000000000000000",- "roundtrip": true,- "decoded": -18446744073709551617- },- {- "cbor": "IA==",- "hex": "20",- "roundtrip": true,- "decoded": -1- },- {- "cbor": "KQ==",- "hex": "29",- "roundtrip": true,- "decoded": -10- },- {- "cbor": "OGM=",- "hex": "3863",- "roundtrip": true,- "decoded": -100- },- {- "cbor": "OQPn",- "hex": "3903e7",- "roundtrip": true,- "decoded": -1000- },- {- "cbor": "+QAA",- "hex": "f90000",- "roundtrip": true,- "decoded": 0.0- },- {- "cbor": "+YAA",- "hex": "f98000",- "roundtrip": true,- "decoded": -0.0- },- {- "cbor": "+TwA",- "hex": "f93c00",- "roundtrip": true,- "decoded": 1.0- },- {- "cbor": "+z/xmZmZmZma",- "hex": "fb3ff199999999999a",- "roundtrip": true,- "decoded": 1.1- },- {- "cbor": "+T4A",- "hex": "f93e00",- "roundtrip": true,- "decoded": 1.5- },- {- "cbor": "+Xv/",- "hex": "f97bff",- "roundtrip": true,- "decoded": 65504.0- },- {- "cbor": "+kfDUAA=",- "hex": "fa47c35000",- "roundtrip": true,- "decoded": 100000.0- },- {- "cbor": "+n9///8=",- "hex": "fa7f7fffff",- "roundtrip": true,- "decoded": 3.4028234663852886e+38- },- {- "cbor": "+3435DyIAHWc",- "hex": "fb7e37e43c8800759c",- "roundtrip": true,- "decoded": 1.0e+300- },- {- "cbor": "+QAB",- "hex": "f90001",- "roundtrip": true,- "decoded": 5.960464477539063e-08- },- {- "cbor": "+QQA",- "hex": "f90400",- "roundtrip": true,- "decoded": 6.103515625e-05- },- {- "cbor": "+cQA",- "hex": "f9c400",- "roundtrip": true,- "decoded": -4.0- },- {- "cbor": "+8AQZmZmZmZm",- "hex": "fbc010666666666666",- "roundtrip": true,- "decoded": -4.1- },- {- "cbor": "+XwA",- "hex": "f97c00",- "roundtrip": true,- "diagnostic": "Infinity"- },- {- "cbor": "+X4A",- "hex": "f97e00",- "roundtrip": true,- "diagnostic": "NaN"- },- {- "cbor": "+fwA",- "hex": "f9fc00",- "roundtrip": true,- "diagnostic": "-Infinity"- },- {- "cbor": "+n+AAAA=",- "hex": "fa7f800000",- "roundtrip": false,- "diagnostic": "Infinity"- },- {- "cbor": "+v+AAAA=",- "hex": "faff800000",- "roundtrip": false,- "diagnostic": "-Infinity"- },- {- "cbor": "+3/wAAAAAAAA",- "hex": "fb7ff0000000000000",- "roundtrip": false,- "diagnostic": "Infinity"- },- {- "cbor": "+//wAAAAAAAA",- "hex": "fbfff0000000000000",- "roundtrip": false,- "diagnostic": "-Infinity"- },- {- "cbor": "9A==",- "hex": "f4",- "roundtrip": true,- "decoded": false- },- {- "cbor": "9Q==",- "hex": "f5",- "roundtrip": true,- "decoded": true- },- {- "cbor": "9g==",- "hex": "f6",- "roundtrip": true,- "decoded": null- },- {- "cbor": "9w==",- "hex": "f7",- "roundtrip": true,- "diagnostic": "undefined"- },- {- "cbor": "8A==",- "hex": "f0",- "roundtrip": true,- "diagnostic": "simple(16)"- },- {- "cbor": "+Bg=",- "hex": "f818",- "roundtrip": true,- "diagnostic": "simple(24)"- },- {- "cbor": "+P8=",- "hex": "f8ff",- "roundtrip": true,- "diagnostic": "simple(255)"- },- {- "cbor": "wHQyMDEzLTAzLTIxVDIwOjA0OjAwWg==",- "hex": "c074323031332d30332d32315432303a30343a30305a",- "roundtrip": true,- "diagnostic": "0(\"2013-03-21T20:04:00Z\")"- },- {- "cbor": "wRpRS2ew",- "hex": "c11a514b67b0",- "roundtrip": true,- "diagnostic": "1(1363896240)"- },- {- "cbor": "wftB1FLZ7CAAAA==",- "hex": "c1fb41d452d9ec200000",- "roundtrip": true,- "diagnostic": "1(1363896240.5)"- },- {- "cbor": "10QBAgME",- "hex": "d74401020304",- "roundtrip": true,- "diagnostic": "23(h'01020304')"- },- {- "cbor": "2BhFZElFVEY=",- "hex": "d818456449455446",- "roundtrip": true,- "diagnostic": "24(h'6449455446')"- },- {- "cbor": "2CB2aHR0cDovL3d3dy5leGFtcGxlLmNvbQ==",- "hex": "d82076687474703a2f2f7777772e6578616d706c652e636f6d",- "roundtrip": true,- "diagnostic": "32(\"http://www.example.com\")"- },- {- "cbor": "QA==",- "hex": "40",- "roundtrip": true,- "diagnostic": "h''"- },- {- "cbor": "RAECAwQ=",- "hex": "4401020304",- "roundtrip": true,- "diagnostic": "h'01020304'"- },- {- "cbor": "YA==",- "hex": "60",- "roundtrip": true,- "decoded": ""- },- {- "cbor": "YWE=",- "hex": "6161",- "roundtrip": true,- "decoded": "a"- },- {- "cbor": "ZElFVEY=",- "hex": "6449455446",- "roundtrip": true,- "decoded": "IETF"- },- {- "cbor": "YiJc",- "hex": "62225c",- "roundtrip": true,- "decoded": "\"\\"- },- {- "cbor": "YsO8",- "hex": "62c3bc",- "roundtrip": true,- "decoded": "ü"- },- {- "cbor": "Y+awtA==",- "hex": "63e6b0b4",- "roundtrip": true,- "decoded": "水"- },- {- "cbor": "ZPCQhZE=",- "hex": "64f0908591",- "roundtrip": true,- "decoded": "𐅑"- },- {- "cbor": "gA==",- "hex": "80",- "roundtrip": true,- "decoded": [-- ]- },- {- "cbor": "gwECAw==",- "hex": "83010203",- "roundtrip": true,- "decoded": [- 1,- 2,- 3- ]- },- {- "cbor": "gwGCAgOCBAU=",- "hex": "8301820203820405",- "roundtrip": true,- "decoded": [- 1,- [- 2,- 3- ],- [- 4,- 5- ]- ]- },- {- "cbor": "mBkBAgMEBQYHCAkKCwwNDg8QERITFBUWFxgYGBk=",- "hex": "98190102030405060708090a0b0c0d0e0f101112131415161718181819",- "roundtrip": true,- "decoded": [- 1,- 2,- 3,- 4,- 5,- 6,- 7,- 8,- 9,- 10,- 11,- 12,- 13,- 14,- 15,- 16,- 17,- 18,- 19,- 20,- 21,- 22,- 23,- 24,- 25- ]- },- {- "cbor": "oA==",- "hex": "a0",- "roundtrip": true,- "decoded": {- }- },- {- "cbor": "ogECAwQ=",- "hex": "a201020304",- "roundtrip": true,- "diagnostic": "{1: 2, 3: 4}"- },- {- "cbor": "omFhAWFiggID",- "hex": "a26161016162820203",- "roundtrip": true,- "decoded": {- "a": 1,- "b": [- 2,- 3- ]- }- },- {- "cbor": "gmFhoWFiYWM=",- "hex": "826161a161626163",- "roundtrip": true,- "decoded": [- "a",- {- "b": "c"- }- ]- },- {- "cbor": "pWFhYUFhYmFCYWNhQ2FkYURhZWFF",- "hex": "a56161614161626142616361436164614461656145",- "roundtrip": true,- "decoded": {- "a": "A",- "b": "B",- "c": "C",- "d": "D",- "e": "E"- }- },- {- "cbor": "X0IBAkMDBAX/",- "hex": "5f42010243030405ff",- "roundtrip": false,- "diagnostic": "(_ h'0102', h'030405')"- },- {- "cbor": "f2VzdHJlYWRtaW5n/w==",- "hex": "7f657374726561646d696e67ff",- "roundtrip": false,- "decoded": "streaming"- },- {- "cbor": "n/8=",- "hex": "9fff",- "roundtrip": false,- "decoded": [-- ]- },- {- "cbor": "nwGCAgOfBAX//w==",- "hex": "9f018202039f0405ffff",- "roundtrip": false,- "decoded": [- 1,- [- 2,- 3- ],- [- 4,- 5- ]- ]- },- {- "cbor": "nwGCAgOCBAX/",- "hex": "9f01820203820405ff",- "roundtrip": false,- "decoded": [- 1,- [- 2,- 3- ],- [- 4,- 5- ]- ]- },- {- "cbor": "gwGCAgOfBAX/",- "hex": "83018202039f0405ff",- "roundtrip": false,- "decoded": [- 1,- [- 2,- 3- ],- [- 4,- 5- ]- ]- },- {- "cbor": "gwGfAgP/ggQF",- "hex": "83019f0203ff820405",- "roundtrip": false,- "decoded": [- 1,- [- 2,- 3- ],- [- 4,- 5- ]- ]- },- {- "cbor": "nwECAwQFBgcICQoLDA0ODxAREhMUFRYXGBgYGf8=",- "hex": "9f0102030405060708090a0b0c0d0e0f101112131415161718181819ff",- "roundtrip": false,- "decoded": [- 1,- 2,- 3,- 4,- 5,- 6,- 7,- 8,- 9,- 10,- 11,- 12,- 13,- 14,- 15,- 16,- 17,- 18,- 19,- 20,- 21,- 22,- 23,- 24,- 25- ]- },- {- "cbor": "v2FhAWFinwID//8=",- "hex": "bf61610161629f0203ffff",- "roundtrip": false,- "decoded": {- "a": 1,- "b": [- 2,- 3- ]- }- },- {- "cbor": "gmFhv2FiYWP/",- "hex": "826161bf61626163ff",- "roundtrip": false,- "decoded": [- "a",- {- "b": "c"- }- ]- },- {- "cbor": "v2NGdW71Y0FtdCH/",- "hex": "bf6346756ef563416d7421ff",- "roundtrip": false,- "decoded": {- "Fun": true,- "Amt": -2- }- }-]