js_int/lib.rs
1//! Crate `js_int` provides JavaScript-interoperable integer types.
2//!
3//! JavaScript does not have native integers. Instead it represents all numeric values with a
4//! single `Number` type which is represented as an [IEEE 754
5//! floating-point](https://en.wikipedia.org/wiki/IEEE_754) value.\* Rust's `i64` and `u64` types
6//! can contain values outside the range of what can be represented in a JavaScript `Number`.
7//!
8//! This crate provides the types `Int` and `UInt` which wrap `i64` and `u64`, respectively. These
9//! types add bounds checking to ensure the contained value is within the range representable by a
10//! JavaScript `Number`. They provide useful trait implementations to easily convert from Rust's
11//! primitive integer types.
12//!
13//! <small>* In the upcoming ECMAScript 2020, JavaScript will probably gain support for integers.
14//! There is a proposal for a [`BigInt`][mdn] type type that is not far from becoming part of the
15//! JavaScript specification. It won't make this crate obsolete in any way though, since there will
16//! still be lots of JS code using `Number`, and code in other languages that assumes its use.
17//! </small>
18//!
19//! [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt
20//!
21//! # `#![no_std]`
22//!
23//! The `js_int` crate does not use Rust's standard library, and is compatible with `#![no_std]`
24//! programs.
25//!
26//! # Features
27//!
28//! * `serde`: Serialization and deserialization support via [serde](https://serde.rs). Disabled by
29//! default. You can use `js_int` + `serde` in `#![no_std]` contexts if you use
30//! `default-features = false` for both.
31//! * `float_deserialize`: Deserialize via `f64`, not via `u64`. If the input has a fraction,
32//! deserialization will fail.
33//! * `lax_deserialize`: Like `float_deserialize`, but if the input has a fraction, it is
34//! deserialized with the fractional part discarded.
35//! Please be aware that `serde_json` doesn't losslessly parse large floats with a fractional part
36//! by default (even if the fractional part is `.0`). To fix that, enable its `float_roundtrip`
37//! feature.
38//! * `std`: Enable `std::error::Error` implementations for `ParseIntError`, `TryFromIntError`.
39//! Enabled by default.
40
41#![deny(missing_debug_implementations, missing_docs)]
42#![allow(clippy::cast_lossless)] // Not useful in this crate
43#![cfg_attr(not(feature = "std"), no_std)]
44
45#[macro_use]
46mod macros;
47mod error;
48mod int;
49mod uint;
50
51pub use self::{
52 error::{ParseIntError, TryFromIntError},
53 int::{Int, MAX_SAFE_INT, MIN_SAFE_INT},
54 uint::{UInt, MAX_SAFE_UINT},
55};
56
57#[cfg(feature = "float_deserialize")]
58#[inline(always)]
59pub(crate) fn is_acceptable_float(float: f64) -> bool {
60 #[cfg(not(feature = "lax_deserialize"))]
61 {
62 if float.fract() != 0.0 {
63 return false;
64 }
65 }
66
67 !float.is_nan()
68}