Subject: [Cbor] building "enum" from CDDL map keys

From: Michael Richardson <[email-masked]>
Date: Sun, 14 Mar 2021 17:08:53 -0400

This seems to be primarily about a specific parser for CDDL, (software), and
the IETF is not entirely concerned about how specific software works (or
fails to), except in as-much that it is implementator feedback.

I have figured out how to use Carsten's "cddl" program to process my CDDL
file for the internal protocol that led me to file-magic and network-address.
Yes, I've actually already implemented in C first (validated with hundreds of
unit tests), and then wrote it down in CDDL before I implement in Rust.
(It was also really a process of discoverying what data was part of which
commands, which has so far remained an internal-only issue)

So I have a series of maps (I'm unclear if I should, in CDDL refer to them as
tables).  So I have, for example:

whack-message = {
  WHACK_STATUS     => { },
  WHACK_SHUTDOWN   => { },
  WHACK_OPTIONS    => OptionsCommand,
  WHACK_CONNECTION => Connection,
  ...
}
...
WHACK_STATUS =  1
WHACK_SHUTDOWN =2
WHACK_OPTIONS  =3
WHACK_CONNECTION=4
...

So to be clear, a single command message is a map, and each map key implies a
command.  This is a kind of very-wide-instruction-set, and is copied from the C-code.
In practice, we rarely do more than one command at the same time.

(I initially used : rather than => and then learnt that was wrong. That cddl
program helped me a lot here.  It also helped me find a typo, "unit" rather
than "uint", although the error handling there could be improved)

With the undocumented "e" option, I can create output like:

#define CDDL_WHACK_STATUS 1
#define CDDL_WHACK_SHUTDOWN 2
#define CDDL_WHACK_OPTIONS 3
#define CDDL_WHACK_CONNECTION 4

(or any other single-line format) which is useful, but not ideal.  What I really want is:

  enum whack_message_keys {
     WHACK_STATUS = 1,
     WHACK_SHUTDOWN=2,
     WHACK_OPTIONS =3,
     WHACK_CONNECTION=4
     ...
  };

A reason I want to do this is so that my compiler can help me identify:
  1) duplicate values
  2) missing handling of case statements

<CORE POINT>
I looked through the cddl code, and I am not at all certain that CDDL has
enough meta information about where the keys are used to be able to do this.
I think that it's also possible to use the same key values in many places,
and I even do this myself.

I think that what I'm doing is not unique: maybe I should be describing this
in CDDL in a different way.
</CORE POINT>

So at this point, I'm generating to another file:
	printf "/* generated from whack.cddl */\n" >include/whack_values.h
	printf "#ifndef WHACKVALUES_H\n#define WHACKVALUES_H\n" >>include/whack_values.h
	cddl docs/whack.cddl ep                  >>include/whack_values.h
	printf "#endif /* WHACKVALUES_H */\n"    >>include/whack_values.h

and then I would have:

enum whack_CBOR_actions {
    WHACK_STATUS =  CDDL_WHACK_STATUS,
    WHACK_SHUTDOWN =CDDL_WHACK_SHUTDOWN,
    WHACK_OPTIONS  =CDDL_WHACK_OPTIONS,
    WHACK_CONNECTION=CDDL_WHACK_CONNECTION,
...

but that requires more work that I'd like, and I won't get the switch(enum)
benefit from the compiler, telling me that I forgot to implement something.

(There are, however, some conflicting requirements here, because I probably
do want a default: clause that skips CBOR that I don't know, in order to
allow for forward and backwards compatibility.  This does not apply at all
levels of the decode though)

--
]               Never tell me the odds!                 | ipv6 mesh networks [
]   Michael Richardson, Sandelman Software Works        |    IoT architect   [
]     [email-masked]  http://www.sandelman.ca/        |   ruby on rails    [

--
Michael Richardson <[email-masked]>   . o O ( IPv6 IøT consulting )
           Sandelman Software Works Inc, Ottawa and Worldwide

---

From: Carsten Bormann <[email-masked]>
Date: Sun, 14 Mar 2021 22:29:53 +0100

> and I even do this myself.

For each rule that defines a map, a tool could look at the keys used in that map and build a C enum from that.  This would require some conventions (i.e., the CDDL should look somewhat like yours), but it doesn’t sound too hard.

In my copious free time, I’ll see if I can hack this into the cddlc tool...

Grüße, Carsten

---

From: Carsten Bormann <[email-masked]>
Date: Mon, 15 Mar 2021 11:44:24 +0100

>  enum whack_message_keys {

cddlc 0.0.2 can do this:

$ cddlc -tenum test-data/whack.cddl
enum whack_message_keys {
  WHACK_STATUS = 1,
  WHACK_SHUTDOWN = 2,
  WHACK_OPTIONS = 3,
  WHACK_CONNECTION = 4,
};

I’m not sure whether keeping the key names undecorated is OK in all cases, but that’s maybe for a 0.0.3.

As usual,

	gem update cddlc

or
	gem install cddlc

if you haven’t used it before).

This is a banana version (it is intended to ripen after shipping), but it seems to work for me.

Grüße, Carsten

---

From: Michael Richardson <[email-masked]>
Date: Tue, 16 Mar 2021 18:40:19 -0400

> enum whack_message_keys {

Very cool.
This reveals that my choices for sub-table names was poor, but that's my fault.

    > This is a banana version (it is intended to ripen after shipping), but

I'll dig into it the source and see what I need to get the equivalent Rust output, which
is probably the major point of using CDDL.