Expand description
Rust uint
crate using const-generics
Implements Uint<BITS, LIMBS>
, the ring of numbers modulo $2^{\mathsf{BITS}}$. It requires two
generic arguments: the number of bits and the number of 64-bit ‘limbs’ required to store those bits.
let answer: Uint<256, 4> = Uint::from(42);
You can compute LIMBS
yourself using $\mathsf{LIMBS} = \left\lceil{\mathsf{BITS} / 64}\right\rceil$,
i.e.LIMBS
equals BITS
divided by $64$ rounded up. Uint
will panic!
if you try to
construct it with incorrect arguments. Ideally this would be a compile time error, but
that is blocked by Rust issue #60551.
A more convenient method on stable is to use the uint!
macro, which constructs the right
Uint
for you.
let answer = uint!(42_U256);
You can also use one of the pre-computed type aliases
:
use ruint2::aliases::*;
let answer: U256 = Uint::from(42);
You can of course also create your own type alias if you need a funny size:
type U1337 = Uint<1337, 21>;
let answer: U1337 = Uint::from(42);
Rust nightly
If you are on nightly, you can use Uint<BITS>
which will
compute the number of limbs for you. Unfortunately this can not be made stable
without generic_const_exprs
support (Rust issue #76560).
use ruint2::nightly::Uint;
let answer: Uint<256> = Uint::<256>::from(42);
Even on nightly, the ergonomics of Rust are limited. In the example above Rust
requires explicit type annotation for Uint::from
, where it did not require
it in the stable version. There are a few more subtle issues that make this
less ideal than it appears. It also looks like it may take some time before
these nightly features are stabilized.
Examples
use ruint2::Uint;
let a: Uint<256, 4> = Uint::from(0xf00f_u64);
let b: Uint<256, 4> = Uint::from(42_u64);
let c = a + b;
assert_eq!(c, Uint::from(0xf039_u64));
There is a convenient macro uint!
to create constants for you. It allows
for arbitrary length constants using standard Rust integer syntax. The size of
the Uint
or Bits
is specified with a U
or B
suffix followed by the
number of bits. The standard Rust syntax of decimal, hexadecimal and even binary and octal is
supported using their prefixes 0x
, 0b
and 0o
. Literals can have
underscores _
added for readability.
let cow = uint!(0xc85ef7d79691fe79573b1a7064c19c1a9819ebdbd1faaab1a8ec92344438aaf4_U256);
In fact, this macro recurses down the parse tree, so you can apply it to entire source files:
uint!{
let a = 42_U256;
let b = 0xf00f_1337_c0d3_U256;
let c = a + b;
assert_eq!(c, 263947537596669_U256);
}
Note that since B
is a valid hexadecimal digit there can be ambiguity. To lessen the impact an underscore separator _B
is required in this case.
Feature flags
There is support for a number of crates. These are enabled by setting the identically named feature flag.
unstable
Enable sem-ver unstable features.rand
: Implements sampling from theStandard
distribution, i.e.rng.gen()
.arbitrary
: Implements theArbitrary
trait, allowingUint
s to be generated for fuzz testing.quickcheck
: Implements theArbitrary
trait, allowingUint
s to be generated for property based testing.proptest
: Implements theArbitrary
trait, allowingUint
s to be generated for property based testing. Proptest is used for theuint
s own test suite.serde
: Implements theSerialize
andDeserialize
traits forUint
andBits
.Serialization uses big-endian hex in human readable formats and big-endian byte strings in machine readable formats.Uint
uses ethereumQuantity
format (0x-prefixed minimal string) when serializing in a human readable format.rlp
: Implements theEncodable
andDecodable
traits forUint
to allow serialization to/from RLP.fastrlp
: Implements theEncodable
andDecodable
traits forUint
to allow serialization to/from RLP.primitive-types
: Implements theFrom<_>
conversions between corresponding types.postgres
: Implements theToSql
trait supporting many column types.num-bigint
: Implements conversion to/fromBigUint
andBigInt
.ark-ff
: Implements conversion to/fromBigInt
andFp
types.sqlx
: Implements database agnostic storage as byte array. Requiressqlx
to be used with thetokio-native-tls
runtime, due to issue sqlx#1627.zeroize
: Implements theZeroize
trait. This makesUint
andBits
compatible with thesecrecy
crate.valuable
: Implements theValuable
trait.pyo3
: Implements theToPyObject
,IntoPy
andFromPyObject
traits.parity-scale-codec
: Implements theEncode
,Decode
,MaxEncodedLen
andHasCompact
traits.bn-rs
: Implements conversion to/from theBN
andBigNumber
.
Building and testing
Format, lint, build and test everything (I recommend creating a shell alias for this):
cargo fmt &&\
cargo clippy --all-features --all-targets &&\
cargo test --workspace --all-features --doc -- --nocapture &&\
cargo test --workspace --all-features --all-targets -- --nocapture &&\
cargo doc --workspace --all-features --no-deps
Run benchmarks with the provided .cargo/config.toml
alias
cargo criterion
Check documentation coverage
RUSTDOCFLAGS="-Z unstable-options --show-coverage" cargo doc --workspace --all-features --no-deps
Features
- All the quality of life features one could want.
- Compatible with std
u64
, etc types. See Rust’s integer methods. - Adhere to Rust API Guidelines
- Montgomery REDC and other algo’s for implementing prime fields.
To do
- Builds
no-std
andwasm
. - Fast platform agnostic generic algorithms.
- Target specific assembly optimizations (where available).
- Optional num-traits, etc, support.
- Run-time sized type with compatible interface.
Modules
- ⚠️ Collection of bignum algorithms.
- Extra features that are nightly only.
Macros
- Compile time for loops with a
const
variable for testing. - The
uint!
macro forUint
andBits
literals
Structs
- A newtype wrapper around
Uint
that restricts operations to those relevant for bit arrays. - The ring of numbers modulo $2^{\mathtt{BITS}}$.
Enums
- Error for
from_base_le
andfrom_base_be
. - Error for
TryFrom<Uint>
. - Error for
from_str_radix
. - Error for
TryFrom<Uint>
forark_ff
and others. - Error for
TryFrom<T>
forUint
.
Traits
- ⚠️ Workaround for Rust issue #50133. Use
TryFrom
instead. - ⚠️ Workaround for Rust issue #50133. Use
TryFrom
instead.
Functions
- Number of bytes required to represent the given number of bits.
- Number of
u64
limbs required to represent the given number of bits. This needs to be public because it is used in theUint
type.