Add TYPEID sigil and use it for inspect

This commit is contained in:
Brett Beatty 2025-06-29 20:51:04 -06:00
parent 5f45fe9306
commit 21129e0011
2 changed files with 56 additions and 10 deletions

View file

@ -26,7 +26,7 @@ defmodule TypeID do
### Example
iex> TypeID.new("acct")
#TypeID<"acct_01h45y0sxkfmntta78gqs1vsw6">
~TYPEID"acct_01h45y0sxkfmntta78gqs1vsw6"
"""
@spec new(prefix :: String.t()) :: t()
@ -54,6 +54,20 @@ defmodule TypeID do
prefix
end
@doc """
A sigil for creating a `TypeID`.
### Example
iex> ~TYPEID"org_01h45y0sxkfmntta78gqs1vsw6"
~TYPEID"org_01h45y0sxkfmntta78gqs1vsw6"
"""
@spec sigil_TYPEID(String.t(), charlist()) :: t()
def sigil_TYPEID(string, _modifiers) do
from_string!(string)
end
@doc """
Returns the base 32 encoded suffix of the given `t:t/0`
@ -160,7 +174,7 @@ defmodule TypeID do
iex> {:ok, tid} = TypeID.from("invoice", "01h45ydzqkemsb9x8gq2q7vpvb")
iex> tid
#TypeID<"invoice_01h45ydzqkemsb9x8gq2q7vpvb">
~TYPEID"invoice_01h45ydzqkemsb9x8gq2q7vpvb"
"""
@spec from(prefix :: String.t(), suffix :: String.t()) :: {:ok, t()} | :error
@ -200,7 +214,7 @@ defmodule TypeID do
iex> {:ok, tid} = TypeID.from_string("game_01h45yhtgqfhxbcrsfbhxdsdvy")
iex> tid
#TypeID<"game_01h45yhtgqfhxbcrsfbhxdsdvy">
~TYPEID"game_01h45yhtgqfhxbcrsfbhxdsdvy"
"""
@spec from_string(String.t()) :: {:ok, t()} | :error
@ -226,7 +240,7 @@ defmodule TypeID do
iex> {:ok, tid} = TypeID.from_uuid("device", "01890be9-b248-777e-964e-af1d244f997d")
iex> tid
#TypeID<"device_01h45ykcj8exz9cknf3mj4z6bx">
~TYPEID"device_01h45ykcj8exz9cknf3mj4z6bx"
"""
@spec from_uuid(prefix :: String.t(), uuid :: String.t()) :: {:ok, t()} | :error
@ -253,7 +267,7 @@ defmodule TypeID do
iex> {:ok, tid} = TypeID.from_uuid_bytes("policy", <<1, 137, 11, 235, 83, 221, 116, 212, 161, 42, 205, 139, 182, 243, 175, 110>>)
iex> tid
#TypeID<"policy_01h45ypmyxekaa2apdhevf7bve">
~TYPEID"policy_01h45ypmyxekaa2apdhevf7bve"
"""
@spec from_uuid_bytes(prefix :: String.t(), uuid_bytes :: binary()) :: {:ok, t()} | :error
@ -319,7 +333,7 @@ defimpl Inspect, for: TypeID do
import Inspect.Algebra
def inspect(tid, _opts) do
concat(["#TypeID<\"", TypeID.to_string(tid), "\">"])
concat(["~TYPEID\"", TypeID.to_string(tid), "\""])
end
end

View file

@ -1,5 +1,6 @@
defmodule TypeIDTest do
use ExUnit.Case, async: true
import TypeID, only: :sigils
doctest TypeID, except: [new: 2]
describe "new/1" do
@ -21,21 +22,45 @@ defmodule TypeIDTest do
describe "prefix/1" do
test "returns the prefix of the given TypeID" do
tid = TypeID.from_string!("test_01h44had5rfswbvpc383ktj0aa")
tid = ~TYPEID"test_01h44had5rfswbvpc383ktj0aa"
assert "test" == TypeID.prefix(tid)
end
end
describe "sigil_TYPEID/2" do
test "constructs a TypeID" do
tid = ~TYPEID"test_01jyzaw6jbe07t67xf6aa22qdd"
assert "test" == TypeID.prefix(tid)
assert "01jyzaw6jbe07t67xf6aa22qdd" == TypeID.suffix(tid)
end
test "validates prefix" do
expected = "invalid prefix: _test. cannot start with an underscore"
assert_raise ArgumentError, expected, fn ->
~TYPEID"_test_01jyzaw6jbe07t67xf6aa22qdd"
end
end
test "validates suffix" do
expected = "invalid base 32 suffix"
assert_raise ArgumentError, expected, fn ->
~TYPEID"test_91jyzaw6jbe07t67xf6aa22qdd"
end
end
end
describe "suffix/1" do
test "returns the base 32 suffix of the given TypeID" do
tid = TypeID.from_string!("test_01h44had5rfswbvpc383ktj0aa")
tid = ~TYPEID"test_01h44had5rfswbvpc383ktj0aa"
assert "01h44had5rfswbvpc383ktj0aa" == TypeID.suffix(tid)
end
end
describe "serialization" do
test "to_string/1 and from_string!/1 are idempotent" do
tid1 = TypeID.from_string!("test_01h44had5rfswbvpc383ktj0aa")
tid1 = ~TYPEID"test_01h44had5rfswbvpc383ktj0aa"
tid2 =
tid1
@ -68,8 +93,15 @@ defmodule TypeIDTest do
end
test "verification" do
tid = TypeID.from_string!("test_01h44yssjcf5daefvfr0yb70s8")
tid = ~TYPEID"test_01h44yssjcf5daefvfr0yb70s8"
assert "test" == TypeID.prefix(tid)
assert "018909ec-e64c-795a-a73f-6fc03cb38328" == TypeID.uuid(tid)
end
describe "Inspect" do
test "inspects as sigil" do
assert inspect(~TYPEID"test_01jyzbm384fm3aaq2pvabybpmf") ==
~S(~TYPEID"test_01jyzbm384fm3aaq2pvabybpmf")
end
end
end