asn1: Add support for decoration w/ external types

This adds support for asn1_compile --decorate=... variation that causes
decoration of an ASN.1 SET/SEQUENCE type with a field of a non-ASN.1
type.

This means we can now have an ASN.1 type to represent a request that can
then have a "hidden" field -- hidden in that it is neither encoded nor
decoded.  This field will be copied and freed when the decoration is of
an ASN.1 type or of a external, C type that comes with copy constructor
and destructor functions.  Decoration with a `void *` field which is
neither copied nor freed is also supported.

We may end up using this to, for example, replace the `hdb_entry_ex`
type by decorating `HDB_entry` with a C type that points to the `HDB` in
which the entry was found or to which it should be written.
This commit is contained in:
Nicolas Williams
2022-01-05 23:16:48 -06:00
parent 10fc7730d0
commit df3e08485b
18 changed files with 958 additions and 244 deletions

View File

@@ -42,43 +42,16 @@
* TBD:
*
* - For OER also encode number of optional/default/extension elements into
* header entry's ptr field, not just the number of entries that follow it
* header entry's ptr field, not just the number of entries that follow it.
*
* - For JER/GSER/whatver, and probably for not-C-coded template interpreters,
* we'll need to have an entry type for the names of structures and their
* fields.
* - For JER we'll need to encode encoding options (encode as array, encode as
* object, etc.)
*
* - For auto open types we need a new opcode, let's call it
* A1_OP_OPENTYPE_OBJSET, and we need to encode into its entry:
* a) the index of the template entry for the type ID field, and
* b) the index of the template entry for the open type field,
* c) 1 bit to indicate whether the object set is sorted by type ID value,
* d) a pointer to the object set's template.
* With that we can then find the struct offsets of those, and also their
* types (since we can find their template entries).
* The object set entries should be encoded into two template entries each:
* one pointing to the value of the type ID field for that object (unless
* the value is an integer, in which case the ptr should be the integer
* value directly), and the other pointing to the template for the type
* identified by the type ID. These will need an opcode each...
* A1_OP_OPENTYPE_ID and A1_OP_OPENTYPE.
* We should also end the object set with an A1_OP_OPENTYPE_OBJSET entry so
* that iterating backwards can be fast. Unless... unless we don't inline
* the object set and its objects but point to the object set's template.
* Also, for extensible object sets we can point to the object set's name,
* and we can then have a function to get an object set template by name,
* one to release that, and one to add an object to the object set (there's
* no need to remove objects from object sets, which helps with thread-
* safety). And then we don't need (c) either.
* The decoder will then not see these entries until after decoding the type
* ID and open type field (as its outer type, so OCTET STRING, BIT STRING,
* or HEIM_ANY) and so it will be able to find those values in the struct at
* their respective offsets.
* The encoder and decoder both need to identify the relevant object in the
* object set, either by linear search or binary search if they are sorted
* by type ID value, then interpret the template for the identified type.
* The encoder needs to place the encoding into the normal location for it
* in the struct, then it can execute the normal template entry for it.
* - For open types we'll need to be able to indicate what encoding rules the
* type uses.
*
* - We have too many bits for tags (20) and probably not enough for ops (4
* bits, and we've used all but one).
*/
/* header:
@@ -155,21 +128,23 @@
* 28..31 op
*/
#define A1_OP_MASK (0xf0000000)
#define A1_OP_TYPE (0x10000000)
#define A1_OP_TYPE_EXTERN (0x20000000)
#define A1_OP_TAG (0x30000000)
#define A1_OP_PARSE (0x40000000)
#define A1_OP_SEQOF (0x50000000)
#define A1_OP_SETOF (0x60000000)
#define A1_OP_BMEMBER (0x70000000)
#define A1_OP_CHOICE (0x80000000)
#define A1_OP_DEFVAL (0x90000000)
#define A1_OP_OPENTYPE_OBJSET (0xa0000000)
#define A1_OP_OPENTYPE_ID (0xb0000000)
#define A1_OP_OPENTYPE (0xc0000000)
#define A1_OP_NAME (0xd0000000)
#define A1_OP_TYPE_DECORATE (0xe0000000)
#define A1_OP_MASK (0xf0000000)
#define A1_OP_TYPE (0x10000000) /* templated type */
#define A1_OP_TYPE_EXTERN (0x20000000) /* templated type (imported) */
#define A1_OP_TAG (0x30000000) /* a tag */
#define A1_OP_PARSE (0x40000000) /* primitive type */
#define A1_OP_SEQOF (0x50000000) /* sequence of */
#define A1_OP_SETOF (0x60000000) /* set of */
#define A1_OP_BMEMBER (0x70000000) /* BIT STRING member */
#define A1_OP_CHOICE (0x80000000) /* CHOICE */
#define A1_OP_DEFVAL (0x90000000) /* def. value */
#define A1_OP_OPENTYPE_OBJSET (0xa0000000) /* object set for open type */
#define A1_OP_OPENTYPE_ID (0xb0000000) /* open type id field */
#define A1_OP_OPENTYPE (0xc0000000) /* open type field */
#define A1_OP_NAME (0xd0000000) /* symbol */
#define A1_OP_TYPE_DECORATE (0xe0000000) /* decoration w/ templated type */
#define A1_OP_TYPE_DECORATE_EXTERN (0xf0000000) /* decoration w/ some C type */
/* 0x00.. is still free */
#define A1_FLAG_MASK (0x0f000000)
#define A1_FLAG_OPTIONAL (0x01000000)