@@ -25,7 +25,7 @@ defmodule Msgpax.Unpacker do
25
25
@ moduledoc false
26
26
27
27
def unpack ( << buffer :: bits >> , options ) do
28
- unpack ( buffer , [ ] , options )
28
+ unpack ( buffer , [ ] , options , [ :root ] , 0 , 1 )
29
29
end
30
30
31
31
formats = % {
@@ -61,14 +61,14 @@ defmodule Msgpax.Unpacker do
61
61
quote ( do: [ 0xD3 , val :: 64 - signed - integer ] ) => { :value , quote ( do: val ) } ,
62
62
63
63
# Array
64
- quote ( do: [ 0b1001 :: 4 , len :: 4 ] ) => { :call , quote ( do: unpack_list ( len ) ) } ,
65
- quote ( do: [ 0xDC , len :: 16 ] ) => { :call , quote ( do: unpack_list ( len ) ) } ,
66
- quote ( do: [ 0xDD , len :: 32 ] ) => { :call , quote ( do: unpack_list ( len ) ) } ,
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
67
68
68
# Map
69
- quote ( do: [ 0b1000 :: 4 , len :: 4 ] ) => { :call , quote ( do: unpack_map ( len ) ) } ,
70
- quote ( do: [ 0xDE , len :: 16 ] ) => { :call , quote ( do: unpack_map ( len ) ) } ,
71
- quote ( do: [ 0xDF , len :: 32 ] ) => { :call , quote ( do: unpack_map ( len ) ) } ,
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
72
73
73
# Extension
74
74
quote ( do: [ 0xD4 , type , val :: 1 - bytes ] ) => { :call , quote ( do: unpack_ext ( type , val ) ) } ,
@@ -84,77 +84,65 @@ defmodule Msgpax.Unpacker do
84
84
import Macro , only: [ pipe: 3 ]
85
85
86
86
for { format , { :value , value } } <- formats do
87
- defp unpack ( << unquote_splicing ( format ) , rest :: bits >> , [ ] , options ) do
88
- unpack ( rest , [ unquote ( value ) ] , options )
87
+ defp unpack ( << unquote_splicing ( format ) , rest :: bits >> , result , options , outer , index , count ) when index < count do
88
+ unpack ( rest , [ unquote ( value ) | result ] , options , outer , index + 1 , count )
89
89
end
90
90
end
91
91
92
92
for { format , { :call , call } } <- formats do
93
- rest = Macro . var ( :rest , nil )
94
93
options = Macro . var ( :options , nil )
95
- defp unpack ( << unquote_splicing ( format ) , rest :: bits >> , [ ] , options ) do
96
- unquote ( pipe ( rest , pipe ( [ ] , pipe ( options , pipe ( [ ] , call , 0 ) , 0 ) , 0 ) , 0 ) )
94
+ defp unpack ( << unquote_splicing ( format ) , rest :: bits >> , result , options , outer , index , count ) when index < count do
95
+ unpack ( rest , [ unquote ( pipe ( options , call , 0 ) ) | result ] , options , outer , index + 1 , count )
97
96
end
98
97
end
99
98
100
- defp unpack ( << byte , _ :: bits >> , [ ] , _options ) do
101
- throw { :bad_format , byte }
102
- end
103
-
104
- defp unpack ( << _ :: bits >> , [ ] , _options ) do
105
- throw :incomplete
106
- end
107
-
108
- defp unpack ( buffer , [ value ] , _options ) do
109
- { value , buffer }
99
+ for { format , { :collection , :list = kind } } <- formats do
100
+ defp unpack ( << unquote_splicing ( format ) , rest :: bits >> , result , options , [ kind | outer ] , index , count ) when index < count do
101
+ unpack ( rest , result , options , [ unquote ( kind ) , { kind , index , count } | outer ] , 0 , unquote ( quote ( do: len ) ) )
102
+ end
110
103
end
111
104
112
- defp unpack_binary ( << buffer :: bits >> , result , % { binary: true } = options , outer , value ) do
113
- unpack_continue ( buffer , [ Msgpax.Bin . new ( value ) | result ] , options , outer )
105
+ for { format , { :collection , :map = kind } } <- formats do
106
+ defp unpack ( << unquote_splicing ( format ) , rest :: bits >> , result , options , [ kind | outer ] , index , count ) when index < count do
107
+ unpack ( rest , result , options , [ unquote ( kind ) , { kind , index , count } | outer ] , 0 , unquote ( quote ( do: len ) ) * 2 )
108
+ end
114
109
end
115
110
116
- defp unpack_binary ( << buffer :: bits >> , result , options , outer , value ) do
117
- unpack_continue ( buffer , [ value | result ] , options , outer )
111
+ defp unpack ( << buffer :: bits >> , result , options , [ kind , { next , index , size } | outer ] , count , count ) do
112
+ unpack ( buffer , build_collection ( result , count , kind ) , options , [ next | outer ] , index + 1 , size )
118
113
end
119
114
120
- defp unpack_list ( << buffer :: bits >> , result , options , outer , length ) do
121
- unpack_collection ( buffer , result , options , outer , 0 , length , :list )
115
+ defp unpack ( << byte , _ :: bits >> , [ ] , _options , _outer , _index , _count ) do
116
+ throw { :bad_format , byte }
122
117
end
123
118
124
- for { format , { :value , value } } <- formats do
125
- defp unpack_collection ( << unquote_splicing ( format ) , rest :: bits >> , result , options , outer , index , length , kind ) when index < length do
126
- unpack_collection ( rest , [ unquote ( value ) | result ] , options , outer , index + 1 , length , kind )
127
- end
119
+ defp unpack ( << _ :: bits >> , [ ] , _options , _outer , _index , _count ) do
120
+ throw :incomplete
128
121
end
129
122
130
- for { format , { :call , call } } <- formats do
131
- rest = Macro . var ( :rest , nil )
132
- result = Macro . var ( :result , nil )
133
- options = Macro . var ( :options , nil )
134
- outer = Macro . var ( :outer , nil )
135
- defp unpack_collection ( << unquote_splicing ( format ) , rest :: bits >> , result , options , outer , index , length , kind ) when index < length do
136
- outer = [ { kind , index , length } | outer ]
137
- unquote ( pipe ( rest , pipe ( result , pipe ( options , pipe ( outer , call , 0 ) , 0 ) , 0 ) , 0 ) )
138
- end
123
+ defp unpack ( buffer , [ value ] , _options , [ :root ] , count , count ) do
124
+ { value , buffer }
139
125
end
140
126
141
- defp unpack_collection ( << buffer :: bits >> , result , options , outer , count , count , kind ) do
142
- unpack_continue ( buffer , build_collection ( result , count , kind ) , options , outer )
127
+ defp unpack_binary ( % { binary: true } , value ) do
128
+ Msgpax.Bin . new ( value )
143
129
end
144
130
145
- defp unpack_map ( << buffer :: bits >> , result , options , outer , length ) do
146
- unpack_collection ( buffer , result , options , outer , 0 , length * 2 , :map )
131
+ defp unpack_binary ( _options , value ) do
132
+ value
147
133
end
148
134
149
- defp unpack_ext ( << buffer :: bits >> , result , options , outer , type , data ) do
135
+ defp unpack_ext ( options , type , data ) do
150
136
if type in 0 .. 127 do
151
- unpack_continue ( buffer , [ unpack_ext ( type , data , options ) | result ] , options , outer )
137
+ unpack_ext_module ( type , data , options )
152
138
else
153
139
throw { :not_supported_ext , type }
154
140
end
155
141
end
156
142
157
- defp unpack_ext ( type , data , % { ext: module } ) when is_atom ( module ) do
143
+ @ compile { :inline , [ unpack_ext_module: 3 ] }
144
+
145
+ defp unpack_ext_module ( type , data , % { ext: module } ) when is_atom ( module ) do
158
146
case module . unpack ( Msgpax.Ext . new ( type , data ) ) do
159
147
{ :ok , result } ->
160
148
result
@@ -163,18 +151,10 @@ defmodule Msgpax.Unpacker do
163
151
end
164
152
end
165
153
166
- defp unpack_ext ( type , data , _options ) do
154
+ defp unpack_ext_module ( type , data , _options ) do
167
155
Msgpax.Ext . new ( type , data )
168
156
end
169
157
170
- defp unpack_continue ( << buffer :: bits >> , result , options , [ { kind , index , length } | outer ] ) do
171
- unpack_collection ( buffer , result , options , outer , index + 1 , length , kind )
172
- end
173
-
174
- defp unpack_continue ( << buffer :: bits >> , result , options , [ ] ) do
175
- unpack ( buffer , result , options )
176
- end
177
-
178
158
@ compile { :inline , [ build_collection: 3 ] }
179
159
180
160
defp build_collection ( result , count , :list ) do
0 commit comments