@@ -25,7 +25,7 @@ defmodule Msgpax.Unpacker do
2525 @ moduledoc false
2626
2727 def unpack ( << buffer :: bits >> , options ) do
28- unpack ( buffer , [ ] , options )
28+ unpack ( buffer , [ ] , options , [ :root ] , 0 , 1 )
2929 end
3030
3131 formats = % {
@@ -61,14 +61,14 @@ defmodule Msgpax.Unpacker do
6161 quote ( do: [ 0xD3 , val :: 64 - signed - integer ] ) => { :value , quote ( do: val ) } ,
6262
6363 # 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 } ,
6767
6868 # 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 } ,
7272
7373 # Extension
7474 quote ( do: [ 0xD4 , type , val :: 1 - bytes ] ) => { :call , quote ( do: unpack_ext ( type , val ) ) } ,
@@ -84,77 +84,65 @@ defmodule Msgpax.Unpacker do
8484 import Macro , only: [ pipe: 3 ]
8585
8686 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 )
8989 end
9090 end
9191
9292 for { format , { :call , call } } <- formats do
93- rest = Macro . var ( :rest , nil )
9493 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 )
9796 end
9897 end
9998
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
110103 end
111104
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
114109 end
115110
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 )
118113 end
119114
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 }
122117 end
123118
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
128121 end
129122
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 }
139125 end
140126
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 )
143129 end
144130
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
147133 end
148134
149- defp unpack_ext ( << buffer :: bits >> , result , options , outer , type , data ) do
135+ defp unpack_ext ( options , type , data ) do
150136 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 )
152138 else
153139 throw { :not_supported_ext , type }
154140 end
155141 end
156142
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
158146 case module . unpack ( Msgpax.Ext . new ( type , data ) ) do
159147 { :ok , result } ->
160148 result
@@ -163,18 +151,10 @@ defmodule Msgpax.Unpacker do
163151 end
164152 end
165153
166- defp unpack_ext ( type , data , _options ) do
154+ defp unpack_ext_module ( type , data , _options ) do
167155 Msgpax.Ext . new ( type , data )
168156 end
169157
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-
178158 @ compile { :inline , [ build_collection: 3 ] }
179159
180160 defp build_collection ( result , count , :list ) do
0 commit comments