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

refactor: add derive_more and adjust imports #86

Merged
merged 1 commit into from
Oct 7, 2024
Merged

Conversation

shuhuiluo
Copy link
Collaborator

@shuhuiluo shuhuiluo commented Oct 7, 2024

Integrated derive_more for Deref attribute across various structs and adjusted the core module imports accordingly. This helps in simplifying the code and reducing redundancy.

Summary by CodeRabbit

  • New Features

    • Introduced a new Price type for handling currency prices with various methods for creation, multiplication, and conversion.
    • Added support for division operations across several currency-related structures.
  • Bug Fixes

    • Enhanced error handling in currency operations to prevent exceeding maximum limits.
  • Refactor

    • Streamlined the implementation of dereferencing behavior in currency structures.
  • Tests

    • Added tests for the new Price struct and its methods to ensure functionality.

Integrated `derive_more` for `Deref` attribute across various structs and adjusted the core module imports accordingly. This helps in simplifying the code and reducing redundancy.
Copy link

coderabbitai bot commented Oct 7, 2024

Walkthrough

The pull request introduces updates to the Cargo.toml file by adding a new dependency on the derive_more crate with the deref feature. This change enables the automatic implementation of the Deref trait for the CurrencyLike struct, simplifying dereferencing behavior. Additionally, several methods in the CurrencyAmount and FractionLike structs are modified to incorporate division capabilities, and a new Price type alias and its associated methods are introduced to manage currency prices effectively.

Changes

File Change Summary
Cargo.toml - Added dependency: derive_more = { version = "1.0.0", features = ["deref"] }
src/entities/currency.rs - Updated CurrencyLike struct to derive Deref and annotated meta field with #[deref]. Removed manual Deref implementation.
src/entities/fractions/currency_amount.rs - Updated CurrencyAmount methods (new, multiply, divide, to_fixed, to_significant) to return Result<Self, Error> and utilize Div trait for division operations. Added checks for MAX_UINT256 and decimal places.
src/entities/fractions/fraction.rs - Updated FractionLike to derive Deref and added Div trait for division operations. Removed manual Deref implementation. Updated trait bounds for FractionBase and FractionTrait.
src/entities/fractions/price.rs - Introduced Price<TBase, TQuote> type alias and PriceMeta<TBase, TQuote> struct. Added methods for creating and manipulating prices, including new, from_currency_amounts, invert, multiply, quote, adjusted_for_decimals, to_significant, and to_fixed.
src/prelude.rs - Removed ops::Div import from core module; consolidated imports to simplify the statement.

Possibly related PRs

Suggested reviewers

  • malik672

Poem

In the meadow where the currencies play,
A new trait joins in the fray.
With derive_more, they hop and twirl,
Making math a joyful whirl!
Prices dance, and amounts align,
In this code, all is divine! 🐇✨


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>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • 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 testing code 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 gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

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 using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • 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/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

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.

Actionable comments posted: 1

🧹 Outside diff range and nitpick comments (11)
Cargo.toml (1)

12-12: LGTM! Consider specifying a minimum version instead.

The addition of the derive_more dependency with the "deref" feature aligns well with the PR objectives. This will indeed simplify the implementation of the Deref trait across multiple structs in the codebase.

Consider using a minimum version specification instead of an exact version:

-derive_more = { version = "1.0.0", features = ["deref"] }
+derive_more = { version = "^1.0.0", features = ["deref"] }

This allows for compatible updates within the 1.x.x range, which can include important bug fixes and performance improvements.

src/prelude.rs (1)

Line range hint 1-34: Consider adding Deref import if widely used.

Given that the PR objectives mention integrating the derive_more crate and its Deref functionality, it might be beneficial to import Deref in this prelude file if it's going to be widely used across the project.

If Deref is now commonly used due to the derive_more integration, consider adding it to the core import:

pub use core::{cmp::Ordering, num::NonZeroU64, ops::Deref, str::FromStr};

This would make Deref easily accessible throughout the project without needing additional imports in individual files.

src/entities/fractions/currency_amount.rs (9)

Line range hint 13-22: Check for zero denominator in new method

While you've added a check for the numerator exceeding MAX_UINT256, it's important to ensure that the denominator is not zero to prevent a division by zero error.

Consider adding a check for a zero denominator:

fn new(
    currency: T,
    numerator: impl Into<BigInt>,
    denominator: impl Into<BigInt>,
) -> Result<Self, Error> {
    let numerator = numerator.into();
    let denominator = denominator.into();
+   if denominator.is_zero() {
+       return Err(Error::DivisionByZero);
+   }
    // Ensure the amount does not exceed MAX_UINT256
    if numerator.div_floor(&denominator) > *MAX_UINT256 {
        return Err(Error::MaxUint);
    }
    let exponent = currency.decimals();
    Ok(FractionBase::new(
        numerator,
        denominator,
        CurrencyMeta {
            currency,
            decimal_scale: BigUint::from(10_u64).pow(exponent as u32),
        },
    ))
}

Line range hint 30-36: Ensure denominator is not zero in from_fractional_amount

