base16 0.1.2.1 → 0.1.3.0
raw patch · 10 files changed
+393/−102 lines, 10 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
+ Data.ByteString.Lazy.Base16: decodeBase16 :: ByteString -> Either Text ByteString
+ Data.ByteString.Lazy.Base16: encodeBase16 :: ByteString -> Text
+ Data.ByteString.Lazy.Base16: encodeBase16' :: ByteString -> ByteString
+ Data.ByteString.Lazy.Base16: isBase16 :: ByteString -> Bool
+ Data.ByteString.Lazy.Base16: isValidBase16 :: ByteString -> Bool
+ Data.Text.Lazy.Encoding.Base16: decodeBase16 :: Text -> Either Text Text
+ Data.Text.Lazy.Encoding.Base16: encodeBase16 :: Text -> Text
+ Data.Text.Lazy.Encoding.Base16: isBase16 :: Text -> Bool
+ Data.Text.Lazy.Encoding.Base16: isValidBase16 :: Text -> Bool
Files
- base16.cabal +3/−2
- benchmarks/Base16Bench.hs +39/−29
- src/Data/ByteString/Base16.hs +35/−5
- src/Data/ByteString/Base16/Internal.hs +0/−46
- src/Data/ByteString/Base16/Internal/W32/Loop.hs +3/−1
- src/Data/ByteString/Base16/Internal/W64/Loop.hs +3/−2
- src/Data/ByteString/Lazy/Base16.hs +104/−0
- src/Data/Text/Encoding/Base16.hs +30/−1
- src/Data/Text/Lazy/Encoding/Base16.hs +87/−0
- test/Base16Tests.hs +89/−16
base16.cabal view
@@ -1,6 +1,6 @@ cabal-version: 2.0 name: base16-version: 0.1.2.1+version: 0.1.3.0 synopsis: RFC 4648-compliant Base16 encodings/decodings description: RFC 4648-compliant Base16 encodings and decodings.@@ -29,10 +29,11 @@ library exposed-modules: Data.ByteString.Base16+ Data.ByteString.Lazy.Base16 Data.Text.Encoding.Base16+ Data.Text.Lazy.Encoding.Base16 other-modules:- Data.ByteString.Base16.Internal Data.ByteString.Base16.Internal.Head Data.ByteString.Base16.Internal.Tables Data.ByteString.Base16.Internal.Utils
benchmarks/Base16Bench.hs view
@@ -7,80 +7,81 @@ import Criterion import Criterion.Main +import Data.ByteString.Lazy (fromStrict) import "memory" Data.ByteArray.Encoding as Mem import Data.ByteString-import "base16" Data.ByteString.Base16 as B16-import "base16-bytestring" Data.ByteString.Base16 as Bos+import "base16" Data.ByteString.Lazy.Base16 as B16+import "base16-bytestring" Data.ByteString.Base16.Lazy as Bos import Data.ByteString.Random (random) main :: IO () main = defaultMain- [ env bs $ \ ~(bs25,bs100,bs1k,bs10k,bs100k,bs1mm) ->+ [ env bs $ \ ~((bs25,bs100,bs1k,bs10k,bs100k,bs1mm),(bs25L,bs100L,bs1kL,bs10kL,bs100kL,bs1mmL)) -> bgroup "encode" [ bgroup "25" [ bench "memory" $ whnf ctob bs25- , bench "base16-bytestring" $ whnf Bos.encode bs25- , bench "base16" $ whnf B16.encodeBase16' bs25+ , bench "base16-bytestring" $ whnf Bos.encode bs25L+ , bench "base16" $ whnf B16.encodeBase16' bs25L ] , bgroup "100" [ bench "memory" $ whnf ctob bs100- , bench "base16-bytestring" $ whnf Bos.encode bs100- , bench "base16" $ whnf B16.encodeBase16' bs100+ , bench "base16-bytestring" $ whnf Bos.encode bs100L+ , bench "base16" $ whnf B16.encodeBase16' bs100L ] , bgroup "1k" [ bench "memory" $ whnf ctob bs1k- , bench "base16-bytestring" $ whnf Bos.encode bs1k- , bench "base16" $ whnf B16.encodeBase16' bs1k+ , bench "base16-bytestring" $ whnf Bos.encode bs1kL+ , bench "base16" $ whnf B16.encodeBase16' bs1kL ] , bgroup "10k" [ bench "memory" $ whnf ctob bs10k- , bench "base16-bytestring" $ whnf Bos.encode bs10k- , bench "base16" $ whnf B16.encodeBase16' bs10k+ , bench "base16-bytestring" $ whnf Bos.encode bs10kL+ , bench "base16" $ whnf B16.encodeBase16' bs10kL ] , bgroup "100k" [ bench "memory" $ whnf ctob bs100k- , bench "base16-bytestring" $ whnf Bos.encode bs100k- , bench "base16" $ whnf B16.encodeBase16' bs100k+ , bench "base16-bytestring" $ whnf Bos.encode bs100kL+ , bench "base16" $ whnf B16.encodeBase16' bs100kL ] , bgroup "1mm" [ bench "memory" $ whnf ctob bs1mm- , bench "base16-bytestring" $ whnf Bos.encode bs1mm- , bench "base16" $ whnf B16.encodeBase16' bs1mm+ , bench "base16-bytestring" $ whnf Bos.encode bs1mmL+ , bench "base16" $ whnf B16.encodeBase16' bs1mmL ] ]- , env bs $ \ ~(bs25,bs100,bs1k,bs10k,bs100k,bs1mm) ->+ , env bs' $ \ ~((bs25,bs100,bs1k,bs10k,bs100k,bs1mm),(bs25L,bs100L,bs1kL,bs10kL,bs100kL,bs1mmL)) -> bgroup "decode" [ bgroup "25" [ bench "memory" $ whnf cfob bs25- , bench "base16-bytestring" $ whnf Bos.decode bs25- , bench "base16" $ whnf B16.decodeBase16 bs25+ , bench "base16-bytestring" $ whnf Bos.decode bs25L+ , bench "base16" $ whnf B16.decodeBase16 bs25L ] , bgroup "100" [ bench "memory" $ whnf cfob bs100- , bench "base16-bytestring" $ whnf Bos.decode bs100- , bench "base16" $ whnf B16.decodeBase16 bs100+ , bench "base16-bytestring" $ whnf Bos.decode bs100L+ , bench "base16" $ whnf B16.decodeBase16 bs100L ] , bgroup "1k" [ bench "memory" $ whnf cfob bs1k- , bench "base16-bytestring" $ whnf Bos.decode bs1k- , bench "base16" $ whnf B16.decodeBase16 bs1k+ , bench "base16-bytestring" $ whnf Bos.decode bs1kL+ , bench "base16" $ whnf B16.decodeBase16 bs1kL ] , bgroup "10k" [ bench "memory" $ whnf cfob bs10k- , bench "base16-bytestring" $ whnf Bos.decode bs10k- , bench "base16" $ whnf B16.decodeBase16 bs10k+ , bench "base16-bytestring" $ whnf Bos.decode bs10kL+ , bench "base16" $ whnf B16.decodeBase16 bs10kL ] , bgroup "100k" [ bench "memory" $ whnf cfob bs100k- , bench "base16-bytestring" $ whnf Bos.decode bs100k- , bench "base16" $ whnf B16.decodeBase16 bs100k+ , bench "base16-bytestring" $ whnf Bos.decode bs100kL+ , bench "base16" $ whnf B16.decodeBase16 bs100kL ] , bgroup "1mm" [ bench "memory" $ whnf cfob bs1mm- , bench "base16-bytestring" $ whnf Bos.decode bs1mm- , bench "base16" $ whnf B16.decodeBase16 bs1mm+ , bench "base16-bytestring" $ whnf Bos.decode bs1mmL+ , bench "base16" $ whnf B16.decodeBase16 bs1mmL ] ] ]@@ -98,4 +99,13 @@ d <- random 10000 e <- random 100000 f <- random 1000000- return (a,b,c,d,e,f)+ return ((a,b,c,d,e,f),(fromStrict a,fromStrict b,fromStrict c,fromStrict d,fromStrict e,fromStrict f))++ bs' = do+ a <- ctob <$> random 25+ b <- ctob <$> random 100+ c <- ctob <$> random 1000+ d <- ctob <$> random 10000+ e <- ctob <$> random 100000+ f <- ctob <$> random 1000000+ return ((a,b,c,d,e,f),(fromStrict a,fromStrict b,fromStrict c,fromStrict d,fromStrict e,fromStrict f))
src/Data/ByteString/Base16.hs view
@@ -12,7 +12,7 @@ -- -- This module contains the combinators implementing the -- RFC 4648 specification for the Base16 encoding including--- unpadded and lenient variants+-- unpadded and lenient variants for bytestrings -- module Data.ByteString.Base16 ( encodeBase16@@ -23,8 +23,9 @@ ) where -import Data.ByteString (ByteString)-import Data.ByteString.Base16.Internal+import Prelude hiding (all, elem)++import Data.ByteString (ByteString, all, elem) import Data.ByteString.Base16.Internal.Head import Data.Either import Data.Text (Text)@@ -57,6 +58,20 @@ -- | Tell whether a 'ByteString' value is base16 encoded. --+-- Examples:+--+-- This example will fail. It conforms to the alphabet, but+-- is not valid because it has an incorrect (odd) length.+--+-- >>> isBase16 "666f6"+-- False+--+-- This example will succeed because it satisfies the alphabet+-- and is considered "valid" (i.e. of the correct size and shape).+--+-- >>> isBase16 "666f"+-- True+-- isBase16 :: ByteString -> Bool isBase16 bs = isValidBase16 bs && isRight (decodeBase16 bs) {-# INLINE isBase16 #-}@@ -64,9 +79,24 @@ -- | Tell whether a 'ByteString' value is a valid Base16 format. -- -- This will not tell you whether or not this is a correct Base16 representation,--- only that it conforms to the correct shape. To check whether it is a true+-- only that it conforms to the correct alphabet. To check whether it is a true -- Base16 encoded 'ByteString' value, use 'isBase16'. --+-- Examples:+--+-- This example will fail because it does not conform to the Hex+-- alphabet.+--+-- >>> isValidBase16 "666f+/6"+-- False+--+-- This example will succeed because it satisfies the alphabet+-- and is considered "valid" (i.e. of the correct size and shape), but+-- is not correct base16 because it is the wrong shape.+--+-- >>> isValidBase16 "666f6"+-- True+-- isValidBase16 :: ByteString -> Bool-isValidBase16 = validateBase16 "0123456789abcdef"+isValidBase16 = all (flip elem "0123456789abcdef") {-# INLINE isValidBase16 #-}
− src/Data/ByteString/Base16/Internal.hs
@@ -1,46 +0,0 @@-{-# LANGUAGE BangPatterns #-}-{-# LANGUAGE CPP #-}-{-# LANGUAGE MagicHash #-}-{-# LANGUAGE MultiWayIf #-}-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE TypeApplications #-}--- |--- Module : Data.ByteString.Base16.Internal--- Copyright : (c) 2020 Emily Pillmore--- License : BSD-style------ Maintainer : Emily Pillmore <emilypi@cohomolo.gy>--- Stability : Experimental--- Portability : portable------ Internal module defining the encoding and decoding--- processes and tables.----module Data.ByteString.Base16.Internal-( validateBase16-) where---import qualified Data.ByteString as BS-import Data.ByteString.Internal--import Foreign.ForeignPtr-import Foreign.Ptr-import Foreign.Storable---- -------------------------------------------------------------------------- ----- Validating Base16--validateBase16 :: ByteString -> ByteString -> Bool-validateBase16 !alphabet (PS fp off l) =- accursedUnutterablePerformIO $ withForeignPtr fp $ \p ->- go (plusPtr p off) (plusPtr p (l + off))- where- go !p !end- | p == end = return True- | otherwise = do- w <- peek p- if BS.elem w alphabet- then go (plusPtr p 1) end- else return False-{-# INLINE validateBase16 #-}
src/Data/ByteString/Base16/Internal/W32/Loop.hs view
@@ -118,8 +118,9 @@ ++ show (src `minusPtr` sptr) else do poke @Word8 dst (a .|. b)- go (plusPtr dst 1) (plusPtr src 2) (n + 1)+ return (Right (PS dfp 0 (n + 1))) + go !dst !src !n | plusPtr src 3 >= end = tailRound16 (castPtr dst) (castPtr src) n | otherwise = do@@ -148,3 +149,4 @@ | otherwise -> do poke @Word16 dst zz go (plusPtr dst 2) (plusPtr src 4) (n + 2)+{-# INLINE decodeLoop #-}
src/Data/ByteString/Base16/Internal/W64/Loop.hs view
@@ -160,7 +160,7 @@ | b == 0xff -> err (plusPtr src 1) | otherwise -> do poke dst (a .|. b)- go (plusPtr dst 1) (plusPtr src 2) (n + 1)+ return (Right (PS dfp 0 (n + 1))) tailRound32 !dst !src !n | plusPtr src 3 >= end = tailRound16 (castPtr dst) (castPtr src) n@@ -190,7 +190,7 @@ | d == 0xff -> err (plusPtr src 3) | otherwise -> do poke @Word16 dst zz- go (plusPtr dst 2) (plusPtr src 4) (n + 2)+ tailRound16 (plusPtr dst 2) (plusPtr src 4) (n + 2) go !dst !src !n | plusPtr src 7 >= end = tailRound32 (castPtr dst) (castPtr src) n@@ -235,3 +235,4 @@ | otherwise -> do poke @Word32 dst zz go (plusPtr dst 4) (plusPtr src 8) (n + 4)+{-# INLINE decodeLoop #-}
+ src/Data/ByteString/Lazy/Base16.hs view
@@ -0,0 +1,104 @@+{-# LANGUAGE OverloadedStrings #-}+-- |+-- Module : Data.ByteString.Base16.Lazy+-- Copyright : (c) 2020 Emily Pillmore+-- License : BSD-style+--+-- Maintainer : Emily Pillmore <emilypi@cohomolo.gy>+-- Stability : Experimental+-- Portability : portable+--+-- This module contains the combinators implementing the+-- RFC 4648 specification for the Base16 encoding including+-- unpadded and lenient variants for lazy bytestrings+--+module Data.ByteString.Lazy.Base16+( encodeBase16+, encodeBase16'+, decodeBase16+, isBase16+, isValidBase16+) where+++import Prelude hiding (all, elem)++import Data.ByteString.Lazy (all, elem)+import Data.ByteString.Lazy.Internal (ByteString(..))+import qualified Data.ByteString.Base16.Internal.Head as B16+import Data.Either+import qualified Data.Text as T+import Data.Text.Lazy (Text)+import qualified Data.Text.Lazy.Encoding as TL+++-- | Encode a lazy 'ByteString' value as Base16 'Text' with padding.+--+-- See: <https://tools.ietf.org/html/rfc4648#section-8 RFC-4648 section 8>+--+encodeBase16 :: ByteString -> Text+encodeBase16 = TL.decodeUtf8 . encodeBase16'+{-# INLINE encodeBase16 #-}++-- | Encode a lazy 'ByteString' value as a Base16 'ByteString' value with padding.+--+-- See: <https://tools.ietf.org/html/rfc4648#section-8 RFC-4648 section 8>+--+encodeBase16' :: ByteString -> ByteString+encodeBase16' Empty = Empty+encodeBase16' (Chunk b bs) = Chunk (B16.encodeBase16_ b) (encodeBase16' bs)+{-# INLINE encodeBase16' #-}++-- | Decode a padded Base16-encoded lazy 'ByteString' value.+--+-- See: <https://tools.ietf.org/html/rfc4648#section-8 RFC-4648 section 8>+--+decodeBase16 :: ByteString -> Either T.Text ByteString+decodeBase16 Empty = Right Empty+decodeBase16 (Chunk b bs) = Chunk <$> B16.decodeBase16_ b <*> decodeBase16 bs+{-# INLINE decodeBase16 #-}++-- | Tell whether a lazy 'ByteString' value is base16 encoded.+--+-- Examples:+--+-- This example will fail. It conforms to the alphabet, but+-- is not valid because it has an incorrect (odd) length.+--+-- >>> isBase16 "666f6"+-- False+--+-- This example will succeed because it satisfies the alphabet+-- and is considered "valid" (i.e. of the correct size and shape).+--+-- >>> isBase16 "666f"+-- True+--+isBase16 :: ByteString -> Bool+isBase16 bs = isValidBase16 bs && isRight (decodeBase16 bs)+{-# INLINE isBase16 #-}++-- | Tell whether a lazy 'ByteString' value is a valid Base16 format.+--+-- This will not tell you whether or not this is a correct Base16 representation,+-- only that it conforms to the correct alphabet. To check whether it is a true+-- Base16 encoded 'ByteString' value, use 'isBase16'.+--+-- Examples:+--+-- This example will fail because it does not conform to the Hex+-- alphabet.+--+-- >>> isValidBase16 "666f+/6"+-- False+--+-- This example will succeed because it satisfies the alphabet+-- and is considered "valid" (i.e. of the correct size and shape), but+-- is not correct base16 because it is the wrong shape.+--+-- >>> isValidBase16 "666f6"+-- True+--+isValidBase16 :: ByteString -> Bool+isValidBase16 = all (flip elem "0123456789abcdef")+{-# INLINE isValidBase16 #-}
src/Data/Text/Encoding/Base16.hs view
@@ -9,7 +9,7 @@ -- -- This module contains the combinators implementing the -- RFC 4648 specification for the Base16 encoding including--- unpadded and lenient variants+-- unpadded and lenient variants for text values -- module Data.Text.Encoding.Base16 ( encodeBase16@@ -42,6 +42,20 @@ -- | Tell whether a 'Text' value is Base16-encoded. --+-- Examples:+--+-- This example will fail. It conforms to the alphabet, but+-- is not valid because it has an incorrect (odd) length.+--+-- >>> isBase16 "666f6"+-- False+--+-- This example will succeed because it satisfies the alphabet+-- and is considered "valid" (i.e. of the correct size and shape).+--+-- >>> isBase16 "666f"+-- True+-- isBase16 :: Text -> Bool isBase16 = B16.isBase16 . T.encodeUtf8 {-# INLINE isBase16 #-}@@ -51,6 +65,21 @@ -- This will not tell you whether or not this is a correct Base16 representation, -- only that it conforms to the correct shape. To check whether it is a true -- Base16 encoded 'Text' value, use 'isBase16'.+--+-- Examples:+--+-- This example will fail because it does not conform to the Hex+-- alphabet.+--+-- >>> isValidBase16 "666f+/6"+-- False+--+-- This example will succeed because it satisfies the alphabet+-- and is considered "valid" (i.e. of the correct size and shape), but+-- is not correct base16 because it is the wrong shape.+--+-- >>> isValidBase16 "666f6"+-- True -- isValidBase16 :: Text -> Bool isValidBase16 = B16.isValidBase16 . T.encodeUtf8
+ src/Data/Text/Lazy/Encoding/Base16.hs view
@@ -0,0 +1,87 @@+-- |+-- Module : Data.Text.Encoding.Base16.Lazy+-- Copyright : (c) 2019 Emily Pillmore+-- License : BSD-style+--+-- Maintainer : Emily Pillmore <emilypi@cohomolo.gy>+-- Stability : Experimental+-- Portability : portable+--+-- This module contains the combinators implementing the+-- RFC 4648 specification for the Base16 encoding including+-- unpadded and lenient variants for lazy textual values+--+module Data.Text.Lazy.Encoding.Base16+( encodeBase16+, decodeBase16+, isBase16+, isValidBase16+) where+++import qualified Data.ByteString.Lazy.Base16 as B16L++import qualified Data.Text as T+import Data.Text.Lazy (Text)+import qualified Data.Text.Lazy.Encoding as TL++-- | Encode a lazy 'Text' value in Base16 with padding.+--+-- See: <https://tools.ietf.org/html/rfc4648#section-8 RFC-4648 section 8>+--+encodeBase16 :: Text -> Text+encodeBase16 = B16L.encodeBase16 . TL.encodeUtf8+{-# INLINE encodeBase16 #-}++-- | Decode a padded Base16-encoded lazy 'Text' value+--+-- See: <https://tools.ietf.org/html/rfc4648#section-8 RFC-4648 section 8>+--+decodeBase16 :: Text -> Either T.Text Text+decodeBase16 = fmap TL.decodeUtf8 . B16L.decodeBase16 . TL.encodeUtf8+{-# INLINE decodeBase16 #-}++-- | Tell whether a lazy 'Text' value is Base16-encoded.+--+-- Examples:+--+-- This example will fail. It conforms to the alphabet, but+-- is not valid because it has an incorrect (odd) length.+--+-- >>> isBase16 "666f6"+-- False+--+-- This example will succeed because it satisfies the alphabet+-- and is considered "valid" (i.e. of the correct size and shape).+--+-- >>> isBase16 "666f"+-- True+--+isBase16 :: Text -> Bool+isBase16 = B16L.isBase16 . TL.encodeUtf8+{-# INLINE isBase16 #-}++-- | Tell whether a lazy 'Text' value is a valid Base16 format.+--+-- This will not tell you whether or not this is a correct Base16 representation,+-- only that it conforms to the correct shape. To check whether it is a true+-- Base16 encoded 'Text' value, use 'isBase16'.+--+-- Examples:+--+-- This example will fail because it does not conform to the Hex+-- alphabet.+--+-- >>> isValidBase16 "666f+/6"+-- False+--+-- This example will succeed because it satisfies the alphabet+-- and is considered "valid" (i.e. of the correct size and shape), but+-- is not correct base16 because it is the wrong shape.+--+-- >>> isValidBase16 "666f6"+-- True+--+isValidBase16 :: Text -> Bool+isValidBase16 = B16L.isValidBase16 . TL.encodeUtf8+{-# INLINE isValidBase16 #-}
test/Base16Tests.hs view
@@ -9,7 +9,9 @@ import Data.Bifunctor import Data.ByteString (ByteString)+import Data.ByteString.Lazy (fromStrict) import "base16" Data.ByteString.Base16 as B16+import "base16" Data.ByteString.Lazy.Base16 as B16L import "memory" Data.ByteArray.Encoding as Mem import Data.ByteString.Random (random) import Data.Functor (void)@@ -32,7 +34,7 @@ testVectors :: TestTree testVectors = testGroup "RFC 4648 Test Vectors"- [ testGroup "encode/decode"+ [ testGroup "strict encode/decode" [ testCaseB16 "" "" , testCaseB16 "f" "66" , testCaseB16 "fo" "666f"@@ -41,6 +43,15 @@ , testCaseB16 "fooba" "666f6f6261" , testCaseB16 "foobar" "666f6f626172" ]+ , testGroup "lazy encode/decode"+ [ testCaseB16L "" ""+ , testCaseB16L "f" "66"+ , testCaseB16L "fo" "666f"+ , testCaseB16L "foo" "666f6f"+ , testCaseB16L "foob" "666f6f62"+ , testCaseB16L "fooba" "666f6f6261"+ , testCaseB16L "foobar" "666f6f626172"+ ] ] where testCaseB16 s t =@@ -54,53 +65,115 @@ step "compare decoding" Right s @=? s' + testCaseB16L s t =+ testCaseSteps (show $ if s == "" then "empty" else s) $ \step -> do+ let t' = B16L.encodeBase16' s+ s' = B16L.decodeBase16 t'++ step "compare encoding"+ t @=? t'++ step "compare decoding"+ Right s @=? s'+ sanityTests :: TestTree sanityTests = testGroup "Sanity tests"- [ testGroup "very large bytestrings don't segfault"+ [ testGroup "strict"+ [ testGroup "very large bytestrings don't segfault" [ chonk ]- , testGroup "`memory` sanity checks"- [ compare32 3- , compare32 4- , compare32 5- , compare32 6- , compare32 1000- , compare32 100000+ , testGroup "`memory` sanity checks"+ [ compare 3+ , compare 4+ , compare 5+ , compare 6+ , compare 1000+ , compare 100000 ]- , testGroup "roundtrip encode/decode"+ , testGroup "roundtrip encode/decode" [ roundtrip 3 , roundtrip 4 , roundtrip 5 , roundtrip 1000 , roundtrip 100000 ]+ ]+ , testGroup "lazy"+ [ testGroup "very large bytestrings don't segfault"+ [ chonkL+ ]+ , testGroup "`memory` sanity checks"+ [ compareL 3+ , compareL 4+ , compareL 5+ , compareL 6+ , compareL 1000+ , compareL 100000+ ]+ , testGroup "roundtrip encode/decode"+ [ roundtripL 3+ , roundtripL 4+ , roundtripL 5+ , roundtripL 1000+ , roundtripL 100000+ ]+ ] ] where chonk = testCase ("Encoding huge bytestrings doesn't result in OOM or segfault") $ do bs <- random 1000000 void $ return $ B16.encodeBase16' bs - compare32 n = testCase ("Testing " ++ show n ++ "-sized bytestrings") $ do+ chonkL = testCase ("Encoding huge bytestrings doesn't result in OOM or segfault") $ do+ bs <- fromStrict <$> random 1000000+ void $ return $ B16L.encodeBase16' bs++ compare n = testCase ("Testing " ++ show n ++ "-sized bytestrings") $ do bs <- random n B16.encodeBase16' bs @=? Mem.convertToBase Mem.Base16 bs B16.decodeBase16 (B16.encodeBase16' bs) @=? first pack (Mem.convertFromBase @ByteString Mem.Base16 (Mem.convertToBase Mem.Base16 bs)) + compareL n = testCase ("Testing " ++ show n ++ "-sized bytestrings") $ do+ bs <- random n+ B16L.encodeBase16' (fromStrict bs) @=? fromStrict (Mem.convertToBase Mem.Base16 bs)++ B16L.decodeBase16 (B16L.encodeBase16' (fromStrict bs)) @=?+ bimap pack fromStrict (Mem.convertFromBase @ByteString Mem.Base16 (Mem.convertToBase Mem.Base16 bs))+ roundtrip n = testCase ("Roundtrip encode/decode for " ++ show n ++ "-sized bytestrings") $ do bs <- random n B16.decodeBase16 (B16.encodeBase16' bs) @=? Right bs + roundtripL n = testCase ("Roundtrip encode/decode for " ++ show n ++ "-sized bytestrings") $ do+ bs <- fromStrict <$> random n+ B16L.decodeBase16 (B16L.encodeBase16' bs) @=? Right bs+ alphabetTests :: TestTree alphabetTests = testGroup "Alphabet tests"- [ base16Tests 0- , base16Tests 4- , base16Tests 5- , base16Tests 6+ [ testGroup "Strict"+ [ conforms 0+ , conforms 4+ , conforms 5+ , conforms 6+ ]+ , testGroup "Lazy"+ [ conformsL 0+ , conformsL 4+ , conformsL 5+ , conformsL 6+ ] ] where- base16Tests n = testCase ("Conforms to Base16 alphabet: " ++ show n) $ do+ conforms n = testCase ("Conforms to Base16 alphabet: " ++ show n) $ do bs <- random n let b = B16.encodeBase16' bs assertBool ("failed validity: " ++ show b) $ B16.isValidBase16 b assertBool ("failed correctness: " ++ show b) $ B16.isBase16 b++ conformsL n = testCase ("Conforms to Base16 alphabet: " ++ show n) $ do+ bs <- fromStrict <$> random n+ let b = B16L.encodeBase16' bs+ assertBool ("failed validity: " ++ show b) $ B16L.isValidBase16 b+ assertBool ("failed correctness: " ++ show b) $ B16L.isBase16 b