diff options
author | Michael Schaefermeyer <michael.schaefermeyer@gmail.com> | 2016-07-19 01:01:18 +0200 |
---|---|---|
committer | Michael Schaefermeyer <michael.schaefermeyer@gmail.com> | 2016-07-19 01:01:18 +0200 |
commit | fe62ea8ee39e5460b663359daf4759e9a379e538 (patch) | |
tree | d7cab1c9abfdd26b56869f75d355800ad2ba51ab /lib/boltex/pack_stream | |
download | boltex-fe62ea8ee39e5460b663359daf4759e9a379e538.tar.gz boltex-fe62ea8ee39e5460b663359daf4759e9a379e538.tar.xz |
Initial commit
Diffstat (limited to 'lib/boltex/pack_stream')
-rw-r--r-- | lib/boltex/pack_stream/encoder.ex | 110 |
1 files changed, 110 insertions, 0 deletions
diff --git a/lib/boltex/pack_stream/encoder.ex b/lib/boltex/pack_stream/encoder.ex new file mode 100644 index 0000000..bd7dc6e --- /dev/null +++ b/lib/boltex/pack_stream/encoder.ex @@ -0,0 +1,110 @@ +defprotocol Boltex.PackStream.Encoder do + @doc "Encodes an item to its binary PackStream Representation" + def encode(entitiy) +end + +defimpl Boltex.PackStream.Encoder, for: Atom do + def encode(nil), do: << 0xC0 >> + def encode(true), do: << 0xC3 >> + def encode(false), do: << 0xC2 >> + def encode(other) when is_atom(other) do + other + |> Atom.to_string + |> Boltex.PackStream.Encoder.encode + end +end + +defimpl Boltex.PackStream.Encoder, for: Integer do + @int8 -127..-17 + @int16_low -32_768..-129 + @int16_high 128..32_767 + @int32_low -2_147_483_648..-32_769 + @int32_high 32_768..2_147_483_647 + @int64_low -9_223_372_036_854_775_808..-2_147_483_649 + @int64_high 2_147_483_648..9_223_372_036_854_775_807 + + def encode(integer) when integer in -16..127 do + <<integer>> + end + def encode(integer) when integer in @int8 do + << 0xC8, integer >> + end + def encode(integer) when integer in @int16_low or integer in @int16_high do + << 0xC9, integer >> + end + def encode(integer) when integer in @int32_low or integer in @int32_high do + << 0xCA, integer >> + end + def encode(integer) when integer in @int64_low or integer in @int64_high do + << 0xCB, integer >> + end +end + +defimpl Boltex.PackStream.Encoder, for: BitString do + def encode(string), do: do_encode(string, byte_size(string)) + + defp do_encode(string, size) when size <= 15 do + << 0x8 :: 4, size :: 4 >> <> string + end + defp do_encode(string, size) when size <= 255 do + << 0xD0, size :: 8 >> <> string + end + defp do_encode(string, size) when size <= 65_535 do + << 0xD1, size :: 16 >> <> string + end + defp do_encode(string, size) when size <= 4_294_967_295 do + << 0xD2, size :: 32 >> <> string + end +end + +defimpl Boltex.PackStream.Encoder, for: List do + def encode(list) do + binary = Enum.map_join list, &Boltex.PackStream.Encoder.encode/1 + + do_encode binary, byte_size(binary) + end + + defp do_encode(binary, list_size) when list_size <= 15 do + << 0x9 :: 4, list_size :: 4 >> <> binary + end + defp do_encode(binary, list_size) when list_size <= 255 do + << 0xD4, list_size :: 8 >> <> binary + end + defp do_encode(binary, list_size) when list_size <= 65_535 do + << 0xD5, list_size :: 16 >> <> binary + end + defp do_encode(binary, list_size) when list_size <= 4_294_967_295 do + << 0xD6, list_size :: 32 >> <> binary + end + defp do_encode(binary, _size) do + << 0xD7 >> <> binary <> <<0xDF>> + end +end + +defimpl Boltex.PackStream.Encoder, for: Map do + def encode(map) do + do_encode map, map_size(map) + end + + defp do_encode(map, size) when size <= 15 do + << 0xA :: 4, size :: 4 >> <> encode_kv(map) + end + defp do_encode(map, size) when size <= 255 do + << 0xD8, size :: 8 >> <> encode_kv(map) + end + defp do_encode(map, size) when size <= 65_535 do + << 0xD9, size :: 16 >> <> encode_kv(map) + end + defp do_encode(map, size) when size <= 4_294_967_295 do + << 0xDA, size :: 32 >> <> encode_kv(map) + end + + defp encode_kv(map) do + Boltex.Utils.reduce_to_binary map, &do_reduce_kv/1 + end + + defp do_reduce_kv({key, value}) do + Boltex.PackStream.Encoder.encode(key) <> + Boltex.PackStream.Encoder.encode(value) + end +end |