defmodule BSON.Binary do @moduledoc """ Represents BSON binary type """ @type t :: %__MODULE__{ binary: binary, subtype: :generic | :function | :binary_old | :uuid_old | :uuid | :md5 | 0x80..0xFF } defstruct binary: nil, subtype: :generic defimpl Inspect do def inspect(%BSON.Binary{binary: value, subtype: :generic}, _opts) do "#BSON.Binary<#{Base.encode16(value, case: :lower)}>" end def inspect(%BSON.Binary{binary: value, subtype: subtype}, _opts) do "#BSON.Binary<#{Base.encode16(value, case: :lower)}, #{subtype}>" end end end defmodule BSON.ObjectId do @moduledoc """ Represents BSON ObjectId type """ defstruct [:value] @type t :: %__MODULE__{value: <<_::96>>} @doc """ Creates a new ObjectId from the consisting parts. For generating a new `BSON.ObjectId` you'd probably want to use `Mongo.object_id/0`. """ def new(machine_id, proc_id, secs, counter) do value = <> %BSON.ObjectId{value: value} end @doc """ Converts string representation of ObjectId to a BSON.ObjectId struct """ def decode!( <> ) do <> catch :throw, :error -> raise ArgumentError else value -> %BSON.ObjectId{value: value} end @doc """ Converts BSON.ObjectId struct to a string representation """ def encode!(%BSON.ObjectId{value: value}), do: do_encode(value) defp do_encode( <> ) do <> catch :throw, :error -> raise ArgumentError else value -> value end @compile {:inline, :d, 1} @compile {:inline, :e, 1} @chars Enum.concat(?0..?9, ?a..?f) for {char, int} <- Enum.with_index(@chars) do defp d(unquote(char)), do: unquote(int) defp e(unquote(int)), do: unquote(char) end for {char, int} <- Enum.with_index(?A..?F) do defp d(unquote(char)), do: unquote(int) end defp d(_), do: throw(:error) defp e(_), do: throw(:error) defimpl Inspect do def inspect(objectid, _opts) do encoded = BSON.ObjectId.encode!(objectid) "#BSON.ObjectId<#{encoded}>" end end end defmodule BSON.Regex do @moduledoc """ Represents BSON Regex type """ @type t :: %__MODULE__{pattern: binary, options: binary} defstruct [:pattern, :options] defimpl Inspect do def inspect(%BSON.Regex{pattern: pattern, options: nil}, _opts) do "#BSON.Regex<#{inspect(pattern)}>" end def inspect(%BSON.Regex{pattern: pattern, options: options}, _opts) do "#BSON.Regex<#{inspect(pattern)}, #{inspect(options)}>" end end end defmodule BSON.JavaScript do @moduledoc """ Represents BSON JavaScript (with and without scope) types """ @type t :: %__MODULE__{code: binary, scope: %{binary => BSON.t()}} defstruct [:code, :scope] defimpl Inspect do def inspect(%BSON.JavaScript{code: code, scope: nil}, _opts) do "#BSON.JavaScript<#{inspect(code)}>" end def inspect(%BSON.JavaScript{code: code, scope: scope}, _opts) do "#BSON.JavaScript<#{inspect(code)}, #{inspect(scope)}>" end end end defmodule BSON.Timestamp do @moduledoc """ Represents BSON Timestamp type """ @type t :: %__MODULE__{value: integer, ordinal: integer} defstruct [:value, :ordinal] defimpl Inspect do def inspect(%BSON.Timestamp{value: value, ordinal: ordinal}, _opts) do "#BSON.Timestamp<#{value}:#{ordinal}>" end end end