Similar to the new method, the from_fractional_amount function should check that the denominator is not zero to avoid potential division by zero errors.

Apply the same zero-check when calling Self::new:

pub fn from_fractional_amount(
    currency: T,
    numerator: impl Into<BigInt>,
    denominator: impl Into<BigInt>,
) -> Result<Self, Error> {
+   if denominator.into().is_zero() {
+       return Err(Error::DivisionByZero);
+   }
    Self::new(currency, numerator, denominator)
}

Line range hint 38-44: Update documentation for multiply method

The multiply method now returns a Result<Self, Error>. It's important to update the method's documentation to reflect the new return type and any possible errors.

Add an error section to the doc comment:

/// Multiplication of currency amount by another fractional amount
+ ///
+ /// # Errors
+ ///
+ /// Returns an error if the resulting amount exceeds `MAX_UINT256`.

Line range hint 46-52: Handle division by zero in divide method

While the divide method returns a Result, it doesn't currently check if the other fraction's numerator is zero, which would cause a division by zero error.

Add a check for division by zero:

pub fn divide<M: Clone>(&self, other: &impl FractionBase<M>) -> Result<Self, Error> {
+   if other.numerator().is_zero() {
+       return Err(Error::DivisionByZero);
+   }
    let divided = self.as_fraction() / other.as_fraction();
    Self::from_fractional_amount(
        self.currency.clone(),
        divided.numerator,
        divided.denominator,
    )
}

Line range hint 70-76: Improve error variant for currency mismatch in add method

Returning Error::NotEqual when currencies do not match may not clearly convey the issue. Consider using a more descriptive error variant like Error::CurrencyMismatch.

Update the error variant:

if !self.currency.equals(&other.currency) {
-   return Err(Error::NotEqual);
+   return Err(Error::CurrencyMismatch);
}

Ensure that the Error enum includes the CurrencyMismatch variant and update any related documentation.


Line range hint 78-84: Consistent error messaging in subtract method

Similar to the add method, update the error variant to Error::CurrencyMismatch for clarity when currencies do not match.

Apply the same change:

if !self.currency.equals(&other.currency) {
-   return Err(Error::NotEqual);
+   return Err(Error::CurrencyMismatch);
}

Line range hint 94-101: Document possible errors in to_significant method

The to_significant method now returns Result<String, Error>. It's important to update the method's documentation to include information about potential errors.

Enhance the documentation:

/// Convert the currency amount to a string with a specified number of significant digits
+ ///
+ /// # Errors
+ ///
+ /// Returns an error if the conversion fails due to invalid input or computation errors.

Line range hint 103-115: Use appropriate error variant in to_fixed method

When decimal_places exceeds the currency's decimals, the method returns Error::NotEqual, which may not accurately describe the error. Consider introducing an Error::InvalidDecimalPlaces variant.

Update the error handling:

if decimal_places > self.currency.decimals() {
-   return Err(Error::NotEqual);
+   return Err(Error::InvalidDecimalPlaces);
}

Don't forget to add the InvalidDecimalPlaces variant to the Error enum and update any associated documentation.


Line range hint 137-168: Update unit tests to accommodate new error handling

The changes to return Result types affect how errors are captured in unit tests. Tests expecting panics should now handle Result::Err.

Modify the tests accordingly. For example:

