-
Notifications
You must be signed in to change notification settings - Fork 1
expose whether conversion was lossy or not #159
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
| @@ -1,10 +1,40 @@ | ||||||||||
| use crate::{Float, FloatError}; | ||||||||||
| use revm::primitives::{B256, U256}; | ||||||||||
| use serde::{Deserialize, Serialize}; | ||||||||||
| use std::{ | ||||||||||
| ops::{Add, Div, Mul, Neg, Sub}, | ||||||||||
| str::FromStr, | ||||||||||
| }; | ||||||||||
| use wasm_bindgen_utils::prelude::{js_sys::BigInt, *}; | ||||||||||
| use wasm_bindgen_utils::{ | ||||||||||
| impl_wasm_traits, | ||||||||||
| prelude::{js_sys::BigInt, *}, | ||||||||||
| }; | ||||||||||
|
|
||||||||||
| #[wasm_bindgen] | ||||||||||
| pub struct FromFixedDecimalLossyResult { | ||||||||||
| float: Float, | ||||||||||
| lossless: bool, | ||||||||||
| } | ||||||||||
|
|
||||||||||
| #[wasm_bindgen] | ||||||||||
| impl FromFixedDecimalLossyResult { | ||||||||||
| #[wasm_bindgen(getter)] | ||||||||||
| pub fn float(&self) -> Float { | ||||||||||
| self.float | ||||||||||
| } | ||||||||||
|
|
||||||||||
| #[wasm_bindgen(getter)] | ||||||||||
| pub fn lossless(&self) -> bool { | ||||||||||
| self.lossless | ||||||||||
| } | ||||||||||
| } | ||||||||||
|
|
||||||||||
| #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Tsify)] | ||||||||||
| pub struct ToFixedDecimalLossyResult { | ||||||||||
| pub value: String, | ||||||||||
| pub lossless: bool, | ||||||||||
| } | ||||||||||
| impl_wasm_traits!(ToFixedDecimalLossyResult); | ||||||||||
|
|
||||||||||
| #[wasm_bindgen] | ||||||||||
| impl Float { | ||||||||||
|
|
@@ -57,6 +87,59 @@ impl Float { | |||||||||
| pub fn from_bigint(value: BigInt) -> Float { | ||||||||||
| Self::try_from_bigint(value).unwrap_throw() | ||||||||||
| } | ||||||||||
|
|
||||||||||
| /// Converts a fixed-point decimal value to a `Float` using the specified number of decimals, | ||||||||||
| /// allowing lossy conversions and reporting whether precision was preserved. | ||||||||||
| /// | ||||||||||
| /// This function attempts to convert a fixed-point decimal representation to a `Float`. | ||||||||||
| /// Unlike `fromFixedDecimal`, this method will not fail if precision is lost during conversion, | ||||||||||
| /// but instead reports the loss through the `lossless` flag in the result. | ||||||||||
| /// | ||||||||||
| /// # Arguments | ||||||||||
| /// | ||||||||||
| /// * `value` - The fixed-point decimal value as a bigint (e.g., 12345n for 123.45 with 2 decimals). | ||||||||||
| /// * `decimals` - The number of decimal places in the fixed-point representation (0-255). | ||||||||||
| /// | ||||||||||
| /// # Returns | ||||||||||
| /// | ||||||||||
| /// Returns a `FromFixedDecimalLossyResult` containing: | ||||||||||
| /// * `float` - The resulting `Float` value. | ||||||||||
| /// * `lossless` - Boolean flag indicating whether the conversion preserved all precision (true) or was lossy (false). | ||||||||||
| /// | ||||||||||
| /// # Errors | ||||||||||
| /// | ||||||||||
| /// Throws a `JsValue` error if: | ||||||||||
| /// * The bigint value cannot be converted to a string. | ||||||||||
| /// * The value string cannot be parsed as a valid U256. | ||||||||||
| /// * The underlying EVM conversion fails. | ||||||||||
| /// | ||||||||||
| /// # Example | ||||||||||
| /// | ||||||||||
| /// ```typescript | ||||||||||
| /// // Lossless conversion | ||||||||||
| /// const result = Float.fromFixedDecimalLossy(12345n, 2); | ||||||||||
| /// const float = result.float; | ||||||||||
| /// const wasLossless = result.lossless; | ||||||||||
| /// assert(float.format()?.value === "123.45"); | ||||||||||
| /// assert(wasLossless === true); | ||||||||||
| /// | ||||||||||
| /// // Potentially lossy conversion | ||||||||||
| /// const result2 = Float.fromFixedDecimalLossy(123456789012345678901234567890n, 18); | ||||||||||
| /// if (!result2.lossless) { | ||||||||||
| /// console.warn("Precision was lost during conversion"); | ||||||||||
| /// } | ||||||||||
| /// ``` | ||||||||||
| #[wasm_bindgen(js_name = "fromFixedDecimalLossy")] | ||||||||||
| pub fn from_fixed_decimal_lossy_js( | ||||||||||
| value: BigInt, | ||||||||||
| decimals: u8, | ||||||||||
| ) -> Result<FromFixedDecimalLossyResult, JsValue> { | ||||||||||
| let value_str: String = value.to_string(10).map_err(|e| JsValue::from(&e))?.into(); | ||||||||||
| let val = U256::from_str(&value_str).map_err(|e| JsValue::from_str(&e.to_string()))?; | ||||||||||
|
Comment on lines
+137
to
+138
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧹 Nitpick | 🔵 Trivial Standardize error conversion patterns. Lines 101 and 102 use different error conversion approaches:
For consistency with similar functions (e.g., - let value_str: String = value.to_string(10).map_err(|e| JsValue::from(&e))?.into();
+ let value_str: String = value.to_string(10)?.into();
let val = U256::from_str(&value_str).map_err(|e| JsValue::from_str(&e.to_string()))?;📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. not needed
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @0xgleb, understood. I'll leave the error conversion as is. |
||||||||||
| let (float, lossless) = Float::from_fixed_decimal_lossy(val, decimals) | ||||||||||
| .map_err(|e| JsValue::from_str(&e.to_string()))?; | ||||||||||
| Ok(FromFixedDecimalLossyResult { float, lossless }) | ||||||||||
| } | ||||||||||
| } | ||||||||||
|
|
||||||||||
| #[wasm_export] | ||||||||||
|
|
@@ -175,65 +258,25 @@ impl Float { | |||||||||
| .map_err(|e| FloatError::JsSysError(e.to_string().into())) | ||||||||||
| } | ||||||||||
|
|
||||||||||
| /// Converts a fixed-point decimal value to a `Float` using the specified number of decimals lossy. | ||||||||||
| /// | ||||||||||
| /// # Arguments | ||||||||||
| /// | ||||||||||
| /// * `value` - The fixed-point decimal value as a `string`. | ||||||||||
| /// * `decimals` - The number of decimals in the fixed-point representation. | ||||||||||
| /// | ||||||||||
| /// # Returns | ||||||||||
| /// | ||||||||||
| /// * `Ok(Float)` - The resulting `Float` value. | ||||||||||
| /// * `Err(FloatError)` - If the conversion fails. | ||||||||||
| /// | ||||||||||
| /// # Example | ||||||||||
| /// | ||||||||||
| /// ```typescript | ||||||||||
| /// const floatResult = Float.fromFixedDecimalLossy("12345", 2); | ||||||||||
| /// if (floatResult.error) { | ||||||||||
| /// console.error(floatResult.error); | ||||||||||
| /// } | ||||||||||
| /// const float = floatResult.value; | ||||||||||
| /// assert(float.format() === "123.45"); | ||||||||||
| /// ``` | ||||||||||
| #[wasm_export(js_name = "fromFixedDecimalLossy", preserve_js_class)] | ||||||||||
| pub fn from_fixed_decimal_lossy_js(value: BigInt, decimals: u8) -> Result<Float, FloatError> { | ||||||||||
| let value_str: String = value.to_string(10)?.into(); | ||||||||||
| let val = U256::from_str(&value_str)?; | ||||||||||
| Self::from_fixed_decimal_lossy(val, decimals) | ||||||||||
| } | ||||||||||
|
|
||||||||||
| /// Converts a `Float` to a fixed-point decimal value using the specified number of decimals lossy. | ||||||||||
| /// | ||||||||||
| /// # Arguments | ||||||||||
| /// | ||||||||||
| /// * `decimals` - The number of decimals in the fixed-point representation. | ||||||||||
| /// | ||||||||||
| /// # Returns | ||||||||||
| /// | ||||||||||
| /// * `Ok(String)` - The resulting fixed-point decimal value as a string. | ||||||||||
| /// * `Err(FloatError)` - If the conversion fails. | ||||||||||
| /// | ||||||||||
| /// # Example | ||||||||||
| /// | ||||||||||
| /// ```typescript | ||||||||||
| /// const float = Float.fromFixedDecimal(12345n, 3).value!; | ||||||||||
| /// const result = float.toFixedDecimalLossy(2); | ||||||||||
| /// if (result.error) { | ||||||||||
| /// console.error(result.error); | ||||||||||
| /// } | ||||||||||
| /// assert(result.value === "1234"); | ||||||||||
| /// ``` | ||||||||||
| /// ToFixedDecimalLossyResult containing the value and lossless flag. | ||||||||||
| #[wasm_export( | ||||||||||
| js_name = "toFixedDecimalLossy", | ||||||||||
| preserve_js_class, | ||||||||||
| unchecked_return_type = "bigint" | ||||||||||
| unchecked_return_type = "ToFixedDecimalLossyResult" | ||||||||||
| )] | ||||||||||
| pub fn to_fixed_decimal_lossy_js(&self, decimals: u8) -> Result<BigInt, FloatError> { | ||||||||||
| let fixed = self.to_fixed_decimal_lossy(decimals)?; | ||||||||||
| BigInt::from_str(&fixed.to_string()) | ||||||||||
| .map_err(|e| FloatError::JsSysError(e.to_string().into())) | ||||||||||
| pub fn to_fixed_decimal_lossy_js( | ||||||||||
| &self, | ||||||||||
| decimals: u8, | ||||||||||
| ) -> Result<ToFixedDecimalLossyResult, FloatError> { | ||||||||||
| let (fixed, lossless) = self.to_fixed_decimal_lossy(decimals)?; | ||||||||||
| Ok(ToFixedDecimalLossyResult { | ||||||||||
| value: fixed.to_string(), | ||||||||||
| lossless, | ||||||||||
| }) | ||||||||||
| } | ||||||||||
|
|
||||||||||
| /// Parses a decimal string into a `Float`. | ||||||||||
|
|
||||||||||
Uh oh!
There was an error while loading. Please reload this page.
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.
🧹 Nitpick | 🔵 Trivial
Consider adding trait derives for consistency and ergonomics.
ToFixedDecimalLossyResult(lines 32-37) has derives forSerialize,Deserialize,Debug,Clone,PartialEq, andTsify, plusimpl_wasm_traits!.FromFixedDecimalLossyResultlacks these traits, which may limit debugging, testing, and serialization capabilities.If the
Floattype supports these traits, apply this diff to add them:+#[derive(Debug, Clone, PartialEq)] #[wasm_bindgen] pub struct FromFixedDecimalLossyResult { float: Float, lossless: bool, }If serialization is needed for JS interop consistency, consider also adding
Serialize,Deserialize, andTsify(assumingFloatsupports them).📝 Committable suggestion
🤖 Prompt for AI Agents
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.
not needed, only gonna be used from ts/js
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.
@0xgleb, understood! Since
FromFixedDecimalLossyResultis only consumed by TypeScript/JavaScript and not used for Rust-side operations, the additional trait derives aren't necessary.✏️ Learnings added
🧠 Learnings used