Age | Commit message (Collapse) | Author |
|
Given:
Semi ::= INTEGER (Lb..MAX, ...)
where Lb is an arbitrary integer, attempting to encode an
integer less than Lb would cause the encoder to enter an
infinite loop.
|
|
Almost always, encode_open_type/1 is called with the return value
from complete/1, which always is a binary. In the rare situation
that encode_open_type/1 is called directly with data from the
user application, call iolist_to_binary/1 before calling
encode_open_type/1.
|
|
|
|
Given the type:
S ::= IA5String (SIZE (5, ...))
attempting to encode (to PER/UPER) a string shorter than 5 characters
would fail. Similarly, attempting to decode such string in the BER
format would fail.
In the case of BER, we can do no range checks if the size constraint
is extensible.
|
|
Consider a type with a size constraint with an extension marker
such as:
S ::= OCTET STRING (SIZE (0..10, ...))
For a length outside the root range (e.g. 42), the PER/UPER encoder
will encode the length field in the same way as it would the type
INTEGER (0..MAX) (i.e., as semi-constrained whole number), while the
decoder would decode the length in the same way as length field
without any constraint.
Clearly, either the encoder or the decoder is wrong. But which one?
Dubuisson's [1] book (page 442) says that the length should be encoded
as a semi-constrained whole number if the length is outside the root
range.
The X.691 standard document [2] also says (e.g. in 15.11) that length
fields should be a semi-constrained number, but gives a reference
to section gives a reference to section 10.9, "General rules for encoding
a length determinant", and not to to 10.7, "Encoding of a
semi-constrained whole number".
Reading the standard that way should imply that a length outside the
root range should be encoded in the same way as an unconstrained
length, and that the decoder does the right thing.
Further support for that interpretation:
- Larmouth's book [3], page 303.
- The ASN.1 playground. [4]
References:
[1] http://www.oss.com/asn1/resources/books-whitepapers-pubs/dubuisson-asn1-book.PDF
[2] http://www.itu.int/ITU-T/studygroups/com17/languages/X.691-0207.pdf
[3] http://www.oss.com/asn1/resources/books-whitepapers-pubs/larmouth-asn1-book.pdf
[4] http://asn1-playground.oss.com
|
|
Optimize the decoding of CHOICE. Most important is to inline decoding
of the extension bit (if present) and decoding of the choice index
to give the BEAM compiler more opportunities for optimization.
We will also change the structure of the generated code. The current
code uses a flattened case for both the root and extension alternatives:
case Choice + NumRootChoices * Ext of
%% Root alternatives.
0 - ...;
:
LastRootAlternative -> ...;
%% Extension alternatives.
LastRootAlternative+1 -> ...;
:
%% Unknown extension.
_ -> ...;
end
We will instead generate nested cases:
case Ext of
0 ->
case Choice of
%% Root alternatives.
0 - ...;
:
LastRootAlternative -> ...
end;
1 ->
%% Extension alternatives.
<Decode the open type here>
case Choice of
0 -> ...;
:
LastExtensionAlternative -> ...;
%% Unknown extension.
_ -> ...;
end
end
Nested cases should be slightly faster. For decoding of the extensions,
it also makes it possible to hoist the decoding of the open type up
from each case to before the case switching on the extension index,
thus reducing the size of the generated code.
We will also do another change to the structure. Currently, the
big flat clase is wrapped in code that repackages the return values:
{Alt,{Value,RemainingEncodedData}} =
case Choice + NumRootChoices * Ext of
:
end,
{{Value,Alt},RemainingEncodedData}.
We still need to do the repackaging, but we can push it down to
the case arm for decoding each alternative. In many cases, that
will give the BEAM compiler the opportunity to avoid building the
temporary tuples.
|
|
If the encoding is empty (i.e. if a top-level type is single-valued
and therefore not encoding), the result should be a single zero
byte.
|
|
|
|
Now that the decoding of all types are generated inline, we can
take out most of the code for decoding lengths.
|
|
|
|
|
|
|
|
We do it in the simplest possible way by converting the bitstring
to a compact bitstring tuple.
The encoding of BIT STRINGs should be cleaned up and optimized.
|
|
|
|
Refactor decoding of BIT STRINGs so that the run-time code does
not spend testing conditions that are known already at compile-time
(which wastes time and produces unnecessary Dialyzer warnings).
There are three ways to decode BIT STRINGs:
1) To a list of bit names (and {bit,Position} for unnamed positions)
if the BIT STRING type has any bit names.
2a) To a list of ones and zeros if there are no named bits, and the
compact_bit_string option was NOT given.
2b) To a {Unused,Bin} tuple if there are no named bits compact_bit_string
option WAS given.
Structure the decoding functions in the same way.
|
|
Always pre-encode the values for the enumeration. Clean up the
code and let the per and uper back-ends share the code.
|
|
The template modules (asn1rtt_*.erl) are based on the existing
run-time modules, but with some simplifications and improvements,
for example:
The run-time functions for BER encoding took a Constraint argument which
was not used. It has been eliminated, along with the unused StringType
argument for the encode_restricted_string function.
The Range argument for decode_enumerated() has been dropped since it
was not used.
|