Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F85596056
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Award Token
Flag For Later
Size
10 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/lib/flake_id.ex b/lib/flake_id.ex
index 20428cf..997fcee 100644
--- a/lib/flake_id.ex
+++ b/lib/flake_id.ex
@@ -1,125 +1,100 @@
# FlakeID: Decentralized, k-ordered ID generation service
# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: LGPL-3.0-only
defmodule FlakeID do
@moduledoc """
Decentralized, k-ordered ID generation service.
"""
import Kernel, except: [to_string: 1]
@doc """
Converts a binary Flake to a String
## Examples
iex> FlakeID.to_string(<<0, 0, 1, 109, 67, 124, 251, 125, 95, 28, 30, 59, 36, 42, 0, 0>>)
"9n2ciuz1wdesFnrGJU"
"""
- # compatibility with older serial integers
- def to_string(<<0::integer-size(64), id::integer-size(64)>>) do
- Kernel.to_string(id)
- end
-
def to_string(<<_::integer-size(64), _::integer-size(48), _::integer-size(16)>> = binary_flake) do
<<integer::integer-size(128)>> = binary_flake
Base62.encode(integer)
end
def to_string(string), do: string
@doc """
Converts a String to a binary Flake
## Examples
iex> FlakeID.from_string("9n2ciuz1wdesFnrGJU")
<<0, 0, 1, 109, 67, 124, 251, 125, 95, 28, 30, 59, 36, 42, 0, 0>>
"""
- @spec from_string(String.t() | integer) :: nil | <<_::128>>
+ @spec from_string(binary()) :: nil | <<_::128>>
def from_string(string)
-
- # zero or -1 is a null flake
- for i <- [-1, 0] do
- def from_string(unquote(i)), do: <<0::integer-size(128)>>
- def from_string(unquote(Kernel.to_string(i))), do: <<0::integer-size(128)>>
- end
-
- def from_string(int) when is_integer(int) do
- int
- |> Kernel.to_string()
- |> from_string()
- end
-
def from_string(<<_::integer-size(128)>> = flake), do: flake
-
- def from_string(string) when is_binary(string) and byte_size(string) < 18 do
- case Integer.parse(string) do
- {id, ""} -> <<0::integer-size(64), id::integer-size(64)>>
- _ -> nil
- end
- end
-
+ def from_string(string) when is_binary(string) and byte_size(string) < 18, do: nil
def from_string(string), do: string |> Base62.decode!() |> from_integer
@doc """
Converts a binary Flake to an integer
## Examples
iex> FlakeID.to_integer(<<0, 0, 1, 109, 67, 124, 251, 125, 95, 28, 30, 59, 36, 42, 0, 0>>)
28939165907792829150732718047232
"""
@spec to_integer(<<_::128>>) :: non_neg_integer
def to_integer(binary_flake)
def to_integer(<<integer::integer-size(128)>>), do: integer
@doc """
Converts an integer to a binary Flake
## Examples
iex> FlakeID.from_integer(28939165907792829150732718047232)
<<0, 0, 1, 109, 67, 124, 251, 125, 95, 28, 30, 59, 36, 42, 0, 0>>
"""
@spec from_integer(integer) :: <<_::128>>
def from_integer(integer) do
<<_time::integer-size(64), _node::integer-size(48), _seq::integer-size(16)>> =
<<integer::integer-size(128)>>
end
@doc """
Generates a string with Flake
"""
@spec get :: String.t()
def get, do: FlakeID.Worker.get() |> to_string()
@doc """
Checks that ID is a valid FlakeID
## Examples
iex> FlakeID.flake_id?("9n2ciuz1wdesFnrGJU")
true
iex> FlakeID.flake_id?("#cofe")
false
iex> FlakeID.flake_id?("pleroma.social")
false
"""
@spec flake_id?(String.t()) :: boolean
def flake_id?(id), do: flake_id?(String.to_charlist(id), true)
defp flake_id?([c | cs], true) when c >= ?0 and c <= ?9, do: flake_id?(cs, true)
defp flake_id?([c | cs], true) when c >= ?A and c <= ?Z, do: flake_id?(cs, true)
defp flake_id?([c | cs], true) when c >= ?a and c <= ?z, do: flake_id?(cs, true)
defp flake_id?([], true), do: true
defp flake_id?(_, _), do: false
end
diff --git a/lib/flake_id/ecto/compat_type.ex b/lib/flake_id/ecto/compat_type.ex
new file mode 100644
index 0000000..1f3fdb1
--- /dev/null
+++ b/lib/flake_id/ecto/compat_type.ex
@@ -0,0 +1,68 @@
+# FlakeID: Decentralized, k-ordered ID generation service
+# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: LGPL-3.0-only
+
+defmodule FlakeID.Ecto.CompatType do
+ @moduledoc """
+ Provides a compatibility Ecto type for someone wishes to migrate from integer ids to flakes.
+
+ ## Schema Example
+
+ @primary_key {:id, FlakeID.Ecto.CompatType, autogenerate: true}
+
+ schema "posts" do
+ add :body, :string
+ end
+
+ """
+
+ import Kernel, except: [to_string: 1]
+
+ @behaviour Ecto.Type
+
+ def embed_as(_), do: :self
+
+ def equal?(term1, term2), do: term1 == term2
+
+ def type, do: :uuid
+
+ defdelegate autogenerate, to: FlakeID, as: :get
+
+ def cast(value) do
+ {:ok, to_string(value)}
+ end
+
+ def load(value) do
+ {:ok, to_string(value)}
+ end
+
+ def dump(value) do
+ {:ok, from_string(value)}
+ end
+
+ defp to_string(<<0::integer-size(64), id::integer-size(64)>>), do: Kernel.to_string(id)
+ defp to_string(binary_flake), do: FlakeID.to_string(binary_flake)
+
+ # zero or -1 is a null flake
+ for i <- [-1, 0] do
+ defp from_string(unquote(i)), do: <<0::integer-size(128)>>
+ defp from_string(unquote(Kernel.to_string(i))), do: <<0::integer-size(128)>>
+ end
+
+ defp from_string(int) when is_integer(int) do
+ int
+ |> Kernel.to_string()
+ |> from_string()
+ end
+
+ defp from_string(<<_::integer-size(128)>> = flake), do: flake
+
+ defp from_string(string) when is_binary(string) and byte_size(string) < 18 do
+ case Integer.parse(string) do
+ {id, ""} -> <<0::integer-size(64), id::integer-size(64)>>
+ _ -> nil
+ end
+ end
+
+ defp from_string(string), do: FlakeID.from_string(string)
+end
diff --git a/test/flake_id/ecto/compat_type_test.exs b/test/flake_id/ecto/compat_type_test.exs
new file mode 100644
index 0000000..c5ea4ce
--- /dev/null
+++ b/test/flake_id/ecto/compat_type_test.exs
@@ -0,0 +1,57 @@
+defmodule FlakeID.Ecto.CompatTypeTest do
+ use ExUnit.Case, async: true
+
+ alias FlakeID.Ecto.CompatType
+
+ @flake_string "9n2ciuz1wdesFnrGJU"
+ @flake_binary <<0, 0, 1, 109, 67, 124, 251, 125, 95, 28, 30, 59, 36, 42, 0, 0>>
+ @fake_flake <<0::integer-size(64), 42::integer-size(64)>>
+
+ test "cast/1" do
+ assert CompatType.cast(@flake_binary) == {:ok, @flake_string}
+ assert CompatType.cast(@flake_string) == {:ok, @flake_string}
+ end
+
+ test "load/1" do
+ assert CompatType.load(@flake_binary) == {:ok, @flake_string}
+ assert CompatType.load(@flake_string) == {:ok, @flake_string}
+ end
+
+ test "dump/1" do
+ assert CompatType.dump(@flake_string) == {:ok, @flake_binary}
+ assert CompatType.dump(@flake_binary) == {:ok, @flake_binary}
+ end
+
+ test "equal?/2" do
+ assert CompatType.equal?(@flake_binary, @flake_binary) == true
+ end
+
+ test "autogenerate/0" do
+ flake = CompatType.autogenerate()
+
+ assert String.valid?(flake)
+ assert FlakeID.flake_id?(flake)
+ end
+
+ describe "fake flakes (compatibility with older serial integers)" do
+ test "with an integer" do
+ assert CompatType.dump(42) == {:ok, @fake_flake}
+ end
+
+ test "with an integer as string" do
+ assert CompatType.dump("42") == {:ok, @fake_flake}
+ end
+
+ test "zero or -1 is a null flake" do
+ null_flake = <<0::integer-size(128)>>
+ assert CompatType.dump(0) == {:ok, null_flake}
+ assert CompatType.dump(-1) == {:ok, null_flake}
+ assert CompatType.dump("0") == {:ok, null_flake}
+ assert CompatType.dump("-1") == {:ok, null_flake}
+ end
+
+ test "cast" do
+ assert CompatType.cast(@fake_flake) == {:ok, "42"}
+ end
+ end
+end
diff --git a/test/flake_id_test.exs b/test/flake_id_test.exs
index 8bcad76..927088d 100644
--- a/test/flake_id_test.exs
+++ b/test/flake_id_test.exs
@@ -1,86 +1,57 @@
defmodule FlakeIDTest do
use ExUnit.Case, async: true
doctest FlakeID
@flake_string "9n2ciuz1wdesFnrGJU"
@flake_binary <<0, 0, 1, 109, 67, 124, 251, 125, 95, 28, 30, 59, 36, 42, 0, 0>>
@flake_integer 28_939_165_907_792_829_150_732_718_047_232
test "flake_id?/1" do
assert FlakeID.flake_id?(@flake_string)
refute FlakeID.flake_id?("http://example.com/activities/3ebbadd1-eb14-4e20-8118-b6f79c0c7b0b")
refute FlakeID.flake_id?("#cofe")
end
test "get/0" do
flake = FlakeID.get()
assert String.valid?(flake)
assert FlakeID.flake_id?(flake)
end
describe "to_string/1" do
test "with binary" do
assert FlakeID.to_string(@flake_binary) == @flake_string
bin = <<1::integer-size(64), 2::integer-size(48), 3::integer-size(16)>>
assert FlakeID.to_string(bin) == "LygHa16ApeN"
end
test "does nothing with other types" do
assert FlakeID.to_string("cofe") == "cofe"
assert FlakeID.to_string(42) == 42
end
end
describe "from_string/1" do
test "with a flake string" do
assert FlakeID.from_string(@flake_string) == @flake_binary
end
- test "with an integer" do
- assert FlakeID.from_string(42) == <<0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42>>
- end
-
- test "with an integer as string" do
- assert FlakeID.from_string("42") == <<0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42>>
- end
-
test "with a flake binary" do
assert FlakeID.from_string(@flake_binary) == @flake_binary
end
test "with a non flake string" do
assert FlakeID.from_string("cofe") == nil
end
end
test "to_integer/1" do
assert FlakeID.to_integer(@flake_binary) == @flake_integer
end
test "from_integer/1" do
assert FlakeID.from_integer(@flake_integer) == @flake_binary
end
-
- describe "fake flakes (compatibility with older serial integers)" do
- test "from_string/1" do
- fake_flake = <<0::integer-size(64), 42::integer-size(64)>>
- assert FlakeID.from_string("42") == fake_flake
- assert FlakeID.from_string(42) == fake_flake
- end
-
- test "to_string/1" do
- fake_flake = <<0::integer-size(64), 42::integer-size(64)>>
- assert FlakeID.to_string(fake_flake) == "42"
- end
-
- test "zero or -1 is a null flake" do
- null_flake = <<0::integer-size(128)>>
- assert FlakeID.from_string(0) == null_flake
- assert FlakeID.from_string(-1) == null_flake
- assert FlakeID.from_string("0") == null_flake
- assert FlakeID.from_string("-1") == null_flake
- end
- end
end
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Tue, Jul 21, 3:04 AM (4 h, 8 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1695638
Default Alt Text
(10 KB)
Attached To
Mode
R17 flake_id
Attached
Detach File
Event Timeline
Log In to Comment