base64-0.1.0.0: README.md
# Base64
[](https://travis-ci.com/emilypi/base64)
[](https://hackage.haskell.org/package/base64)
Padded and unpadded base64 and base64url encodings for `Text` and `ByteString` values, along with their optics.
### Summary
What does this library provide? Here is the summary:
- 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
### 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.