aboutsummaryrefslogtreecommitdiff
path: root/lib/boltex/pack_stream
diff options
context:
space:
mode:
authorMichael Schaefermeyer <michael.schaefermeyer@gmail.com>2016-07-19 01:01:18 +0200
committerMichael Schaefermeyer <michael.schaefermeyer@gmail.com>2016-07-19 01:01:18 +0200
commitfe62ea8ee39e5460b663359daf4759e9a379e538 (patch)
treed7cab1c9abfdd26b56869f75d355800ad2ba51ab /lib/boltex/pack_stream
downloadboltex-fe62ea8ee39e5460b663359daf4759e9a379e538.tar.gz
boltex-fe62ea8ee39e5460b663359daf4759e9a379e538.tar.xz
Initial commit
Diffstat (limited to 'lib/boltex/pack_stream')
-rw-r--r--lib/boltex/pack_stream/encoder.ex110
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