0

Roll rust_decimal: 1.36.0 => 1.37.0 in //third_party/rust.

This CL has been created semi-automatically.  The expected review
process and other details can be found at
//tools/crates/create_update_cl.md

Updated crates:

* rust_decimal: 1.36.0 => 1.37.0

Chromium `supply-chain/config.toml` policy requires that the following
audit criteria are met (note that these are the *minimum* required
criteria and `supply-chain/audits.toml` can and should record a stricter
certification if possible;  see also //docs/rust-unsafe.md):

* rust_decimal@1.37.0: crypto-safe, safe-to-deploy, ub-risk-2

Bug: None
Change-Id: I3b6c0bef42af62ea7202337decae3e1c3afb49f0
Cq-Include-Trybots: chromium/try:android-rust-arm32-rel
Cq-Include-Trybots: chromium/try:android-rust-arm64-dbg
Cq-Include-Trybots: chromium/try:android-rust-arm64-rel
Cq-Include-Trybots: chromium/try:linux-rust-x64-dbg
Cq-Include-Trybots: chromium/try:linux-rust-x64-rel
Cq-Include-Trybots: chromium/try:win-rust-x64-dbg
Cq-Include-Trybots: chromium/try:win-rust-x64-rel
Disable-Rts: True
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6374342
Reviewed-by: Łukasz Anforowicz <lukasza@chromium.org>
Reviewed-by: Daniel Cheng <dcheng@chromium.org>
Commit-Queue: Chris Palmer <palmer@google.com>
Cr-Commit-Position: refs/heads/main@{#1436392}
This commit is contained in:
Chris Palmer
2025-03-21 18:12:42 -07:00
committed by Chromium LUCI CQ
parent 0fd3717f03
commit 12e6ddd0d6
71 changed files with 3784 additions and 285 deletions

@ -740,8 +740,8 @@ third_party/rust/chromium_crates_io/vendor/regex-automata-0.4.9/tests/nfa/thomps
third_party/rust/chromium_crates_io/vendor/regex-syntax-0.8.5 2 2
third_party/rust/chromium_crates_io/vendor/relative-path-1.9.3/src 1 1
third_party/rust/chromium_crates_io/vendor/rustc_version-0.4.1/.github/workflows 1 1
third_party/rust/chromium_crates_io/vendor/rust_decimal-1.36.0 4 3
third_party/rust/chromium_crates_io/vendor/rust_decimal-1.36.0/.github/workflows 1 1
third_party/rust/chromium_crates_io/vendor/rust_decimal-1.37.0 3 2
third_party/rust/chromium_crates_io/vendor/rust_decimal-1.37.0/.github/workflows 1 1
third_party/rust/chromium_crates_io/vendor/rustversion-1.0.20 2 1
third_party/rust/chromium_crates_io/vendor/rustversion-1.0.20/.github/workflows 2 1
third_party/rust/chromium_crates_io/vendor/rustversion-1.0.20/src 1 1

@ -1166,7 +1166,7 @@ dependencies = [
[[package]]
name = "rust_decimal"
version = "1.36.0"
version = "1.37.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"arrayvec",

@ -3192,6 +3192,12 @@ and there were no hits except:
https://chromium-review.googlesource.com/c/chromium/src/+/6187726/2/third_party/rust/chromium_crates_io/vendor/rust_decimal-1.36.0/tests/decimal_tests.rs
'''
[[audits.rust_decimal]]
who = "Chris Palmer <palmer@google.com>"
criteria = ["safe-to-deploy", "does-not-implement-crypto", "ub-risk-0"]
delta = "1.36.0 -> 1.37.0"
notes = "New `unsafe` in a test."
[[audits.rustc-demangle]]
who = "danakj@chromium.org"
criteria = ["safe-to-run", "does-not-implement-crypto"]

@ -404,7 +404,10 @@ criteria = ["crypto-safe", "safe-to-run"]
[policy."rstest_macros:0.22.0"]
criteria = ["crypto-safe", "safe-to-run"]
[policy."rust_decimal:1.36.0"]
[policy."rstest_reuse:0.7.0"]
criteria = ["crypto-safe", "safe-to-run"]
[policy."rust_decimal:1.37.0"]
criteria = ["crypto-safe", "safe-to-deploy", "ub-risk-2"]
[policy."rustc-demangle-capi:0.1.0"]

@ -1,6 +0,0 @@
{
"git": {
"sha1": "38ab8254ad77e0a612f8eef8f12a2f7febee3ff8"
},
"path_in_vcs": ""
}

@ -0,0 +1,6 @@
{
"git": {
"sha1": "ffe9495d7734d8021718050f98e3f48f39c428b2"
},
"path_in_vcs": ""
}

@ -59,7 +59,7 @@ jobs:
- uses: dtolnay/rust-toolchain@stable
with:
toolchain: 1.60.0
toolchain: 1.67.1
- name: Cache cargo registry
uses: actions/cache@v4

@ -1,5 +1,7 @@
# Version History
**Please see [Github Releases](https://github.com/paupino/rust-decimal/releases) for version history going forward.**
# 1.36.0
### Fixed

File diff suppressed because it is too large Load Diff

@ -11,12 +11,13 @@
[package]
edition = "2021"
rust-version = "1.60"
rust-version = "1.67.1"
name = "rust_decimal"
version = "1.36.0"
version = "1.37.0"
authors = ["Paul Mason <paul@form1.co.nz>"]
build = "build.rs"
exclude = ["tests/generated/*"]
autolib = false
autobins = false
autoexamples = false
autotests = false
@ -46,10 +47,82 @@ rustdoc-args = [
"docsrs",
]
[features]
borsh = [
"dep:borsh",
"std",
]
c-repr = []
db-diesel-mysql = [
"diesel/mysql_backend",
"std",
]
db-diesel-postgres = [
"diesel/postgres",
"std",
]
db-diesel2-mysql = ["db-diesel-mysql"]
db-diesel2-postgres = ["db-diesel-postgres"]
db-postgres = [
"dep:bytes",
"dep:postgres-types",
"std",
]
db-tokio-postgres = [
"dep:bytes",
"dep:postgres-types",
"std",
]
default = [
"serde",
"std",
]
legacy-ops = []
macros = ["dep:rust_decimal_macros"]
maths = []
maths-nopanic = ["maths"]
ndarray = ["dep:ndarray"]
proptest = ["dep:proptest"]
rand = ["dep:rand"]
rkyv = ["dep:rkyv"]
rkyv-safe = ["rkyv/validation"]
rocket-traits = [
"dep:rocket",
"std",
]
rust-fuzz = ["dep:arbitrary"]
serde = ["dep:serde"]
serde-arbitrary-precision = ["serde-with-arbitrary-precision"]
serde-bincode = ["serde-str"]
serde-float = ["serde-with-float"]
serde-str = ["serde-with-str"]
serde-with-arbitrary-precision = [
"serde",
"serde_json/arbitrary_precision",
"serde_json/std",
]
serde-with-float = ["serde"]
serde-with-str = ["serde"]
std = [
"arrayvec/std",
"borsh?/std",
"bytes?/std",
"rand?/std",
"rkyv?/std",
"serde?/std",
"serde_json?/std",
]
tokio-pg = ["db-tokio-postgres"]
[lib]
name = "rust_decimal"
path = "src/lib.rs"
[[example]]
name = "rkyv-remote"
path = "examples/rkyv-remote.rs"
required-features = ["macros"]
[[test]]
name = "decimal_tests"
path = "tests/decimal_tests.rs"
@ -95,7 +168,7 @@ optional = true
default-features = false
[dependencies.diesel]
version = "2.2"
version = "2.2.3"
optional = true
default-features = false
@ -125,6 +198,12 @@ version = "0.8"
optional = true
default-features = false
[dependencies.rand-0_9]
version = "0.9"
optional = true
default-features = false
package = "rand"
[dependencies.rkyv]
version = "0.7.42"
features = [
@ -139,6 +218,11 @@ version = "0.5.0-rc.3"
optional = true
default-features = false
[dependencies.rust_decimal_macros]
version = "1"
optional = true
default-features = false
[dependencies.serde]
version = "1.0"
optional = true
@ -169,6 +253,11 @@ default-features = false
[dev-dependencies.csv]
version = "1"
[dev-dependencies.diesel]
version = "2.2.3"
features = ["mysql"]
default-features = false
[dev-dependencies.futures]
version = "0.3"
default-features = false
@ -182,9 +271,15 @@ version = "0.8"
features = ["getrandom"]
default-features = false
[dev-dependencies.rust_decimal_macros]
version = "1.33"
[dev-dependencies.rand-0_9]
version = "0.9"
features = ["thread_rng"]
default-features = false
package = "rand"
[dev-dependencies.rkyv-0_8]
version = "0.8"
package = "rkyv"
[dev-dependencies.serde]
version = "1.0"
@ -214,66 +309,3 @@ features = [
"markdown_deps_updated",
]
default-features = false
[features]
borsh = [
"dep:borsh",
"std",
]
c-repr = []
db-diesel-mysql = [
"diesel/mysql",
"std",
]
db-diesel-postgres = [
"diesel/postgres",
"std",
]
db-diesel2-mysql = ["db-diesel-mysql"]
db-diesel2-postgres = ["db-diesel-postgres"]
db-postgres = [
"dep:bytes",
"dep:postgres-types",
"std",
]
db-tokio-postgres = [
"dep:bytes",
"dep:postgres-types",
"std",
]
default = [
"serde",
"std",
]
legacy-ops = []
maths = []
maths-nopanic = ["maths"]
ndarray = ["dep:ndarray"]
proptest = ["dep:proptest"]
rand = ["dep:rand"]
rkyv = ["dep:rkyv"]
rkyv-safe = ["rkyv/validation"]
rocket-traits = ["dep:rocket"]
rust-fuzz = ["dep:arbitrary"]
serde = ["dep:serde"]
serde-arbitrary-precision = ["serde-with-arbitrary-precision"]
serde-bincode = ["serde-str"]
serde-float = ["serde-with-float"]
serde-str = ["serde-with-str"]
serde-with-arbitrary-precision = [
"serde",
"serde_json/arbitrary_precision",
"serde_json/std",
]
serde-with-float = ["serde"]
serde-with-str = ["serde"]
std = [
"arrayvec/std",
"borsh?/std",
"bytes?/std",
"rand?/std",
"rkyv?/std",
"serde?/std",
"serde_json?/std",
]
tokio-pg = ["db-tokio-postgres"]

@ -11,8 +11,8 @@ license = "MIT"
name = "rust_decimal"
readme = "./README.md"
repository = "https://github.com/paupino/rust-decimal"
rust-version = "1.60"
version = "1.36.0"
rust-version = "1.67.1"
version = "1.37.0"
[package.metadata.docs.rs]
all-features = true
@ -23,15 +23,16 @@ arbitrary = { default-features = false, optional = true, version = "1.0" }
arrayvec = { default-features = false, version = "0.7" }
borsh = { default-features = false, features = ["derive", "unstable__schema"], optional = true, version = "1.1.1" }
bytes = { default-features = false, optional = true, version = "1.0" }
diesel = { default-features = false, optional = true, version = "2.2" }
diesel = { default-features = false, optional = true, version = "2.2.3" }
ndarray = { default-features = false, optional = true, version = "0.15.6" }
num-traits = { default-features = false, features = ["i128"], version = "0.2" }
postgres-types = { default-features = false, optional = true, version = "0.2" }
proptest = { default-features = false, optional = true, features = ["std"], version = "1.0" }
rand = { default-features = false, optional = true, version = "0.8" }
rand-0_9 = { default-features = false, optional = true, package = "rand", version = "0.9" }
rust_decimal_macros = { path = "macros", default-features = false, optional = true, version = "1" }
rkyv = { default-features = false, features = ["size_32", "std"], optional = true, version = "0.7.42" }
rocket = { default-features = false, optional = true, version = "0.5.0-rc.3" }
#rust_decimal_macros = { default-features = false, optional = true, version = "1.34" } # This needs to a published version
serde = { default-features = false, optional = true, version = "1.0" }
serde_json = { default-features = false, optional = true, version = "1.0" }
tokio-postgres = { default-features = false, optional = true, version = "0.7" }
@ -41,9 +42,12 @@ bincode = { default-features = false, version = "1.0" }
bytes = { default-features = false, version = "1.0" }
criterion = { default-features = false, version = "0.5" }
csv = "1"
diesel = { default-features = false, features = ["mysql"], version = "2.2.3" }
futures = { default-features = false, version = "0.3" }
rand = { default-features = false, features = ["getrandom"], version = "0.8" }
rust_decimal_macros = { default-features = false, version = "1.33" }
rand-0_9 = { default-features = false, features = ["thread_rng"], package = "rand", version = "0.9" }
rkyv-0_8 = { version = "0.8", package = "rkyv" }
rust_decimal_macros = { path = "macros" }
serde = { default-features = false, features = ["derive"], version = "1.0" }
serde_json = "1.0"
tokio = { default-features = false, features = ["macros", "rt-multi-thread", "test-util"], version = "1.0" }
@ -53,18 +57,17 @@ tokio-postgres = { default-features = false, version = "0.7" }
[features]
default = ["serde", "std"]
# Removed in 1.34.2 due to an issue during version resolution
#macros = ["dep:rust_decimal_macros"]
borsh = ["dep:borsh", "std"]
c-repr = [] # Force Decimal to be repr(C)
db-diesel-mysql = ["diesel/mysql", "std"]
db-diesel-mysql = ["diesel/mysql_backend", "std"]
db-diesel-postgres = ["diesel/postgres", "std"]
db-diesel2-mysql = ["db-diesel-mysql"]
db-diesel2-postgres = ["db-diesel-postgres"]
db-postgres = ["dep:bytes", "dep:postgres-types", "std"]
db-tokio-postgres = ["dep:bytes", "dep:postgres-types", "std"]
legacy-ops = []
macros = ["dep:rust_decimal_macros"]
maths = []
maths-nopanic = ["maths"]
ndarray = ["dep:ndarray"]
@ -72,7 +75,7 @@ proptest = ["dep:proptest"]
rand = ["dep:rand"]
rkyv = ["dep:rkyv"]
rkyv-safe = ["rkyv/validation"]
rocket-traits = ["dep:rocket"]
rocket-traits = ["dep:rocket", "std"]
rust-fuzz = ["dep:arbitrary"]
serde = ["dep:serde"]
serde-arbitrary-precision = ["serde-with-arbitrary-precision"]
@ -90,9 +93,13 @@ harness = false
name = "comparison"
path = "benches/comparison.rs"
[[example]]
name = "rkyv-remote"
required-features = ["macros"]
[workspace]
members = [
".",
"./macros"
"./macros",
]
resolver = "2"

@ -25,28 +25,23 @@ can be truncated using the `normalize` or `round_dp` functions.
$ cargo add rust_decimal
```
In addition, if you would like to use the optimized macro for convenient creation of decimals:
```sh
$ cargo add rust_decimal_macros
```
Alternatively, you can edit your `Cargo.toml` directly and run `cargo update`:
```toml
[dependencies]
rust_decimal = "1.36"
rust_decimal_macros = "1.36"
rust_decimal = "1.37"
```
## Usage
Decimal numbers can be created in a few distinct ways. The easiest and most efficient method of creating a Decimal is to
use the procedural macro that can be enabled using the `macros` feature:
use the macro:
```rust
// Import the `rust_decimal_macros` crate and use the macro directly from there.
use rust_decimal_macros::dec;
// Import via use rust_decimal_macros or use the `macros` feature to import at the crate level
// `use rust_decimal_macros::dec;`
// or
// `use rust_decimal::dec;`
let number = dec!(-1.23) + dec!(3.45);
assert_eq!(number, dec!(2.22));
@ -87,13 +82,16 @@ assert_eq!("3", my_int.to_string());
// Using the raw decimal representation
let pi = Decimal::from_parts(1_102_470_952, 185_874_565, 1_703_060_790, false, 28);
assert_eq!("3.1415926535897932384626433832", pi.to_string());
// If the `macros` feature is enabled, it also allows for the `dec!` macro
let amount = dec!(25.12);
assert_eq!("25.12", amount.to_string());
```
Once you have instantiated your `Decimal` number you can perform calculations with it just like any other number:
```rust
use rust_decimal::prelude::*;
use rust_decimal_macros::dec;
use rust_decimal::prelude::*; // Includes the `dec` macro when feature specified
let amount = dec!(25.12);
let tax_percentage = dec!(0.085);
@ -195,9 +193,15 @@ two).
### `rkyv`
Enables [rkyv](https://github.com/rkyv/rkyv) serialization for `Decimal`.
Enables [rkyv](https://github.com/rkyv/rkyv) serialization for `Decimal`. In order to avoid breaking changes, this is
currently locked at version `0.7`.
Supports rkyv's safe API when the `rkyv-safe` feature is enabled as well.
If `rkyv` support for versions `0.8` of greater is desired, `rkyv`'
s [remote derives](https://rkyv.org/derive-macro-features/remote-derive.html) should be used instead. See
`examples/rkyv-remote`.
### `rocket-traits`
Enable support for Rocket forms by implementing the `FromFormField` trait.
@ -365,9 +369,7 @@ Please refer to the [Build document](BUILD.md) for more information on building
## Minimum Rust Compiler Version
The current _minimum_ compiler version
is [`1.60.0`](https://github.com/rust-lang/rust/blob/master/RELEASES.md#version-1600-2022-04-07)
which was released on `2022-04-07`.
The current _minimum_ compiler version is `1.67.1` which was released on `2023-02-09`.
This library maintains support for rust compiler versions that are 4 minor versions away from the current stable rust
compiler version.

@ -37,13 +37,16 @@ fn prepare(readme: &str) -> Result<String, Box<dyn std::error::Error>> {
"(https://github.com/paupino/rust-decimal/blob/master/BUILD.md)",
)
)?;
} else if feature_section && line.starts_with("```rust") {
// This is a bit naive, but it's to make the Serde examples cleaner. Should probably
// be a bit more "defensive" here.
} else if line.starts_with("```rust") {
writeln!(cleaned, "```rust")?;
writeln!(cleaned, "# use rust_decimal::Decimal;")?;
writeln!(cleaned, "# use serde::{{Serialize, Deserialize}};")?;
write!(cleaned, "# #[cfg(features = \"{feature}\")]")?;
writeln!(cleaned, "# use rust_decimal_macros::dec;")?;
if feature_section {
// This is a bit naive, but it's to make the Serde examples cleaner. Should probably
// be a bit more "defensive" here.
writeln!(cleaned, "# use serde::{{Serialize, Deserialize}};")?;
write!(cleaned, "# #[cfg(features = \"{feature}\")]")?;
}
} else {
if !feature_section && line.starts_with("## Features") {
feature_section = true;

@ -14,3 +14,6 @@ cargo run
This example shows how to use the `serde` crate to serialize and deserialize the `Decimal` type using multiple different
serialization formats.
## rkyv-remote
This example shows shows how to use the `rkyv` crate's remote derive for the `Decimal` type.

@ -0,0 +1,35 @@
extern crate rkyv_0_8 as rkyv;
use rkyv::{rancor::Error, Archive, Deserialize, Serialize};
use rust_decimal::prelude::{dec, Decimal};
/// The type containing a [`Decimal`] that will be de/serialized.
#[derive(Archive, Serialize, Deserialize, Debug, PartialEq, Eq)]
struct Root {
#[rkyv(with = RkyvDecimal)]
decimal: Decimal,
}
/// Archived layout of [`Decimal`]
#[derive(Archive, Serialize, Deserialize)]
#[rkyv(remote = Decimal)]
struct RkyvDecimal {
#[rkyv(getter = Decimal::serialize)]
bytes: [u8; 16],
}
impl From<RkyvDecimal> for Decimal {
fn from(RkyvDecimal { bytes }: RkyvDecimal) -> Self {
Self::deserialize(bytes)
}
}
fn main() {
let test_value = Root { decimal: dec!(123.456) };
let bytes = rkyv::to_bytes::<Error>(&test_value).expect("Failed to serialize");
let roundtrip_value = rkyv::from_bytes::<Root, Error>(&bytes).expect("Failed to deserialize");
assert_eq!(test_value, roundtrip_value);
}

@ -33,5 +33,15 @@ command = "cargo"
args = ["test", "--workspace", "--features=rkyv", "--features=rkyv-safe", "rkyv_tests", "--", "--skip", "generated"]
[tasks.test-rand]
dependencies = [
"test-rand-0_8",
"test-rand-0_9"
]
[tasks.test-rand-0_8]
command = "cargo"
args = ["test", "--workspace", "--features=rand", "rand_tests", "--", "--skip", "generated"]
[tasks.test-rand-0_9]
command = "cargo"
args = ["test", "--workspace", "--features=rand-0_9", "rand_tests", "--", "--skip", "generated"]

@ -151,7 +151,7 @@ macro_rules! forward_val_val_binop {
}
forward_all_binop!(impl Add for Decimal, add);
impl<'a, 'b> Add<&'b Decimal> for &'a Decimal {
impl Add<&Decimal> for &Decimal {
type Output = Decimal;
#[inline(always)]
@ -208,7 +208,7 @@ impl Inv for Decimal {
}
forward_all_binop!(impl Div for Decimal, div);
impl<'a, 'b> Div<&'b Decimal> for &'a Decimal {
impl Div<&Decimal> for &Decimal {
type Output = Decimal;
#[inline]
@ -222,7 +222,7 @@ impl<'a, 'b> Div<&'b Decimal> for &'a Decimal {
}
forward_all_binop!(impl Mul for Decimal, mul);
impl<'a, 'b> Mul<&'b Decimal> for &'a Decimal {
impl Mul<&Decimal> for &Decimal {
type Output = Decimal;
#[inline]
@ -235,7 +235,7 @@ impl<'a, 'b> Mul<&'b Decimal> for &'a Decimal {
}
forward_all_binop!(impl Rem for Decimal, rem);
impl<'a, 'b> Rem<&'b Decimal> for &'a Decimal {
impl Rem<&Decimal> for &Decimal {
type Output = Decimal;
#[inline]
@ -249,7 +249,7 @@ impl<'a, 'b> Rem<&'b Decimal> for &'a Decimal {
}
forward_all_binop!(impl Sub for Decimal, sub);
impl<'a, 'b> Sub<&'b Decimal> for &'a Decimal {
impl Sub<&Decimal> for &Decimal {
type Output = Decimal;
#[inline(always)]

@ -20,13 +20,13 @@ pub const SIGN_SHIFT: u32 = 31;
// to the byte boundary for simplicity.
pub const MAX_STR_BUFFER_SIZE: usize = 32;
// The maximum supported precision
pub const MAX_PRECISION: u8 = 28;
// The maximum supported [`Decimal::scale`] value
pub const MAX_SCALE: u8 = 28;
#[cfg(not(feature = "legacy-ops"))]
// u8 to i32 is infallible, therefore, this cast will never overflow
pub const MAX_PRECISION_I32: i32 = MAX_PRECISION as _;
pub const MAX_SCALE_I32: i32 = MAX_SCALE as _;
// u8 to u32 is infallible, therefore, this cast will never overflow
pub const MAX_PRECISION_U32: u32 = MAX_PRECISION as _;
pub const MAX_SCALE_U32: u32 = MAX_SCALE as _;
// 79,228,162,514,264,337,593,543,950,335
pub const MAX_I128_REPR: i128 = 0x0000_0000_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF;

@ -1,5 +1,5 @@
use crate::constants::{
MAX_I128_REPR, MAX_PRECISION_U32, POWERS_10, SCALE_MASK, SCALE_SHIFT, SIGN_MASK, SIGN_SHIFT, U32_MASK, U8_MASK,
MAX_I128_REPR, MAX_SCALE_U32, POWERS_10, SCALE_MASK, SCALE_SHIFT, SIGN_MASK, SIGN_SHIFT, U32_MASK, U8_MASK,
UNSIGN_MASK,
};
use crate::ops;
@ -272,6 +272,14 @@ impl Decimal {
/// assert_eq!(Decimal::ONE_THOUSAND, dec!(1000));
/// ```
pub const ONE_THOUSAND: Decimal = ONE_THOUSAND;
/// The maximum supported scale value.
///
/// Some operations, such as [`Self::rescale`] may accept larger scale values, but these
/// operations will result in a final value with a scale no larger than this.
///
/// Note that the maximum scale is _not_ the same as the maximum possible numeric precision in
/// base-10.
pub const MAX_SCALE: u32 = MAX_SCALE_U32;
/// A constant representing π as 3.1415926535897932384626433833
///
@ -385,7 +393,7 @@ impl Decimal {
///
/// # Panics
///
/// This function panics if `scale` is > 28.
/// This function panics if `scale` is > [`Self::MAX_SCALE`].
///
/// # Example
///
@ -403,7 +411,7 @@ impl Decimal {
}
}
/// Checked version of `Decimal::new`. Will return `Err` instead of panicking at run-time.
/// Checked version of [`Self::new`]. Will return an error instead of panicking at run-time.
///
/// # Example
///
@ -414,7 +422,7 @@ impl Decimal {
/// assert!(max.is_err());
/// ```
pub const fn try_new(num: i64, scale: u32) -> crate::Result<Decimal> {
if scale > MAX_PRECISION_U32 {
if scale > Self::MAX_SCALE {
return Err(Error::ScaleExceedsMaximumPrecision(scale));
}
let flags: u32 = scale << SCALE_SHIFT;
@ -444,7 +452,8 @@ impl Decimal {
///
/// # Panics
///
/// This function panics if `scale` is > 28 or if `num` exceeds the maximum supported 96 bits.
/// This function panics if `scale` is > [`Self::MAX_SCALE`] or if `num` exceeds the maximum
/// supported 96 bits.
///
/// # Example
///
@ -474,26 +483,27 @@ impl Decimal {
/// assert!(max.is_err());
/// ```
pub const fn try_from_i128_with_scale(num: i128, scale: u32) -> crate::Result<Decimal> {
if scale > MAX_PRECISION_U32 {
return Err(Error::ScaleExceedsMaximumPrecision(scale));
}
let mut neg = false;
let mut wrapped = num;
if num > MAX_I128_REPR {
return Err(Error::ExceedsMaximumPossibleValue);
if scale > Self::MAX_SCALE {
Err(Error::ScaleExceedsMaximumPrecision(scale))
} else if num > MAX_I128_REPR {
Err(Error::ExceedsMaximumPossibleValue)
} else if num < -MAX_I128_REPR {
return Err(Error::LessThanMinimumPossibleValue);
} else if num < 0 {
neg = true;
wrapped = -num;
Err(Error::LessThanMinimumPossibleValue)
} else {
Ok(Self::from_i128_with_scale_unchecked(num, scale))
}
let flags: u32 = flags(neg, scale);
Ok(Decimal {
}
#[inline]
pub(crate) const fn from_i128_with_scale_unchecked(num: i128, scale: u32) -> Decimal {
let flags = flags(num < 0, scale);
let num = num.unsigned_abs();
Decimal {
flags,
lo: (wrapped as u64 & U32_MASK) as u32,
mid: ((wrapped as u64 >> 32) & U32_MASK) as u32,
hi: ((wrapped as u128 >> 64) as u64 & U32_MASK) as u32,
})
lo: (num as u64 & U32_MASK) as u32,
mid: ((num as u64 >> 32) & U32_MASK) as u32,
hi: ((num >> 64) as u64 & U32_MASK) as u32,
}
}
/// Returns a `Decimal` using the instances constituent parts.
@ -504,14 +514,7 @@ impl Decimal {
/// * `mid` - The middle 32 bits of a 96-bit integer.
/// * `hi` - The high 32 bits of a 96-bit integer.
/// * `negative` - `true` to indicate a negative number.
/// * `scale` - A power of 10 ranging from 0 to 28.
///
/// # Caution: Undefined behavior
///
/// While a scale greater than 28 can be passed in, it will be automatically capped by this
/// function at the maximum precision. The library opts towards this functionality as opposed
/// to a panic to ensure that the function can be treated as constant. This may lead to
/// undefined behavior in downstream applications and should be treated with caution.
/// * `scale` - A power of 10 ranging from 0 to [`Self::MAX_SCALE`].
///
/// # Example
///
@ -523,6 +526,7 @@ impl Decimal {
/// ```
#[must_use]
pub const fn from_parts(lo: u32, mid: u32, hi: u32, negative: bool, scale: u32) -> Decimal {
assert!(scale <= Self::MAX_SCALE, "Scale exceeds maximum supported scale");
Decimal {
lo,
mid,
@ -533,7 +537,7 @@ impl Decimal {
} else {
negative
},
scale % (MAX_PRECISION_U32 + 1),
scale,
),
}
}
@ -573,7 +577,7 @@ impl Decimal {
pub fn from_scientific(value: &str) -> Result<Decimal, Error> {
const ERROR_MESSAGE: &str = "Failed to parse";
let mut split = value.splitn(2, |c| c == 'e' || c == 'E');
let mut split = value.splitn(2, ['e', 'E']);
let base = split.next().ok_or_else(|| Error::from(ERROR_MESSAGE))?;
let exp = split.next().ok_or_else(|| Error::from(ERROR_MESSAGE))?;
@ -583,6 +587,9 @@ impl Decimal {
if let Some(stripped) = exp.strip_prefix('-') {
let exp: u32 = stripped.parse().map_err(|_| Error::from(ERROR_MESSAGE))?;
if exp > Self::MAX_SCALE {
return Err(Error::ScaleExceedsMaximumPrecision(exp));
}
ret.set_scale(current_scale + exp)?;
} else {
let exp: u32 = exp.parse().map_err(|_| Error::from(ERROR_MESSAGE))?;
@ -596,7 +603,7 @@ impl Decimal {
// we've parsed 1.2 as the base and 10 as the exponent. To represent this within a
// Decimal type we effectively store the mantissa as 12,000,000,000 and scale as
// zero.
if exp > MAX_PRECISION_U32 {
if exp > Self::MAX_SCALE {
return Err(Error::ScaleExceedsMaximumPrecision(exp));
}
let mut exp = exp as usize;
@ -702,7 +709,7 @@ impl Decimal {
///
/// ```
/// # use rust_decimal::prelude::*;
/// use rust_decimal_macros::dec;
/// # use rust_decimal_macros::dec;
///
/// let num = dec!(-1.2345678);
/// assert_eq!(num.mantissa(), -12345678i128);
@ -856,7 +863,7 @@ impl Decimal {
/// # }
/// ```
pub fn set_scale(&mut self, scale: u32) -> Result<(), Error> {
if scale > MAX_PRECISION_U32 {
if scale > Self::MAX_SCALE {
return Err(Error::ScaleExceedsMaximumPrecision(scale));
}
self.flags = (scale << SCALE_SHIFT) | (self.flags & SIGN_MASK);
@ -870,7 +877,7 @@ impl Decimal {
/// cause the newly created `Decimal` to perform rounding using the `MidpointAwayFromZero` strategy.
///
/// Scales greater than the maximum precision that can be represented by `Decimal` will be
/// automatically rounded to either `Decimal::MAX_PRECISION` or the maximum precision that can
/// automatically rounded to either [`Self::MAX_SCALE`] or the maximum precision that can
/// be represented with the given mantissa.
///
/// # Arguments
@ -880,7 +887,7 @@ impl Decimal {
///
/// ```
/// # use rust_decimal::prelude::*;
/// use rust_decimal_macros::dec;
/// # use rust_decimal_macros::dec;
///
/// // Rescaling to a higher scale preserves the value
/// let mut number = dec!(1.123);
@ -960,14 +967,20 @@ impl Decimal {
// Bits 24-30: unused
// Bit 31: the sign of the Decimal value, 0 meaning positive and 1 meaning negative.
let mut raw = Decimal {
flags: ((bytes[0] as u32) | (bytes[1] as u32) << 8 | (bytes[2] as u32) << 16 | (bytes[3] as u32) << 24)
flags: ((bytes[0] as u32)
| ((bytes[1] as u32) << 8)
| ((bytes[2] as u32) << 16)
| ((bytes[3] as u32) << 24))
& 0x801F_0000,
lo: (bytes[4] as u32) | (bytes[5] as u32) << 8 | (bytes[6] as u32) << 16 | (bytes[7] as u32) << 24,
mid: (bytes[8] as u32) | (bytes[9] as u32) << 8 | (bytes[10] as u32) << 16 | (bytes[11] as u32) << 24,
hi: (bytes[12] as u32) | (bytes[13] as u32) << 8 | (bytes[14] as u32) << 16 | (bytes[15] as u32) << 24,
lo: (bytes[4] as u32) | ((bytes[5] as u32) << 8) | ((bytes[6] as u32) << 16) | ((bytes[7] as u32) << 24),
mid: (bytes[8] as u32) | ((bytes[9] as u32) << 8) | ((bytes[10] as u32) << 16) | ((bytes[11] as u32) << 24),
hi: (bytes[12] as u32)
| ((bytes[13] as u32) << 8)
| ((bytes[14] as u32) << 16)
| ((bytes[15] as u32) << 24),
};
// Scale must be bound to maximum precision. Only two values can be greater than this
if raw.scale() > MAX_PRECISION_U32 {
if raw.scale() > Self::MAX_SCALE {
let mut bits = raw.mantissa_array3();
let remainder = match raw.scale() {
29 => ops::array::div_by_power::<1>(&mut bits),
@ -981,7 +994,7 @@ impl Decimal {
raw.lo = bits[0];
raw.mid = bits[1];
raw.hi = bits[2];
raw.flags = flags(raw.is_sign_negative(), MAX_PRECISION_U32);
raw.flags = flags(raw.is_sign_negative(), Self::MAX_SCALE);
}
raw
}
@ -1502,7 +1515,7 @@ impl Decimal {
///
/// ```
/// # use rust_decimal::Decimal;
/// use rust_decimal_macros::dec;
/// # use rust_decimal_macros::dec;
///
/// let value = dec!(305.459);
/// assert_eq!(value.round_sf(0), Some(dec!(0)));
@ -1544,7 +1557,7 @@ impl Decimal {
///
/// ```
/// # use rust_decimal::{Decimal, RoundingStrategy};
/// use rust_decimal_macros::dec;
/// # use rust_decimal_macros::dec;
///
/// let value = dec!(305.459);
/// assert_eq!(value.round_sf_with_strategy(0, RoundingStrategy::ToZero), Some(dec!(0)));
@ -1656,7 +1669,7 @@ impl Decimal {
///
/// ```
/// # use rust_decimal::Decimal;
/// use rust_decimal_macros::dec;
/// # use rust_decimal_macros::dec;
///
/// let pi = dec!(3.1415926535897932384626433832);
/// assert_eq!(format!("{:?}", pi), "3.1415926535897932384626433832");
@ -2190,6 +2203,9 @@ fn base2_to_decimal(
exponent10 -= 1;
exponent5 += 1;
ops::array::shl1_internal(bits, 0);
} else if exponent10 * 2 > -exponent5 {
// Multiplying by >=2 which, due to the previous condition, means an overflow.
return None;
} else {
// The mantissa would overflow if shifted. Therefore it should be
// directly divided by 5. This will lose significant digits, unless
@ -2201,7 +2217,7 @@ fn base2_to_decimal(
// At this point, the mantissa has assimilated the exponent5, but
// exponent10 might not be suitable for assignment. exponent10 must be
// in the range [-MAX_PRECISION..0], so the mantissa must be scaled up or
// in the range [-MAX_SCALE..0], so the mantissa must be scaled up or
// down appropriately.
while exponent10 > 0 {
// In order to bring exponent10 down to 0, the mantissa should be
@ -2215,10 +2231,10 @@ fn base2_to_decimal(
}
}
// In order to bring exponent up to -MAX_PRECISION, the mantissa should
// In order to bring exponent up to -MAX_SCALE, the mantissa should
// be divided by 10 to compensate. If the exponent10 is too small, this
// will cause the mantissa to underflow and become 0.
while exponent10 < -(MAX_PRECISION_U32 as i32) {
while exponent10 < -(Decimal::MAX_SCALE as i32) {
let rem10 = ops::array::div_by_u32(bits, 10);
exponent10 += 1;
if ops::array::is_all_zero(bits) {
@ -2306,7 +2322,7 @@ impl ToPrimitive for Decimal {
fn to_i128(&self) -> Option<i128> {
let d = self.trunc();
let raw: i128 = ((i128::from(d.hi) << 64) | i128::from(d.mid) << 32) | i128::from(d.lo);
let raw: i128 = ((i128::from(d.hi) << 64) | (i128::from(d.mid) << 32)) | i128::from(d.lo);
if self.is_sign_negative() {
Some(-raw)
} else {
@ -2417,7 +2433,7 @@ impl Neg for Decimal {
}
}
impl<'a> Neg for &'a Decimal {
impl Neg for &Decimal {
type Output = Decimal;
fn neg(self) -> Decimal {
@ -2446,7 +2462,7 @@ impl<'a> AddAssign<&'a Decimal> for Decimal {
}
}
impl<'a> AddAssign<Decimal> for &'a mut Decimal {
impl AddAssign<Decimal> for &mut Decimal {
fn add_assign(&mut self, other: Decimal) {
Decimal::add_assign(*self, other)
}
@ -2474,7 +2490,7 @@ impl<'a> SubAssign<&'a Decimal> for Decimal {
}
}
impl<'a> SubAssign<Decimal> for &'a mut Decimal {
impl SubAssign<Decimal> for &mut Decimal {
fn sub_assign(&mut self, other: Decimal) {
Decimal::sub_assign(*self, other)
}
@ -2502,7 +2518,7 @@ impl<'a> MulAssign<&'a Decimal> for Decimal {
}
}
impl<'a> MulAssign<Decimal> for &'a mut Decimal {
impl MulAssign<Decimal> for &mut Decimal {
fn mul_assign(&mut self, other: Decimal) {
Decimal::mul_assign(*self, other)
}
@ -2530,7 +2546,7 @@ impl<'a> DivAssign<&'a Decimal> for Decimal {
}
}
impl<'a> DivAssign<Decimal> for &'a mut Decimal {
impl DivAssign<Decimal> for &mut Decimal {
fn div_assign(&mut self, other: Decimal) {
Decimal::div_assign(*self, other)
}
@ -2558,7 +2574,7 @@ impl<'a> RemAssign<&'a Decimal> for Decimal {
}
}
impl<'a> RemAssign<Decimal> for &'a mut Decimal {
impl RemAssign<Decimal> for &mut Decimal {
fn rem_assign(&mut self, other: Decimal) {
Decimal::rem_assign(*self, other)
}

@ -1,4 +1,4 @@
use crate::{constants::MAX_PRECISION_U32, Decimal};
use crate::Decimal;
use alloc::string::String;
use core::fmt;
@ -57,7 +57,8 @@ impl fmt::Display for Error {
Self::ScaleExceedsMaximumPrecision(ref scale) => {
write!(
f,
"Scale exceeds the maximum precision allowed: {scale} > {MAX_PRECISION_U32}"
"Scale exceeds the maximum precision allowed: {scale} > {}",
Decimal::MAX_SCALE
)
}
Self::ConversionTo(ref type_name) => {

@ -8,7 +8,7 @@ impl Arbitrary<'_> for crate::Decimal {
let mid = u32::arbitrary(u)?;
let hi = u32::arbitrary(u)?;
let negative = bool::arbitrary(u)?;
let scale = u32::arbitrary(u)?;
let scale = u32::arbitrary(u)? % (Self::MAX_SCALE + 1);
Ok(Decimal::from_parts(lo, mid, hi, negative, scale))
}
}

@ -9,7 +9,7 @@ mod constants;
mod decimal;
mod error;
mod ops;
mod str;
pub mod str;
// We purposely place this here for documentation ordering
mod arithmetic_impls;
@ -30,6 +30,8 @@ mod postgres;
mod proptest;
#[cfg(feature = "rand")]
mod rand;
#[cfg(feature = "rand-0_9")]
mod rand_0_9;
#[cfg(feature = "rocket-traits")]
mod rocket;
#[cfg(all(
@ -57,20 +59,20 @@ pub use error::Error;
#[cfg(feature = "maths")]
pub use maths::MathematicalOps;
// #[cfg(feature = "macros")]
// pub use rust_decimal_macros::dec;
/// A convenience module appropriate for glob imports (`use rust_decimal::prelude::*;`).
pub mod prelude {
#[cfg(feature = "macros")]
pub use super::dec;
#[cfg(feature = "maths")]
pub use crate::maths::MathematicalOps;
pub use crate::{Decimal, RoundingStrategy};
pub use core::str::FromStr;
pub use num_traits::{FromPrimitive, One, Signed, ToPrimitive, Zero};
// #[cfg(feature = "macros")]
// pub use rust_decimal_macros::dec;
}
#[cfg(feature = "macros")]
pub use rust_decimal_macros::dec;
#[cfg(feature = "diesel")]
extern crate diesel;

@ -48,7 +48,8 @@ const FACTORIAL: [Decimal; 28] = [
];
/// Trait exposing various mathematical operations that can be applied using a Decimal. This is only
/// present when the `maths` feature has been enabled.
/// present when the `maths` feature has been enabled, e.g. by adding the crate with
// `cargo add rust_decimal --features maths` and importing in your Rust file with `use rust_decimal::MathematicalOps;`
pub trait MathematicalOps {
/// The estimated exponential function, e<sup>x</sup>. Stops calculating when it is within
/// tolerance of roughly `0.0000002`.

@ -1,6 +1,4 @@
use crate::constants::{
MAX_I32_SCALE, MAX_PRECISION_U32, POWERS_10, SCALE_MASK, SCALE_SHIFT, SIGN_MASK, U32_MASK, U32_MAX,
};
use crate::constants::{MAX_I32_SCALE, POWERS_10, SCALE_MASK, SCALE_SHIFT, SIGN_MASK, U32_MASK, U32_MAX};
use crate::decimal::{CalculationResult, Decimal};
use crate::ops::common::{Buf24, Dec64};
@ -263,7 +261,7 @@ fn unaligned_add(
rescale_factor -= MAX_I32_SCALE;
if tmp64 > U32_MAX || scale > MAX_PRECISION_U32 {
if tmp64 > U32_MAX || scale > Decimal::MAX_SCALE {
break;
} else {
high = tmp64 as u32;

@ -1,4 +1,4 @@
use crate::constants::{MAX_PRECISION_U32, POWERS_10, U32_MASK};
use crate::constants::{MAX_SCALE_U32, POWERS_10, U32_MASK};
/// Rescales the given decimal to new scale.
/// e.g. with 1.23 and new scale 3 rescale the value to 1.230
@ -15,7 +15,7 @@ fn rescale<const ROUND: bool>(value: &mut [u32; 3], value_scale: &mut u32, new_s
}
if is_all_zero(value) {
*value_scale = new_scale.min(MAX_PRECISION_U32);
*value_scale = new_scale.min(MAX_SCALE_U32);
return;
}
@ -278,8 +278,8 @@ pub(crate) fn shl1_internal(bits: &mut [u32], carry: u32) -> u32 {
pub(crate) fn cmp_internal(left: &[u32; 3], right: &[u32; 3]) -> core::cmp::Ordering {
let left_hi: u32 = left[2];
let right_hi: u32 = right[2];
let left_lo: u64 = u64::from(left[1]) << 32 | u64::from(left[0]);
let right_lo: u64 = u64::from(right[1]) << 32 | u64::from(right[0]);
let left_lo: u64 = (u64::from(left[1]) << 32) | u64::from(left[0]);
let right_lo: u64 = (u64::from(right[1]) << 32) | u64::from(right[0]);
if left_hi < right_hi || (left_hi <= right_hi && left_lo < right_lo) {
core::cmp::Ordering::Less
} else if left_hi == right_hi && left_lo == right_lo {

@ -1,4 +1,4 @@
use crate::constants::{MAX_I32_SCALE, MAX_PRECISION_I32, POWERS_10};
use crate::constants::{MAX_I32_SCALE, MAX_SCALE_I32, POWERS_10};
use crate::Decimal;
#[derive(Debug)]
@ -96,12 +96,12 @@ impl Buf12 {
return Some(x);
}
if scale > MAX_PRECISION_I32 - 9 {
if scale > MAX_SCALE_I32 - 9 {
// We can't scale by 10^9 without exceeding the max scale factor.
// Instead, we'll try to scale by the most that we can and see if that works.
// This is safe to do due to the check above. e.g. scale > 19 in the above, so it will
// evaluate to 9 or less below.
x = (MAX_PRECISION_I32 - scale) as usize;
x = (MAX_SCALE_I32 - scale) as usize;
if hi < POWER_OVERFLOW_VALUES[x - 1].data[2] {
if x as i32 + scale < 0 {
// We still overflow
@ -350,8 +350,8 @@ impl Buf24 {
}
// Make sure we scale enough to bring it into a valid range
if rescale_target < scale - MAX_PRECISION_I32 {
rescale_target = scale - MAX_PRECISION_I32;
if rescale_target < scale - MAX_SCALE_I32 {
rescale_target = scale - MAX_SCALE_I32;
}
if rescale_target > 0 {

@ -1,4 +1,4 @@
use crate::constants::{MAX_PRECISION_I32, POWERS_10};
use crate::constants::{MAX_SCALE_I32, POWERS_10};
use crate::decimal::{CalculationResult, Decimal};
use crate::ops::common::{Buf12, Buf16, Dec64};
@ -260,7 +260,7 @@ pub(crate) fn div_impl(dividend: &Decimal, divisor: &Decimal) -> CalculationResu
// We have a remainder so we effectively want to try to adjust the quotient and add
// the remainder into the quotient. We do this below, however first of all we want
// to try to avoid overflowing so we do that check first.
let will_overflow = if scale == MAX_PRECISION_I32 {
let will_overflow = if scale == MAX_SCALE_I32 {
true
} else {
// Figure out how much we can scale by
@ -376,7 +376,7 @@ pub(crate) fn div_impl(dividend: &Decimal, divisor: &Decimal) -> CalculationResu
// We have a remainder so we effectively want to try to adjust the quotient and add
// the remainder into the quotient. We do this below, however first of all we want
// to try to avoid overflowing so we do that check first.
let will_overflow = if scale == MAX_PRECISION_I32 {
let will_overflow = if scale == MAX_SCALE_I32 {
true
} else {
// Figure out how much we can scale by
@ -467,7 +467,7 @@ pub(crate) fn div_impl(dividend: &Decimal, divisor: &Decimal) -> CalculationResu
// We have a remainder so we effectively want to try to adjust the quotient and add
// the remainder into the quotient. We do this below, however first of all we want
// to try to avoid overflowing so we do that check first.
let will_overflow = if scale == MAX_PRECISION_I32 {
let will_overflow = if scale == MAX_SCALE_I32 {
true
} else {
// Figure out how much we can scale by

@ -1,5 +1,5 @@
use crate::{
constants::{MAX_PRECISION_U32, POWERS_10, U32_MASK},
constants::{POWERS_10, U32_MASK},
decimal::{CalculationResult, Decimal},
ops::array::{
add_by_internal, cmp_internal, div_by_u32, is_all_zero, mul_by_u32, mul_part, rescale_internal, shl1_internal,
@ -171,16 +171,16 @@ pub(crate) fn div_impl(d1: &Decimal, d2: &Decimal) -> CalculationResult {
// Check for underflow
let mut final_scale: u32 = quotient_scale as u32;
if final_scale > MAX_PRECISION_U32 {
if final_scale > Decimal::MAX_SCALE {
let mut remainder = 0;
// Division underflowed. We must remove some significant digits over using
// an invalid scale.
while final_scale > MAX_PRECISION_U32 && !is_all_zero(&quotient) {
while final_scale > Decimal::MAX_SCALE && !is_all_zero(&quotient) {
remainder = div_by_u32(&mut quotient, 10);
final_scale -= 1;
}
if final_scale > MAX_PRECISION_U32 {
if final_scale > Decimal::MAX_SCALE {
// Result underflowed so set to zero
final_scale = 0;
quotient_negative = false;
@ -228,8 +228,8 @@ pub(crate) fn mul_impl(d1: &Decimal, d2: &Decimal) -> CalculationResult {
let mut u64_result = u64_to_array(u64::from(my[0]) * u64::from(ot[0]));
// If we're above max precision then this is a very small number
if final_scale > MAX_PRECISION_U32 {
final_scale -= MAX_PRECISION_U32;
if final_scale > Decimal::MAX_SCALE {
final_scale -= Decimal::MAX_SCALE;
// If the number is above 19 then this will equate to zero.
// This is because the max value in 64 bits is 1.84E19
@ -258,7 +258,7 @@ pub(crate) fn mul_impl(d1: &Decimal, d2: &Decimal) -> CalculationResult {
u64_result[0] += 1;
}
final_scale = MAX_PRECISION_U32;
final_scale = Decimal::MAX_SCALE;
}
return CalculationResult::Ok(Decimal::from_parts(
u64_result[0],
@ -350,17 +350,17 @@ pub(crate) fn mul_impl(d1: &Decimal, d2: &Decimal) -> CalculationResult {
// If we're still above max precision then we'll try again to
// reduce precision - we may be dealing with a limit of "0"
if final_scale > MAX_PRECISION_U32 {
if final_scale > Decimal::MAX_SCALE {
// We're in an underflow situation
// The easiest way to remove precision is to divide off the result
while final_scale > MAX_PRECISION_U32 && !is_all_zero(&product) {
while final_scale > Decimal::MAX_SCALE && !is_all_zero(&product) {
div_by_u32(&mut product, 10);
final_scale -= 1;
}
// If we're still at limit then we can't represent any
// significant decimal digits and will return an integer only
// Can also be invoked while representing 0.
if final_scale > MAX_PRECISION_U32 {
if final_scale > Decimal::MAX_SCALE {
final_scale = 0;
}
} else if !(product[3] == 0 && product[4] == 0 && product[5] == 0) {
@ -478,7 +478,7 @@ pub(crate) fn cmp_impl(d1: &Decimal, d2: &Decimal) -> Ordering {
#[inline]
fn add_part(left: u32, right: u32) -> (u32, u32) {
let added = u64::from(left) + u64::from(right);
((added & U32_MASK) as u32, (added >> 32 & U32_MASK) as u32)
((added & U32_MASK) as u32, ((added >> 32) & U32_MASK) as u32)
}
#[inline(always)]
@ -590,7 +590,7 @@ fn add_by_internal3(value: &mut [u32; 3], by: &[u32; 3]) -> u32 {
#[inline]
const fn u64_to_array(value: u64) -> [u32; 2] {
[(value & U32_MASK) as u32, (value >> 32 & U32_MASK) as u32]
[(value & U32_MASK) as u32, ((value >> 32) & U32_MASK) as u32]
}
fn add_with_scale_internal(

@ -1,4 +1,4 @@
use crate::constants::{BIG_POWERS_10, MAX_I64_SCALE, MAX_PRECISION_U32, U32_MAX};
use crate::constants::{BIG_POWERS_10, MAX_I64_SCALE, U32_MAX};
use crate::decimal::{CalculationResult, Decimal};
use crate::ops::common::Buf24;
@ -18,15 +18,15 @@ pub(crate) fn mul_impl(d1: &Decimal, d2: &Decimal) -> CalculationResult {
if d2.hi() | d2.mid() == 0 {
// We're multiplying two 32 bit integers, so we can take some liberties to optimize this.
let mut low64 = d1.lo() as u64 * d2.lo() as u64;
if scale > MAX_PRECISION_U32 {
if scale > Decimal::MAX_SCALE {
// We've exceeded maximum scale so we need to start reducing the precision (aka
// rounding) until we have something that fits.
// If we're too big then we effectively round to zero.
if scale > MAX_PRECISION_U32 + MAX_I64_SCALE {
if scale > Decimal::MAX_SCALE + MAX_I64_SCALE {
return CalculationResult::Ok(Decimal::ZERO);
}
scale -= MAX_PRECISION_U32 + 1;
scale -= Decimal::MAX_SCALE + 1;
let mut power = BIG_POWERS_10[scale as usize];
let tmp = low64 / power;
@ -39,7 +39,7 @@ pub(crate) fn mul_impl(d1: &Decimal, d2: &Decimal) -> CalculationResult {
low64 += 1;
}
scale = MAX_PRECISION_U32;
scale = Decimal::MAX_SCALE;
}
// Early exit
@ -129,7 +129,7 @@ pub(crate) fn mul_impl(d1: &Decimal, d2: &Decimal) -> CalculationResult {
// We may want to "rescale". This is the case if the mantissa is > 96 bits or if the scale
// exceeds the maximum precision.
let upper_word = product.upper_word();
if upper_word > 2 || scale > MAX_PRECISION_U32 {
if upper_word > 2 || scale > Decimal::MAX_SCALE {
scale = if let Some(new_scale) = product.rescale(upper_word, scale) {
new_scale
} else {

@ -1,4 +1,4 @@
use crate::constants::{MAX_I32_SCALE, MAX_PRECISION_I32, POWERS_10};
use crate::constants::{MAX_I32_SCALE, MAX_SCALE_I32, POWERS_10};
use crate::decimal::{CalculationResult, Decimal};
use crate::ops::common::{Buf12, Buf16, Buf24, Dec64};
@ -74,7 +74,7 @@ pub(crate) fn rem_impl(d1: &Decimal, d2: &Decimal) -> CalculationResult {
loop {
// Figure out how much we can scale by
let power_scale;
if let Some(u) = quotient.find_scale(MAX_PRECISION_I32 + scale) {
if let Some(u) = quotient.find_scale(MAX_SCALE_I32 + scale) {
if u >= POWERS_10.len() {
power_scale = 9;
} else {

@ -1,4 +1,3 @@
use crate::constants::MAX_PRECISION_U32;
use crate::{
ops::array::{div_by_u32, is_all_zero, mul_by_u32},
Decimal,
@ -44,7 +43,7 @@ impl Decimal {
let fractionals_part_count = digits.len() as i32 + (-weight as i32) - 1;
let integers_part_count = weight as i32 + 1;
let mut result = Decimal::ZERO;
let mut result = Self::ZERO;
// adding integer part
if integers_part_count > 0 {
let (start_integers, last) = if integers_part_count > digits.len() as i32 {
@ -54,25 +53,25 @@ impl Decimal {
};
let integers: Vec<_> = digits.drain(..last as usize).collect();
for digit in integers {
result = result.checked_mul(Decimal::from_i128_with_scale(10i128.pow(4), 0))?;
result = result.checked_add(Decimal::new(digit as i64, 0))?;
result = result.checked_mul(Self::from_i128_with_scale(10i128.pow(4), 0))?;
result = result.checked_add(Self::new(digit as i64, 0))?;
}
result = result.checked_mul(Decimal::from_i128_with_scale(10i128.pow(4 * start_integers as u32), 0))?;
result = result.checked_mul(Self::from_i128_with_scale(10i128.pow(4 * start_integers as u32), 0))?;
}
// adding fractional part
if fractionals_part_count > 0 {
let start_fractionals = if weight < 0 { (-weight as u32) - 1 } else { 0 };
for (i, digit) in digits.into_iter().enumerate() {
let fract_pow = 4_u32.checked_mul(i as u32 + 1 + start_fractionals)?;
if fract_pow <= MAX_PRECISION_U32 {
if fract_pow <= Self::MAX_SCALE {
result = result.checked_add(
Decimal::new(digit as i64, 0) / Decimal::from_i128_with_scale(10i128.pow(fract_pow), 0),
Self::new(digit as i64, 0) / Self::from_i128_with_scale(10i128.pow(fract_pow), 0),
)?;
} else if fract_pow == MAX_PRECISION_U32 + 4 {
} else if fract_pow == Self::MAX_SCALE + 4 {
// rounding last digit
if digit >= 5000 {
result = result.checked_add(
Decimal::new(1_i64, 0) / Decimal::from_i128_with_scale(10i128.pow(MAX_PRECISION_U32), 0),
Self::new(1_i64, 0) / Self::from_i128_with_scale(10i128.pow(Self::MAX_SCALE), 0),
)?;
}
}
@ -81,7 +80,7 @@ impl Decimal {
result.set_sign_negative(neg);
// Rescale to the postgres value, automatically rounding as needed.
result.rescale((scale as u32).min(MAX_PRECISION_U32));
result.rescale((scale as u32).min(Self::MAX_SCALE));
Some(result)
}

@ -17,7 +17,7 @@ impl Distribution<Decimal> for Standard {
rng.next_u32(),
rng.next_u32(),
rng.gen(),
rng.next_u32(),
rng.gen_range(0..=Decimal::MAX_SCALE),
)
}
}
@ -44,7 +44,7 @@ impl UniformSampler for DecimalSampler {
///
/// ```
/// # use rand::Rng;
/// # use rust_decimal_macros::dec;
/// # use rust_decimal::dec;
/// let mut rng = rand::rngs::OsRng;
/// let random = rng.gen_range(dec!(1.00)..dec!(2.00));
/// assert!(random >= dec!(1.00));
@ -71,7 +71,7 @@ impl UniformSampler for DecimalSampler {
///
/// ```
/// # use rand::Rng;
/// # use rust_decimal_macros::dec;
/// # use rust_decimal::dec;
/// let mut rng = rand::rngs::OsRng;
/// let random = rng.gen_range(dec!(1.00)..=dec!(2.00));
/// assert!(random >= dec!(1.00));

@ -0,0 +1,178 @@
use crate::Decimal;
use rand_0_9::{
distr::{
uniform::{SampleBorrow, SampleUniform, UniformInt, UniformSampler},
Distribution, StandardUniform,
},
Rng,
};
impl Distribution<Decimal> for StandardUniform {
fn sample<R>(&self, rng: &mut R) -> Decimal
where
R: Rng + ?Sized,
{
Decimal::from_parts(
rng.next_u32(),
rng.next_u32(),
rng.next_u32(),
rng.random(),
rng.random_range(0..=Decimal::MAX_SCALE),
)
}
}
impl SampleUniform for Decimal {
type Sampler = DecimalSampler;
}
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct DecimalSampler {
mantissa_sampler: UniformInt<i128>,
scale: u32,
}
impl UniformSampler for DecimalSampler {
type X = Decimal;
/// Creates a new sampler that will yield random decimal objects between `low` and `high`.
///
/// The sampler will always provide decimals at the same scale as the inputs; if the inputs
/// have different scales, the higher scale is used.
///
/// # Example
///
/// ```
/// # use rand_0_9 as rand;
/// # use rand::Rng;
/// # use rust_decimal_macros::dec;
/// let mut rng = rand::rng();
/// let random = rng.random_range(dec!(1.00)..dec!(2.00));
/// assert!(random >= dec!(1.00));
/// assert!(random < dec!(2.00));
/// assert_eq!(random.scale(), 2);
/// ```
#[inline]
fn new<B1, B2>(low: B1, high: B2) -> Result<Self, rand_0_9::distr::uniform::Error>
where
B1: SampleBorrow<Self::X> + Sized,
B2: SampleBorrow<Self::X> + Sized,
{
let (low, high) = sync_scales(*low.borrow(), *high.borrow());
let high = Decimal::from_i128_with_scale(high.mantissa() - 1, high.scale());
UniformSampler::new_inclusive(low, high)
}
/// Creates a new sampler that will yield random decimal objects between `low` and `high`.
///
/// The sampler will always provide decimals at the same scale as the inputs; if the inputs
/// have different scales, the higher scale is used.
///
/// # Example
///
/// ```
/// # use rand_0_9 as rand;
/// # use rand::Rng;
/// # use rust_decimal_macros::dec;
/// let mut rng = rand::rng();
/// let random = rng.random_range(dec!(1.00)..=dec!(2.00));
/// assert!(random >= dec!(1.00));
/// assert!(random <= dec!(2.00));
/// assert_eq!(random.scale(), 2);
/// ```
#[inline]
fn new_inclusive<B1, B2>(low: B1, high: B2) -> Result<Self, rand_0_9::distr::uniform::Error>
where
B1: SampleBorrow<Self::X> + Sized,
B2: SampleBorrow<Self::X> + Sized,
{
let (low, high) = sync_scales(*low.borrow(), *high.borrow());
// Return our sampler, which contains an underlying i128 sampler so we
// outsource the actual randomness implementation.
Ok(Self {
mantissa_sampler: UniformInt::new_inclusive(low.mantissa(), high.mantissa())?,
scale: low.scale(),
})
}
#[inline]
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Self::X {
let mantissa = self.mantissa_sampler.sample(rng);
Decimal::from_i128_with_scale(mantissa, self.scale)
}
}
/// Return equivalent Decimal objects with the same scale as one another.
#[inline]
fn sync_scales(mut a: Decimal, mut b: Decimal) -> (Decimal, Decimal) {
if a.scale() == b.scale() {
return (a, b);
}
// Set scales to match one another, because we are relying on mantissas'
// being comparable in order outsource the actual sampling implementation.
a.rescale(a.scale().max(b.scale()));
b.rescale(a.scale().max(b.scale()));
// Edge case: If the values have _wildly_ different scales, the values may not have rescaled far enough to match one another.
//
// In this case, we accept some precision loss because the randomization approach we are using assumes that the scales will necessarily match.
if a.scale() != b.scale() {
a.rescale(a.scale().min(b.scale()));
b.rescale(a.scale().min(b.scale()));
}
(a, b)
}
#[cfg(test)]
mod rand_tests {
use std::collections::HashSet;
use super::*;
macro_rules! dec {
($e:expr) => {
Decimal::from_str_exact(stringify!($e)).unwrap()
};
}
#[test]
fn has_random_decimal_instances() {
let mut rng = rand_0_9::rng();
let random: [Decimal; 32] = rng.random();
assert!(random.windows(2).any(|slice| { slice[0] != slice[1] }));
}
#[test]
fn generates_within_range() {
let mut rng = rand_0_9::rng();
for _ in 0..128 {
let random = rng.random_range(dec!(1.00)..dec!(1.05));
assert!(random < dec!(1.05));
assert!(random >= dec!(1.00));
}
}
#[test]
fn generates_within_inclusive_range() {
let mut rng = rand_0_9::rng();
let mut values: HashSet<Decimal> = HashSet::new();
for _ in 0..256 {
let random = rng.random_range(dec!(1.00)..=dec!(1.01));
// The scale is 2, so 1.00 and 1.01 are the only two valid choices.
assert!(random == dec!(1.00) || random == dec!(1.01));
values.insert(random);
}
// Somewhat flaky, will fail 1 out of every 2^255 times this is run.
// Probably acceptable in the real world.
assert_eq!(values.len(), 2);
}
#[test]
fn test_edge_case_scales_match() {
let (low, high) = sync_scales(dec!(1.000_000_000_000_000_000_01), dec!(100_000_000_000_000_000_001));
assert_eq!(low.scale(), high.scale());
}
}

@ -370,8 +370,10 @@ impl<'de> serde::de::Visitor<'de> for DecimalVisitor {
}
}
#[cfg(any(feature = "serde-with-float", feature = "serde-with-arbitrary-precision"))]
struct OptionDecimalVisitor;
#[cfg(any(feature = "serde-with-float", feature = "serde-with-arbitrary-precision"))]
impl<'de> serde::de::Visitor<'de> for OptionDecimalVisitor {
type Value = Option<Decimal>;

@ -1,5 +1,5 @@
use crate::{
constants::{BYTES_TO_OVERFLOW_U64, MAX_PRECISION, MAX_STR_BUFFER_SIZE, OVERFLOW_U96, WILL_OVERFLOW_U64},
constants::{BYTES_TO_OVERFLOW_U64, MAX_SCALE, MAX_STR_BUFFER_SIZE, OVERFLOW_U96, WILL_OVERFLOW_U64},
error::{tail_error, Error},
ops::array::{add_by_internal_flattened, add_one_internal, div_by_u32, is_all_zero, mul_by_u32},
Decimal,
@ -32,7 +32,7 @@ pub(crate) fn to_str_internal(
let (prec, additional) = match precision {
Some(prec) => {
let max: usize = MAX_PRECISION.into();
let max: usize = MAX_SCALE.into();
if prec > max {
(max, Some(prec - max))
} else {

@ -3136,6 +3136,30 @@ fn it_converts_from_f64_limits() {
assert!(Decimal::try_from(f64::MIN).is_err(), "try_from(f64::MAX)");
}
#[test]
fn it_converts_from_f64_dec_limits() {
use num_traits::FromPrimitive;
// Note Decimal MAX is: 79_228_162_514_264_337_593_543_950_335
let over_max = 79_228_162_514_264_355_185_729_994_752_f64;
let max_plus_one = 79_228_162_514_264_337_593_543_950_336_f64;
let under_max = 79_228_162_514_264_328_797_450_928_128_f64;
assert!(
Decimal::from_f64(over_max).is_none(),
"from_f64(79_228_162_514_264_355_185_729_994_752_f64) -> none (too large)"
);
assert!(
Decimal::from_f64(max_plus_one).is_none(),
"from_f64(79_228_162_514_264_337_593_543_950_336_f64) -> none (too large)"
);
assert_eq!(
"79228162514264328797450928128",
Decimal::from_f64(under_max).unwrap().to_string(),
"from_f64(79_228_162_514_264_328_797_450_928_128_f64) -> some (inside limits)"
);
}
#[test]
fn it_converts_from_f64_retaining_bits() {
let tests = [
@ -3339,20 +3363,25 @@ fn it_can_parse_individual_parts() {
#[test]
fn it_can_parse_scientific_notation() {
let tests = &[
("9.7e-7", "0.00000097"),
("9e-7", "0.0000009"),
("1.2e10", "12000000000"),
("1.2e+10", "12000000000"),
("12e10", "120000000000"),
("9.7E-7", "0.00000097"),
("1.2345E-24", "0.0000000000000000000000012345"),
("12345E-28", "0.0000000000000000000000012345"),
("1.2345E0", "1.2345"),
("1E28", "10000000000000000000000000000"),
("9.7e-7", Ok("0.00000097".to_string())),
("9e-7", Ok("0.0000009".to_string())),
("1.2e10", Ok("12000000000".to_string())),
("1.2e+10", Ok("12000000000".to_string())),
("12e10", Ok("120000000000".to_string())),
("9.7E-7", Ok("0.00000097".to_string())),
("1.2345E-24", Ok("0.0000000000000000000000012345".to_string())),
("12345E-28", Ok("0.0000000000000000000000012345".to_string())),
("1.2345E0", Ok("1.2345".to_string())),
("1E28", Ok("10000000000000000000000000000".to_string())),
(
"-20165.4676_e-+4294967292",
Err(Error::ScaleExceedsMaximumPrecision(4294967292)),
),
];
for &(value, expected) in tests {
assert_eq!(expected, Decimal::from_scientific(value).unwrap().to_string());
for &(value, ref expected) in tests {
let actual = Decimal::from_scientific(value).map(|d| d.to_string());
assert_eq!(*expected, actual);
}
}
@ -4778,7 +4807,7 @@ mod issues {
// 288230376151711744
let a = Decimal::from_parts(0, 67108864, 0, false, 0);
// 714606955844629274884780.85120
let b = Decimal::from_parts(0, 0, 3873892070, false, 3873892070);
let b = Decimal::from_parts(0, 0, 3873892070, false, 5);
let c = a.checked_sub(b);
assert!(c.is_some());

@ -12,40 +12,41 @@ cargo_crate("lib") {
crate_name = "rust_decimal"
epoch = "1"
crate_type = "rlib"
crate_root = "//third_party/rust/chromium_crates_io/vendor/rust_decimal-1.36.0/src/lib.rs"
crate_root = "//third_party/rust/chromium_crates_io/vendor/rust_decimal-1.37.0/src/lib.rs"
sources = [
"//third_party/rust/chromium_crates_io/vendor/rust_decimal-1.36.0/src/arithmetic_impls.rs",
"//third_party/rust/chromium_crates_io/vendor/rust_decimal-1.36.0/src/constants.rs",
"//third_party/rust/chromium_crates_io/vendor/rust_decimal-1.36.0/src/decimal.rs",
"//third_party/rust/chromium_crates_io/vendor/rust_decimal-1.36.0/src/error.rs",
"//third_party/rust/chromium_crates_io/vendor/rust_decimal-1.36.0/src/fuzz.rs",
"//third_party/rust/chromium_crates_io/vendor/rust_decimal-1.36.0/src/lib.rs",
"//third_party/rust/chromium_crates_io/vendor/rust_decimal-1.36.0/src/maths.rs",
"//third_party/rust/chromium_crates_io/vendor/rust_decimal-1.36.0/src/mysql.rs",
"//third_party/rust/chromium_crates_io/vendor/rust_decimal-1.36.0/src/ops.rs",
"//third_party/rust/chromium_crates_io/vendor/rust_decimal-1.36.0/src/ops/add.rs",
"//third_party/rust/chromium_crates_io/vendor/rust_decimal-1.36.0/src/ops/array.rs",
"//third_party/rust/chromium_crates_io/vendor/rust_decimal-1.36.0/src/ops/cmp.rs",
"//third_party/rust/chromium_crates_io/vendor/rust_decimal-1.36.0/src/ops/common.rs",
"//third_party/rust/chromium_crates_io/vendor/rust_decimal-1.36.0/src/ops/div.rs",
"//third_party/rust/chromium_crates_io/vendor/rust_decimal-1.36.0/src/ops/legacy.rs",
"//third_party/rust/chromium_crates_io/vendor/rust_decimal-1.36.0/src/ops/mul.rs",
"//third_party/rust/chromium_crates_io/vendor/rust_decimal-1.36.0/src/ops/rem.rs",
"//third_party/rust/chromium_crates_io/vendor/rust_decimal-1.36.0/src/postgres.rs",
"//third_party/rust/chromium_crates_io/vendor/rust_decimal-1.36.0/src/postgres/common.rs",
"//third_party/rust/chromium_crates_io/vendor/rust_decimal-1.36.0/src/postgres/diesel.rs",
"//third_party/rust/chromium_crates_io/vendor/rust_decimal-1.36.0/src/postgres/driver.rs",
"//third_party/rust/chromium_crates_io/vendor/rust_decimal-1.36.0/src/proptest.rs",
"//third_party/rust/chromium_crates_io/vendor/rust_decimal-1.36.0/src/rand.rs",
"//third_party/rust/chromium_crates_io/vendor/rust_decimal-1.36.0/src/rocket.rs",
"//third_party/rust/chromium_crates_io/vendor/rust_decimal-1.36.0/src/serde.rs",
"//third_party/rust/chromium_crates_io/vendor/rust_decimal-1.36.0/src/str.rs",
"//third_party/rust/chromium_crates_io/vendor/rust_decimal-1.37.0/src/arithmetic_impls.rs",
"//third_party/rust/chromium_crates_io/vendor/rust_decimal-1.37.0/src/constants.rs",
"//third_party/rust/chromium_crates_io/vendor/rust_decimal-1.37.0/src/decimal.rs",
"//third_party/rust/chromium_crates_io/vendor/rust_decimal-1.37.0/src/error.rs",
"//third_party/rust/chromium_crates_io/vendor/rust_decimal-1.37.0/src/fuzz.rs",
"//third_party/rust/chromium_crates_io/vendor/rust_decimal-1.37.0/src/lib.rs",
"//third_party/rust/chromium_crates_io/vendor/rust_decimal-1.37.0/src/maths.rs",
"//third_party/rust/chromium_crates_io/vendor/rust_decimal-1.37.0/src/mysql.rs",
"//third_party/rust/chromium_crates_io/vendor/rust_decimal-1.37.0/src/ops.rs",
"//third_party/rust/chromium_crates_io/vendor/rust_decimal-1.37.0/src/ops/add.rs",
"//third_party/rust/chromium_crates_io/vendor/rust_decimal-1.37.0/src/ops/array.rs",
"//third_party/rust/chromium_crates_io/vendor/rust_decimal-1.37.0/src/ops/cmp.rs",
"//third_party/rust/chromium_crates_io/vendor/rust_decimal-1.37.0/src/ops/common.rs",
"//third_party/rust/chromium_crates_io/vendor/rust_decimal-1.37.0/src/ops/div.rs",
"//third_party/rust/chromium_crates_io/vendor/rust_decimal-1.37.0/src/ops/legacy.rs",
"//third_party/rust/chromium_crates_io/vendor/rust_decimal-1.37.0/src/ops/mul.rs",
"//third_party/rust/chromium_crates_io/vendor/rust_decimal-1.37.0/src/ops/rem.rs",
"//third_party/rust/chromium_crates_io/vendor/rust_decimal-1.37.0/src/postgres.rs",
"//third_party/rust/chromium_crates_io/vendor/rust_decimal-1.37.0/src/postgres/common.rs",
"//third_party/rust/chromium_crates_io/vendor/rust_decimal-1.37.0/src/postgres/diesel.rs",
"//third_party/rust/chromium_crates_io/vendor/rust_decimal-1.37.0/src/postgres/driver.rs",
"//third_party/rust/chromium_crates_io/vendor/rust_decimal-1.37.0/src/proptest.rs",
"//third_party/rust/chromium_crates_io/vendor/rust_decimal-1.37.0/src/rand.rs",
"//third_party/rust/chromium_crates_io/vendor/rust_decimal-1.37.0/src/rand_0_9.rs",
"//third_party/rust/chromium_crates_io/vendor/rust_decimal-1.37.0/src/rocket.rs",
"//third_party/rust/chromium_crates_io/vendor/rust_decimal-1.37.0/src/serde.rs",
"//third_party/rust/chromium_crates_io/vendor/rust_decimal-1.37.0/src/str.rs",
]
inputs = []
build_native_rust_unit_tests = false
edition = "2021"
cargo_pkg_version = "1.36.0"
cargo_pkg_version = "1.37.0"
cargo_pkg_authors = "Paul Mason <paul@form1.co.nz>"
cargo_pkg_name = "rust_decimal"
cargo_pkg_description = "Decimal number implementation written in pure Rust suitable for financial and fixed-precision calculations."
@ -60,9 +61,9 @@ cargo_crate("lib") {
"//third_party/rust/arrayvec/v0_7:lib",
"//third_party/rust/num_traits/v0_2:lib",
]
build_root = "//third_party/rust/chromium_crates_io/vendor/rust_decimal-1.36.0/build.rs"
build_root = "//third_party/rust/chromium_crates_io/vendor/rust_decimal-1.37.0/build.rs"
build_sources = [
"//third_party/rust/chromium_crates_io/vendor/rust_decimal-1.36.0/build.rs",
"//third_party/rust/chromium_crates_io/vendor/rust_decimal-1.37.0/build.rs",
]
build_script_outputs = [ "README-lib.md" ]
rustflags = [

@ -1,9 +1,9 @@
Name: rust_decimal
URL: https://crates.io/crates/rust_decimal
Version: 1.36.0
Revision: 38ab8254ad77e0a612f8eef8f12a2f7febee3ff8
Version: 1.37.0
Revision: ffe9495d7734d8021718050f98e3f48f39c428b2
License: MIT
License File: //third_party/rust/chromium_crates_io/vendor/rust_decimal-1.36.0/LICENSE
License File: //third_party/rust/chromium_crates_io/vendor/rust_decimal-1.37.0/LICENSE
Shipped: yes
Security Critical: yes