Skip to content

Support non-table types as types #161

Open

Description

@alistair23

I'm hitting this TODO

None => unimplemented!("TODO: non-table types as types: {:?}", group),

it would be great to have this implemented :)

I wanted to open this to help track implementing it

Activity

  1. rooooooooob commented on Mar 23, 2023

    @rooooooooob
    Contributor

    @alistair23 can you post the CDDL file (or snippet from it) that encountered it? It's possible it could be rewritten to work around it in the meantime (and good to reference for the issue in general).

  2. alistair23 commented on Mar 23, 2023

    @alistair23
    Author

    Yep!

    So running

    RUST_BACKTRACE=1 cargo run -- --input test.cddl --output rust-code

    On

    class-map = non-empty<{
      ? &(class-id: 0) => $class-id-type-choice
      ? &(vendor: 1) => tstr
      ? &(model: 2) => tstr
      ? &(layer: 3) => uint
      ? &(index: 4) => uint
    }>
    
    environment-map = non-empty<{
      ? &(class: 0) => class-map
      ? &(instance: 1) => $instance-id-type-choice
      ? &(group: 2) => $group-id-type-choice
    }>
    

    Gives me this

    int
    int
    Switching from scope 'lib' to 'lib'
    class-map
    environment-map
    _CDDL_CODEGEN_EXTERN_TYPE_
    _CDDL_CODEGEN_RAW_BYTES_TYPE_
    
    
    ------------------------------------------
    - Handling rule: lib:_CDDL_CODEGEN_EXTERN_TYPE_
    ------------------------------------
    _CDDL_CODEGEN_EXTERN_TYPE_
    
    
    ------------------------------------------
    - Handling rule: lib:_CDDL_CODEGEN_RAW_BYTES_TYPE_
    ------------------------------------
    _CDDL_CODEGEN_RAW_BYTES_TYPE_
    
    
    ------------------------------------------
    - Handling rule: lib:class-map
    ------------------------------------
    class-map
    non-empty
    non-empty
    thread 'main' panicked at 'not implemented: TODO: non-table types as types: Group { group_choices: [GroupChoice { group_entries: [(ValueMemberKey { ge: ValueMemberKeyEntry { occur: Some(Occurrence { occur: Optional { span: (64, 65, 4) }, comments: None, _a: PhantomData<&()> }), member_key: Some(Type1 { t1: Type1 { type2: ChoiceFromInlineGroup { group: Group { group_choices: [GroupChoice { group_entries: [(ValueMemberKey { ge: ValueMemberKeyEntry { occur: None, member_key: Some(Bareword { ident: Identifier { ident: "class-id", socket: None, span: (68, 76, 4) }, span: (68, 77, 4), comments: None, comments_after_colon: None }), entry_type: Type { type_choices: [TypeChoice { type1: Type1 { type2: UintValue { value: 0, span: (78, 79, 4) }, operator: None, span: (78, 79, 4), comments_after_type: None }, comments_before_type: None, comments_after_type: None }], span: (78, 79, 4) } }, span: (68, 79, 4), leading_comments: None, trailing_comments: None }, OptionalComma { optional_comma: false, trailing_comments: None, _a: PhantomData<&()> })], span: (68, 79, 4), comments_before_grpchoice: None }], span: (68, 79, 4) }, span: (66, 79, 4), comments: None, comments_before_group: None, comments_after_group: None }, operator: None, span: (66, 80, 4), comments_after_type: None }, is_cut: false, span: (66, 105, 4), comments_before_cut: None, comments_after_cut: None, comments_after_arrowmap: None }), entry_type: Type { type_choices: [TypeChoice { type1: Type1 { type2: Typename { ident: Identifier { ident: "class-id-type-choice", socket: Some(TYPE), span: (84, 105, 4) }, generic_args: None, span: (84, 105, 4) }, operator: None, span: (84, 105, 4), comments_after_type: None }, comments_before_type: None, comments_after_type: None }], span: (84, 105, 4) } }, span: (64, 105, 4), leading_comments: None, trailing_comments: None }, OptionalComma { optional_comma: false, trailing_comments: None, _a: PhantomData<&()> }), (ValueMemberKey { ge: ValueMemberKeyEntry { occur: Some(Occurrence { occur: Optional { span: (108, 109, 5) }, comments: None, _a: PhantomData<&()> }), member_key: Some(Type1 { t1: Type1 { type2: ChoiceFromInlineGroup { group: Group { group_choices: [GroupChoice { group_entries: [(ValueMemberKey { ge: ValueMemberKeyEntry { occur: None, member_key: Some(Bareword { ident: Identifier { ident: "vendor", socket: None, span: (112, 118, 5) }, span: (112, 119, 5), comments: None, comments_after_colon: None }), entry_type: Type { type_choices: [TypeChoice { type1: Type1 { type2: UintValue { value: 1, span: (120, 121, 5) }, operator: None, span: (120, 121, 5), comments_after_type: None }, comments_before_type: None, comments_after_type: None }], span: (120, 121, 5) } }, span: (112, 121, 5), leading_comments: None, trailing_comments: None }, OptionalComma { optional_comma: false, trailing_comments: None, _a: PhantomData<&()> })], span: (112, 121, 5), comments_before_grpchoice: None }], span: (112, 121, 5) }, span: (110, 121, 5), comments: None, comments_before_group: None, comments_after_group: None }, operator: None, span: (110, 122, 5), comments_after_type: None }, is_cut: false, span: (110, 130, 5), comments_before_cut: None, comments_after_cut: None, comments_after_arrowmap: None }), entry_type: Type { type_choices: [TypeChoice { type1: Type1 { type2: Typename { ident: Identifier { ident: "tstr", socket: None, span: (126, 130, 5) }, generic_args: None, span: (126, 130, 5) }, operator: None, span: (126, 130, 5), comments_after_type: None }, comments_before_type: None, comments_after_type: None }], span: (126, 130, 5) } }, span: (108, 130, 5), leading_comments: None, trailing_comments: None }, OptionalComma { optional_comma: false, trailing_comments: None, _a: PhantomData<&()> }), (ValueMemberKey { ge: ValueMemberKeyEntry { occur: Some(Occurrence { occur: Optional { span: (133, 134, 6) }, comments: None, _a: PhantomData<&()> }), member_key: Some(Type1 { t1: Type1 { type2: ChoiceFromInlineGroup { group: Group { group_choices: [GroupChoice { group_entries: [(ValueMemberKey { ge: ValueMemberKeyEntry { occur: None, member_key: Some(Bareword { ident: Identifier { ident: "model", socket: None, span: (137, 142, 6) }, span: (137, 143, 6), comments: None, comments_after_colon: None }), entry_type: Type { type_choices: [TypeChoice { type1: Type1 { type2: UintValue { value: 2, span: (144, 145, 6) }, operator: None, span: (144, 145, 6), comments_after_type: None }, comments_before_type: None, comments_after_type: None }], span: (144, 145, 6) } }, span: (137, 145, 6), leading_comments: None, trailing_comments: None }, OptionalComma { optional_comma: false, trailing_comments: None, _a: PhantomData<&()> })], span: (137, 145, 6), comments_before_grpchoice: None }], span: (137, 145, 6) }, span: (135, 145, 6), comments: None, comments_before_group: None, comments_after_group: None }, operator: None, span: (135, 146, 6), comments_after_type: None }, is_cut: false, span: (135, 154, 6), comments_before_cut: None, comments_after_cut: None, comments_after_arrowmap: None }), entry_type: Type { type_choices: [TypeChoice { type1: Type1 { type2: Typename { ident: Identifier { ident: "tstr", socket: None, span: (150, 154, 6) }, generic_args: None, span: (150, 154, 6) }, operator: None, span: (150, 154, 6), comments_after_type: None }, comments_before_type: None, comments_after_type: None }], span: (150, 154, 6) } }, span: (133, 154, 6), leading_comments: None, trailing_comments: None }, OptionalComma { optional_comma: false, trailing_comments: None, _a: PhantomData<&()> }), (ValueMemberKey { ge: ValueMemberKeyEntry { occur: Some(Occurrence { occur: Optional { span: (157, 158, 7) }, comments: None, _a: PhantomData<&()> }), member_key: Some(Type1 { t1: Type1 { type2: ChoiceFromInlineGroup { group: Group { group_choices: [GroupChoice { group_entries: [(ValueMemberKey { ge: ValueMemberKeyEntry { occur: None, member_key: Some(Bareword { ident: Identifier { ident: "layer", socket: None, span: (161, 166, 7) }, span: (161, 167, 7), comments: None, comments_after_colon: None }), entry_type: Type { type_choices: [TypeChoice { type1: Type1 { type2: UintValue { value: 3, span: (168, 169, 7) }, operator: None, span: (168, 169, 7), comments_after_type: None }, comments_before_type: None, comments_after_type: None }], span: (168, 169, 7) } }, span: (161, 169, 7), leading_comments: None, trailing_comments: None }, OptionalComma { optional_comma: false, trailing_comments: None, _a: PhantomData<&()> })], span: (161, 169, 7), comments_before_grpchoice: None }], span: (161, 169, 7) }, span: (159, 169, 7), comments: None, comments_before_group: None, comments_after_group: None }, operator: None, span: (159, 170, 7), comments_after_type: None }, is_cut: false, span: (159, 178, 7), comments_before_cut: None, comments_after_cut: None, comments_after_arrowmap: None }), entry_type: Type { type_choices: [TypeChoice { type1: Type1 { type2: Typename { ident: Identifier { ident: "uint", socket: None, span: (174, 178, 7) }, generic_args: None, span: (174, 178, 7) }, operator: None, span: (174, 178, 7), comments_after_type: None }, comments_before_type: None, comments_after_type: None }], span: (174, 178, 7) } }, span: (157, 178, 7), leading_comments: None, trailing_comments: None }, OptionalComma { optional_comma: false, trailing_comments: None, _a: PhantomData<&()> }), (ValueMemberKey { ge: ValueMemberKeyEntry { occur: Some(Occurrence { occur: Optional { span: (181, 182, 8) }, comments: None, _a: PhantomData<&()> }), member_key: Some(Type1 { t1: Type1 { type2: ChoiceFromInlineGroup { group: Group { group_choices: [GroupChoice { group_entries: [(ValueMemberKey { ge: ValueMemberKeyEntry { occur: None, member_key: Some(Bareword { ident: Identifier { ident: "index", socket: None, span: (185, 190, 8) }, span: (185, 191, 8), comments: None, comments_after_colon: None }), entry_type: Type { type_choices: [TypeChoice { type1: Type1 { type2: UintValue { value: 4, span: (192, 193, 8) }, operator: None, span: (192, 193, 8), comments_after_type: None }, comments_before_type: None, comments_after_type: None }], span: (192, 193, 8) } }, span: (185, 193, 8), leading_comments: None, trailing_comments: None }, OptionalComma { optional_comma: false, trailing_comments: None, _a: PhantomData<&()> })], span: (185, 193, 8), comments_before_grpchoice: None }], span: (185, 193, 8) }, span: (183, 193, 8), comments: None, comments_before_group: None, comments_after_group: None }, operator: None, span: (183, 194, 8), comments_after_type: None }, is_cut: false, span: (183, 202, 8), comments_before_cut: None, comments_after_cut: None, comments_after_arrowmap: None }), entry_type: Type { type_choices: [TypeChoice { type1: Type1 { type2: Typename { ident: Identifier { ident: "uint", socket: None, span: (198, 202, 8) }, generic_args: None, span: (198, 202, 8) }, operator: None, span: (198, 202, 8), comments_after_type: None }, comments_before_type: None, comments_after_type: None }], span: (198, 202, 8) } }, span: (181, 202, 8), leading_comments: None, trailing_comments: None }, OptionalComma { optional_comma: false, trailing_comments: None, _a: PhantomData<&()> })], span: (61, 202, 3), comments_before_grpchoice: None }], span: (61, 202, 3) }', src/parsing.rs:1231:33
    stack backtrace:
       0: rust_begin_unwind
                 at /rustc/2c8cc343237b8f7d5a3c3703e3a87f2eb2c54a74/library/std/src/panicking.rs:575:5
       1: core::panicking::panic_fmt
                 at /rustc/2c8cc343237b8f7d5a3c3703e3a87f2eb2c54a74/library/core/src/panicking.rs:64:14
       2: cddl_codegen::parsing::rust_type_from_type2
                 at ./src/parsing.rs:1231:33
       3: cddl_codegen::parsing::rust_type_from_type1
                 at ./src/parsing.rs:1074:21
       4: cddl_codegen::parsing::parse_type::{{closure}}
                 at ./src/parsing.rs:544:49
       5: core::iter::adapters::map::map_fold::{{closure}}
                 at /rustc/2c8cc343237b8f7d5a3c3703e3a87f2eb2c54a74/library/core/src/iter/adapters/map.rs:84:28
       6: core::iter::traits::iterator::Iterator::fold
                 at /rustc/2c8cc343237b8f7d5a3c3703e3a87f2eb2c54a74/library/core/src/iter/traits/iterator.rs:2438:21
       7: <core::iter::adapters::map::Map<I,F> as core::iter::traits::iterator::Iterator>::fold
                 at /rustc/2c8cc343237b8f7d5a3c3703e3a87f2eb2c54a74/library/core/src/iter/adapters/map.rs:124:9
       8: core::iter::traits::iterator::Iterator::for_each
                 at /rustc/2c8cc343237b8f7d5a3c3703e3a87f2eb2c54a74/library/core/src/iter/traits/iterator.rs:837:9
       9: alloc::vec::Vec<T,A>::extend_trusted
                 at /rustc/2c8cc343237b8f7d5a3c3703e3a87f2eb2c54a74/library/alloc/src/vec/mod.rs:2885:17
      10: <alloc::vec::Vec<T,A> as alloc::vec::spec_extend::SpecExtend<T,I>>::spec_extend
                 at /rustc/2c8cc343237b8f7d5a3c3703e3a87f2eb2c54a74/library/alloc/src/vec/spec_extend.rs:26:9
      11: <alloc::vec::Vec<T> as alloc::vec::spec_from_iter_nested::SpecFromIterNested<T,I>>::from_iter
                 at /rustc/2c8cc343237b8f7d5a3c3703e3a87f2eb2c54a74/library/alloc/src/vec/spec_from_iter_nested.rs:62:9
      12: <alloc::vec::Vec<T> as alloc::vec::spec_from_iter::SpecFromIter<T,I>>::from_iter
                 at /rustc/2c8cc343237b8f7d5a3c3703e3a87f2eb2c54a74/library/alloc/src/vec/spec_from_iter.rs:33:9
      13: <alloc::vec::Vec<T> as core::iter::traits::collect::FromIterator<T>>::from_iter
                 at /rustc/2c8cc343237b8f7d5a3c3703e3a87f2eb2c54a74/library/alloc/src/vec/mod.rs:2753:9
      14: core::iter::traits::iterator::Iterator::collect
                 at /rustc/2c8cc343237b8f7d5a3c3703e3a87f2eb2c54a74/library/core/src/iter/traits/iterator.rs:1860:9
      15: cddl_codegen::parsing::parse_type
                 at ./src/parsing.rs:540:60
      16: cddl_codegen::parsing::parse_rule
                 at ./src/parsing.rs:82:21
      17: cddl_codegen::main
                 at ./src/main.rs:121:9
      18: core::ops::function::FnOnce::call_once
                 at /rustc/2c8cc343237b8f7d5a3c3703e3a87f2eb2c54a74/library/core/src/ops/function.rs:250:5
    note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.

    If you have any ideas of how to re-write it please let me know :)

  3. rooooooooob commented on Mar 23, 2023

    @rooooooooob
    Contributor

    What are you trying to achieve with &(class-id: 0)? We had never used & in the specs we've been generating from but what is the point in doing it on a basic group of only 1 value? Doesn't that create a type choice of only 1 option, that being 0? Or does this do something with the group encoding when you're putting it in the outer group? Forgive me if I'm not understanding things.

    If those are just meant to be the uint values for each of those keys then try directly placing them as:

    class-map = non-empty<{
      ?  0: $class-id-type-choice, ; @name class_id
      ? 1: tstr ; @name vendor
      ? 2: tstr, ; @name 
      ? 3: uint, ; @name layer
      ? 4: uint, ; @name index
    }>
    

    The generic support is also rather weak so you might need to avoid using it (what is the definition for non-empty<T>?) I stuck in those ; @name comments since it lets our parser name fields custom things instead of trying to name it after the key's value (key_0, key_1, key_2, etc here without those)

  4. alistair23 commented on Mar 23, 2023

    @alistair23
    Author

    I have no idea, the class-map is taken from here:

    https://github.com/ietf-rats-wg/draft-ietf-rats-corim/blob/b4c4b88550c2c2fbad47e9866bc6e0f1c6a303b3/cddl/class-map.cddl#L1

    I'm not sure why they put it in a choice. I haven't yet wrapped my head around CDDL to have any idea why someone would do that.

    As for the non-empty, it's also defined here: https://github.com/ietf-rats-wg/draft-ietf-rats-corim/blob/b4c4b88550c2c2fbad47e9866bc6e0f1c6a303b3/draft-ietf-rats-corim.md?plain=1#L151

  5. rooooooooob commented on Mar 23, 2023

    @rooooooooob
    Contributor

    I don't think we can work around that non-empty restriction via cddl-codegen/changing the CDDL then. You can still try doing just:

    class-map = {
      ? 0: $class-id-type-choice, ; @name class_id
      ? 1: tstr, ; @name vendor
      ? 2: tstr, ; @name model
      ? 3: uint, ; @name layer
      ? 4: uint, ; @name index
    }
    
    environment-map = {
      ? 0: class-map, ; @name class
      ? 1: $instance-id-type-choice, ; @name instance
      ? 2: $group-id-type-choice, ; @name group
    }
    

    and either not care that it doesn't enforce the non-empty requirement, or write that check yourself (should be like 1-2 lines of code).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions