Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 35 additions & 24 deletions src/Data/Binary/Class.hs
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@
{-# LANGUAGE DefaultSignatures #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE InstanceSigs #-}
{-# LANGUAGE MultiWayIf #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE PatternGuards #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE Trustworthy #-}

Check warning on line 10 in src/Data/Binary/Class.hs

View workflow job for this annotation

GitHub Actions / build (8.0.2)

‘Data.Binary.Class’ is marked as Trustworthy but has been inferred as safe!

Check warning on line 10 in src/Data/Binary/Class.hs

View workflow job for this annotation

GitHub Actions / build (8.0.2)

‘Data.Binary.Class’ is marked as Trustworthy but has been inferred as safe!

#if MIN_VERSION_base(4,10,0)
{-# LANGUAGE MultiWayIf #-}
Expand Down Expand Up @@ -57,6 +58,7 @@
import Prelude hiding (Foldable(..))
import Data.Foldable (Foldable(..))

import Data.Char (chr)
import Data.Word
import Data.Bits
import Data.Int
Expand Down Expand Up @@ -499,35 +501,44 @@

------------------------------------------------------------------------

-- Char is serialised as UTF-8
-- | Uses WTF-8 (like UTF-8, but surrogates are allowed).
instance Binary Char where
put = putCharUtf8
putList str = put (length str) <> putStringUtf8 str
get = do
let getByte = liftM (fromIntegral :: Word8 -> Int) get
shiftL6 = flip shiftL 6 :: Int -> Int
w <- getByte
r <- case () of
_ | w < 0x80 -> return w
| w < 0xe0 -> do
x <- liftM (xor 0x80) getByte
return (x .|. shiftL6 (xor 0xc0 w))
| w < 0xf0 -> do
x <- liftM (xor 0x80) getByte
y <- liftM (xor 0x80) getByte
return (y .|. shiftL6 (x .|. shiftL6
(xor 0xe0 w)))
| otherwise -> do
x <- liftM (xor 0x80) getByte
y <- liftM (xor 0x80) getByte
z <- liftM (xor 0x80) getByte
return (z .|. shiftL6 (y .|. shiftL6
(x .|. shiftL6 (xor 0xf0 w))))
getChr r
w <- fmap fromIntegral getWord8
if
| w < 0x80 -> getChr w
| w < 0xc2 -> invalid -- continuation byte or overlong encoding
| w < 0xe0 -> do
x <- getWord8 >>= continuationByte
getChr ((x .&. 0x3f) .|. ((w .&. 0x1f) `shiftL` 6))
| w < 0xf0 -> do
x <- getWord8 >>= continuationByte
when (w == 0xe0 && x < 0xa0) invalid -- overlong encoding
y <- getWord8 >>= continuationByte
getChr ((y .&. 0x3f) .|. ((x .&. 0x3f) `shiftL` 6) .|. ((w .&. 0x0f) `shiftL` 12))
| w < 0xf5 -> do
x <- getWord8 >>= continuationByte
when (w == 0xf0 && x < 0x90) invalid -- overlong encoding
when (w == 0xf4 && x > 0x8f) invalid -- outside of Unicode range
y <- getWord8 >>= continuationByte
z <- getWord8 >>= continuationByte
getChr ((z .&. 0x3f) .|. ((y .&. 0x3f) `shiftL` 6) .|. ((x .&. 0x3f) `shiftL` 12) .|. ((w .&. 0x07) `shiftL` 18))
| otherwise -> invalid
where
getChr w
| w <= 0x10ffff = return $! toEnum $ fromEnum w
| otherwise = fail "Not a valid Unicode code point!"
invalid :: Get a
invalid = fail "invalid Char encoding"

continuationByte :: Word8 -> Get Int
continuationByte x =
let x' = x .&. 0xc0
in if x' == 0x80
then pure (fromIntegral x)
else invalid -- no continuation byte

getChr :: Int -> Get Char
getChr i = pure $! chr i

------------------------------------------------------------------------
-- Instances for the first few tuples
Expand Down Expand Up @@ -844,9 +855,9 @@

#if __GLASGOW_HASKELL__ < 901
-- | @since 0.8.4.0
instance Binary a => Binary (Semigroup.Option a) where

Check warning on line 858 in src/Data/Binary/Class.hs

View workflow job for this annotation

GitHub Actions / build (9.0.2)

In the use of type constructor or class ‘Option’

Check warning on line 858 in src/Data/Binary/Class.hs

View workflow job for this annotation

GitHub Actions / build (9.0.2)

In the use of type constructor or class ‘Option’
get = fmap Semigroup.Option get

Check warning on line 859 in src/Data/Binary/Class.hs

View workflow job for this annotation

GitHub Actions / build (9.0.2)

In the use of data constructor ‘Option’

Check warning on line 859 in src/Data/Binary/Class.hs

View workflow job for this annotation

GitHub Actions / build (9.0.2)

In the use of data constructor ‘Option’
put = put . Semigroup.getOption

Check warning on line 860 in src/Data/Binary/Class.hs

View workflow job for this annotation

GitHub Actions / build (9.0.2)

In the use of ‘getOption’ (imported from Data.Semigroup):

Check warning on line 860 in src/Data/Binary/Class.hs

View workflow job for this annotation

GitHub Actions / build (9.0.2)

In the use of ‘getOption’ (imported from Data.Semigroup):
#endif

-- | @since 0.8.4.0
Expand Down
10 changes: 9 additions & 1 deletion tests/QC.hs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
import Data.ByteString.Short (ShortByteString)
import Data.Int
import Data.Ratio
import Data.Typeable

Check warning on line 22 in tests/QC.hs

View workflow job for this annotation

GitHub Actions / build (8.0.2)

The import of ‘Data.Typeable’ is redundant
import Data.Word
import System.IO.Unsafe

Expand All @@ -29,7 +29,7 @@
import Numeric.Natural
#endif

import GHC.Exts (Array#, Word#)

Check warning on line 32 in tests/QC.hs

View workflow job for this annotation

GitHub Actions / build (8.0.2)

The import of ‘GHC.Exts’ is redundant
import GHC.Fingerprint
import GHC.Generics (Generic)

Expand Down Expand Up @@ -187,7 +187,7 @@
, typeRep (Proxy :: Proxy (Array# Int))
]

instance Arbitrary TypeRep where

Check warning on line 190 in tests/QC.hs

View workflow job for this annotation

GitHub Actions / build (8.4.4)

Orphan instance: instance Arbitrary TypeRep

Check warning on line 190 in tests/QC.hs

View workflow job for this annotation

GitHub Actions / build (9.10.3)

Orphan class instance: instance Arbitrary TypeRep

Check warning on line 190 in tests/QC.hs

View workflow job for this annotation

GitHub Actions / build (8.8.4)

Orphan instance: instance Arbitrary TypeRep

Check warning on line 190 in tests/QC.hs

View workflow job for this annotation

GitHub Actions / build (8.10.7)

Orphan instance: instance Arbitrary TypeRep

Check warning on line 190 in tests/QC.hs

View workflow job for this annotation

GitHub Actions / build (9.6.7)

Orphan instance: instance Arbitrary TypeRep

Check warning on line 190 in tests/QC.hs

View workflow job for this annotation

GitHub Actions / build (8.2.2)

Orphan instance: instance Arbitrary TypeRep

Check warning on line 190 in tests/QC.hs

View workflow job for this annotation

GitHub Actions / build (8.6.5)

Orphan instance: instance Arbitrary TypeRep

Check warning on line 190 in tests/QC.hs

View workflow job for this annotation

GitHub Actions / build (9.0.2)

Orphan instance: instance Arbitrary TypeRep

Check warning on line 190 in tests/QC.hs

View workflow job for this annotation

GitHub Actions / build (9.8.4)

Orphan class instance: instance Arbitrary TypeRep

Check warning on line 190 in tests/QC.hs

View workflow job for this annotation

GitHub Actions / build (9.12.2)

Orphan class instance: instance Arbitrary TypeRep

Check warning on line 190 in tests/QC.hs

View workflow job for this annotation

GitHub Actions / build (9.4.8)

Orphan instance: instance Arbitrary TypeRep

Check warning on line 190 in tests/QC.hs

View workflow job for this annotation

GitHub Actions / build (9.2.8)

Orphan instance: instance Arbitrary TypeRep

Check warning on line 190 in tests/QC.hs

View workflow job for this annotation

GitHub Actions / build (9.14.1)

Orphan class instance: instance Arbitrary TypeRep
arbitrary = elements atomicTypeReps
#else
testTypeable :: Test
Expand Down Expand Up @@ -742,6 +742,14 @@
, testTypeable

, testGroup "Generic"
[ testProperty "Generic256" $ prop_Generic256
[ testProperty "Generic256" prop_Generic256
]

, testGroup "Char"
[ testProperty "encodings are unique" $
withMaxSize 4 $ \bs ->
case runGetOrFail (get :: Get Char) bs of
Left _ -> discard
Right (_, n, x) -> runPut (put x) === L.take n bs
]
]
Loading