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:

committed by
Chromium LUCI CQ

parent
0fd3717f03
commit
12e6ddd0d6
infra
third_party/rust
chromium_crates_io
Cargo.lock
supply-chain
vendor
rust_decimal-1.36.0
rust_decimal-1.37.0
.buildnumber.cargo-checksum.json.gitignoreBUILD.mdCHANGELOG.mdCODE_OF_CONDUCT.mdCONTRIBUTING.mdCargo.lockCargo.tomlCargo.toml.origLICENSEMakefile.tomlREADME.md
.cargo
.cargo_vcs_info.json.editorconfig.github
workflows
benches
build.rsexamples
make
rustfmt.tomlsrc
arithmetic_impls.rsconstants.rsdecimal.rserror.rsfuzz.rslib.rsmaths.rsmysql.rsops.rs
ops
postgres.rspostgres
proptest.rsrand.rsrand_0_9.rsrocket.rsserde.rsstr.rstests
rust_decimal
@ -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
|
||||
|
2
third_party/rust/chromium_crates_io/Cargo.lock
generated
vendored
2
third_party/rust/chromium_crates_io/Cargo.lock
generated
vendored
@ -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": ""
|
||||
}
|
@ -1,3 +1,3 @@
|
||||
1
|
||||
36
|
||||
37
|
||||
0
|
6
third_party/rust/chromium_crates_io/vendor/rust_decimal-1.37.0/.cargo_vcs_info.json
vendored
Normal file
6
third_party/rust/chromium_crates_io/vendor/rust_decimal-1.37.0/.cargo_vcs_info.json
vendored
Normal file
@ -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
|
3169
third_party/rust/chromium_crates_io/vendor/rust_decimal-1.37.0/Cargo.lock
generated
vendored
Normal file
3169
third_party/rust/chromium_crates_io/vendor/rust_decimal-1.37.0/Cargo.lock
generated
vendored
Normal file
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"]
|
27
third_party/rust/chromium_crates_io/vendor/rust_decimal-1.36.0/Cargo.toml.orig → third_party/rust/chromium_crates_io/vendor/rust_decimal-1.37.0/Cargo.toml.orig
generated
vendored
27
third_party/rust/chromium_crates_io/vendor/rust_decimal-1.36.0/Cargo.toml.orig → third_party/rust/chromium_crates_io/vendor/rust_decimal-1.37.0/Cargo.toml.orig
generated
vendored
@ -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.
|
35
third_party/rust/chromium_crates_io/vendor/rust_decimal-1.37.0/examples/rkyv-remote.rs
vendored
Normal file
35
third_party/rust/chromium_crates_io/vendor/rust_decimal-1.37.0/examples/rkyv-remote.rs
vendored
Normal file
@ -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("ient) {
|
||||
while final_scale > Decimal::MAX_SCALE && !is_all_zero("ient) {
|
||||
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));
|
178
third_party/rust/chromium_crates_io/vendor/rust_decimal-1.37.0/src/rand_0_9.rs
vendored
Normal file
178
third_party/rust/chromium_crates_io/vendor/rust_decimal-1.37.0/src/rand_0_9.rs
vendored
Normal file
@ -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());
|
||||
|
61
third_party/rust/rust_decimal/v1/BUILD.gn
vendored
61
third_party/rust/rust_decimal/v1/BUILD.gn
vendored
@ -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
|
||||
|
||||
|
Reference in New Issue
Block a user