The and_then combinator performs a kind of bitwise and operation on two
Option types here. This is useful since the `checked` arithmetic
returns an option thereby accumulating Option types. Therefore, either
the checked arithmetic operation performs the addition of the unwrapped
accumulator, or it returns None.
Instead of using `and_then` use the provided `try_fold` method which
will short circuit on `None` when the checked arithmetic is used. Also,
simplify the staring condition using `Amount:ZERO` since this is
logically equivalent to using the first value if one exists.
Lastly, by using the built in `try_fold`, it's possible the performance
will be improved by making use of the short circuit ability instead of
evaluating each item even when the accumulator holds a None type.
We currently use the `NumOpResult` for operations involving more than
just amount types (e.g. `FeeRate`) however when the `result` module was
written we only used amount types.
To make the intention of the custom result types more clear introduce a
top level `result` module and move the general code there. Leave the
amount implementations in the `amount` module. Note that both `result`
modules are private.
Move the `OptionExt` impls because later we will add a bunch more of them.
Internal change only, no logic changes.
This private function is used for string-parsing an amount. It returns a
sign boolean and a u64, but its surrounding logic can be simplified if
it just returns a i64 (which is OK now since the range of `Amount` fits
into the range of i64).
Along the way we eliminate some instances of from_sat_unchecked.
Annoyingly we still need the bool to distinguish -0 from +0; when
parsing Amount we reject -0 (and we have tests for this).
This causes a couple error constructors to no longer be used outside of
unit tests. May be worth looking at whether we need them, or whether we
should be using them in parse_signed_to_satoshi.
Enforcing the MAX_MONEY invariant is quite involved because it means
multiple things:
- Constructing amounts is now fallible
- Converting from unsigned to signed is now infallible
- Taking the absolute value is now infallible
- Integer overflow is illuminated in various places
Details:
- Update from_sat to check the invariant
- Fix all docs including examples
- Use the unchecked constructor in test code
- Comment any other use of the unchecked constructor
- Deprecate unchecked_abs
- Fail serde (using the horrible string error variant)
- Try not to use the unchecked constructor in rustdocs, no need to encourage unsuspecting users to use it.
- Use ? in rustdoc examples (required by Rust API guidlines)
- Remove TryFrom<Amount> for SignedAmount because the conversion is now infallible. Add a From impl.
- Fix the arbitrary impls
- Maintain correct formatting
- Remove private check_max function as its no longer needed
Now that we have the `NumOpResult<Amount>` type that is used to show a
math calculation returned a valid amount we can use it when multiplying
weight and fee rates thus removing panics.
A public enum with simple variants gets an automatic integer variant
that can be cast by library consumers. This puts a unnecessary
maintenance burden upon us because we cannot then add variants in the
middle of others.
Add a hidden variant to the single public non-error enum in `units`.
We would like to return an error when doing math ops on amount types.
We cannot however use the stdlib `Result` or `Option` because we want to
implement ops on the result type.
Add an `AmountOpResult` type. Return this type from all math operations
on `Amount` and `SignedAmount`.
Implement `core::iter::Sum` for the new type to allow summing iterators
of amounts - somewhat ugly to use, see tests for example usage.
`µ` is the correct letter for the SI unit micro but is not on most
standard keyboards. `u` was used instead because it looks similar.
Add `µBTC` to the list of recognized strings for MicroBitcoin and to the
rustdocs.
Preemptively addressing these mutants before introducing the
cargo-mutants workflow
There are several types of changes:
- Changes that address mutants that were actually missing
- Changes that address test values that cause `cargo-mutants` to think
mutants were missed. For example, `cargo-mutants` will replace the
return values for unsigned integer types with 0 and 1. While a function
might be tested, the test might be testing the function with a call that
results in 0 or 1. When `cargo-mutants` substitutes the function call
with `Ok(1)`, the test will still pass, and it will consider this a
mutant. `cargo-mutants` also replaces operations (+, -, /, %), bitwise
operations (&, |, ^, etc), so an operation such as `3 - 2` results in a
mutant because changing it to `3 / 2` yields the same result
- TODOs to ignore functions/impls in the future
Rust macros, while at times useful, are a maintenance nightmare. And
we have been bitten by calling macros from other crates multiple times
in the past.
In a push to just use less macros remove the usage of the
`impl_from_infallible` macro in all the leaf crates and just write the
code.
The `untis::error` module is just a code organisation thing it should
never have been public. We already re-export all the error types and
this is verified by the `units/tests/api.rs` test file.
Make the module private and remove it from the paths in the `api` test.
04dfe8dd45 Add api test to check Arbitrary impls (Shing Him Ng)
678fc71b88 Implement Arbitrary for units types (Shing Him Ng)
Pull request description:
Implement Arbitrary for the rest of the types in `units`. Also moved the implementation in `FeeRate` right before the `tests` module
Closes#3705
ACKs for top commit:
apoelstra:
ACK 04dfe8dd45fae9b55dacfe9eb0d73ea306db14ba; successfully ran local tests
tcharding:
ACK 04dfe8dd45
Tree-SHA512: 156bd26d4de85d484711d476df1d2758805387125209f0307aa786dd1585ff9953dbe41b0864b00ae101419176647e3bde7994ed9257c18307d161463b1c8d2e
Add all the pedantic lints to the repository by way of the repository
manifest. Then enable these lints in the `units` manifest.
Some things worth mentioning:
- Fix `needless_pass_by_value` by adding derives to `FormatOptions`.
- Fix lint `cast_lossless` using `cargo clippy --fix``
- While fixing `lint enum_glob_use` introduce a new style to the
codebase; import enums using a single character. Doing so prevents
namespace clashes, improves clarity, and maintains terseness.
Audit:
Use the following lints locally and audit all the warnings, they produce
many false positives so we can't enable them permentently.
- `cast_possible_truncation`
- `cast_possible_lint`
- `cast_sign_loss`
60f2089dcd Clean up possibly confusing (Tobin C. Harding)
Pull request description:
Put the list of possibly confusing forms in the same order as the enum and fix the rustdocs to show the actual error variants returned.
ACKs for top commit:
apoelstra:
ACK 60f2089dcdd697b8ab53c9f96b2192ca030237ac; successfully ran local tests
Tree-SHA512: 109fd3e9b72860c3e2a1268aeafab30d6b2b6fac5d5835db6c216a434b9e175911e6445c187f6b80ab2d8c54184df9338230985a4e030aa146cd9fa410971216
There are two `private` modules in `amount` but they do slightly
different things. One provides a private `Token` and one is for trait
sealing. We have various other trait sealing modules in the codebase and
they are all called `sealed` not `private`. Also the seal trait is
called `Sealed`.
Rename the `private` module and the trait to be uniform with the rest of
the codebase.
Close the two pubic enum error types in `units::amounts`. All the other
structs are closed already because they either have private fields or
marked `non_exhaustive`.
In an effort to make the `amount` module more readable move the
`SignedAmount` type to a private submodule.
Re-export everything so this is not a breaking change.
Code move and re-exports only.
When we move `SignedAmount` to a submodule linking to `self` introduces
a clippy warning, I'm not exactly sure why but lets remove the link in
preparation for the move.
In an effort to make the `amount` module more readable move the `Amount`
type to a private submodule.
Re-export everything so this is not a breaking change.
Code move and re-exports only.
There is _a lot_ of error types in the `amount` module. Move them to a
separate `error` module.
Add a bunch of `pub(super)` to keep things private to the `amount`
module.
Eventually we will want to close all these errors.
In preparation for splitting the error types out of `amount.rs` into
their own file move the `amount.rs` file to `amount/mod.rs`.
File move only, no other changes.