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

no_std #21

Merged
merged 2 commits into from
Oct 31, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 3 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,7 @@ license = "MIT"
description = "This is a Rust fixed-point numeric library targeting blockchain development. Originally created and used as a part of the Invariant Protocol. The current version leverages macros, traits and generics to exchange dozens of lines of error prone code with a single line and generating the rest."

[dependencies]
safe_decimal_core = { path = "decimal_core"}
# checked_decimal_macro_core = "0.1.4"
safe_decimal_core = { path = "decimal_core" }
integer-sqrt = "0.1.5"
uint = "0.9"
num-traits = "0.2.14"
uint = { version = "0.9", default-features = false }
num-traits = { version = "0.2.14", default-features = false }
8 changes: 4 additions & 4 deletions decimal_core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ license = "MIT"
proc-macro = true

[dependencies]
proc-macro2 = "1.0"
quote = "1.0"
regex = "1"
syn = { version = "1.0.60", features = ["full"] }
proc-macro2 = { version = "1.0.67", default-features = false }
quote = { version = "1.0.33", default-features = false }
regex = { version = "1", default-features = false }
syn = { version = "2.0.38", features = ["full"] }
12 changes: 6 additions & 6 deletions decimal_core/src/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ pub fn generate_base(characteristics: DecimalCharacteristics) -> proc_macro::Tok
fn here<T: TryFrom<Self::U>>(&self) -> T {
match T::try_from(self.#field_name) {
Ok(v) => v,
Err(_) => std::panic!("could not parse {} to {}", "T", "u8"),
Err(_) => core::panic!("could not parse {} to {}", "T", "u8"),
}
}

Expand All @@ -50,20 +50,20 @@ pub fn generate_base(characteristics: DecimalCharacteristics) -> proc_macro::Tok
fn one<T: TryFrom<u128>>() -> T {
match T::try_from(#denominator) {
Ok(v) => v,
Err(_) => std::panic!("denominator wouldn't fit into this type",),
Err(_) => core::panic!("denominator wouldn't fit into this type",),
}
}

