Current section

Files

Jump to
bson lib bson_decoder.ex
Raw

lib/bson_decoder.ex

defmodule BsonDecodeError do
defexception [:message, :at]
def message(m) do
inspect(m)
end
end
defprotocol BsonDecoder do
@moduledoc """
Similarly to `BsonEncoder`, this protocol defines decoding of chunks of Bson document.
Chunks are identified by tokens and isolate an element of a Bson document.
There is one implementation of the protocol for every struct defined in `BsonTk`
"""
@doc """
Returns a elixir term decoded from a chunk of a Bson document.
"""
def decode(token, bson)
end
defimpl BsonDecoder, for: BsonTk.Int32 do
def decode(%BsonTk.Int32{part: {from, _}}, bson), do: Bson.int32(bson, from)
end
defimpl BsonDecoder, for: BsonTk.Int64 do
def decode(%BsonTk.Int64{part: {from, _}}, bson), do: Bson.int64(bson, from)
end
defimpl BsonDecoder, for: BsonTk.String do
def decode(%BsonTk.String{part: part}, bson), do: :erlang.binary_part(bson, part)
end
defimpl BsonDecoder, for: BsonTk.Atom do
def decode(%BsonTk.Atom{part: part}, bson), do: :erlang.binary_part(bson, part) |> String.to_atom
end
defimpl BsonDecoder, for: BsonTk.Float do
def decode(%BsonTk.Float{part: {from, _}}, bson), do: Bson.float(bson, from)
end
defimpl BsonDecoder, for: BsonTk.Bool do
def decode(%BsonTk.Bool{part: {from, _}}, bson), do: Bson.bool(bson, from)
end
defimpl BsonDecoder, for: BsonTk.Doc do
def decode(%BsonTk.Doc{part: {from, len}}, bson) do
BsonTk.tokenize_e_list(bson, from, from+len)
|> Enum.map(&Bson.decode_kv(&1, bson))
|> :maps.from_list
end
end
defimpl BsonDecoder, for: BsonTk.Array do
def decode(%BsonTk.Array{part: {from, len}}, bson) do
BsonTk.tokenize_e_list(bson, from, from+len)
|> Enum.map &(Bson.decode_v(&1, bson))
end
end
defimpl BsonDecoder, for: Atom do
def decode(nil, _bson) , do: nil
def decode(MIN_KEY, _bson) , do: MIN_KEY
def decode(MAX_KEY, _bson) , do: MAX_KEY
end
defimpl BsonDecoder, for: BsonTk.ObjectId do
def decode(oid, bson) do
%Bson.ObjectId{oid: :erlang.binary_part(bson, oid.part)}
end
end
defimpl BsonDecoder, for: BsonTk.Bin do
def decode(bin, bson) do
%Bson.Bin{bin: :erlang.binary_part(bson, bin.part), subtype: bin.subtype}
end
end
defimpl BsonDecoder, for: BsonTk.Regex do
def decode(regex, bson) do
%Bson.Regex{pattern: :erlang.binary_part(bson, regex.pattern), opts: :erlang.binary_part(bson, regex.opts)}
end
end
defimpl BsonDecoder, for: BsonTk.JS do
def decode(js, bson) do
%Bson.JS{code: :erlang.binary_part(bson, js.code), scope:
case js.scope do
nil -> nil
part -> BsonDecoder.BsonTk.Doc.decode(%BsonTk.Doc{part: part}, bson)
end}
end
end
defimpl BsonDecoder, for: BsonTk.Timestamp do
def decode(%BsonTk.Timestamp{inc: {inc_from, _}, ts: {ts_from, _}}, bson) do
%Bson.Timestamp{inc: Bson.int32(bson, inc_from), ts: Bson.int32(bson, ts_from)}
end
end
defimpl BsonDecoder, for: BsonTk.Now do
def decode(%BsonTk.Now{part: {from, _}}, bson) do
ms = Bson.int64(bson, from)
{div(ms, 1000000000), rem(div(ms, 1000), 1000000), rem(ms * 1000, 1000000)}
end
end