base64 0.1.0.0 → 0.2.0.0
raw patch · 6 files changed
+23/−362 lines, 6 filesdep −lensdep ~bytestringdep ~deepseqdep ~textPVP ok
version bump matches the API change (PVP)
Dependencies removed: lens
Dependency ranges changed: bytestring, deepseq, text
API changes (from Hackage documentation)
- Data.ByteString.Base64.Lens: _Base64 :: Prism' ByteString ByteString
- Data.ByteString.Base64.Lens: _Base64Unpadded :: Prism' ByteString ByteString
- Data.ByteString.Base64.Lens: _Base64Url :: Prism' ByteString ByteString
- Data.ByteString.Base64.Lens: _Base64UrlUnpadded :: Prism' ByteString ByteString
- Data.ByteString.Base64.Lens: pattern Base64 :: ByteString -> ByteString
- Data.ByteString.Base64.Lens: pattern Base64Unpadded :: ByteString -> ByteString
- Data.ByteString.Base64.Lens: pattern Base64Url :: ByteString -> ByteString
- Data.ByteString.Base64.Lens: pattern Base64UrlUnpadded :: ByteString -> ByteString
- Data.Text.Encoding.Base64.Lens: _Base64 :: Prism' Text Text
- Data.Text.Encoding.Base64.Lens: _Base64Unpadded :: Prism' Text Text
- Data.Text.Encoding.Base64.Lens: _Base64Url :: Prism' Text Text
- Data.Text.Encoding.Base64.Lens: _Base64UrlUnpadded :: Prism' Text Text
- Data.Text.Encoding.Base64.Lens: pattern Base64 :: Text -> Text
- Data.Text.Encoding.Base64.Lens: pattern Base64Unpadded :: Text -> Text
- Data.Text.Encoding.Base64.Lens: pattern Base64Url :: Text -> Text
- Data.Text.Encoding.Base64.Lens: pattern Base64UrlUnpadded :: Text -> Text
Files
- CHANGELOG.md +13/−1
- README.md +5/−70
- base64.cabal +5/−27
- src/Data/ByteString/Base64/Internal.hs +0/−6
- src/Data/ByteString/Base64/Lens.hs +0/−129
- src/Data/Text/Encoding/Base64/Lens.hs +0/−129
CHANGELOG.md view
@@ -1,5 +1,17 @@ # Revision history for base64 -## 0.1.0.0 -- YYYY-mm-dd+## 0.2.0.0 -- 2020-01-05 +* After a discussion with phadej, we're doing away with the flags, and splitting the optics out into their own separate library+* Removed unnecessary inline pragmas++## 0.1.0.0 -- 2020-01-05++* Do away with the typeclasses, and just provide prisms + synonyms+* Continued performance improvements to decoding+* Corrected benchmarks++## 0.0.1.0 -- 2020-01-03+ * First version. Released on an unsuspecting world.+* Preliminary release
README.md view
@@ -13,79 +13,14 @@ - Better performance over existing Base64 libraries (2x and 3x for most use-cases - see [PERFORMANCE.md](benchmarks/PERFORMANCE.md)) - Support for unpadded Base64 and Base64-url - Support for `Text` encodings and decodings-- Optics for handling more complex structures with Base64 representations+- Optics for handling more complex structures with Base64 representations via the `base64-lens` package +There are no dependencies aside from `base`: ++ ### Motivation Haskell has two main libraries for Base64: `memory`, and `base64-bytestring`. -Of these, `memory` is geared towards integration with other memory primitives in the library, without much of an eye towards performance, while `base64-bytestring` is built to exclusively address `ByteString` encoding and decoding, and is very performant. Many great strides have been made in the realm of Base64 performance and vectorization just in the past 5 years, which this library attempts to capture. Additionally, we attempt to fix percieved shortcomings with both APIs in the support of unpadded Base64 and Base64-url support (which `memory` provides, but not `base64-bytestring`), as well as supporting `Text` values (neither libraries provide), supplying some optics for composing structures with Base64-encodable/decodable focii (neither libraries provide), and convenient pattern synonyms (no library to date does this).--### Patterns--The pattern synonyms provided in this library are:--```haskell-pattern Base64 :: ByteString -> ByteString-pattern Base64Url :: ByteString -> ByteString-pattern Base64Unpadded :: ByteString -> ByteString-pattern Base64UrlUnpadded :: ByteString -> ByteString---- and--pattern Base64 :: Text -> Text-pattern Base64Url :: Text -> Text-pattern Base64Unpadded :: Text -> Text-pattern Base64UrlUnpadded :: Text -> Text-```--These provide a convenient high level interface for passing Base64 encoded values.---### Optics--`Prism`s for encoding and decoding `Text` and `ByteString` values are given as part of the library:---```haskell-_Base64 :: Prism' ByteString ByteString-_Base64Url :: Prism' ByteString ByteString-_Base64Unpadded :: Prism' ByteString ByteString-_Base64UrlUnpadded :: Prism' ByteString ByteString---- and--_Base64 :: Prism' Text Text-_Base64Url :: Prism' Text Text-_Base64Unpadded :: Prism' Text Text-_Base64UrlUnpadded :: Prism' Text Text--```--If a particular structure has a `Lens` into some `Text` or `ByteString` value they might want to encode (or decode), then composing such a `Lens` with these `Prisms` yields an affine `Traversal`, resulting in a structure which has the focus of its `Lens` encoded as or decoded from Base64(-url). All one needs to do is compose their optics:--```haskell--data MyStruct = MyStruct- { _a :: Int- , _b :: Text- } deriving Show--b :: Lens' MyStruct Text-b = lens _b (\t b_ -> t { _b = b_ })--myB64Struct :: Traversal' s Text-myB64Struct = b . _Base64---- >>> MyStruct 3 "U3Vu" ^? b . _Base64--- MyStruct {_a = 3, _b = "Sun"}--bRe :: Review MyStruct Text-bRe = unto (\b -> MyStruct 0 b)---- >>> bRe . _Base64 # "Sun"--- MyStruct {_a = 0, _b = "UV3u"}-```--The data of a `Prism` naturally conforms to this "encoding/decoding" dichotomy, where the `Review`, or "builder" half of the `Prism` of type `b -> t` is an encoding, and the "Matcher" half of the prism, of type `s -> Either t a`, represents a decoding of a similar structure. Hence, `Prism` is the most appropriate structure.+Of these, `memory` is geared towards integration with other memory primitives in the library, without much of an eye towards performance, while `base64-bytestring` is built to exclusively address `ByteString` encoding and decoding, and is very performant. Many great strides have been made in the realm of Base64 performance and vectorization just in the past 5 years, which this library attempts to capture. Additionally, we attempt to fix percieved shortcomings with both APIs in the support of unpadded Base64 and Base64-url support (which `memory` provides, but not `base64-bytestring`), as well as supporting `Text` values (neither libraries provide).
base64.cabal view
@@ -1,7 +1,7 @@ cabal-version: 2.4 name: base64-version: 0.1.0.0+version: 0.2.0.0 synopsis: RFC 4648-compliant padded and unpadded base64 and base64url encodings description: RFC 4648-compliant padded and unpadded base64 and base64url encoding and decoding.@@ -24,18 +24,6 @@ type: git location: https://github.com/emilypi/base64.git --flag optics- description: Enable optics for base64-encoding text and bytestrings- manual: True- default: True--flag perf-flags- description: Performance tuning flags and information- manual: True- default: False-- library exposed-modules: Data.ByteString.Base64 , Data.ByteString.Base64.URL@@ -45,24 +33,14 @@ other-modules: Data.ByteString.Base64.Internal - build-depends: base >=4.10 && <5- , bytestring- , deepseq- , text+ build-depends: base >=4.10 && <5+ , bytestring ^>=0.10+ , deepseq ^>=1.4+ , text ^>=1.2 hs-source-dirs: src default-language: Haskell2010 ghc-options: -Wall-- if flag(optics)- exposed-modules: Data.ByteString.Base64.Lens- , Data.Text.Encoding.Base64.Lens- build-depends: lens ^>= 4.18-- if flag(perf-flags)- ghc-options: -ddump-simpl- -ddump-to-file- -ddump-stranal test-suite tasty
src/Data/ByteString/Base64/Internal.hs view
@@ -92,7 +92,6 @@ , !j <- [0..63] ] in EncodingTable (Ptr alphabet) (writeNPlainForeignPtrBytes 8192 bs)-{-# INLINE packTable #-} base64UrlTable :: EncodingTable base64UrlTable = packTable "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"#@@ -134,11 +133,9 @@ encodeBase64_' !padded (Ptr !alpha) !etable !sptr !dptr !end = go sptr dptr where ix (W8# i) = W8# (indexWord8OffAddr# alpha (word2Int# i))- {-# INLINE ix #-} w32 :: Word8 -> Word32 w32 = fromIntegral- {-# INLINE w32 #-} go !src !dst | plusPtr src 2 >= end = finalize src (castPtr dst)@@ -280,17 +277,14 @@ decodeBase64_' !dtable !sptr !dptr !end !dfp = go dptr sptr 0 where err = return . Left . T.pack- {-# INLINE err #-} finalize !n = return (Right (PS dfp 0 n))- {-# INLINE finalize #-} look :: Ptr Word8 -> IO Word32 look p = do !i <- peekByteOff @Word8 p 0 !v <- peekByteOff @Word8 dtable (fromIntegral i) return (fromIntegral v)- {-# INLINE look #-} go !dst !src !n | src >= end = return (Right (PS dfp 0 n))
− src/Data/ByteString/Base64/Lens.hs
@@ -1,129 +0,0 @@-{-# LANGUAGE PatternSynonyms #-}-{-# LANGUAGE ViewPatterns #-}--- |--- Module : Data.Text.Encoding.Base64.Lens--- Copyright : (c) 2019 Emily Pillmore--- License : BSD-style------ Maintainer : Emily Pillmore <emilypi@cohomolo.gy>--- Stability : Experimental--- Portability : non-portable------ This module contains 'Control.Lens.Type.Prism's Base64-encoding and--- decoding 'ByteString' values.----module Data.ByteString.Base64.Lens-( -- * Prisms- _Base64-, _Base64Url-, _Base64Unpadded-, _Base64UrlUnpadded- -- * Patterns-, pattern Base64-, pattern Base64Url-, pattern Base64Unpadded-, pattern Base64UrlUnpadded-) where---import Control.Lens--import Data.ByteString (ByteString)-import qualified Data.ByteString.Base64 as B64-import qualified Data.ByteString.Base64.URL as B64U----- -------------------------------------------------------------------------- ----- Optics---- | A 'Control.Lens.Type.Prism' into the Base64 encoding of a 'ByteString' value------ >>> _Base64 # "Sun"--- "UV3u"------ >>> "UV3u" ^? _Base64--- Just "Sun"----_Base64 :: Prism' ByteString ByteString-_Base64 = prism' B64.encodeBase64 $ \s -> case B64.decodeBase64 s of- Left _ -> Nothing- Right a -> Just a-{-# INLINE _Base64 #-}---- | A 'Control.Lens.Type.Prism' into the Base64-url encoding of a 'ByteString' value------ >>> _Base64Url # "Sun"--- "UV3u"------ >>> "PDw_Pz8-Pg==" ^? _Base64Url--- Just "<<???>>"----_Base64Url :: Prism' ByteString ByteString-_Base64Url = prism' B64U.encodeBase64 $ \s -> case B64U.decodeBase64 s of- Left _ -> Nothing- Right a -> Just a-{-# INLINE _Base64Url #-}---- | A 'Control.Lens.Type.Prism' into the unpadded Base64 encoding of a--- 'ByteString' value------ Please note that unpadded variants should only be used--- when assumptions about the data can be made. In particular, if the length of--- the input is divisible by 3, then this is a safe function to call.------ >>> _Base64Unpadded # "Sun"--- "UV3u"------ >>> "UV3u" ^? _Base64Unpadded--- Just "Sun"----_Base64Unpadded :: Prism' ByteString ByteString-_Base64Unpadded = prism' B64.encodeBase64Unpadded $ \s -> case B64.decodeBase64Unpadded s of- Left _ -> Nothing- Right a -> Just a-{-# INLINE _Base64Unpadded #-}---- | A 'Control.Lens.Type.Prism' into the Base64-url encoding of a 'ByteString' value------ Please note that unpadded variants should only be used--- when assumptions about the data can be made. In particular, if the length of--- the input is divisible by 3, then this is a safe function to call.------ >>> _Base64UrlUnpadded # "<<??>>"--- "PDw_Pz4-"------ >>> "PDw_Pz4-" ^? _Base64UrlUnpadded--- Just "<<??>>"----_Base64UrlUnpadded :: Prism' ByteString ByteString-_Base64UrlUnpadded = prism' B64U.encodeBase64Unpadded $ \s -> case B64U.decodeBase64Unpadded s of- Left _ -> Nothing- Right a -> Just a-{-# INLINE _Base64UrlUnpadded #-}---- -------------------------------------------------------------------------- ----- Patterns---- | Unidirectional pattern synonym for base64-encoded 'ByteString' values.----pattern Base64 :: ByteString -> ByteString-pattern Base64 a <- (preview _Base64 -> Just a) where- Base64 a = _Base64 # a---- | Unidirectional pattern synonym for base64url-encoded 'ByteString' values.----pattern Base64Url :: ByteString -> ByteString-pattern Base64Url a <- (preview _Base64Url -> Just a) where- Base64Url a = _Base64Url # a---- | Unidirectional pattern synonym for unpadded base64-encoded 'ByteString' values.----pattern Base64Unpadded :: ByteString -> ByteString-pattern Base64Unpadded a <- (preview _Base64Unpadded -> Just a) where- Base64Unpadded a = _Base64Unpadded # a---- | Unidirectional pattern synonym for unpadded base64url-encoded 'ByteString' values.----pattern Base64UrlUnpadded :: ByteString -> ByteString-pattern Base64UrlUnpadded a <- (preview _Base64UrlUnpadded -> Just a) where- Base64UrlUnpadded a = _Base64UrlUnpadded # a
− src/Data/Text/Encoding/Base64/Lens.hs
@@ -1,129 +0,0 @@-{-# LANGUAGE PatternSynonyms #-}-{-# LANGUAGE ViewPatterns #-}--- |--- Module : Data.Text.Encoding.Base64.Lens--- Copyright : (c) 2019 Emily Pillmore--- License : BSD-style------ Maintainer : Emily Pillmore <emilypi@cohomolo.gy>--- Stability : Experimental--- Portability : non-portable------ This module contains 'Control.Lens.Type.Prism's Base64-encoding and--- decoding 'Text' values.----module Data.Text.Encoding.Base64.Lens-( -- * Prisms- _Base64-, _Base64Url-, _Base64Unpadded-, _Base64UrlUnpadded- -- * Patterns-, pattern Base64-, pattern Base64Url-, pattern Base64Unpadded-, pattern Base64UrlUnpadded-) where---import Control.Lens--import Data.Text (Text)-import qualified Data.Text.Encoding.Base64 as B64T-import qualified Data.Text.Encoding.Base64.URL as B64TU----- -------------------------------------------------------------------------- ----- Optics---- | A 'Control.Lens.Type.Prism' into the Base64 encoding of a 'Text' value.------ >>> _Base64 # "Sun"--- "UV3u"------ >>> "UV3u" ^? _Base64--- Just "Sun"----_Base64 :: Prism' Text Text-_Base64 = prism' B64T.encodeBase64 $ \s -> case B64T.decodeBase64 s of- Left _ -> Nothing- Right a -> Just a-{-# INLINE _Base64 #-}---- | A 'Control.Lens.Type.Prism' into the Base64-url encoding of a 'Text' value.------ >>> _Base64Url # "Sun"--- "UV3u"------ >>> "PDw_Pz8-Pg==" ^? _Base64Url--- Just "<<???>>"----_Base64Url :: Prism' Text Text-_Base64Url = prism' B64TU.encodeBase64 $ \s -> case B64TU.decodeBase64 s of- Left _ -> Nothing- Right a -> Just a-{-# INLINE _Base64Url #-}---- | A 'Control.Lens.Type.Prism' into the unpadded Base64 encoding of a--- 'Text' value.------ Please note that unpadded variants should only be used--- when assumptions about the data can be made. In particular, if the length of--- the input is divisible by 3, then this is a safe function to call.------ >>> _Base64Unpadded # "Sun"--- "UV3u"------ >>> "UV3u" ^? _Base64Unpadded--- Just "Sun"----_Base64Unpadded :: Prism' Text Text-_Base64Unpadded = prism' B64T.encodeBase64Unpadded $ \s -> case B64T.decodeBase64Unpadded s of- Left _ -> Nothing- Right a -> Just a-{-# INLINE _Base64Unpadded #-}---- | A 'Control.Lens.Type.Prism' into the Base64-url encoding of a 'Text' value.------ Please note that unpadded variants should only be used--- when assumptions about the data can be made. In particular, if the length of--- the input is divisible by 3, then this is a safe function to call.------ >>> _Base64UrlUnpadded # "<<??>>"--- "PDw_Pz4-"------ >>> "PDw_Pz4-" ^? _Base64UrlUnpadded--- Just "<<??>>"----_Base64UrlUnpadded :: Prism' Text Text-_Base64UrlUnpadded = prism' B64TU.encodeBase64Unpadded $ \s -> case B64TU.decodeBase64Unpadded s of- Left _ -> Nothing- Right a -> Just a-{-# INLINE _Base64UrlUnpadded #-}---- -------------------------------------------------------------------------- ----- Patterns---- | Unidirectional pattern synonym for base64-encoded 'Text' values.----pattern Base64 :: Text -> Text-pattern Base64 a <- (preview _Base64 -> Just a) where- Base64 a = _Base64 # a---- | Unidirectional pattern synonym for base64url-encoded 'Text' values.----pattern Base64Url :: Text -> Text-pattern Base64Url a <- (preview _Base64Url -> Just a) where- Base64Url a = _Base64Url # a---- | Unidirectional pattern synonym for unpadded base64-encoded 'Text' values.----pattern Base64Unpadded :: Text -> Text-pattern Base64Unpadded a <- (preview _Base64Unpadded -> Just a) where- Base64Unpadded a = _Base64Unpadded # a---- | Unidirectional pattern synonym for unpadded base64url-encoded 'Text' values.----pattern Base64UrlUnpadded :: Text -> Text-pattern Base64UrlUnpadded a <- (preview _Base64UrlUnpadded -> Just a) where- Base64UrlUnpadded a = _Base64UrlUnpadded # a