# elm-cardano/base64

Fast Base64 encoding and decoding for Elm `Bytes`.

## API

```elm
import Base64

Base64.fromBytes bytes         -- Bytes -> String
Base64.toBytes "Zm9v"          -- String -> Maybe Bytes
Base64.toBytesUnsafe "Zm9v"    -- String -> Bytes (no validation)
```

See the [module docs](https://package.elm-lang.org/packages/elm-cardano/base64/1.0.0/Base64) for the full API.

## Install

```sh
elm install elm-cardano/base64
```

## Performance

Performance is a first-class concern for this package. Every function has been benchmarked and optimized, with multiple implementation strategies tested and compared. Here are the key techniques:

- **Batched decoding**: `fromBytes` reads 60 bytes per outer loop iteration (via `Decode.map5` over five 12-byte `Decode.map3` blocks), minimizing loop overhead. Each 12-byte block unpacks three `Int32` words into four 24-bit groups and emits 16 base64 characters.
- **ConsString-aware accumulation**: String concatenation with `(++)` is O(1) in V8 (creates a rope node), which we exploit throughout. This beats `List String` accumulators with `String.concat` by ~11%.
- **Fused validation**: The safe decoder (`toBytes`) validates input characters inline during the decode fold, using a `bad` accumulator that OR-collects sentinel values. One pass, no separate validation walk — within ~4% of the unsafe path.
- **`String.foldl`-based decoding**: The decoder operates on the input string directly via `String.foldl`, building output through `Encode.Encoder` lists, avoiding `Bytes.Decode`-side accumulation entirely.

As a reference point, here is how we compare to [`danfishgold/base64-bytes`](https://package.elm-lang.org/packages/danfishgold/base64-bytes/latest/) (the most popular Elm Base64 package):

| Function | Size | elm-cardano/base64 | danfishgold/base64-bytes | Speedup |
|----------|------|-------------------:|-------------------------:|--------:|
| `fromBytes` | 0-32 B | 18,144 ns | 20,599 ns | **14%** |
| `fromBytes` | 1024 B | 19,299 ns | 24,704 ns | **28%** |
| `fromBytes` | 10 kB | 190,233 ns | 242,915 ns | **28%** |
| `toBytes` | 16 B | 579 ns | 953 ns | **65%** |
| `toBytes` | 1024 B | 27,105 ns | 50,688 ns | **87%** |

See [`bench/`](https://github.com/elm-cardano/base64/tree/main/bench) for the full benchmarking setup and methodology.
See [`bench/REPORT.md`](https://github.com/elm-cardano/base64/tree/main/bench/REPORT.md) for the history of attempted optimizations.

## Development

```sh
pnpm install
pnpm test           # run tests
pnpm review         # elm-review
pnpm format:check   # check formatting
pnpm bench:build    # build benchmarks
pnpm bench:test     # run benchmark correctness checks
```
