Last active
August 29, 2015 13:56
-
-
Save caindy/8821426 to your computer and use it in GitHub Desktop.
Elixir module to create unique identifiers of specified length, with serialization to and from strings. Put here to solicit feedback on coding style/correctness, as I am new to Elixir.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
defmodule Hello.Util.UUID do | |
def new(byte_count // 16) do | |
dividend = div(byte_count, 16) | |
remainder = rem(byte_count, 16) | |
cnt = case remainder do | |
r when r === 0 -> dividend | |
_ -> dividend + remainder | |
end | |
make cnt, byte_count, <<>> | |
end | |
defp make(0, byte_count, acc), do: | |
binary_part(acc, 0, byte_count) | |
defp make(cnt, byte_count, acc) do | |
u = :ossp_uuid.make :v4, :binary | |
make(cnt - 1, byte_count, acc <> u) | |
end | |
def valid?(uuid, bytes // 16) | |
def valid?(uuid, bytes) when is_binary(uuid) do | |
case uuid do | |
<<_::[size(bytes), binary]>> -> true | |
_ -> false | |
end | |
end | |
def valid?(uuid, bytes) when is_list(uuid) do | |
chars = bytes * 2 | |
{:ok, r} = Regex.compile("[A-F0-9]{#{chars}}") | |
Regex.match?(r, uuid) and length_valid?(uuid, chars) | |
end | |
defp length_valid?(uuid, chars) when is_binary(uuid), do: | |
length_valid?(bitstring_to_list(uuid), chars) | |
defp length_valid?(uuid, chars) when is_list(uuid), do: | |
length(uuid) === chars | |
def to_string(uuid) when is_binary(uuid) do | |
l = lc <<nibble::4>> inbits uuid, do: hd(integer_to_list(nibble, 16)) | |
:erlang.list_to_binary l | |
end | |
def from_string(uuid) when is_binary(uuid), do: | |
from_string(bitstring_to_list(uuid)) | |
def from_string(uuid) when is_list(uuid), do: | |
append_byte(uuid, <<>>) | |
defp append_byte([], acc), do: acc | |
defp append_byte([x,y|rest], acc), do: | |
append_byte(rest, acc <> <<list_to_integer([x, y], 16)>>) | |
end |
Hi Peter, thanks for checking this out!
So, I've been using the if/unless/cond
for nil tests, mostly, but I agree the case
here obscures the intent. In fact, this code was wrong. Here's the corrected version.
def new(byte_count // 16) do
dividend = div(byte_count, 16)
add = if rem(byte_count, 16) > 0, do: 1, else: 0
make (dividend + add), byte_count, <<>>
end
Thanks for your feedback 😊
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I'm also new to Elixir, so keep that in mind :)
In lines 6-9,
r when r === 0 ->
instead of just a0 ->
?cnt = dividend + remainder
. Or did I overlook something?As said, I'm new, and I'm glad to have this learning opportunity to learn on someone else's code example (probably I should push something public myself, but felt too shy :))