Support 0.3.0 spec (#30)

* replace shell script with elixir script

* update to 0.3.0 spec

* update parser to support 0.3.0 spec

* use binary_part/3 for elixir 1.11 support

* add .exs extension to update_spec script
This commit is contained in:
sloane 2024-04-22 10:00:51 -04:00 committed by GitHub
parent f0e24c7231
commit eadb269342
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 83 additions and 21 deletions

View file

@ -174,17 +174,23 @@ defmodule TypeID do
Like `from_string/1` but raises an error if the string is invalid.
"""
@spec from_string!(String.t()) :: t() | no_return()
def from_string!(str) when byte_size(str) <= 26, do: from!("", str)
def from_string!(str) do
case String.split(str, <<@seperator>>) do
[prefix, suffix] when prefix != "" ->
from!(prefix, suffix)
size = byte_size(str)
[suffix] ->
from!("", suffix)
prefix =
str
|> binary_part(0, size - 26)
|> String.replace(~r/_$/, "")
_ ->
raise ArgumentError, "invalid TypeID"
suffix = binary_part(str, size - 26, 26)
if prefix == "" do
raise ArgumentError, "A TypeID without a prefix should not have a leading underscore"
end
from!(prefix, suffix)
end
@doc """
@ -258,11 +264,26 @@ defmodule TypeID do
end
defp validate_prefix!(prefix) do
unless prefix =~ ~r/^[a-z]{0,63}$/ do
raise ArgumentError, "invalid prefix: #{prefix}. prefix should match [a-z]{0,63}"
end
cond do
String.starts_with?(prefix, "_") ->
invalid_prefix!(prefix, "cannot start with an underscore")
:ok
String.ends_with?(prefix, "_") ->
invalid_prefix!(prefix, "cannot end with an underscore")
byte_size(prefix) > 63 ->
invalid_prefix!(prefix, "cannot be more than 63 characters")
not Regex.match?(~r/^[a-z_]*$/, prefix) ->
invalid_prefix!(prefix, "can contain only lowercase letters and underscores")
true ->
:ok
end
end
defp invalid_prefix!(prefix, message) do
raise ArgumentError, "invalid prefix: #{prefix}. #{message}"
end
defp validate_suffix!(suffix) do

View file

@ -4,7 +4,7 @@
# Each example contains an invalid TypeID string. Implementations are expected
# to throw an error when attempting to parse/validate these strings.
#
# Last updated: 2023-07-05
# Last updated: 2024-04-10 (for version 0.3.0 of the spec)
- name: prefix-uppercase
typeid: "PREFIX_00000000000000000000000000"
@ -18,9 +18,10 @@
typeid: "pre.fix_00000000000000000000000000"
description: "The prefix can't have symbols, it needs to be alphabetic"
- name: prefix-underscore
typeid: "pre_fix_00000000000000000000000000"
description: "The prefix can't have symbols, it needs to be alphabetic"
# Test removed in v0.3.0 we now allow underscores in the prefix
# - name: prefix-underscore
# typeid: "pre_fix_00000000000000000000000000"
# description: "The prefix can't have symbols, it needs to be alphabetic"
- name: prefix-non-ascii
typeid: "préfix_00000000000000000000000000"
@ -85,4 +86,14 @@
- name: suffix-overflow
# This is the first suffix that overflows into 129 bits
typeid: "prefix_8zzzzzzzzzzzzzzzzzzzzzzzzz"
description: "The should encode at most 128-bits"
description: "The suffix should encode at most 128-bits"
# Tests below were added in v0.3.0 when we started allowing '_' within the
# type prefix.
- name: prefix-underscore-start
typeid: "_prefix_00000000000000000000000000"
description: "The prefix can't start with an underscore"
- name: prefix-underscore-end
typeid: "prefix__00000000000000000000000000"
description: "The prefix can't end with an underscore"

View file

@ -23,7 +23,7 @@
# note that not all of them are UUIDv7s. When *generating* new random typeids,
# implementations should always use UUIDv7s.
#
# Last updated: 2023-07-05
# Last updated: 2024-04-10 (for version 0.3.0 of the spec)
- name: nil
typeid: "00000000000000000000000000"
@ -64,3 +64,10 @@
typeid: "prefix_01h455vb4pex5vsknk084sn02q"
prefix: "prefix"
uuid: "01890a5d-ac96-774b-bcce-b302099a8057"
# Tests below were added in v0.3.0 when we started allowing '_' within the
# type prefix.
- name: prefix-underscore
typeid: "pre_fix_00000000000000000000000000"
prefix: "pre_fix"
uuid: "00000000-0000-0000-0000-000000000000"

27
scripts/update_spec.exs Executable file
View file

@ -0,0 +1,27 @@
#!/usr/bin/env -S ERL_FLAGS=+B elixir
Mix.install(req: "~> 0.4")
files = [
{"https://raw.githubusercontent.com/jetpack-io/typeid/main/spec/invalid.yml", "priv/spec/invalid.yml"},
{"https://raw.githubusercontent.com/jetpack-io/typeid/main/spec/valid.yml", "priv/spec/valid.yml"}
]
IO.puts("Updating spec YAML files")
:ok = for {src, dest} <- files, reduce: :ok do
:ok ->
IO.write("Downloading #{src} to #{dest}... ")
with {:ok, io} <- File.open(dest, [:write]),
{:ok, _} <- Req.get(src, into: IO.binstream(io, 500)) do
IO.puts("OK")
:ok
else
other ->
IO.puts("ERROR")
other
end
failure -> failure
end
IO.puts("Done!")

View file

@ -1,4 +0,0 @@
#!/usr/bin/env bash -ex
wget https://raw.githubusercontent.com/jetpack-io/typeid/main/spec/invalid.yml -O priv/spec/invalid.yml
wget https://raw.githubusercontent.com/jetpack-io/typeid/main/spec/valid.yml -O priv/spec/valid.yml