#[test]
- #[should_panic(expected = "AMOUNT")]
fn test_token_amount_exceeds_max_uint256() {
-   let _w = CurrencyAmount::from_raw_amount(TOKEN18.clone(), MAX_UINT256.clone() + 1);
-   assert!(_w.is_ok(), "AMOUNT");
+ fn test_token_amount_exceeds_max_uint256() {
+   let result = CurrencyAmount::from_raw_amount(TOKEN18.clone(), MAX_UINT256.clone() + 1);
+   assert!(matches!(result, Err(Error::MaxUint)), "Expected MaxUint error");
}

Apply similar changes to other tests that are affected by the new error handling.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 0c6cc04 and dc23646.

📒 Files selected for processing (6)
  • Cargo.toml (1 hunks)
  • src/entities/currency.rs (3 hunks)
  • src/entities/fractions/currency_amount.rs (1 hunks)
  • src/entities/fractions/fraction.rs (1 hunks)
  • src/entities/fractions/price.rs (0 hunks)
  • src/prelude.rs (1 hunks)
💤 Files with no reviewable changes (1)
  • src/entities/fractions/price.rs
🧰 Additional context used
🔇 Additional comments (11)
Cargo.toml (1)

12-12: Verify the usage of derive_more and implementation of Deref

To ensure that this dependency is being utilized effectively:

  1. Confirm that derive_more is imported and used in the relevant Rust files.
  2. Verify that the Deref trait is correctly implemented for the intended structs (e.g., CurrencyLike, CurrencyAmount, FractionLike).
  3. Check that the core module imports have been adjusted as mentioned in the PR objectives.

Run the following script to verify the usage of derive_more and the implementation of Deref:

Please review the output of this script to ensure that derive_more is being used correctly and that the Deref trait is implemented as intended.

✅ Verification successful

Further Verification Needed: Proper Implementation of Deref Trait

To ensure that the Deref trait is correctly implemented:

  1. Search for #[derive(Deref)] annotations in the codebase.
  2. Check for any manual implementations of the Deref trait.

Please run the following script and review the output:


derive_more Usage and Deref Implementation Verified

  • derive_more::Deref is correctly imported in:

    • src/entities/currency.rs
    • src/entities/fractions/fraction.rs
  • Deref trait is implemented via #[derive(Deref)] in these files.

  • No manual implementations of the Deref trait were found.

  • Core module imports have been adjusted as per PR objectives.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the usage of derive_more and implementation of Deref

# Test 1: Check for imports of derive_more
echo "Checking for imports of derive_more:"
rg --type rust 'use derive_more::Deref;'

# Test 2: Check for Deref implementations
echo "Checking for Deref implementations:"
ast-grep --lang rust --pattern $'#[derive(Deref)]
struct $STRUCT_NAME {
  $$$
}'

# Test 3: Check for changes in core module imports
echo "Checking for changes in core module imports:"
rg --type rust '^use (crate::)?core::'

Length of output: 1114


Script:

#!/bin/bash
# Description: Verify the implementation of the Deref trait

# Test 1: Search for #[derive(Deref)]
echo "Searching for #[derive(Deref)]:"
rg '#\[derive\(Deref\)\]' --type rust

# Test 2: Search for manual implementations of Deref
echo "Searching for manual implementations of Deref trait:"
rg 'impl\s+Deref\s+for\s+' --type rust

Length of output: 268

src/prelude.rs (1)

28-28: Approve change, but verify impact of removing ops::Div.

The removal of ops::Div from the core imports aligns with the PR objectives of adjusting core module imports. However, we should ensure this change doesn't inadvertently break any existing functionality.

To verify the impact of this change, please run the following script:

Consider adding a comment explaining why ops::Div was removed, e.g.:

// Note: ops::Div removed as it's now derived using the `derive_more` crate
pub use core::{cmp::Ordering, num::NonZeroU64, str::FromStr};

This will help future maintainers understand the reasoning behind this change.

src/entities/currency.rs (4)

3-3: LGTM: Correct import of Deref from derive_more

The import is correctly placed and aligns with the PR objectives of integrating the derive_more crate for implementing the Deref trait.


13-13: Excellent: Deref trait automatically derived for CurrencyLike

The addition of Deref to the derive macro for CurrencyLike is a good improvement. This change:

  1. Automatically implements the Deref trait, reducing boilerplate code.
  2. Maintains backwards compatibility by keeping other derived traits.
  3. Aligns with the PR objectives of simplifying the codebase.

This modification should make the code more maintainable and easier to work with.


28-29: Great: #[deref] attribute correctly applied to meta field

The addition of the #[deref] attribute to the meta field is a good change:

  1. It specifies that the meta field should be used for the Deref implementation.
  2. This allows direct access to the underlying metadata type M without explicit dereferencing.
  3. It's consistent with the Deref derive macro added to the struct.
  4. This change, combined with the derive macro, effectively replaces the manual Deref implementation, as mentioned in the PR summary.

This modification simplifies the usage of CurrencyLike and makes the code more intuitive.


Line range hint 1-138: Summary: Successful integration of derive_more for Deref implementation

The changes in this file successfully integrate the derive_more crate to implement the Deref trait for the CurrencyLike struct. The modifications include:

  1. Importing the Deref trait from derive_more.
  2. Adding Deref to the derive macro for CurrencyLike.
  3. Applying the #[deref] attribute to the meta field.

These changes align well with the PR objectives and should result in:

  • Simplified code by removing the need for a manual Deref implementation.
  • Improved readability and maintainability.
  • No apparent negative impact on existing functionality.

The implementation looks correct and consistent. Great job on this refactoring!

src/entities/fractions/currency_amount.rs (1)

2-2: Importing core::ops::Div

The addition of use core::ops::Div; is appropriate as the Div trait is utilized in the divide method for division operations. Good job ensuring all necessary traits are correctly imported.

src/entities/fractions/fraction.rs (4)

4-4: LGTM: Correct inclusion of Div in ops imports

Adding Div to the ops imports enables division operations, aligning with the new implementations for FractionLike<M>.


6-6: LGTM: Appropriate use of derive_more::Deref

Introducing derive_more::Deref simplifies the dereferencing of FractionLike<M>, enhancing code readability.


Line range hint 57-62: LGTM: Addition of Div trait bounds enhances arithmetic capabilities

Including Div<Output = Self> in the trait bounds of FractionTrait extends the arithmetic operations, enabling division on fractions.


Line range hint 74-74: LGTM: Inclusion of Div in FractionBase trait bounds

Adding Div<Output = Self> to the FractionBase trait ensures that all implementing types support division, maintaining consistency across arithmetic operations.

src/entities/fractions/fraction.rs Show resolved Hide resolved
@malik672 malik672 merged commit f94c2a1 into master Oct 7, 2024
3 checks passed
@shuhuiluo shuhuiluo deleted the derive-deref branch October 7, 2024 07:46
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