fn checked_one<T: TryFrom<u128>>() -> std::result::Result<T, String> where
T::Error: std::fmt::Display,
fn checked_one<T: TryFrom<u128>>() -> core::result::Result<T, alloc::string::String> where
T::Error: core::fmt::Display,
{
T::try_from(#denominator).map_err(|err| format!("checked_one: can not get one to type {} : {}", std::any::type_name::<T>(), err.to_string()))
T::try_from(#denominator).map_err(|err| alloc::format!("checked_one: can not get one to type {} : {}", core::any::type_name::<T>(), alloc::string::ToString::to_string(&err)))
}

fn almost_one<T: TryFrom<u128>>() -> T {
match T::try_from(#almost_denominator) {
Ok(v) => v,
Err(_) => std::panic!("denominator wouldn't fit into this type",),
Err(_) => core::panic!("denominator wouldn't fit into this type",),
}
}
}
Expand Down
61 changes: 30 additions & 31 deletions decimal_core/src/big_ops.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use alloc::string::ToString;
use quote::quote;

use crate::utils::string_to_ident;
Expand Down Expand Up @@ -25,106 +26,105 @@ pub fn generate_big_ops(characteristics: DecimalCharacteristics) -> proc_macro::
fn big_mul(self, rhs: T) -> Self {
Self::new(
#big_type::try_from(self.get())
.unwrap_or_else(|_| std::panic!("decimal: lhs value can't fit into `{}` type in {}::big_mul()", #big_str, #name_str))
.unwrap_or_else(|_| core::panic!("decimal: lhs value can't fit into `{}` type in {}::big_mul()", #big_str, #name_str))
.checked_mul(
rhs.get()
.try_into()
.unwrap_or_else(|_| std::panic!("decimal: rhs value can't fit into `{}` type in {}::big_mul()", #big_str, #name_str))
.unwrap_or_else(|_| core::panic!("decimal: rhs value can't fit into `{}` type in {}::big_mul()", #big_str, #name_str))
)
.unwrap_or_else(|| std::panic!("decimal: overflow in method {}::big_mul()", #name_str))
.unwrap_or_else(|| core::panic!("decimal: overflow in method {}::big_mul()", #name_str))
.checked_div(
T::one()
)
.unwrap_or_else(|| std::panic!("decimal: overflow in method {}::big_mul()", #name_str))
.unwrap_or_else(|| core::panic!("decimal: overflow in method {}::big_mul()", #name_str))
.try_into()
.unwrap_or_else(|_| std::panic!("decimal: overflow casting result to `{}` type in method {}::big_mul()", #underlying_str, #name_str))
.unwrap_or_else(|_| core::panic!("decimal: overflow casting result to `{}` type in method {}::big_mul()", #underlying_str, #name_str))

)
}

fn big_mul_up(self, rhs: T) -> Self {
Self::new(
#big_type::try_from(self.get())
.unwrap_or_else(|_| std::panic!("decimal: lhs value can't fit into `{}` type in {}::big_mul_up()", #big_str, #name_str))
.unwrap_or_else(|_| core::panic!("decimal: lhs value can't fit into `{}` type in {}::big_mul_up()", #big_str, #name_str))
.checked_mul(
rhs.get()
.try_into()
.unwrap_or_else(|_| std::panic!("decimal: rhs value can't fit into `{}` type in {}::big_mul_up()", #big_str, #name_str))
.unwrap_or_else(|_| core::panic!("decimal: rhs value can't fit into `{}` type in {}::big_mul_up()", #big_str, #name_str))
)
.unwrap_or_else(|| std::panic!("decimal: overflow in method {}::big_mul_up()", #name_str))
.unwrap_or_else(|| core::panic!("decimal: overflow in method {}::big_mul_up()", #name_str))
.checked_add(T::almost_one())
.unwrap_or_else(|| std::panic!("decimal: overflow in method {}::big_mul_up()", #name_str))
.unwrap_or_else(|| core::panic!("decimal: overflow in method {}::big_mul_up()", #name_str))
.checked_div(
T::one()
)
.unwrap_or_else(|| std::panic!("decimal: overflow in method {}::big_mul_up()", #name_str))
.unwrap_or_else(|| core::panic!("decimal: overflow in method {}::big_mul_up()", #name_str))
.try_into()
.unwrap_or_else(|_| std::panic!("decimal: overflow casting result to `{}` type in method {}::big_mul_up()", #underlying_str, #name_str))
.unwrap_or_else(|_| core::panic!("decimal: overflow casting result to `{}` type in method {}::big_mul_up()", #underlying_str, #name_str))
)
}

fn big_div(self, rhs: T) -> Self {
Self::new(
#big_type::try_from(self.get())
.unwrap_or_else(|_| std::panic!("decimal: lhs value can't fit into `{}` type in {}::big_div()", #big_str, #name_str))
.unwrap_or_else(|_| core::panic!("decimal: lhs value can't fit into `{}` type in {}::big_div()", #big_str, #name_str))
.checked_mul(
T::one()
)
.unwrap_or_else(|| std::panic!("decimal: overflow in method {}::big_div()", #name_str))
.unwrap_or_else(|| core::panic!("decimal: overflow in method {}::big_div()", #name_str))
.checked_div(
rhs.get()
.try_into()
.unwrap_or_else(|_| std::panic!("decimal: rhs value can't fit into `{}` type in {}::big_div()", #big_str, #name_str))
.unwrap_or_else(|_| core::panic!("decimal: rhs value can't fit into `{}` type in {}::big_div()", #big_str, #name_str))
)
.unwrap_or_else(|| std::panic!("decimal: overflow in method {}::big_div()", #name_str))
.unwrap_or_else(|| core::panic!("decimal: overflow in method {}::big_div()", #name_str))
.try_into()
.unwrap_or_else(|_| std::panic!("decimal: overflow casting result to `{}` type in method {}::big_div()", #underlying_str, #name_str))
.unwrap_or_else(|_| core::panic!("decimal: overflow casting result to `{}` type in method {}::big_div()", #underlying_str, #name_str))
)
}

fn checked_big_div(self, rhs: T) -> std::result::Result<Self, String> {
fn checked_big_div(self, rhs: T) -> core::result::Result<Self, alloc::string::String> {
Ok(
Self::new(
#big_type::try_from(self.get())
.map_err(|_| format!("decimal: lhs value can't fit into `{}` type in {}::big_div()", #big_str, #name_str))?
.map_err(|_| alloc::format!("decimal: lhs value can't fit into `{}` type in {}::big_div()", #big_str, #name_str))?
.checked_mul(
T::one()
)
.ok_or_else(|| format!("decimal: overflow in method {}::big_div()", #name_str))?
.ok_or_else(|| alloc::format!("decimal: overflow in method {}::big_div()", #name_str))?
.checked_div(
rhs.get()
.try_into()
.map_err(|_| format!("decimal: rhs value can't fit into `{}` type in {}::big_div()", #big_str, #name_str))?
.map_err(|_| alloc::format!("decimal: rhs value can't fit into `{}` type in {}::big_div()", #big_str, #name_str))?
)
.ok_or_else(|| format!("decimal: overflow in method {}::big_div()", #name_str))?
.ok_or_else(|| alloc::format!("decimal: overflow in method {}::big_div()", #name_str))?
.try_into()
.map_err(|_| format!("decimal: overflow casting result to `{}` type in method {}::big_div()", #underlying_str, #name_str))?
.map_err(|_| alloc::format!("decimal: overflow casting result to `{}` type in method {}::big_div()", #underlying_str, #name_str))?
)
)
}

fn big_div_up(self, rhs: T) -> Self {
Self::new(
#big_type::try_from(self.get())
.unwrap_or_else(|_| std::panic!("decimal: lhs value can't fit into `{}` type in {}::big_div_up()", #big_str, #name_str))
.unwrap_or_else(|_| core::panic!("decimal: lhs value can't fit into `{}` type in {}::big_div_up()", #big_str, #name_str))
.checked_mul(
T::one()
)
.unwrap_or_else(|| std::panic!("decimal: overflow in method {}::big_div_up()", #name_str))
.unwrap_or_else(|| core::panic!("decimal: overflow in method {}::big_div_up()", #name_str))
.checked_add(
rhs.get()
.try_into()
.unwrap_or_else(|_| std::panic!("decimal: rhs value can't fit into `{}` type in {}::big_div_up()", #big_str, #name_str))
.unwrap_or_else(|_| core::panic!("decimal: rhs value can't fit into `{}` type in {}::big_div_up()", #big_str, #name_str))
.checked_sub(#big_type::from(1u128)).unwrap()
)
.unwrap_or_else(|| std::panic!("decimal: overflow in method {}::big_div_up()", #name_str))
.unwrap_or_else(|| core::panic!("decimal: overflow in method {}::big_div_up()", #name_str))
.checked_div(
rhs.get()
.try_into().unwrap_or_else(|_| std::panic!("rhs value could not be converted to big type in `big_div_up`")),
.try_into().unwrap_or_else(|_| core::panic!("rhs value could not be converted to big type in `big_div_up`")),
)
.unwrap_or_else(|| std::panic!("decimal: overflow in method {}::big_div_up()", #name_str))
.unwrap_or_else(|| core::panic!("decimal: overflow in method {}::big_div_up()", #name_str))
.try_into()
.unwrap_or_else(|_| std::panic!("decimal: overflow casting result to `{}` type in method {}::big_div_up()", #underlying_str, #name_str))
.unwrap_or_else(|_| core::panic!("decimal: overflow casting result to `{}` type in method {}::big_div_up()", #underlying_str, #name_str))
)
}
}
Expand Down Expand Up @@ -154,7 +154,6 @@ pub fn generate_big_ops(characteristics: DecimalCharacteristics) -> proc_macro::
assert_eq!(a.big_div(b), #struct_name::new(2));
}


#[test]
fn test_checked_big_div () {
let a = #struct_name::new(29);
Expand Down
12 changes: 7 additions & 5 deletions decimal_core/src/by_number.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use alloc::string::ToString;
use quote::quote;

use crate::utils::string_to_ident;
Expand Down Expand Up @@ -27,7 +28,7 @@ pub fn generate_by_number(characteristics: DecimalCharacteristics) -> proc_macro
)
}

fn checked_big_div_by_number(self, rhs: #big_type) -> std::result::Result<Self, String> {
fn checked_big_div_by_number(self, rhs: #big_type) -> core::result::Result<Self, alloc::string::String> {
Ok(Self::new(
#big_type::try_from(self.get()).map_err(|_| "checked_big_div_by_number: can't convert self to big_type")?
.checked_mul(Self::checked_one()?).ok_or_else(|| "checked_big_div_by_number: (self * Self::one()) multiplication overflow")?
Expand All @@ -50,7 +51,7 @@ pub fn generate_by_number(characteristics: DecimalCharacteristics) -> proc_macro
)
}

fn checked_big_div_by_number_up(self, rhs: #big_type) -> std::result::Result<Self, String> {
fn checked_big_div_by_number_up(self, rhs: #big_type) -> core::result::Result<Self, alloc::string::String> {
Ok(Self::new(
#big_type::try_from(self.get()).map_err(|_| "checked_big_div_by_number_up: can't convert self to big_type")?
.checked_mul(Self::checked_one()?).ok_or_else(|| "checked_big_div_by_number_up: (self * Self::one()) multiplication overflow")?
Expand All @@ -67,23 +68,24 @@ pub fn generate_by_number(characteristics: DecimalCharacteristics) -> proc_macro
where
T::U: TryInto<#big_type>,
{

// mul(l/r) = U256::from(l) * U256::from(r) / U256::from(r::one())
fn big_mul_to_value(self, rhs: T) -> #big_type {
#big_type::try_from(self.get()).unwrap()
.checked_mul(
rhs.get()
.try_into().unwrap_or_else(|_| std::panic!("rhs value could not be converted to big type in `big_mul`")),
.try_into().unwrap_or_else(|_| core::panic!("rhs value could not be converted to big type in `big_mul`")),
).unwrap()
.checked_div(
T::one()
).unwrap()
}

// mul_up(l/r) = U256::from(l) * U256::from(r) + U256::from(r::almost_one()) / U256::from(r::one())
fn big_mul_to_value_up(self, rhs: T) -> #big_type {
#big_type::try_from(self.get()).unwrap()
.checked_mul(
rhs.get()
.try_into().unwrap_or_else(|_| std::panic!("rhs value could not be converted to big type in `big_mul_up`")),
.try_into().unwrap_or_else(|_| core::panic!("rhs value could not be converted to big type in `big_mul_up`")),
).unwrap()
.checked_add(T::almost_one()).unwrap()
.checked_div(
Expand Down
12 changes: 7 additions & 5 deletions decimal_core/src/checked_ops.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use alloc::string::ToString;
use quote::quote;

use crate::utils::string_to_ident;
Expand All @@ -11,21 +12,21 @@ pub fn generate_checked_ops(characteristics: DecimalCharacteristics) -> proc_mac

proc_macro::TokenStream::from(quote!(
impl CheckedOps for #struct_name {
fn checked_add(self, rhs: Self) -> std::result::Result<Self, String> {
fn checked_add(self, rhs: Self) -> core::result::Result<Self, alloc::string::String> {
Ok(Self::new(
self.get().checked_add(rhs.get())
.ok_or_else(|| "checked_add: (self + rhs) additional overflow")?
))
}

fn checked_sub(self, rhs: Self) -> std::result::Result<Self, String> {
fn checked_sub(self, rhs: Self) -> core::result::Result<Self, alloc::string::String> {
Ok(Self::new(
self.get().checked_sub(rhs.get())
.ok_or_else(|| "checked_sub: (self - rhs) subtraction underflow")?
))
}

fn checked_div(self, rhs: Self) -> std::result::Result<Self, String> {
fn checked_div(self, rhs: Self) -> core::result::Result<Self, alloc::string::String> {
Ok(Self::new(
self.get()
.checked_mul(Self::one())
Expand All @@ -37,6 +38,9 @@ pub fn generate_checked_ops(characteristics: DecimalCharacteristics) -> proc_mac
}
}




#[cfg(test)]
pub mod #module_name {
use super::*;
Expand Down Expand Up @@ -69,7 +73,6 @@ pub fn generate_checked_ops(characteristics: DecimalCharacteristics) -> proc_mac
fn test_checked_div() {
let a = #struct_name::new(2);
let b = #struct_name::new(#struct_name::one());

assert_eq!(a.checked_div(b), Ok(#struct_name::new(2)));
}

Expand All @@ -78,7 +81,6 @@ pub fn generate_checked_ops(characteristics: DecimalCharacteristics) -> proc_mac
let a = #struct_name::new(47);
let b = #struct_name::new(0);
let result = a.checked_div(b);

assert!(result.is_err());
}

Expand Down
Loading
Loading