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

feat: add get_default_empty_record #40

Merged
merged 1 commit into from
Feb 23, 2024

Conversation

lucatrv
Copy link
Contributor

@lucatrv lucatrv commented Feb 20, 2024

Summary by CodeRabbit

  • New Features
    • Introduced a function to retrieve default deserialized records for structs, enhancing customization of default record definitions.

Copy link

coderabbitai bot commented Feb 20, 2024

Walkthrough

This update introduces a new function get_default_serde_record to the library, enhancing the serde::Deserialize trait implementation. It's designed to simplify the process of defining default records for structs, particularly useful when working with custom default definitions. The addition is complemented by test cases to ensure its functionality and reliability, marking a significant improvement in the library's usability for developers dealing with serialization and deserialization.

Changes

File(s) Change Summary
src/serde_introspection.rs Added get_default_serde_record function and test cases for enhanced usability.

🐇✨
In the land of code and byte,
A rabbit hopped into the light.
With a flick and a hop, a new function's born,
To ease the devs' toil from dusk till morn.
"Fear not," it squeaked, with a twinkle in its eye,
"For I bring ease to serialize, no longer shall you sigh."
🌟📜

Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

Share

Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>.
    • Generate unit-tests for this file.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit tests for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai generate interesting stats about this repository from git and render them as a table.
    • @coderabbitai show all the console.log statements in this repository.
    • @coderabbitai read src/utils.ts and generate unit tests.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (invoked as PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger a review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai help to get help.

Additionally, you can add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.

CodeRabbit Configration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • The JSON schema for the configuration file is available here.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/coderabbit-overrides.v2.json

CodeRabbit Discord Community

Join our Discord Community to get help, request features, and share feedback.

@iddm
Copy link
Owner

iddm commented Feb 21, 2024

@coderabbitai review

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review Status

Actionable comments generated: 2

Configuration used: CodeRabbit UI

Commits Files that changed from the base of the PR and between 3180d95 and f729679.
Files selected for processing (1)
  • src/serde_introspection.rs (2 hunks)
Additional comments: 1
src/serde_introspection.rs (1)
  • 117-148: The example provided in the documentation for get_default_empty_record is clear and demonstrates the function's usage effectively. It's good practice to include such examples in the documentation, as it helps users understand how to use the function in their code. No changes are needed here, but ensure that the documentation stays up-to-date if the function's behavior changes in the future.

src/serde_introspection.rs Outdated Show resolved Hide resolved
src/serde_introspection.rs Outdated Show resolved Hide resolved
@iddm
Copy link
Owner

iddm commented Feb 21, 2024

Hi @lucatrv ! First and foremost, thank you for your contribution!

Can you please provide a use case for this function to be useful? I am not sure I understand why, for example, and when, I would use it. For example, the code you provided:

#[derive(serde::Deserialize, PartialEq, Debug)]
struct Record {
    #[serde(default = "default_string")]
    label: String,
    #[serde(default = "default_f64")]
    value: f64,
}

fn default_string() -> String {
    String::from("default")
}

fn default_f64() -> f64 {
    1.0
}

let empty_record = get_default_empty_record::<Record>().unwrap();
assert_eq!(
    empty_record,
    Record {
        label: String::from("default"),
        value: 1.0
    }
);

How is it different from this, without using serde at all?

#[derive(serde::Deserialize, PartialEq, Debug)]
struct Record {
    label: String,
    value: f64,
}

impl Default for Record {
    fn default() -> Self {
        Self {
            label: default_string(),
            value: default_f64(),
        }
    }
}

fn default_string() -> String {
    String::from("default")
}

fn default_f64() -> f64 {
    1.0
}

let empty_record = Record::default();
assert_eq!(
    empty_record,
    Record {
        label: String::from("default"),
        value: 1.0
    }
);

@lucatrv
Copy link
Contributor Author

lucatrv commented Feb 21, 2024

@iddm I agree that the example above is trivial and can easily be implemented as you showed, however it was intended just to show how the get_default_empty_record method works, not to show a useful use case.

Please consider however that often we deal with long deserialize structs having most fields implementing the Default trait, while maybe one or two use custom types which do not implement it (for instance Result<f64, String>). Of course it is always possible to deal also with these cases as you showed, but it is much simpler and cleaner to rely on Serde's #[serde(default = "path")] field attribute.

In general, any time the #[serde(default = "path")] field attribute is used, it is much easier and safe to use the get_default_empty_record instead of implementing the Default trait separately, paying attention to follow exactly what was specified through Serde's field attributes, which may easily lead to bugs as well.

From another point of view, IMHO what you wrote could also be applied to most helping functions. For instance we could certainly live for instance also without the deserialize_bool_from_anything, as we can implement it in our code as needed, but I think they are all useful helping functions which shorten and simplifies our code.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review Status

Actionable comments generated: 0

Configuration used: CodeRabbit UI

Commits Files that changed from the base of the PR and between 3180d95 and 06dacf9.
Files selected for processing (1)
  • src/serde_introspection.rs (2 hunks)
Files skipped from review as they are similar to previous changes (1)
  • src/serde_introspection.rs

@lucatrv
Copy link
Contributor Author

lucatrv commented Feb 22, 2024

I added some more explanation in the docstring and example.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review Status

Actionable comments generated: 0

Configuration used: CodeRabbit UI

Commits Files that changed from the base of the PR and between 3180d95 and 1af9f95.
Files selected for processing (1)
  • src/serde_introspection.rs (2 hunks)
Files skipped from review as they are similar to previous changes (1)
  • src/serde_introspection.rs

@iddm
Copy link
Owner

iddm commented Feb 22, 2024

@iddm I agree that the example above is trivial and can easily be implemented as you showed, however it was intended just to show how the get_default_empty_record method works, not to show a useful use case.

Please consider however that often we deal with long deserialize structs having most fields implementing the Default trait, while maybe one or two use custom types which do not implement it (for instance Result<f64, String>). Of course it is always possible to deal also with these cases as you showed, but it is much simpler and cleaner to rely on Serde's #[serde(default = "path")] field attribute.

In general, any time the #[serde(default = "path")] field attribute is used, it is much easier and safe to use the get_default_empty_record instead of implementing the Default trait separately, paying attention to follow exactly what was specified through Serde's field attributes, which may easily lead to bugs as well.

From another point of view, IMHO what you wrote could also be applied to most helping functions. For instance we could certainly live for instance also without the deserialize_bool_from_anything, as we can implement it in our code as needed, but I think they are all useful helping functions which shorten and simplifies our code.

I see. Thank you for the explanation.

What do you think about renaming the function to get_default_serde_record? To show that it will use the #[serde(default)]. Also, do you mind if we add a clearer text explanation in the document to explain the difference between this function and using the Default trait, the same way you explained it to me? Would it make sense?

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review Status

Actionable comments generated: 0

Configuration used: CodeRabbit UI

Commits Files that changed from the base of the PR and between 3180d95 and dbcdb37.
Files selected for processing (1)
  • src/serde_introspection.rs (2 hunks)
Additional comments: 2
src/serde_introspection.rs (2)
  • 117-168: The implementation of get_default_serde_record is concise and leverages Serde's deserialization capabilities effectively to instantiate a default record. This approach is particularly useful when combined with Serde's #[serde(default = "path")] attribute, as it simplifies struct initialization without manually implementing the Default trait. The documentation and example provided are clear and demonstrate the function's utility well.

However, it's important to ensure that all potential error cases are handled appropriately when using this function in a broader context. Specifically, consider adding error handling advice in the documentation for consumers of this API, as deserialization errors can occur for various reasons (e.g., missing required fields, type mismatches).

Overall, the addition of get_default_serde_record enhances the library's functionality by providing a convenient way to obtain default instances of structs that are compatible with Serde's deserialization process.

  • 214-251: > 📝 NOTE

This review was outside the diff hunks and was mapped to the diff hunk with the greatest overlap. Original lines [174-250]

The test cases provided for get_default_serde_record and serde_introspect functions are comprehensive and cover the basic functionality expected from these utilities. The tests validate the correct instantiation of structs with default values and the introspection of serialization names for both structs and enums.

One suggestion for improvement is to include more edge cases in the test suite. For example, testing structs with more complex nested structures or enums with associated values could provide additional confidence in the robustness of these functions. Additionally, considering negative test cases, such as attempting to deserialize a struct with missing required fields, could help document the expected behavior in error scenarios.

Overall, the tests are well-structured and serve their purpose of validating the functionality introduced in this PR.

@lucatrv
Copy link
Contributor Author

lucatrv commented Feb 22, 2024

What do you think about renaming the function to get_default_serde_record? To show that it will use the #[serde(default)]. Also, do you mind if we add a clearer text explanation in the document to explain the difference between this function and using the Default trait, the same way you explained it to me? Would it make sense?

I did as suggested, see if you like it now otherwise please feel free to elaborate further as you will.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review Status

Actionable comments generated: 0

Configuration used: CodeRabbit UI

Commits Files that changed from the base of the PR and between 3180d95 and 07c970a.
Files selected for processing (1)
  • src/serde_introspection.rs (2 hunks)
Files skipped from review as they are similar to previous changes (1)
  • src/serde_introspection.rs

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review Status

Actionable comments generated: 0

Configuration used: CodeRabbit UI

Commits Files that changed from the base of the PR and between 3180d95 and c8bbf70.
Files selected for processing (1)
  • src/serde_introspection.rs (2 hunks)
Files skipped from review as they are similar to previous changes (1)
  • src/serde_introspection.rs

@iddm
Copy link
Owner

iddm commented Feb 23, 2024

Thank you for the contribution and taking time to implement this!

@iddm iddm merged commit 5526aba into iddm:master Feb 23, 2024
10 checks passed
@iddm
Copy link
Owner

iddm commented Feb 23, 2024

@lucatrv lucatrv deleted the add_get_default_empty_record branch February 24, 2024 08:22
@lucatrv lucatrv restored the add_get_default_empty_record branch February 24, 2024 08:28
@lucatrv lucatrv deleted the add_get_default_empty_record branch February 24, 2024 08:28
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

Successfully merging this pull request may close these issues.

2 participants