Using Active Directory GUID with Ecto UUID field

This was a cool little problem!

First step, find the “correct” format of the expected UUID “4FC10CDB-5197-4B99-8058-17603B0A21AF”

iex(50)> Ecto.UUID.dump("4FC10CDB-5197-4B99-8058-17603B0A21AF")
{:ok, <<79, 193, 12, 219, 81, 151, 75, 153, 128, 88, 23, 96, 59, 10, 33, 175>>}

Hmmm, some of those numbers look similar. Let’s look at them side by side (aligned by comma):

[79,  193, 12,  219, 81,  151, 75,  153, 128, 88, 23, 96, 59, 10, 33, 175]
[219, 12,  193, 79,  151, 81,  153, 75,  128, 88, 23, 96, 59, 10, 33, 175]

In chunks:

[79,  193, 12,  219,  |  81,  151,   |  75,  153,  |  128, 88, 23, 96, 59, 10, 33, 175]
[219, 12,  193, 79,   |  151, 81,    |  153, 75,   |  128, 88, 23, 96, 59, 10, 33, 175]

So for some reason (someone else may understand the reason) the first 4 numbers are reversed, then the next two, and the next two again, but all the rest after that match (which is why “8058-17603B0A21AF” is decoded correctly).

So you can write a function to convert as follows:

defmodule Test do
  def convert(list) do
    {first4, rest} = Enum.split(list, 4)
    {second2, rest} = Enum.split(rest, 2)
    {third2, rest} = Enum.split(rest, 2)

    Enum.reverse(first4)
    |> Enum.concat(Enum.reverse(second2))
    |> Enum.concat(Enum.reverse(third2))
    |> Enum.concat(rest)
  end
end

Which can then be used for the desired output:

iex(55)> list = [219, 12, 193, 79, 151, 81, 153, 75, 128, 88, 23, 96, 59, 10, 33, 175]
[219, 12, 193, 79, 151, 81, 153, 75, 128, 88, 23, 96, 59, 10, 33, 175]
iex(56)> Test.convert(list) |> :binary.list_to_bin() |> Ecto.UUID.load()
{:ok, "4fc10cdb-5197-4b99-8058-17603b0a21af"}