@@ -35,7 +35,12 @@ expand(BitstrMeta, Fun, [{'::', Meta, [Left, Right]} | T], Acc, S, E, Alignment,
35
35
36
36
MatchOrRequireSize = RequireSize or is_match_size (T , EL ),
37
37
EType = expr_type (ELeft ),
38
- {ERight , EAlignment , SS , ES } = expand_specs (EType , Meta , Right , SL , OriginalS , EL , MatchOrRequireSize ),
38
+ ExpectSize = case ELeft of
39
+ {'^' , _ , [{_ , _ , _ }]} -> {infer , ELeft };
40
+ _ when MatchOrRequireSize -> required ;
41
+ _ -> optional
42
+ end ,
43
+ {ERight , EAlignment , SS , ES } = expand_specs (EType , Meta , Right , SL , OriginalS , EL , ExpectSize ),
39
44
40
45
EAcc = concat_or_prepend_bitstring (Meta , ELeft , ERight , Acc , ES , MatchOrRequireSize ),
41
46
expand (BitstrMeta , Fun , T , EAcc , {SS , OriginalS }, ES , alignment (Alignment , EAlignment ), RequireSize );
@@ -147,7 +152,7 @@ expand_expr(Meta, Component, Fun, S, E) ->
147
152
148
153
% % Expands and normalizes types of a bitstring.
149
154
150
- expand_specs (ExprType , Meta , Info , S , OriginalS , E , RequireSize ) ->
155
+ expand_specs (ExprType , Meta , Info , S , OriginalS , E , ExpectSize ) ->
151
156
Default =
152
157
#{size => default ,
153
158
unit => default ,
@@ -158,11 +163,17 @@ expand_specs(ExprType, Meta, Info, S, OriginalS, E, RequireSize) ->
158
163
expand_each_spec (Meta , unpack_specs (Info , []), Default , S , OriginalS , E ),
159
164
160
165
MergedType = type (Meta , ExprType , Type , E ),
161
- validate_size_required (Meta , RequireSize , ExprType , MergedType , Size , ES ),
166
+ validate_size_required (Meta , ExpectSize , ExprType , MergedType , Size , ES ),
162
167
SizeAndUnit = size_and_unit (Meta , ExprType , Size , Unit , ES ),
163
168
Alignment = compute_alignment (MergedType , Size , Unit ),
164
169
165
- [H | T ] = build_spec (Meta , Size , Unit , MergedType , Endianness , Sign , SizeAndUnit , ES ),
170
+ MaybeInferredSize = case {ExpectSize , MergedType , SizeAndUnit } of
171
+ {{infer , PinnedVar }, binary , []} -> [{size , Meta , [{{'.' , Meta , [erlang , byte_size ]}, Meta , [PinnedVar ]}]}];
172
+ {{infer , PinnedVar }, bitstring , []} -> [{size , Meta , [{{'.' , Meta , [erlang , bit_size ]}, Meta , [PinnedVar ]}]}];
173
+ _ -> SizeAndUnit
174
+ end ,
175
+
176
+ [H | T ] = build_spec (Meta , Size , Unit , MergedType , Endianness , Sign , MaybeInferredSize , ES ),
166
177
{lists :foldl (fun (I , Acc ) -> {'-' , Meta , [Acc , I ]} end , H , T ), Alignment , SS , ES }.
167
178
168
179
type (_ , default , default , _ ) ->
@@ -276,7 +287,7 @@ validate_spec_arg(Meta, unit, Value, _S, _OriginalS, E) when not is_integer(Valu
276
287
validate_spec_arg (_Meta , _Key , _Value , _S , _OriginalS , _E ) ->
277
288
ok .
278
289
279
- validate_size_required (Meta , true , default , Type , default , E ) when Type == binary ; Type == bitstring ->
290
+ validate_size_required (Meta , required , default , Type , default , E ) when Type == binary ; Type == bitstring ->
280
291
function_error (Meta , E , ? MODULE , unsized_binary ),
281
292
ok ;
282
293
validate_size_required (_ , _ , _ , _ , _ , _ ) ->
0 commit comments