mirleft / ocaml-asn1-combinators

Embed typed ASN.1 grammars in OCaml
ISC License
35 stars 20 forks source link

support for enumerations (simple type 0x0A) #19

Closed hannesm closed 7 years ago

hannesm commented 7 years ago

documentation is e.g. here -- an enumerate is just an integer which maps to sth high level.

I took the liberty to cap enumerated at int size, instead of full Z.t range - this is much more convenient for writing (but wrong according to the standard, feel free to complain about it).

the reason I want to have enumerate is RFC5280 again (CRL, there in the revocation list a CRLReason extension may be present):

id-ce-cRLReasons OBJECT IDENTIFIER ::= { id-ce 21 }

CRLReason ::= ENUMERATED {
     unspecified             (0),
     keyCompromise           (1),
     cACompromise            (2),
     affiliationChanged      (3),
     superseded              (4),
     cessationOfOperation    (5),
     certificateHold         (6),
     removeFromCRL           (8),
     privilegeWithdrawn      (9),
     aACompromise           (10) }
pqwy commented 7 years ago

Woah.

let enumerated f g = map f g @@ implicit ~cls:`Universal 0x0a int

A grammar like

Bacon ::= ENUMERATED {
  this   (0),
  that   (1),
  other  (19)
}

can be modeled, as it stands, as

let bacon =
  enumerate
  (function 0 -> `this | 1 -> `that | 19 -> `other | n -> invalid_arg "")
  (function `this -> 0 | `that -> 1 | `other -> 19)

using the above technology.

A function which takes (int * 'a) list and builds the two mappings can be created from that. There are several considerations:

There are many ways to cut it, and this is the reason I omitted special support for ENUMERATED in the first place (and then forgot to add the technology from the beginning). The idea was that a heavy user would create their own convenience functions like this. I can add a predominant form if it sees lots of usage, but there is one single use so far.

Note, bit_string_flags that this is based off is different in that it doesn't have n cases, but more like k n = n * (1 + k (n - 1)).

As for int vs. Z.t, I'm happy to SIGSEGV the process on any grammar with an enumeration label 4611686018427387904.

hannesm commented 7 years ago

Thank you @pqwy - the drawback of cc7d86f is that I've to write down the mapping twice, once as `Foo -> 0 and once 0 -> `Foo -- but I get your point (and the cstruct enum machinery can help to avoid writing the mapping twice).

pqwy commented 7 years ago

As I said, the higher-up combinator can (and should) still be written, and if it proves broadly useful, I will stick it in the library. There are examples of such utilities in X509.