-
Notifications
You must be signed in to change notification settings - Fork 44
feat: Use the Serde attributes and check for conflicting attributes #377
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
base: main
Are you sure you want to change the base?
Conversation
| if avro.skip && !serde.skip { | ||
| errors.push(syn::Error::new( | ||
| span, | ||
| "`#[avro(skip)]` requires `#[serde(skip)]`, it's also deprecated. Please use only `#[serde(skip)]`" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a way to report the usage of a deprecated avro(attribute) as a warning without depending on the value of its respective serde counter-part ?
I.e. pseudo code:
if avro.skip { report a warning like "#[avro(skip)] is deprecated. Use #[serde(skip)] instead" }
if avro.skip != serde.skip {report an error, without the ", it's also deprecated" text}
Currently the user will be notified that a deprecated avro attribute is used only if the avro value differs from the serde's one.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's only possible on nightly sadly (rust-lang/rust#54140). We could put #[rustversion::attr(not(nightly), ignore)] on a codeblock and only emit warnings on nightly
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds good!
Let's do it!
Then once it is in stable and our MSRV is at least this stable version we could delete just this attribute to enable it for all.
762c230 to
4efa998
Compare
This commit changes the attribute parsing in `#[derive(AvroSchema)]` to also use the Serde attributes. It will use the Serde attributes and check that they match the Avro attributes if provided. It will also check that known incompatible Serde attributes result in a compile error instead of a runtime panic. Testing for the compile errors is done using `trybuild`. These tests run only on nightly as the output can vary between compiler versions (otherwise MSRV and latest stable could have different outputs and break the entire CI).
4efa998 to
392ae2c
Compare
|
A PR has been opened at Derling repo with an example how to parse We may borrow something useful from it. |
| } | ||
| pub fn from_str(rename_all_str: &str) -> Result<Self, ParseError> { | ||
| match rename_all_str { | ||
| "lowercase" => Ok(Self::LowerCase), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why this no more uses RENAME_RULES ? Now the rules are duplicated.
RENAME_RULES
.iter()
.find(|(name, _)| *name == rename_all_str)
.map(|(_, rule)| *rule)
.ok_or_else(|| ParseError {
unknown: rename_all_str.to_string(),
})| impl RenameAll { | ||
| fn from_expr(expr: &Expr) -> darling::Result<Self> { | ||
| let Expr::Lit(lit) = expr else { | ||
| return Err(darling::Error::custom("Expected a string or a tuple!")); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| return Err(darling::Error::custom("Expected a string or a tuple!")); | |
| return Err(darling::Error::custom("Expected a string literal!")); |
The tuple form is handled by FromMeta derive.
| if avro.skip && !serde.skip { | ||
| errors.push(syn::Error::new( | ||
| span, | ||
| "`#[avro(skip)]` requires `#[serde(skip)]`, it's also deprecated. Please use only `#[serde(skip)]`" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds good!
Let's do it!
Then once it is in stable and our MSRV is at least this stable version we could delete just this attribute to enable it for all.
| if avro.rename.is_some() && serde.rename != avro.rename { | ||
| errors.push(syn::Error::new( | ||
| span, | ||
| "`#[avro(rename = \"..\")]` must match `#[serde(rename = \"..\")]`, it's also deprecated. Please use only `#[serde(rename = \"..\")]`" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| "`#[avro(rename = \"..\")]` must match `#[serde(rename = \"..\")]`, it's also deprecated. Please use only `#[serde(rename = \"..\")]`" | |
| "`#[avro(rename = \"..\")]` must match `#[serde(rename = \"..\")]`, it's also deprecated. Please use only `#[serde(rename = \"..\")]`" |
| if avro.rename.is_some() && serde.rename != avro.rename { | ||
| errors.push(syn::Error::new( | ||
| span, | ||
| "`#[avro(rename = \"..\")]` must match `#[serde(rename = \"..\")]`, it's also deprecated. Please use only `#[serde(rename = \"..\")]`" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| "`#[avro(rename = \"..\")]` must match `#[serde(rename = \"..\")]`, it's also deprecated. Please use only `#[serde(rename = \"..\")]`" | |
| "`#[avro(rename = \"..\")]` must match `#[serde(rename = \"..\")]`, it's also deprecated. Please use only `#[serde(rename = \"..\")]`" |
| assert_eq!(obj, serde(obj.clone()).unwrap()); | ||
| } | ||
|
|
||
| /// Takes in a type that implements the right combination of traits and runs it through a Serde Cycle and asserts that the error matches the expected string |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| /// Takes in a type that implements the right combination of traits and runs it through a Serde Cycle and asserts that the error matches the expected string | |
| /// Takes in a type that implements the right combination of traits and runs it through a Serde round-trip and asserts that the error matches the expected string |
| if let Some(res) = reader.next() { | ||
| return res.and_then(|v| from_value::<T>(&v)); | ||
| } | ||
| unreachable!("Nothing was encoded!") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| unreachable!("Nothing was encoded!") | |
| panic!("Nothing was encoded!") |
| let schema = r#" | ||
| { | ||
| "type":"record", | ||
| "name":"Foo", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't this be "Bar" ?!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| "name":"bar", | ||
| "type": { | ||
| "type":"record", | ||
| "name":"Foo", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Bar ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| pub struct ContainerAttributes { | ||
| #[darling(rename = "rename")] | ||
| /// Rename this container. | ||
| pub _rename: Option<String>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I just noticed in tests/serde.rs that this attribute is ignored.
Shall we try to support it too ?
- if
#[avro(name=...)]is provided then use it - if
#[serde(rename=...)]is provided then use it - if both are provided then error
- if none are provided then use the struct name
WDYT ?
| errors.push(syn::Error::new( | ||
| span, | ||
| "AvroSchema derive does not support Serde `transparent` attribute", | ||
| )) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| )) | |
| )); |
| errors.push(syn::Error::new( | ||
| span, | ||
| "AvroSchema derive does not support different rename rules for serializing and deserializing (`rename_all(serialize = \"..\", deserialize = \"..\")`)" | ||
| )) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| )) | |
| )); |
| errors.push(syn::Error::new( | ||
| span, | ||
| "#[avro(rename_all = \"..\")] must match #[serde(rename_all = \"..\")], it's also deprecated. Please use only `#[serde(rename_all = \"..\")]`", | ||
| )) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| )) | |
| )); |
This commit changes the attribute parsing in
#[derive(AvroSchema)]to also use the Serde attributes. It will use the Serde attributes and check that they match the Avro attributes if provided. It will also check that known incompatible Serde attributes result in a compile error instead of a runtime panic.Testing for the compile errors is done using
trybuild. These tests run only on nightly as the output can vary between compiler versions (otherwise MSRV and latest stable could have different outputs and break the entire CI).For some reason Github closed #373, not sure why. This is the exact same commit.