Skip to content

Commit

Permalink
Wrapper JSON Overhaul (#224)
Browse files Browse the repository at this point in the history
Wrapper JSON Overhaul

Wrapper newtypes will generate custom implementations that will defer to
the inner type's JSON traits instead of deriving to get them.
This gives us much nicer JSON implementations allowing directly `T`
instead of `{ inner: T }`.

Bytes newtypes will have a specialization that serializes to hex
bytestring instead of the `[number]` array that would otherwise be used.

Introduces `@custom_json` comment DSL for newtypes that tell
cddl-codegen to avoid generating/deriving any JSON traits under the
assumption that some custom trait impls will be provided post-generation
by the user.
  • Loading branch information
rooooooooob authored Jan 30, 2024
1 parent 8d0de82 commit 656c507
Show file tree
Hide file tree
Showing 10 changed files with 485 additions and 40 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,4 @@ book/
# Test files
tests/*/export/**
tests/*/export_wasm/**
tests/*/export_preserve/**
8 changes: 8 additions & 0 deletions docs/docs/comment_dsl.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,14 @@ Putting this comment on a type forces that type to derive those traits even if i
This is useful for when you are writing utility code that would put them in a map and want the generated code to have it already,
which is particularly useful for re-generating as it lets your `mod.rs` files remain untouched.

## @custom_json

```cddl
foo = uint ; @newtype @custom_json
```

Avoids generating and/or deriving json-related traits under the assumption that the user will supply their own implementation to be used in the generated library.

## _CDDL_CODEGEN_EXTERN_TYPE_

While not as a comment, this allows you to compose in hand-written structs into a cddl spec.
Expand Down
44 changes: 43 additions & 1 deletion src/comment_ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ pub struct RuleMetadata {
pub is_newtype: bool,
pub no_alias: bool,
pub used_as_key: bool,
pub custom_json: bool,
}

pub fn merge_metadata(r1: &RuleMetadata, r2: &RuleMetadata) -> RuleMetadata {
Expand All @@ -26,6 +27,7 @@ pub fn merge_metadata(r1: &RuleMetadata, r2: &RuleMetadata) -> RuleMetadata {
is_newtype: r1.is_newtype || r2.is_newtype,
no_alias: r1.no_alias || r2.no_alias,
used_as_key: r1.used_as_key || r2.used_as_key,
custom_json: r1.custom_json || r2.custom_json,
};
merged.verify();
merged
Expand All @@ -36,6 +38,7 @@ enum ParseResult {
Name(String),
DontGenAlias,
UsedAsKey,
CustomJson,
}

impl RuleMetadata {
Expand All @@ -61,6 +64,9 @@ impl RuleMetadata {
ParseResult::UsedAsKey => {
base.used_as_key = true;
}
ParseResult::CustomJson => {
base.custom_json = true;
}
}
}
base.verify();
Expand Down Expand Up @@ -101,9 +107,21 @@ fn tag_used_as_key(input: &str) -> IResult<&str, ParseResult> {
Ok((input, ParseResult::UsedAsKey))
}

fn tag_custom_json(input: &str) -> IResult<&str, ParseResult> {
let (input, _) = tag("@custom_json")(input)?;

Ok((input, ParseResult::CustomJson))
}

fn whitespace_then_tag(input: &str) -> IResult<&str, ParseResult> {
let (input, _) = take_while(char::is_whitespace)(input)?;
let (input, result) = alt((tag_name, tag_newtype, tag_no_alias, tag_used_as_key))(input)?;
let (input, result) = alt((
tag_name,
tag_newtype,
tag_no_alias,
tag_used_as_key,
tag_custom_json,
))(input)?;

Ok((input, result))
}
Expand Down Expand Up @@ -144,6 +162,7 @@ fn parse_comment_name() {
is_newtype: false,
no_alias: false,
used_as_key: false,
custom_json: false,
}
))
);
Expand All @@ -160,6 +179,7 @@ fn parse_comment_newtype() {
is_newtype: true,
no_alias: false,
used_as_key: false,
custom_json: false,
}
))
);
Expand All @@ -176,6 +196,7 @@ fn parse_comment_newtype_and_name() {
is_newtype: true,
no_alias: false,
used_as_key: false,
custom_json: false,
}
))
);
Expand All @@ -192,6 +213,7 @@ fn parse_comment_newtype_and_name_and_used_as_key() {
is_newtype: true,
no_alias: false,
used_as_key: true,
custom_json: false,
}
))
);
Expand All @@ -208,6 +230,7 @@ fn parse_comment_used_as_key() {
is_newtype: false,
no_alias: false,
used_as_key: true,
custom_json: false,
}
))
);
Expand All @@ -224,6 +247,7 @@ fn parse_comment_newtype_and_name_inverse() {
is_newtype: true,
no_alias: false,
used_as_key: false,
custom_json: false,
}
))
);
Expand All @@ -240,6 +264,24 @@ fn parse_comment_name_noalias() {
is_newtype: false,
no_alias: true,
used_as_key: false,
custom_json: false,
}
))
);
}

#[test]
fn parse_comment_newtype_and_custom_json() {
assert_eq!(
rule_metadata("@custom_json @newtype"),
Ok((
"",
RuleMetadata {
name: None,
is_newtype: true,
no_alias: false,
used_as_key: false,
custom_json: true,
}
))
);
Expand Down
Loading

0 comments on commit 656c507

Please sign in to comment.