diff --git a/CHANGELOG.md b/CHANGELOG.md index abe8ba9..8bda45c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,8 +5,24 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [Unreleased] -## v3.0.0 +## v3.0.0 (15.07.2023) + +Breaking change, ShortUUIDs created by `< v3.0.0` will produce bad results when decoded. +The new output of `encode` is the reverse of the previous output. +This follows a change in other languages ShortUUID libraries. + +To migrate ShortUUIDs created by `< v3.0.0` reverse them before passing to `decode`. + +```elixir +# UUID "00000001-0001-0001-0001-000000000001" encoded using v2.1.2 to "UD6ibhr3V4YXvriP822222" +# reversing the encoded string before decode with v3.0.0 will produce the correct result +iex> "UD6ibhr3V4YXvriP822222" |> String.reverse() |> ShortUUID.decode!() +"00000001-0001-0001-0001-000000000001" +``` + +### Changed * move most significant bit to the beginning of the encoded result similar to libraries in other languages (most importantly python shortuuid) * drop support for decoding of un-padded ShortUUIDs * drop support for formats other than regular hyphenated and unhyphenated UUIDs, MS format and binary UUIDs like are stored in PostgreSQL uuid type @@ -15,13 +31,21 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Benchmarks Results are not comparable to previous benchmarks due to them being run on a different system - -Operating System: macOS -CPU Information: Apple M2 Max -Number of Available Cores: 12 -Available memory: 32 GB -Elixir 1.15.2 -Erlang 25.3.2.3 + ``` + Operating System: macOS + CPU Information: Apple M2 Max + Number of Available Cores: 12 + Available memory: 32 GB + Elixir 1.15.2 + Erlang 25.3.2.3 + + Benchmark suite executing with the following configuration: + warmup: 2 s + time: 5 s + memory time: 0 ns + parallel: 1 + inputs: none specified + ``` * v3.0.0 ``` diff --git a/README.md b/README.md index 4d5f033..95e030c 100644 --- a/README.md +++ b/README.md @@ -43,18 +43,16 @@ iex> "00000001-0001-0001-0001-000000000001" |> ShortUUID.encode ``` -To decode ShortUUID created with version < v3.0.0 use one of two methods +To migrate ShortUUIDs created using `< v3.0.0` reverse them before passing to `decode`. ```elixir -iex> "UD6ibhr3V4YXvriP822222" |> String.reverse() |> ShortUUID.decode() -{:ok, "00000001-0001-0001-0001-000000000001"} - -iex> "UD6ibhr3V4YXvriP822222" |> ShortUUID.decode(legacy: true) -{:ok, "00000001-0001-0001-0001-000000000001"} - +# UUID "00000001-0001-0001-0001-000000000001" encoded using v2.1.2 to "UD6ibhr3V4YXvriP822222" +# reversing the encoded string before decode with v3.0.0 will produce the correct result +iex> "UD6ibhr3V4YXvriP822222" |> String.reverse() |> ShortUUID.decode!() +"00000001-0001-0001-0001-000000000001" ``` -Decoding legacy ShortUUIDs without either reversing the string first or using the legacy option will not fail but produce an incorrect result +*Warning:* Decoding ShortUUIDs created using a version `< v3.0.0` without reversing the string first will not fail but produce an incorrect result ```elixir iex> "UD6ibhr3V4YXvriP822222" |> ShortUUID.decode!() === "00000001-0001-0001-0001-000000000001" @@ -70,7 +68,7 @@ Add `:shortuuid` to your list of dependencies in `mix.exs`: ```elixir def deps do [ - {:shortuuid, "~> 2.0"} + {:shortuuid, "~> 3.0"} ] end ``` diff --git a/lib/shortuuid.ex b/lib/shortuuid.ex index 0b1158b..bc5807e 100644 --- a/lib/shortuuid.ex +++ b/lib/shortuuid.ex @@ -122,13 +122,10 @@ defmodule ShortUUID do @doc """ Decodes a ShortUUID string into a UUID. """ - @spec decode(String.t(), keyword()) :: {:ok, String.t()} | {:error, String.t()} - def decode(shortuuid, opts \\ [legacy: false]) - + @spec decode(String.t()) :: {:ok, String.t()} | {:error, String.t()} def decode( <>, - legacy: false + c13::8, c14::8, c15::8, c16::8, c17::8, c18::8, c19::8, c20::8, c21::8, c22::8>> ) do uuid_int_value = [ @@ -178,19 +175,7 @@ defmodule ShortUUID do {:error, "Invalid input"} end - def decode( - <>, - legacy: true - ) do - decode( - <>, - legacy: false - ) - end - - def decode(_string, _opts) do + def decode(_string) do {:error, "Invalid input"} end @@ -199,9 +184,9 @@ defmodule ShortUUID do Raises an ArgumentError if the ShortUUID is invalid. """ - @spec decode!(String.t(), keyword()) :: String.t() | no_return() - def decode!(string, opts \\ [legacy: false]) do - case decode(string, opts) do + @spec decode!(String.t()) :: String.t() | no_return() + def decode!(string) do + case decode(string) do {:ok, uuid} -> uuid {:error, message} -> raise ArgumentError, message: message end diff --git a/test/shortuuid_test.exs b/test/shortuuid_test.exs index 092f37b..4a1ad73 100644 --- a/test/shortuuid_test.exs +++ b/test/shortuuid_test.exs @@ -118,7 +118,7 @@ defmodule ShortUUIDTest do end end - describe "decode/2" do + describe "decode/1" do test "decodes a valid shortuuid" do assert {:ok, "2a162ee5-02f4-4701-9e87-72762cbce5e2"} = ShortUUID.decode("9VprZJ9U7Tgg2PJ8BfTAek") @@ -177,18 +177,13 @@ defmodule ShortUUIDTest do assert {:error, _} = ShortUUID.decode(false) end - test "decodes legacy shortuuid" do - assert {:ok, "2a162ee5-02f4-4701-9e87-72762cbce5e2"} = - ShortUUID.decode("keATfB8JP2ggT7U9JZrpV9", legacy: true) + test "reversed legacy short UUID will produce correct result" do + assert {:ok, "00000001-0001-0001-0001-000000000001"} = + "UD6ibhr3V4YXvriP822222" |> String.reverse() |> ShortUUID.decode() end end - describe "decode!/2" do - test "decodes legacy shortuuid" do - assert "2a162ee5-02f4-4701-9e87-72762cbce5e2" = - ShortUUID.decode!("keATfB8JP2ggT7U9JZrpV9", legacy: true) - end - + describe "decode!/1" do test "raises an ArgumentError for and invalid ShortUUID" do assert_raise ArgumentError, fn -> ShortUUID.decode!("invalid-shortuuid")