├── .formatter.exs ├── .github ├── renovate.json └── workflows │ ├── rebase.yml │ └── test.yml ├── .gitignore ├── LICENSE ├── README.md ├── lib └── base62.ex ├── mix.exs ├── mix.lock └── test ├── base62_test.exs └── test_helper.exs /.formatter.exs: -------------------------------------------------------------------------------- 1 | [ 2 | inputs: ["mix.exs", "{config,lib,test}/**/*.{ex,exs}"] 3 | ] 4 | -------------------------------------------------------------------------------- /.github/renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://docs.renovatebot.com/renovate-schema.json", 3 | "extends": ["igas/.github:lib"] 4 | } 5 | -------------------------------------------------------------------------------- /.github/workflows/rebase.yml: -------------------------------------------------------------------------------- 1 | name: Automatic Rebase 2 | 3 | on: 4 | issue_comment: 5 | types: [created] 6 | 7 | jobs: 8 | rebase: 9 | name: Rebase 10 | if: github.event.issue.pull_request != '' && contains(github.event.comment.body, '/rebase') 11 | runs-on: ubuntu-latest 12 | steps: 13 | - name: Checkout the latest code 14 | uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 15 | with: 16 | token: ${{ secrets.GITHUB_TOKEN }} 17 | fetch-depth: 0 # otherwise, you will fail to push refs to dest repo 18 | 19 | - name: Automatic Rebase 20 | uses: cirrus-actions/rebase@b87d48154a87a85666003575337e27b8cd65f691 # 1.8 21 | env: 22 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 23 | -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | - pull_request 5 | - push 6 | 7 | jobs: 8 | test: 9 | name: mix test (Elixir ${{ matrix.elixir }} OTP ${{ matrix.otp }}) 10 | runs-on: ${{ matrix.os || 'ubuntu-latest' }} 11 | strategy: 12 | fail-fast: false 13 | matrix: 14 | include: 15 | - elixir: 1.11.x 16 | otp: 21.x 17 | os: ubuntu-20.04 18 | - elixir: 1.11.x 19 | otp: 22.x 20 | os: ubuntu-20.04 21 | - elixir: 1.11.x 22 | otp: 23.x 23 | os: ubuntu-20.04 24 | - elixir: 1.12.x 25 | otp: 22.x 26 | os: ubuntu-20.04 27 | - elixir: 1.12.x 28 | otp: 23.x 29 | os: ubuntu-20.04 30 | - elixir: 1.12.x 31 | otp: 24.x 32 | os: ubuntu-20.04 33 | - elixir: 1.13.x 34 | otp: 22.x 35 | os: ubuntu-20.04 36 | - elixir: 1.13.x 37 | otp: 23.x 38 | os: ubuntu-20.04 39 | - elixir: 1.13.x 40 | otp: 24.x 41 | os: ubuntu-20.04 42 | - elixir: 1.14.x 43 | otp: 23.x 44 | os: ubuntu-20.04 45 | - elixir: 1.14.x 46 | otp: 24.x 47 | os: ubuntu-20.04 48 | - elixir: 1.14.x 49 | otp: 25.x 50 | os: ubuntu-20.04 51 | - elixir: 1.15.x 52 | otp: 24.x 53 | os: ubuntu-20.04 54 | - elixir: 1.15.x 55 | otp: 25.x 56 | os: ubuntu-20.04 57 | steps: 58 | - name: Checkout source 59 | uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 60 | 61 | - name: Setup cache 62 | uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2 63 | with: 64 | key: ${{ github.job }}-${{ matrix.elixir }}-${{ matrix.otp }}-${{ hashFiles('mix.lock') }}-1 65 | path: _build 66 | 67 | - name: Install runtime 68 | uses: erlef/setup-beam@0a541161e47ec43ccbd9510053c5f336ca76c2a2 # v1.17.6 69 | with: 70 | elixir-version: ${{ matrix.elixir }} 71 | otp-version: ${{ matrix.otp }} 72 | 73 | - name: Install Dependencies 74 | run: mix deps.get 75 | 76 | - name: Run tests 77 | run: mix test 78 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.ez 2 | /_build 3 | /.elixir_ls 4 | /deps 5 | /doc 6 | erl_crash.dump 7 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Igor Kapkov 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Base62 [![Version](https://img.shields.io/hexpm/v/base62.svg?style=flat-square)](https://hex.pm/packages/base62)[![License](https://img.shields.io/hexpm/l/base62.svg?style=flat-square)](https://github.com/elixirs/base62/blob/main/LICENSE)![Build Status](https://img.shields.io/github/workflow/status/elixirs/base62/CI/main?style=flat-square)[![Issues](https://img.shields.io/github/issues/elixirs/base62.svg?style=flat-square)](https://github.com/elixirs/base62/issues)[![Downloads](https://img.shields.io/hexpm/dt/base62.svg?style=flat-square)](https://hex.pm/packages/base62) 2 | 3 | Base62 encoder/decoder in pure Elixir. 4 | 5 | ## Usage 6 | 7 | ### Encode 8 | 9 | ```elixir 10 | iex> Base62.encode(28) 11 | "S" 12 | 13 | iex> Base62.encode(44) 14 | "i" 15 | 16 | iex> Base62.encode(280) 17 | "4W" 18 | ``` 19 | 20 | ### Decode! 21 | 22 | ```elixir 23 | iex> Base62.decode!("100") 24 | 3844 25 | 26 | iex> Base62.decode!("igas") 27 | 10650166 28 | 29 | iex> Base62.decode!("EvilMartians") 30 | 776957886790921093120 31 | ``` 32 | 33 | ### Decode 34 | 35 | ```elixir 36 | iex> Base62.decode("42") 37 | {:ok, 250} 38 | 39 | iex> Base62.decode("Игас") 40 | :error 41 | 42 | iex> Base62.decode("Elixir") 43 | {:ok, 13531063449} 44 | ``` 45 | 46 | # [License](https://github.com/elixirs/base62/blob/main/LICENSE) 47 | 48 | Released under the MIT License. 49 | -------------------------------------------------------------------------------- /lib/base62.ex: -------------------------------------------------------------------------------- 1 | defmodule Base62 do 2 | use CustomBase, '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz' 3 | 4 | @moduledoc """ 5 | This module provides data encoding and decoding functions for base62 alphabet: 6 | 7 | | Value | Encoding | Value | Encoding | Value | Encoding | Value | Encoding | 8 | |------:|---------:|------:|---------:|------:|---------:|------:|---------:| 9 | | 0| 0| 16| G| 32| W| 48| m| 10 | | 1| 1| 17| H| 33| X| 49| n| 11 | | 2| 2| 18| I| 34| Y| 50| o| 12 | | 3| 3| 19| J| 35| Z| 51| p| 13 | | 4| 4| 20| K| 36| a| 52| q| 14 | | 5| 5| 21| L| 37| b| 53| r| 15 | | 6| 6| 22| M| 38| c| 54| s| 16 | | 7| 7| 23| N| 39| d| 55| t| 17 | | 8| 8| 24| O| 40| e| 56| u| 18 | | 9| 9| 25| P| 41| f| 57| v| 19 | | 10| A| 26| Q| 42| g| 58| w| 20 | | 11| B| 27| R| 43| h| 59| x| 21 | | 12| C| 28| S| 44| i| 60| y| 22 | | 13| D| 29| T| 45| j| 61| z| 23 | | 14| E| 30| U| 46| k| | | 24 | | 15| F| 31| V| 47| l| | | 25 | """ 26 | 27 | @doc """ 28 | Encode base 10 integer to base 62 char from alphabet above. 29 | """ 30 | def encode(integer) 31 | 32 | @doc """ 33 | Decode base 62 char from alphabet above to base 10 integer. 34 | 35 | Returns tuple `{:ok, number}` if binary can be converted using alphabet, 36 | `:error` instead. 37 | """ 38 | def decode(binary) 39 | 40 | @doc """ 41 | Same as `decode/1` except this function return just number or raise error if 42 | binary can not be converted. 43 | """ 44 | def decode!(binary) 45 | end 46 | -------------------------------------------------------------------------------- /mix.exs: -------------------------------------------------------------------------------- 1 | defmodule Base62.Mixfile do 2 | use Mix.Project 3 | 4 | @version "1.2.2" 5 | @github "https://github.com/elixirs/base62" 6 | 7 | def project do 8 | [ 9 | app: :base62, 10 | version: @version, 11 | elixir: "~> 1.0", 12 | name: "Base62", 13 | description: description(), 14 | package: package(), 15 | source_url: @github, 16 | docs: docs(), 17 | deps: deps() 18 | ] 19 | end 20 | 21 | def application, do: [] 22 | 23 | defp docs do 24 | [ 25 | extras: ["README.md"], 26 | main: "readme", 27 | name: "Base62", 28 | canonical: "https://hexdocs.pm/base62", 29 | source_ref: "v#{@version}", 30 | source_url: @github 31 | ] 32 | end 33 | 34 | defp deps do 35 | [ 36 | {:custom_base, "~> 0.2.1"}, 37 | {:ex_doc, "~> 0.16", only: :dev}, 38 | {:earmark, "~> 1.2", only: :dev}, 39 | {:stream_data, "~> 0.6", only: :test} 40 | ] 41 | end 42 | 43 | defp description do 44 | "Base62 encoder/decoder in pure Elixir." 45 | end 46 | 47 | defp package do 48 | [ 49 | maintainers: ["Igor Kapkov"], 50 | files: ["lib", "mix.exs", "README.md", "LICENSE"], 51 | licenses: ["MIT"], 52 | links: %{"Github" => @github} 53 | ] 54 | end 55 | end 56 | -------------------------------------------------------------------------------- /mix.lock: -------------------------------------------------------------------------------- 1 | %{ 2 | "custom_base": {:hex, :custom_base, "0.2.1", "4a832a42ea0552299d81652aa0b1f775d462175293e99dfbe4d7dbaab785a706", [:mix], [], "hexpm", "8df019facc5ec9603e94f7270f1ac73ddf339f56ade76a721eaa57c1493ba463"}, 3 | "earmark": {:hex, :earmark, "1.4.15", "2c7f924bf495ec1f65bd144b355d0949a05a254d0ec561740308a54946a67888", [:mix], [{:earmark_parser, ">= 1.4.13", [hex: :earmark_parser, repo: "hexpm", optional: false]}], "hexpm", "3b1209b85bc9f3586f370f7c363f6533788fb4e51db23aa79565875e7f9999ee"}, 4 | "earmark_parser": {:hex, :earmark_parser, "1.4.39", "424642f8335b05bb9eb611aa1564c148a8ee35c9c8a8bba6e129d51a3e3c6769", [:mix], [], "hexpm", "06553a88d1f1846da9ef066b87b57c6f605552cfbe40d20bd8d59cc6bde41944"}, 5 | "ex_doc": {:hex, :ex_doc, "0.33.0", "690562b153153c7e4d455dc21dab86e445f66ceba718defe64b0ef6f0bd83ba0", [:mix], [{:earmark_parser, "~> 1.4.39", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_c, ">= 0.1.0", [hex: :makeup_c, repo: "hexpm", optional: true]}, {:makeup_elixir, "~> 0.14 or ~> 1.0", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1 or ~> 1.0", [hex: :makeup_erlang, repo: "hexpm", optional: false]}, {:makeup_html, ">= 0.1.0", [hex: :makeup_html, repo: "hexpm", optional: true]}], "hexpm", "3f69adc28274cb51be37d09b03e4565232862a4b10288a3894587b0131412124"}, 6 | "makeup": {:hex, :makeup, "1.1.2", "9ba8837913bdf757787e71c1581c21f9d2455f4dd04cfca785c70bbfff1a76a3", [:mix], [{:nimble_parsec, "~> 1.2.2 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "cce1566b81fbcbd21eca8ffe808f33b221f9eee2cbc7a1706fc3da9ff18e6cac"}, 7 | "makeup_elixir": {:hex, :makeup_elixir, "0.16.2", "627e84b8e8bf22e60a2579dad15067c755531fea049ae26ef1020cad58fe9578", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.2.3 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "41193978704763f6bbe6cc2758b84909e62984c7752b3784bd3c218bb341706b"}, 8 | "makeup_erlang": {:hex, :makeup_erlang, "1.0.0", "6f0eff9c9c489f26b69b61440bf1b238d95badae49adac77973cbacae87e3c2e", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "ea7a9307de9d1548d2a72d299058d1fd2339e3d398560a0e46c27dab4891e4d2"}, 9 | "nimble_parsec": {:hex, :nimble_parsec, "1.4.0", "51f9b613ea62cfa97b25ccc2c1b4216e81df970acd8e16e8d1bdc58fef21370d", [:mix], [], "hexpm", "9c565862810fb383e9838c1dd2d7d2c437b3d13b267414ba6af33e50d2d1cf28"}, 10 | "stream_data": {:hex, :stream_data, "0.6.0", "e87a9a79d7ec23d10ff83eb025141ef4915eeb09d4491f79e52f2562b73e5f47", [:mix], [], "hexpm", "b92b5031b650ca480ced047578f1d57ea6dd563f5b57464ad274718c9c29501c"}, 11 | } 12 | -------------------------------------------------------------------------------- /test/base62_test.exs: -------------------------------------------------------------------------------- 1 | defmodule Base62Test do 2 | use ExUnit.Case, async: true 3 | use ExUnitProperties 4 | 5 | import Base62 6 | 7 | property "decode encoded value returns original value" do 8 | check all number <- 9 | integer(0..999_999_999_999_999_999_999_999_999_999_999_999_999_999_999_999), 10 | max_runs: 10_000 do 11 | assert number == decode!(encode(number)) 12 | end 13 | end 14 | 15 | test :encode do 16 | assert encode(0) == "0" 17 | assert encode(1) == "1" 18 | assert encode(2) == "2" 19 | assert encode(3) == "3" 20 | assert encode(4) == "4" 21 | assert encode(5) == "5" 22 | assert encode(6) == "6" 23 | assert encode(7) == "7" 24 | assert encode(8) == "8" 25 | assert encode(9) == "9" 26 | assert encode(10) == "A" 27 | assert encode(11) == "B" 28 | assert encode(12) == "C" 29 | assert encode(13) == "D" 30 | assert encode(14) == "E" 31 | assert encode(15) == "F" 32 | assert encode(16) == "G" 33 | assert encode(17) == "H" 34 | assert encode(18) == "I" 35 | assert encode(19) == "J" 36 | assert encode(20) == "K" 37 | assert encode(21) == "L" 38 | assert encode(22) == "M" 39 | assert encode(23) == "N" 40 | assert encode(24) == "O" 41 | assert encode(25) == "P" 42 | assert encode(26) == "Q" 43 | assert encode(27) == "R" 44 | assert encode(28) == "S" 45 | assert encode(29) == "T" 46 | assert encode(30) == "U" 47 | assert encode(31) == "V" 48 | assert encode(32) == "W" 49 | assert encode(33) == "X" 50 | assert encode(34) == "Y" 51 | assert encode(35) == "Z" 52 | assert encode(36) == "a" 53 | assert encode(37) == "b" 54 | assert encode(38) == "c" 55 | assert encode(39) == "d" 56 | assert encode(40) == "e" 57 | assert encode(41) == "f" 58 | assert encode(42) == "g" 59 | assert encode(43) == "h" 60 | assert encode(44) == "i" 61 | assert encode(45) == "j" 62 | assert encode(46) == "k" 63 | assert encode(47) == "l" 64 | assert encode(48) == "m" 65 | assert encode(49) == "n" 66 | assert encode(50) == "o" 67 | assert encode(51) == "p" 68 | assert encode(52) == "q" 69 | assert encode(53) == "r" 70 | assert encode(54) == "s" 71 | assert encode(55) == "t" 72 | assert encode(56) == "u" 73 | assert encode(57) == "v" 74 | assert encode(58) == "w" 75 | assert encode(59) == "x" 76 | assert encode(60) == "y" 77 | assert encode(61) == "z" 78 | assert encode(62) == "10" 79 | assert encode(100) == "1c" 80 | assert encode(124) == "20" 81 | assert encode(4_815_162_342) == "5Frvgk" 82 | assert encode(9_223_372_036_854_775_807) == "AzL8n0Y58m7" 83 | assert encode(26_567_849_713_993_370_845_693_800_611_841) == "8zIcpbAKe8shBxXUtl" 84 | end 85 | 86 | test :decode do 87 | assert decode("0") == {:ok, 0} 88 | assert decode("1") == {:ok, 1} 89 | assert decode("2") == {:ok, 2} 90 | assert decode("3") == {:ok, 3} 91 | assert decode("4") == {:ok, 4} 92 | assert decode("5") == {:ok, 5} 93 | assert decode("6") == {:ok, 6} 94 | assert decode("7") == {:ok, 7} 95 | assert decode("8") == {:ok, 8} 96 | assert decode("9") == {:ok, 9} 97 | assert decode("A") == {:ok, 10} 98 | assert decode("B") == {:ok, 11} 99 | assert decode("C") == {:ok, 12} 100 | assert decode("D") == {:ok, 13} 101 | assert decode("E") == {:ok, 14} 102 | assert decode("F") == {:ok, 15} 103 | assert decode("G") == {:ok, 16} 104 | assert decode("H") == {:ok, 17} 105 | assert decode("I") == {:ok, 18} 106 | assert decode("J") == {:ok, 19} 107 | assert decode("K") == {:ok, 20} 108 | assert decode("L") == {:ok, 21} 109 | assert decode("M") == {:ok, 22} 110 | assert decode("N") == {:ok, 23} 111 | assert decode("O") == {:ok, 24} 112 | assert decode("P") == {:ok, 25} 113 | assert decode("Q") == {:ok, 26} 114 | assert decode("R") == {:ok, 27} 115 | assert decode("S") == {:ok, 28} 116 | assert decode("T") == {:ok, 29} 117 | assert decode("U") == {:ok, 30} 118 | assert decode("V") == {:ok, 31} 119 | assert decode("W") == {:ok, 32} 120 | assert decode("X") == {:ok, 33} 121 | assert decode("Y") == {:ok, 34} 122 | assert decode("Z") == {:ok, 35} 123 | assert decode("a") == {:ok, 36} 124 | assert decode("b") == {:ok, 37} 125 | assert decode("c") == {:ok, 38} 126 | assert decode("d") == {:ok, 39} 127 | assert decode("e") == {:ok, 40} 128 | assert decode("f") == {:ok, 41} 129 | assert decode("g") == {:ok, 42} 130 | assert decode("h") == {:ok, 43} 131 | assert decode("i") == {:ok, 44} 132 | assert decode("j") == {:ok, 45} 133 | assert decode("k") == {:ok, 46} 134 | assert decode("l") == {:ok, 47} 135 | assert decode("m") == {:ok, 48} 136 | assert decode("n") == {:ok, 49} 137 | assert decode("o") == {:ok, 50} 138 | assert decode("p") == {:ok, 51} 139 | assert decode("q") == {:ok, 52} 140 | assert decode("r") == {:ok, 53} 141 | assert decode("s") == {:ok, 54} 142 | assert decode("t") == {:ok, 55} 143 | assert decode("u") == {:ok, 56} 144 | assert decode("v") == {:ok, 57} 145 | assert decode("w") == {:ok, 58} 146 | assert decode("x") == {:ok, 59} 147 | assert decode("y") == {:ok, 60} 148 | assert decode("z") == {:ok, 61} 149 | assert decode("10") == {:ok, 62} 150 | assert decode("1c") == {:ok, 100} 151 | assert decode("20") == {:ok, 124} 152 | assert decode("5Frvgk") == {:ok, 4_815_162_342} 153 | assert decode("zzzzzz") == {:ok, 56_800_235_583} 154 | assert decode("AzL8n0Y58m7") == {:ok, 9_223_372_036_854_775_807} 155 | assert decode("8zIcpbAKe8shBxXUtl") == {:ok, 26_567_849_713_993_370_845_693_800_611_841} 156 | end 157 | 158 | test :decode! do 159 | assert decode!("0") == 0 160 | assert decode!("1") == 1 161 | assert decode!("2") == 2 162 | assert decode!("3") == 3 163 | assert decode!("4") == 4 164 | assert decode!("5") == 5 165 | assert decode!("6") == 6 166 | assert decode!("7") == 7 167 | assert decode!("8") == 8 168 | assert decode!("9") == 9 169 | assert decode!("A") == 10 170 | assert decode!("B") == 11 171 | assert decode!("C") == 12 172 | assert decode!("D") == 13 173 | assert decode!("E") == 14 174 | assert decode!("F") == 15 175 | assert decode!("G") == 16 176 | assert decode!("H") == 17 177 | assert decode!("I") == 18 178 | assert decode!("J") == 19 179 | assert decode!("K") == 20 180 | assert decode!("L") == 21 181 | assert decode!("M") == 22 182 | assert decode!("N") == 23 183 | assert decode!("O") == 24 184 | assert decode!("P") == 25 185 | assert decode!("Q") == 26 186 | assert decode!("R") == 27 187 | assert decode!("S") == 28 188 | assert decode!("T") == 29 189 | assert decode!("U") == 30 190 | assert decode!("V") == 31 191 | assert decode!("W") == 32 192 | assert decode!("X") == 33 193 | assert decode!("Y") == 34 194 | assert decode!("Z") == 35 195 | assert decode!("a") == 36 196 | assert decode!("b") == 37 197 | assert decode!("c") == 38 198 | assert decode!("d") == 39 199 | assert decode!("e") == 40 200 | assert decode!("f") == 41 201 | assert decode!("g") == 42 202 | assert decode!("h") == 43 203 | assert decode!("i") == 44 204 | assert decode!("j") == 45 205 | assert decode!("k") == 46 206 | assert decode!("l") == 47 207 | assert decode!("m") == 48 208 | assert decode!("n") == 49 209 | assert decode!("o") == 50 210 | assert decode!("p") == 51 211 | assert decode!("q") == 52 212 | assert decode!("r") == 53 213 | assert decode!("s") == 54 214 | assert decode!("t") == 55 215 | assert decode!("u") == 56 216 | assert decode!("v") == 57 217 | assert decode!("w") == 58 218 | assert decode!("x") == 59 219 | assert decode!("y") == 60 220 | assert decode!("z") == 61 221 | assert decode!("10") == 62 222 | assert decode!("1c") == 100 223 | assert decode!("20") == 124 224 | assert decode!("5Frvgk") == 4_815_162_342 225 | assert decode!("zzzzzz") == 56_800_235_583 226 | assert decode!("AzL8n0Y58m7") == 9_223_372_036_854_775_807 227 | assert decode!("8zIcpbAKe8shBxXUtl") == 26_567_849_713_993_370_845_693_800_611_841 228 | end 229 | end 230 | -------------------------------------------------------------------------------- /test/test_helper.exs: -------------------------------------------------------------------------------- 1 | ExUnit.start() 2 | --------------------------------------------------------------------------------