Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support non-table types as types #161

Open
alistair23 opened this issue Mar 23, 2023 · 5 comments
Open

Support non-table types as types #161

alistair23 opened this issue Mar 23, 2023 · 5 comments

Comments

@alistair23
Copy link

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

@rooooooooob
Copy link
Collaborator

@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).

@alistair23
Copy link
Author

alistair23 commented Mar 23, 2023

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 :)

@rooooooooob
Copy link
Collaborator

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)

@alistair23
Copy link
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

@rooooooooob
Copy link
Collaborator

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
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants