zf

zenflows testing
git clone https://s.sonu.ch/~srfsh/zf.git
Log | Files | Refs | Submodules | README | LICENSE

uuid.ex (5806B)


      1 defmodule Ecto.UUID do
      2   @moduledoc """
      3   An Ecto type for UUID strings.
      4   """
      5 
      6   use Ecto.Type
      7 
      8   @typedoc """
      9   A hex-encoded UUID string.
     10   """
     11   @type t :: <<_::288>>
     12 
     13   @typedoc """
     14   A raw binary representation of a UUID.
     15   """
     16   @type raw :: <<_::128>>
     17 
     18   @doc false
     19   def type, do: :uuid
     20 
     21   @doc """
     22   Casts to a UUID.
     23   """
     24   @spec cast(t | raw | any) :: {:ok, t} | :error
     25   def cast(<< a1, a2, a3, a4, a5, a6, a7, a8, ?-,
     26               b1, b2, b3, b4, ?-,
     27               c1, c2, c3, c4, ?-,
     28               d1, d2, d3, d4, ?-,
     29               e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12 >>) do
     30     << c(a1), c(a2), c(a3), c(a4),
     31        c(a5), c(a6), c(a7), c(a8), ?-,
     32        c(b1), c(b2), c(b3), c(b4), ?-,
     33        c(c1), c(c2), c(c3), c(c4), ?-,
     34        c(d1), c(d2), c(d3), c(d4), ?-,
     35        c(e1), c(e2), c(e3), c(e4),
     36        c(e5), c(e6), c(e7), c(e8),
     37        c(e9), c(e10), c(e11), c(e12) >>
     38   catch
     39     :error -> :error
     40   else
     41     hex_uuid -> {:ok, hex_uuid}
     42   end
     43 
     44   def cast(<< _::128 >> = raw_uuid), do: {:ok, encode(raw_uuid)}
     45   def cast(_), do: :error
     46 
     47   @doc """
     48   Same as `cast/1` but raises `Ecto.CastError` on invalid arguments.
     49   """
     50   @spec cast!(t | raw | any) :: t
     51   def cast!(value) do
     52     case cast(value) do
     53       {:ok, hex_uuid} -> hex_uuid
     54       :error -> raise Ecto.CastError, type: __MODULE__, value: value
     55     end
     56   end
     57 
     58   @compile {:inline, c: 1}
     59 
     60   defp c(?0), do: ?0
     61   defp c(?1), do: ?1
     62   defp c(?2), do: ?2
     63   defp c(?3), do: ?3
     64   defp c(?4), do: ?4
     65   defp c(?5), do: ?5
     66   defp c(?6), do: ?6
     67   defp c(?7), do: ?7
     68   defp c(?8), do: ?8
     69   defp c(?9), do: ?9
     70   defp c(?A), do: ?a
     71   defp c(?B), do: ?b
     72   defp c(?C), do: ?c
     73   defp c(?D), do: ?d
     74   defp c(?E), do: ?e
     75   defp c(?F), do: ?f
     76   defp c(?a), do: ?a
     77   defp c(?b), do: ?b
     78   defp c(?c), do: ?c
     79   defp c(?d), do: ?d
     80   defp c(?e), do: ?e
     81   defp c(?f), do: ?f
     82   defp c(_),  do: throw(:error)
     83 
     84   @doc """
     85   Converts a string representing a UUID into a raw binary.
     86   """
     87   @spec dump(t | any) :: {:ok, raw} | :error
     88   def dump(<< a1, a2, a3, a4, a5, a6, a7, a8, ?-,
     89               b1, b2, b3, b4, ?-,
     90               c1, c2, c3, c4, ?-,
     91               d1, d2, d3, d4, ?-,
     92               e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12 >>) do
     93     << d(a1)::4, d(a2)::4, d(a3)::4, d(a4)::4,
     94        d(a5)::4, d(a6)::4, d(a7)::4, d(a8)::4,
     95        d(b1)::4, d(b2)::4, d(b3)::4, d(b4)::4,
     96        d(c1)::4, d(c2)::4, d(c3)::4, d(c4)::4,
     97        d(d1)::4, d(d2)::4, d(d3)::4, d(d4)::4,
     98        d(e1)::4, d(e2)::4, d(e3)::4, d(e4)::4,
     99        d(e5)::4, d(e6)::4, d(e7)::4, d(e8)::4,
    100        d(e9)::4, d(e10)::4, d(e11)::4, d(e12)::4 >>
    101   catch
    102     :error -> :error
    103   else
    104     raw_uuid -> {:ok, raw_uuid}
    105   end
    106 
    107   def dump(_), do: :error
    108 
    109   @compile {:inline, d: 1}
    110 
    111   defp d(?0), do: 0
    112   defp d(?1), do: 1
    113   defp d(?2), do: 2
    114   defp d(?3), do: 3
    115   defp d(?4), do: 4
    116   defp d(?5), do: 5
    117   defp d(?6), do: 6
    118   defp d(?7), do: 7
    119   defp d(?8), do: 8
    120   defp d(?9), do: 9
    121   defp d(?A), do: 10
    122   defp d(?B), do: 11
    123   defp d(?C), do: 12
    124   defp d(?D), do: 13
    125   defp d(?E), do: 14
    126   defp d(?F), do: 15
    127   defp d(?a), do: 10
    128   defp d(?b), do: 11
    129   defp d(?c), do: 12
    130   defp d(?d), do: 13
    131   defp d(?e), do: 14
    132   defp d(?f), do: 15
    133   defp d(_),  do: throw(:error)
    134 
    135   @doc """
    136   Same as `dump/1` but raises `Ecto.ArgumentError` on invalid arguments.
    137   """
    138   @spec dump!(t | any) :: raw
    139   def dump!(value) do
    140     case dump(value) do
    141       {:ok, raw_uuid} -> raw_uuid
    142       :error -> raise ArgumentError, "cannot dump given UUID to binary: #{inspect(value)}"
    143     end
    144   end
    145 
    146   @doc """
    147   Converts a binary UUID into a string.
    148   """
    149   @spec load(raw | any) :: {:ok, t} | :error
    150   def load(<<_::128>> = raw_uuid), do: {:ok, encode(raw_uuid)}
    151 
    152   def load(<<_::64, ?-, _::32, ?-, _::32, ?-, _::32, ?-, _::96>> = string) do
    153     raise ArgumentError, "trying to load string UUID as Ecto.UUID: #{inspect string}. " <>
    154                          "Maybe you wanted to declare :uuid as your database field?"
    155   end
    156 
    157   def load(_), do: :error
    158 
    159   @doc """
    160   Same as `load/1` but raises `Ecto.ArgumentError` on invalid arguments.
    161   """
    162   @spec load!(raw | any) :: t
    163   def load!(value) do
    164     case load(value) do
    165       {:ok, hex_uuid} -> hex_uuid
    166       :error -> raise ArgumentError, "cannot load given binary as UUID: #{inspect(value)}"
    167     end
    168   end
    169 
    170   @doc """
    171   Generates a random, version 4 UUID.
    172   """
    173   @spec generate() :: t
    174   def generate(), do: encode(bingenerate())
    175 
    176   @doc """
    177   Generates a random, version 4 UUID in the binary format.
    178   """
    179   @spec bingenerate() :: raw
    180   def bingenerate() do
    181     <<u0::48, _::4, u1::12, _::2, u2::62>> = :crypto.strong_rand_bytes(16)
    182     <<u0::48, 4::4, u1::12, 2::2, u2::62>>
    183   end
    184 
    185   # Callback invoked by autogenerate fields.
    186   @doc false
    187   def autogenerate, do: generate()
    188 
    189   @spec encode(raw) :: t
    190   defp encode(<< a1::4, a2::4, a3::4, a4::4,
    191                  a5::4, a6::4, a7::4, a8::4,
    192                  b1::4, b2::4, b3::4, b4::4,
    193                  c1::4, c2::4, c3::4, c4::4,
    194                  d1::4, d2::4, d3::4, d4::4,
    195                  e1::4, e2::4, e3::4, e4::4,
    196                  e5::4, e6::4, e7::4, e8::4,
    197                  e9::4, e10::4, e11::4, e12::4 >>) do
    198     << e(a1), e(a2), e(a3), e(a4), e(a5), e(a6), e(a7), e(a8), ?-,
    199        e(b1), e(b2), e(b3), e(b4), ?-,
    200        e(c1), e(c2), e(c3), e(c4), ?-,
    201        e(d1), e(d2), e(d3), e(d4), ?-,
    202        e(e1), e(e2), e(e3), e(e4), e(e5), e(e6), e(e7), e(e8), e(e9), e(e10), e(e11), e(e12) >>
    203   end
    204 
    205   @compile {:inline, e: 1}
    206 
    207   defp e(0),  do: ?0
    208   defp e(1),  do: ?1
    209   defp e(2),  do: ?2
    210   defp e(3),  do: ?3
    211   defp e(4),  do: ?4
    212   defp e(5),  do: ?5
    213   defp e(6),  do: ?6
    214   defp e(7),  do: ?7
    215   defp e(8),  do: ?8
    216   defp e(9),  do: ?9
    217   defp e(10), do: ?a
    218   defp e(11), do: ?b
    219   defp e(12), do: ?c
    220   defp e(13), do: ?d
    221   defp e(14), do: ?e
    222   defp e(15), do: ?f
    223 end