Skip to content

Commit f22686b

Browse files
committed
WIP (Refine and split defitions by categories)
1 parent 1955c5e commit f22686b

File tree

1 file changed

+90
-86
lines changed

1 file changed

+90
-86
lines changed

lib/msgpax/unpacker.ex

Lines changed: 90 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -28,131 +28,135 @@ defmodule Msgpax.Unpacker do
2828
unpack(buffer, [], options, [:root], 0, 1)
2929
end
3030

31-
formats = %{
32-
quote(do: [0xC0]) => {:value, quote(do: nil)},
33-
quote(do: [0xC2]) => {:value, quote(do: false)},
34-
quote(do: [0xC3]) => {:value, quote(do: true)},
35-
36-
# String
37-
quote(do: [0b101::3, length::5, value::size(length)-bytes]) => {:value, quote(do: value)},
38-
quote(do: [0xD9, length::integer, value::size(length)-bytes]) => {:value, quote(do: value)},
39-
quote(do: [0xDA, length::16-integer, value::size(length)-bytes]) => {:value, quote(do: value)},
40-
quote(do: [0xDB, length::32-integer, value::size(length)-bytes]) => {:value, quote(do: value)},
41-
42-
# Binary
43-
quote(do: [0xC4, len::integer, val::size(len)-bytes]) => {:call, quote(do: unpack_binary(val))},
44-
quote(do: [0xC5, len::16-integer, val::size(len)-bytes]) => {:call, quote(do: unpack_binary(val))},
45-
quote(do: [0xC6, len::32-integer, val::size(len)-bytes]) => {:call, quote(do: unpack_binary(val))},
46-
47-
# Float
48-
quote(do: [0xCA, val::32-big-float]) => {:value, quote(do: val)},
49-
quote(do: [0xCB, val::64-big-float]) => {:value, quote(do: val)},
50-
51-
# Integer
52-
quote(do: [0::1, val::7]) => {:value, quote(do: val)},
53-
quote(do: [0xCC, val]) => {:value, quote(do: val)},
54-
quote(do: [0xCD, val::16]) => {:value, quote(do: val)},
55-
quote(do: [0xCE, val::32]) => {:value, quote(do: val)},
56-
quote(do: [0xCF, val::64]) => {:value, quote(do: val)},
57-
quote(do: [0b111::3, val::5]) => {:value, quote(do: val - 0b100000)},
58-
quote(do: [0xD0, val::signed-integer]) => {:value, quote(do: val)},
59-
quote(do: [0xD1, val::16-signed-integer]) => {:value, quote(do: val)},
60-
quote(do: [0xD2, val::32-signed-integer]) => {:value, quote(do: val)},
61-
quote(do: [0xD3, val::64-signed-integer]) => {:value, quote(do: val)},
62-
63-
# Array
64-
quote(do: [0b1001::4, len::4]) => {:collection, :list},
65-
quote(do: [0xDC, len::16]) => {:collection, :list},
66-
quote(do: [0xDD, len::32]) => {:collection, :list},
67-
68-
# Map
69-
quote(do: [0b1000::4, len::4]) => {:collection, :map},
70-
quote(do: [0xDE, len::16]) => {:collection, :map},
71-
quote(do: [0xDF, len::32]) => {:collection, :map},
72-
73-
# Extension
74-
quote(do: [0xD4, type, val::1-bytes]) => {:call, quote(do: unpack_ext(type, val))},
75-
quote(do: [0xD5, type, val::2-bytes]) => {:call, quote(do: unpack_ext(type, val))},
76-
quote(do: [0xD6, type, val::4-bytes]) => {:call, quote(do: unpack_ext(type, val))},
77-
quote(do: [0xD7, type, val::8-bytes]) => {:call, quote(do: unpack_ext(type, val))},
78-
quote(do: [0xD8, type, val::16-bytes]) => {:call, quote(do: unpack_ext(type, val))},
79-
quote(do: [0xC7, len, type, val::size(len)-bytes]) => {:call, quote(do: unpack_ext(type, val))},
80-
quote(do: [0xC8, len::16, type, val::size(len)-bytes]) => {:call, quote(do: unpack_ext(type, val))},
81-
quote(do: [0xC9, len::32, type, val::size(len)-bytes]) => {:call, quote(do: unpack_ext(type, val))},
31+
defp unpack(<<buffer::bits>>, result, options, [kind, index, length | outer], count, count) do
32+
unpack(buffer, build_collection(result, count, kind), options, outer, index + 1, length)
33+
end
34+
35+
primitives = %{
36+
[quote(do: [0xC0])] => quote(do: nil),
37+
[quote(do: [0xC2])] => quote(do: false),
38+
[quote(do: [0xC3])] => quote(do: true),
39+
[# Strings
40+
quote(do: [0b101::3, length::5, value::size(length)-bytes]),
41+
quote(do: [0xD9, length::8, value::size(length)-bytes]),
42+
quote(do: [0xDA, length::16, value::size(length)-bytes]),
43+
quote(do: [0xDB, length::32, value::size(length)-bytes]),
44+
45+
# Floats
46+
quote(do: [0xCA, value::32-float]),
47+
quote(do: [0xCB, value::64-float]),
48+
49+
# Integers
50+
quote(do: [0::1, value::7]),
51+
quote(do: [0xCC, value::8]),
52+
quote(do: [0xCD, value::16]),
53+
quote(do: [0xCE, value::32]),
54+
quote(do: [0xCF, value::64]),
55+
quote(do: [0xD0, value::8-signed]),
56+
quote(do: [0xD1, value::16-signed]),
57+
quote(do: [0xD2, value::32-signed]),
58+
quote(do: [0xD3, value::64-signed])] => quote(do: value),
59+
# Negative fixint
60+
[quote(do: [0b111::3, value::5])] => quote(do: value - 0b100000),
8261
}
83-
84-
import Macro, only: [pipe: 3]
85-
86-
defp unpack(<<buffer::bits>>, result, options, [kind, index, size | outer], count, count) do
87-
unpack(buffer, build_collection(result, count, kind), options, outer, index + 1, size)
62+
for {formats, value} <- primitives, format <- formats do
63+
defp unpack(<<unquote_splicing(format), rest::bits>>, result, options, outer, index, count) when index < count do
64+
unpack(rest, [unquote(value) | result], options, outer, index + 1, count)
65+
end
8866
end
8967

90-
for {format, {:value, value}} <- formats do
91-
defp unpack(<<unquote_splicing(format), rest::bits>>, result, options, outer, index, count) do
92-
unpack(rest, [unquote(value) | result], options, outer, index + 1, count)
68+
lists = [
69+
quote(do: [0b1001::4, length::4]),
70+
quote(do: [0xDC, length::16]),
71+
quote(do: [0xDD, length::32]),
72+
]
73+
for format <- lists do
74+
defp unpack(<<unquote_splicing(format), rest::bits>>, result, options, outer, index, count) when index < count do
75+
unpack(rest, result, options, [:list, index, count | outer], 0, unquote(quote(do: length)))
9376
end
9477
end
9578

96-
for {format, {:call, call}} <- formats do
97-
options = Macro.var(:options, nil)
98-
defp unpack(<<unquote_splicing(format), rest::bits>>, result, options, outer, index, count) do
99-
unpack(rest, [unquote(pipe(options, call, 0)) | result], options, outer, index + 1, count)
79+
maps = [
80+
quote(do: [0b1000::4, length::4]),
81+
quote(do: [0xDE, length::16]),
82+
quote(do: [0xDF, length::32]),
83+
]
84+
for format <- maps do
85+
defp unpack(<<unquote_splicing(format), rest::bits>>, result, options, outer, index, count) when index < count do
86+
unpack(rest, result, options, [:map, index, count | outer], 0, unquote(quote(do: length)) * 2)
10087
end
10188
end
10289

103-
for {format, {:collection, :list = kind}} <- formats do
104-
defp unpack(<<unquote_splicing(format), rest::bits>>, result, options, outer, index, count) do
105-
unpack(rest, result, options, [unquote(kind), index, count | outer], 0, unquote(quote(do: len)))
90+
binaries = [
91+
quote(do: [0xC4, length::8, content::size(length)-bytes]),
92+
quote(do: [0xC5, length::16, content::size(length)-bytes]),
93+
quote(do: [0xC6, length::32, content::size(length)-bytes]),
94+
]
95+
for format <- binaries do
96+
defp unpack(<<unquote_splicing(format), rest::bits>>, result, options, outer, index, count) when index < count do
97+
value = unpack_binary(unquote(quote(do: content)), options)
98+
unpack(rest, [value | result], options, outer, index + 1, count)
10699
end
107100
end
108101

109-
for {format, {:collection, :map = kind}} <- formats do
110-
defp unpack(<<unquote_splicing(format), rest::bits>>, result, options, outer, index, count) do
111-
unpack(rest, result, options, [unquote(kind), index, count | outer], 0, unquote(quote(do: len)) * 2)
102+
extensions = [
103+
quote(do: [0xD4, type, content::1-bytes]),
104+
quote(do: [0xD5, type, content::2-bytes]),
105+
quote(do: [0xD6, type, content::4-bytes]),
106+
quote(do: [0xD7, type, content::8-bytes]),
107+
quote(do: [0xD8, type, content::16-bytes]),
108+
quote(do: [0xC7, length::8, type, content::size(length)-bytes]),
109+
quote(do: [0xC8, length::16, type, content::size(length)-bytes]),
110+
quote(do: [0xC9, length::32, type, content::size(length)-bytes]),
111+
]
112+
for format <- extensions do
113+
defp unpack(<<unquote_splicing(format), rest::bits>>, result, options, outer, index, count) when index < count do
114+
value = unpack_ext(unquote(quote(do: type)), unquote(quote(do: content)), options)
115+
unpack(rest, [value | result], options, outer, index + 1, count)
112116
end
113117
end
114118

115-
defp unpack(<<byte, _::bits>>, [], _options, _outer, _index, _count) do
116-
throw {:bad_format, byte}
119+
defp unpack(<<buffer::bits>>, [value], _options, [:root], count, count) do
120+
{value, buffer}
117121
end
118122

119-
defp unpack(<<_::bits>>, [], _options, _outer, _index, _count) do
120-
throw :incomplete
123+
defp unpack(<<byte, _::bits>>, _result, _options, _outer, _index, _count) do
124+
throw {:bad_format, byte}
121125
end
122126

123-
defp unpack(buffer, [value], _options, [:root], count, count) do
124-
{value, buffer}
127+
defp unpack(<<_::bits>>, _result, _options, _outer, _index, _count) do
128+
throw :incomplete
125129
end
126130

127-
defp unpack_binary(%{binary: true}, value) do
128-
Msgpax.Bin.new(value)
131+
defp unpack_binary(content, %{binary: true}) do
132+
Msgpax.Bin.new(content)
129133
end
130134

131-
defp unpack_binary(_options, value) do
132-
value
135+
defp unpack_binary(content, _options) do
136+
content
133137
end
134138

135-
defp unpack_ext(options, type, data) do
139+
defp unpack_ext(type, content, options) do
136140
if type in 0..127 do
137-
unpack_ext_module(type, data, options)
141+
unpack_ext_module(type, content, options)
138142
else
139143
throw {:not_supported_ext, type}
140144
end
141145
end
142146

143147
@compile {:inline, [unpack_ext_module: 3]}
144148

145-
defp unpack_ext_module(type, data, %{ext: module}) when is_atom(module) do
146-
case module.unpack(Msgpax.Ext.new(type, data)) do
149+
defp unpack_ext_module(type, content, %{ext: module}) when is_atom(module) do
150+
case module.unpack(Msgpax.Ext.new(type, content)) do
147151
{:ok, result} ->
148152
result
149153
:error ->
150-
throw {:ext_unpack_failure, type, module, data}
154+
throw {:ext_unpack_failure, type, module, content}
151155
end
152156
end
153157

154-
defp unpack_ext_module(type, data, _options) do
155-
Msgpax.Ext.new(type, data)
158+
defp unpack_ext_module(type, content, _options) do
159+
Msgpax.Ext.new(type, content)
156160
end
157161

158162
@compile {:inline, [build_collection: 3]}

0 commit comments

Comments
 (0)