Subject: [Cbor] CDDL "type definition" vs instance definition (was: Re: Maps used as keys?)

From: Toerless Eckert <[email-masked]>
Date: Mon, 4 Dec 2017 23:45:57 +0100

The discus from Brian was started with me trying to do something which i am not
sure CDDL  supports well - or how.  So looking for suggestions how to best do it:

We want to standardize for GRASP protocols a map where keys are uint, every 
assigned key gets registed by an IANA registry and the type and definition of
the key dpeends then of course on the spec of that key. Which could be multiple RFCs.

Aka: Good ol' TLV registry with CBOR/CDDL.

So the first definition was trying to sepcify this, see below.

The [2] lines are actual key definitions, for key 1 (named sender-loop-count) and key 2 
(named srv-element). The lines [1] are meant to express the intended typing, aka:
map with uint key and per-key value. 

But... I have problems with [1]: if i include it as specified, then this means
every possible uint is valid and every possible value for every possible key. Which
is not true. 

Now, if i would just remove the [1] lines, i had no definition anymore that
relement needs to be a "registered" uint...

So... how to best fix this ?

Thanks
    Toerless

objective-value  /= { 1*elements }
elements        //= ( @rfcXXXX: { 1*relement } )

relement  = ( relement-codepoint => relement-value ) ; [1]
relement-codepoint = uint                            ; [1]
relement-value     = any                             ; [1]

relement //= ( &(sender-loop-count:1) => 1..255 )    ; [2]
relement //= ( &(srv-element:2) => context-element ) ; [2]

context-element  =  {
     ?( &(private:0)      => any),
     ?( &(msg-type:1)     => msg-type),
     ?( &(service:2)      => tstr),
     *( &(instance:3)     => tstr),
     ?( &(domain:4)       => tstr),
     ?( &(priority:5)     => 0..65535 ),
     ?( &(weight:6)       => 0..65535 ),
     *( &(kvpairs:7)      => { *(tstr: any) }),
    }

---

From: Carsten Bormann <[email-masked]>
Date: Tue, 5 Dec 2017 00:09:04 +0100

> So... how to best fix this ?

This is what .within was invented for.

I’d write something like

foo = { 1*relement }
relement = $$relement .within relement-generic

relement-generic = ( relement-codepoint => relement-value ) ; [1]
relement-codepoint = uint                            ; [1]
relement-value     = any                             ; [1]

$$relement //= ( &(sender-loop-count:1) => 1..255 )    ; [2]
$$relement //= ( &(srv-element:2) => context-element ) ; [2]
context-element = "and so on”

… except that .within is for types, not for groups.  
So we have to do this in a bit more circuitous way:

foo = foo-specific .within foo-generic
foo-specific = { 1*$$relement }
foo-generic = { 1*relement-generic }

relement-generic = ( relement-codepoint => relement-value ) ; [1]
relement-codepoint = uint                            ; [1]
relement-value     = any                             ; [1]

$$relement //= ( &(sender-loop-count:1) => 1..255 )    ; [2]
$$relement //= ( &(srv-element:2) => context-element ) ; [2]
context-element = "and so on”

Grüße, Carsten