commit 7236333e9cb43b71b9605326d1612f6c7ba723e1
parent 1043f8f1846579fbfc853bee5494d00d9cf959e7
Author: Zack Newman <zack@philomathiclife.com>
Date: Fri, 20 Mar 2026 15:13:21 -0600
update deps and lints. address new deps and lints
Diffstat:
| M | Cargo.toml | | | 178 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------------- |
| M | README.md | | | 12 | +++++++----- |
| M | src/cache.rs | | | 114 | ++++++++++++++++++++++++++++++++++++++++++++----------------------------------- |
| M | src/lib.rs | | | 2777 | ++++++++++++++++++++++++++++++++++++------------------------------------------- |
| M | src/main.rs | | | 16 | +++++++--------- |
5 files changed, 1467 insertions(+), 1630 deletions(-)
diff --git a/Cargo.toml b/Cargo.toml
@@ -9,8 +9,8 @@ license = "MIT OR Apache-2.0"
name = "calc_rational"
readme = "README.md"
repository = "https://git.philomathiclife.com/repos/calc_rational/"
-rust-version = "1.87.0"
-version = "2.4.1"
+rust-version = "1.93.1"
+version = "3.0.0"
[lib]
name = "calc_lib"
@@ -19,58 +19,108 @@ path = "src/lib.rs"
[[bin]]
name = "calc"
path = "src/main.rs"
+required-features = ["std"]
[lints.rust]
-ambiguous_negative_literals = { level = "deny", priority = -1 }
-closure_returning_async_block = { level = "deny", priority = -1 }
-deprecated_safe = { level = "deny", priority = -1 }
-deref_into_dyn_supertrait = { level = "deny", priority = -1 }
-ffi_unwind_calls = { level = "deny", priority = -1 }
-future_incompatible = { level = "deny", priority = -1 }
-#fuzzy_provenance_casts = { level = "deny", priority = -1 }
-impl_trait_redundant_captures = { level = "deny", priority = -1 }
-keyword_idents = { level = "deny", priority = -1 }
-let_underscore = { level = "deny", priority = -1 }
-#linker_messages = { level = "deny", priority = -1 }
-#lossy_provenance_casts = { level = "deny", priority = -1 }
-macro_use_extern_crate = { level = "deny", priority = -1 }
-meta_variable_misuse = { level = "deny", priority = -1 }
-missing_copy_implementations = { level = "deny", priority = -1 }
-missing_debug_implementations = { level = "deny", priority = -1 }
-missing_docs = { level = "deny", priority = -1 }
-#multiple_supertrait_upcastable = { level = "deny", priority = -1 }
-#must_not_suspend = { level = "deny", priority = -1 }
-non_ascii_idents = { level = "deny", priority = -1 }
-#non_exhaustive_omitted_patterns = { level = "deny", priority = -1 }
-nonstandard_style = { level = "deny", priority = -1 }
-redundant_imports = { level = "deny", priority = -1 }
-redundant_lifetimes = { level = "deny", priority = -1 }
-refining_impl_trait = { level = "deny", priority = -1 }
-rust_2018_compatibility = { level = "deny", priority = -1 }
-rust_2018_idioms = { level = "deny", priority = -1 }
-rust_2021_compatibility = { level = "deny", priority = -1 }
-rust_2024_compatibility = { level = "deny", priority = -1 }
-single_use_lifetimes = { level = "deny", priority = -1 }
-#supertrait_item_shadowing_definition = { level = "deny", priority = -1 }
-trivial_casts = { level = "deny", priority = -1 }
-trivial_numeric_casts = { level = "deny", priority = -1 }
-unit_bindings = { level = "deny", priority = -1 }
-unnameable_types = { level = "deny", priority = -1 }
-#unqualified_local_imports = { level = "deny", priority = -1 }
-unreachable_pub = { level = "deny", priority = -1 }
-unsafe_code = { level = "deny", priority = -1 }
-unstable_features = { level = "deny", priority = -1 }
+deprecated-safe = { level = "deny", priority = -1 }
+future-incompatible = { level = "deny", priority = -1 }
+keyword-idents = { level = "deny", priority = -1 }
+let-underscore = { level = "deny", priority = -1 }
+nonstandard-style = { level = "deny", priority = -1 }
+refining-impl-trait = { level = "deny", priority = -1 }
+rust-2018-compatibility = { level = "deny", priority = -1 }
+rust-2018-idioms = { level = "deny", priority = -1 }
+rust-2021-compatibility = { level = "deny", priority = -1 }
+rust-2024-compatibility = { level = "deny", priority = -1 }
+unknown-or-malformed-diagnostic-attributes = { level = "deny", priority = -1 }
unused = { level = "deny", priority = -1 }
-unused_crate_dependencies = { level = "deny", priority = -1 }
-unused_import_braces = { level = "deny", priority = -1 }
-unused_lifetimes = { level = "deny", priority = -1 }
-unused_qualifications = { level = "deny", priority = -1 }
-unused_results = { level = "deny", priority = -1 }
-variant_size_differences = { level = "deny", priority = -1 }
warnings = { level = "deny", priority = -1 }
+ambiguous-negative-literals = { level = "deny", priority = -1 }
+closure-returning-async-block = { level = "deny", priority = -1 }
+deprecated-in-future = { level = "deny", priority = -1 }
+deref-into-dyn-supertrait = { level = "deny", priority = -1 }
+ffi-unwind-calls = { level = "deny", priority = -1 }
+#fuzzy-provenance-casts = { level = "deny", priority = -1 }
+impl-trait-redundant-captures = { level = "deny", priority = -1 }
+linker-messages = { level = "deny", priority = -1 }
+#lossy-provenance-casts = { level = "deny", priority = -1 }
+macro-use-extern-crate = { level = "deny", priority = -1 }
+meta-variable-misuse = { level = "deny", priority = -1 }
+missing-copy-implementations = { level = "deny", priority = -1 }
+missing-debug-implementations = { level = "deny", priority = -1 }
+missing-docs = { level = "deny", priority = -1 }
+#multiple-supertrait-upcastable = { level = "deny", priority = -1 }
+#must-not-suspend = { level = "deny", priority = -1 }
+non-ascii-idents = { level = "deny", priority = -1 }
+#non-exhaustive-omitted-patterns = { level = "deny", priority = -1 }
+redundant-imports = { level = "deny", priority = -1 }
+redundant-lifetimes = { level = "deny", priority = -1 }
+#resolving-to-items-shadowing-supertrait-items = { level = "deny", priority = -1 }
+#shadowing-supertrait-items = { level = "deny", priority = -1 }
+single-use-lifetimes = { level = "deny", priority = -1 }
+trivial-casts = { level = "deny", priority = -1 }
+trivial-numeric-casts = { level = "deny", priority = -1 }
+unit-bindings = { level = "deny", priority = -1 }
+unnameable-types = { level = "deny", priority = -1 }
+#unqualified-local-imports = { level = "deny", priority = -1 }
+unreachable-pub = { level = "deny", priority = -1 }
+unsafe-code = { level = "deny", priority = -1 }
+unstable-features = { level = "deny", priority = -1 }
+unused-crate-dependencies = { level = "deny", priority = -1 }
+unused-import-braces = { level = "deny", priority = -1 }
+unused-lifetimes = { level = "deny", priority = -1 }
+unused-qualifications = { level = "deny", priority = -1 }
+unused-results = { level = "deny", priority = -1 }
+variant-size-differences = { level = "deny", priority = -1 }
+# Before publishing to crates.io, comment above and uncomment below.
+#warnings = { level = "allow", priority = -1 }
+#ambiguous-associated-items = { level = "allow", priority = -1 }
+#arithmetic-overflow = { level = "allow", priority = -1 }
+#binary-asm-labels = { level = "allow", priority = -1 }
+#bindings-with-variant-name = { level = "allow", priority = -1 }
+#conflicting-repr-hints = { level = "allow", priority = -1 }
+#dangerous-implicit-autorefs = { level = "allow", priority = -1 }
+#default-overrides-default-fields = { level = "allow", priority = -1 }
+#dependency-on-unit-never-type-fallback = { level = "allow", priority = -1 }
+#deref-nullptr = { level = "allow", priority = -1 }
+#elided-lifetimes-in-associated-constant = { level = "allow", priority = -1 }
+#enum-intrinsics-non-enums = { level = "allow", priority = -1 }
+#explicit-builtin-cfgs-in-flags = { level = "allow", priority = -1 }
+#ill-formed-attribute-input = { level = "allow", priority = -1 }
+#incomplete-include = { level = "allow", priority = -1 }
+#ineffective-unstable-trait-impl = { level = "allow", priority = -1 }
+#invalid-atomic-ordering = { level = "allow", priority = -1 }
+#invalid-from-utf8-unchecked = { level = "allow", priority = -1 }
+#invalid-macro-export-arguments = { level = "allow", priority = -1 }
+#invalid-null-arguments = { level = "allow", priority = -1 }
+#invalid-reference-casting = { level = "allow", priority = -1 }
+#invalid-type-param-default = { level = "allow", priority = -1 }
+#legacy-derive-helpers = { level = "allow", priority = -1 }
+#let-underscore-lock = { level = "allow", priority = -1 }
+#long-running-const-eval = { level = "allow", priority = -1 }
+#macro-expanded-macro-exports-accessed-by-absolute-paths = { level = "allow", priority = -1 }
+#mutable-transmutes = { level = "allow", priority = -1 }
+#named-asm-labels = { level = "allow", priority = -1 }
+#never-type-fallback-flowing-into-unsafe = { level = "allow", priority = -1 }
+#no-mangle-const-items = { level = "allow", priority = -1 }
+#out-of-scope-macro-calls = { level = "allow", priority = -1 }
+#overflowing-literals = { level = "allow", priority = -1 }
+#patterns-in-fns-without-body = { level = "allow", priority = -1 }
+#proc-macro-derive-resolution-fallback = { level = "allow", priority = -1 }
+#pub-use-of-private-extern-crate = { level = "allow", priority = -1 }
+#repr-transparent-non-zst-fields = { level = "allow", priority = -1 }
+#semicolon-in-expressions-from-macros = { level = "allow", priority = -1 }
+#soft-unstable = { level = "allow", priority = -1 }
+#test-unstable-lint = { level = "allow", priority = -1 }
+#text-direction-codepoint-in-comment = { level = "allow", priority = -1 }
+#text-direction-codepoint-in-literal = { level = "allow", priority = -1 }
+#unconditional-panic = { level = "allow", priority = -1 }
+#undropped-manually-drops = { level = "allow", priority = -1 }
+#unknown-crate-types = { level = "allow", priority = -1 }
+#useless-deprecated = { level = "allow", priority = -1 }
+# Before publishing to crates.io, comment below.
[lints.clippy]
-all = { level = "deny", priority = -1 }
cargo = { level = "deny", priority = -1 }
complexity = { level = "deny", priority = -1 }
correctness = { level = "deny", priority = -1 }
@@ -91,30 +141,47 @@ pub_use = "allow"
question_mark_used = "allow"
ref_patterns = "allow"
return_and_then = "allow"
+semicolon_outside_block = "allow"
single_call_fn = "allow"
single_char_lifetime_names = "allow"
unseparated_literal_suffix = "allow"
+[lints.rustdoc]
+# Before publishing to crates.io, comment below and uncomment below that.
+all = { level = "deny", priority = -1 }
+#all = "allow"
+
[package.metadata.docs.rs]
all-features = true
-rustdoc-args = ["--cfg", "docsrs"]
+default-target = "x86_64-unknown-linux-gnu"
+targets = [
+ "aarch64-apple-darwin",
+ "aarch64-pc-windows-msvc",
+ "aarch64-unknown-linux-gnu",
+ "i686-pc-windows-msvc",
+ "i686-unknown-linux-gnu",
+ "x86_64-pc-windows-gnu",
+ "x86_64-pc-windows-msvc",
+ "x86_64-unknown-freebsd",
+ "x86_64-unknown-linux-musl",
+ "x86_64-unknown-netbsd"
+]
[dependencies]
num-bigint = { version = "0.4.6", default-features = false }
num-integer = { version = "0.1.46", default-features = false }
num-rational = { version = "0.4.2", default-features = false, features = ["num-bigint"] }
num-traits = { version = "0.2.19", default-features = false }
-priv_sep = { version = "3.0.0-alpha.1.3", default-features = false, optional = true }
-rand = { version = "0.9.2", default-features = false, features = ["thread_rng"], optional = true }
+rand = { version = "0.10.0", default-features = false, features = ["thread_rng"], optional = true }
+
+[target.'cfg(target_os = "openbsd")'.dependencies]
+priv_sep = { version = "3.0.0-alpha.5.0", default-features = false }
### FEATURES #################################################################
[features]
-default = ["priv_sep"]
-
-# Provide pledge and unveil for OpenBSD.
-priv_sep = ["dep:priv_sep", "std"]
+default = ["rand"]
# Provide random functions.
rand = ["dep:rand", "std"]
@@ -123,6 +190,7 @@ rand = ["dep:rand", "std"]
std = []
[profile.release]
+codegen-units = 1
lto = true
panic = 'abort'
strip = true
diff --git a/README.md b/README.md
@@ -188,11 +188,13 @@ at your option.
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you,
as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.
-Before any PR is sent, `cargo clippy` and `cargo t` should be run _for each possible combination of "features"_
-using stable Rust. One easy way to achieve this is by building `ci` and invoking it with no commands in the
-`calc_rational` directory or sub-directories. You can fetch `ci` via `git clone https://git.philomathiclife.com/repos/ci`,
-and it can be built with `cargo build --release`. Additionally,
-`RUSTDOCFLAGS="--cfg docsrs" cargo +nightly doc --all-features` should be run to ensure documentation can be built.
+Before any PR is sent, `cargo clippy --all-targets`, `cargo test --all-targets -- --include-ignored`, and
+`cargo test --doc` should be run _for each possible combination of "features"_ using the stable and MSRV toolchains.
+One easy way to achieve this is by invoking [`ci-cargo`](https://crates.io/crates/ci-cargo) as
+`ci-cargo clippy --all-targets test --all-targets --include-ignored` in the `calc_rational` directory.
+
+Last, `RUSTDOCFLAGS="--cfg docsrs" cargo +nightly doc --all-features` should be run to ensure documentation can be
+built.
### Status
diff --git a/src/cache.rs b/src/cache.rs
@@ -178,7 +178,7 @@ where
mod tests {
use super::Cache;
#[test]
- fn test_len() {
+ fn len() {
let mut c = Cache::<bool, 1>::new();
assert_eq!(0, c.len());
c.push(false);
@@ -187,65 +187,66 @@ mod tests {
assert_eq!(1, c.len());
}
#[test]
- fn test_is_empty() {
+ fn is_empty() {
let mut c = Cache::<bool, 1>::new();
assert!(c.is_empty());
c.push(false);
assert!(!c.is_empty());
}
+ #[expect(clippy::cognitive_complexity, reason = "a lot to test")]
#[test]
- fn test_get() {
+ fn get() {
let mut c = Cache::<bool, 4>::new();
- assert!(c.get(0).is_none());
- assert!(c.get(1).is_none());
- assert!(c.get(2).is_none());
- assert!(c.get(3).is_none());
- assert!(c.get(4).is_none());
- assert!(c.get(5).is_none());
- assert!(c.get(usize::MAX).is_none());
+ assert_eq!(c.get(0), None);
+ assert_eq!(c.get(1), None);
+ assert_eq!(c.get(2), None);
+ assert_eq!(c.get(3), None);
+ assert_eq!(c.get(4), None);
+ assert_eq!(c.get(5), None);
+ assert_eq!(c.get(usize::MAX), None);
c.push(true);
- assert!(c.get(0).unwrap());
- assert!(c.get(1).is_none());
- assert!(c.get(2).is_none());
- assert!(c.get(3).is_none());
- assert!(c.get(4).is_none());
- assert!(c.get(5).is_none());
- assert!(c.get(usize::MAX).is_none());
+ assert_eq!(c.get(0), Some(&true));
+ assert_eq!(c.get(1), None);
+ assert_eq!(c.get(2), None);
+ assert_eq!(c.get(3), None);
+ assert_eq!(c.get(4), None);
+ assert_eq!(c.get(5), None);
+ assert_eq!(c.get(usize::MAX), None);
c.push(false);
- assert!(!c.get(0).unwrap());
- assert!(c.get(1).unwrap());
- assert!(c.get(2).is_none());
- assert!(c.get(3).is_none());
- assert!(c.get(4).is_none());
- assert!(c.get(5).is_none());
- assert!(c.get(usize::MAX).is_none());
+ assert_eq!(c.get(0), Some(&false));
+ assert_eq!(c.get(1), Some(&true));
+ assert_eq!(c.get(2), None);
+ assert_eq!(c.get(3), None);
+ assert_eq!(c.get(4), None);
+ assert_eq!(c.get(5), None);
+ assert_eq!(c.get(usize::MAX), None);
c.push(false);
- assert!(!c.get(0).unwrap());
- assert!(!c.get(1).unwrap());
- assert!(c.get(2).unwrap());
- assert!(c.get(3).is_none());
- assert!(c.get(4).is_none());
- assert!(c.get(5).is_none());
- assert!(c.get(usize::MAX).is_none());
+ assert_eq!(c.get(0), Some(&false));
+ assert_eq!(c.get(1), Some(&false));
+ assert_eq!(c.get(2), Some(&true));
+ assert_eq!(c.get(3), None);
+ assert_eq!(c.get(4), None);
+ assert_eq!(c.get(5), None);
+ assert_eq!(c.get(usize::MAX), None);
c.push(true);
- assert!(c.get(0).unwrap());
- assert!(!c.get(1).unwrap());
- assert!(!c.get(2).unwrap());
- assert!(c.get(3).unwrap());
- assert!(c.get(4).is_none());
- assert!(c.get(5).is_none());
- assert!(c.get(usize::MAX).is_none());
+ assert_eq!(c.get(0), Some(&true));
+ assert_eq!(c.get(1), Some(&false));
+ assert_eq!(c.get(2), Some(&false));
+ assert_eq!(c.get(3), Some(&true));
+ assert_eq!(c.get(4), None);
+ assert_eq!(c.get(5), None);
+ assert_eq!(c.get(usize::MAX), None);
c.push(true);
- assert!(c.get(0).unwrap());
- assert!(c.get(1).unwrap());
- assert!(!c.get(2).unwrap());
- assert!(!c.get(3).unwrap());
- assert!(c.get(4).is_none());
- assert!(c.get(5).is_none());
- assert!(c.get(usize::MAX).is_none());
+ assert_eq!(c.get(0), Some(&true));
+ assert_eq!(c.get(1), Some(&true));
+ assert_eq!(c.get(2), Some(&false));
+ assert_eq!(c.get(3), Some(&false));
+ assert_eq!(c.get(4), None);
+ assert_eq!(c.get(5), None);
+ assert_eq!(c.get(usize::MAX), None);
}
#[test]
- fn test_get_unsafe() {
+ fn get_unsafe() {
let mut c = Cache::<bool, 4>::new();
assert!(!c.get_unchecked(0));
assert!(!c.get_unchecked(1));
@@ -259,36 +260,47 @@ mod tests {
assert!(!c.get_unchecked(3));
assert!(c.get_unchecked(4));
}
+ #[expect(clippy::indexing_slicing, reason = "comment justifies correctness")]
#[test]
- fn test_index() {
+ fn index() {
let mut c = Cache::<bool, 4>::new();
c.push(true);
+ // `c.len() > 0`.
assert!(c[0]);
}
+ #[expect(clippy::indexing_slicing, reason = "comment justifies correctness")]
#[test]
- #[should_panic]
- fn test_index_panic() {
+ #[should_panic(expected = "called `Option::unwrap()` on a `None` value")]
+ fn index_panic() {
let c = Cache::<bool, 4>::new();
+ // `c.len() > 0`.
assert!(c[0]);
}
+ #[expect(clippy::indexing_slicing, reason = "comments justify correctness")]
#[test]
- fn test_push() {
+ fn push() {
let mut c = Cache::<bool, 4>::new();
c.push(true);
+ // `c.len() > 0`.
assert!(c[0]);
c.push(true);
+ // `c.len() > 0`.
assert!(c[0]);
c.push(false);
+ // `c.len() > 0`.
assert!(!c[0]);
c.push(true);
+ // `c.len() > 0`.
assert!(c[0]);
c.push(false);
+ // `c.len() > 0`.
assert!(!c[0]);
c.push(false);
+ // `c.len() > 0`.
assert!(!c[0]);
}
#[test]
- fn test_new() {
+ fn new() {
_ = Cache::<bool, 0>::new();
_ = Cache::<bool, 32>::new();
_ = Cache::<bool, 31>::new();
diff --git a/src/lib.rs b/src/lib.rs
@@ -111,6 +111,10 @@
//! For a more precise specification of the “calc language”, one can read the
//! [calc language specification](https://git.philomathiclife.com/calc_rational/lang.pdf).
#![expect(
+ clippy::doc_paragraphs_missing_punctuation,
+ reason = "false positive for crate documentation having image links"
+)]
+#![expect(
clippy::arithmetic_side_effects,
reason = "calculator can't realistically avoid this"
)]
@@ -144,13 +148,12 @@ use num_rational::Ratio;
#[cfg(feature = "rand")]
use num_traits::ToPrimitive as _;
use num_traits::{Inv as _, Pow as _};
-#[cfg(feature = "priv_sep")]
+#[cfg(target_os = "openbsd")]
use priv_sep as _;
-#[cfg_attr(docsrs, doc(cfg(feature = "rand")))]
#[cfg(feature = "rand")]
pub use rand;
#[cfg(feature = "rand")]
-use rand::{RngCore as _, rngs::ThreadRng};
+use rand::{Rng as _, rngs::ThreadRng};
/// Fixed-sized cache that automatically overwrites the oldest data
/// when a new item is added and the cache is full.
///
@@ -163,6 +166,7 @@ pub mod cache;
pub mod lending_iterator;
/// Error due to a language violation.
#[non_exhaustive]
+#[cfg_attr(test, derive(Eq, PartialEq))]
#[derive(Debug)]
pub enum LangErr {
/// The input began with a `q` but had non-whitespace
@@ -217,15 +221,12 @@ pub enum LangErr {
/// by symbols that could not be chained with the preceding expression.
TrailingSyms(usize),
/// The input contained an invalid random expression.
- #[cfg_attr(docsrs, doc(cfg(feature = "rand")))]
#[cfg(feature = "rand")]
InvalidRand(usize),
/// Error when the second argument is less than first in the rand function.
- #[cfg_attr(docsrs, doc(cfg(feature = "rand")))]
#[cfg(feature = "rand")]
RandInvalidArgs(usize),
/// Error when there are no 64-bit integers in the interval passed to the random function.
- #[cfg_attr(docsrs, doc(cfg(feature = "rand")))]
#[cfg(feature = "rand")]
RandNoInts(usize),
}
@@ -262,6 +263,7 @@ impl Display for LangErr {
}
}
/// A successful evaluation of an input.
+#[cfg_attr(test, derive(Eq, PartialEq))]
#[derive(Debug)]
pub enum O<'a> {
/// The input only contained whitespace.
@@ -402,6 +404,7 @@ pub struct Evaluator<'input, 'cache, 'prev, 'scratch, 'rand> {
/// Random number generator.
#[cfg(feature = "rand")]
rng: &'rand mut ThreadRng,
+ /// Need to use `'rand`.
#[cfg(not(feature = "rand"))]
_rng: PhantomData<fn() -> &'rand ()>,
}
@@ -1136,7 +1139,6 @@ impl<'input, 'cache, 'prev, 'scratch, 'rand> Evaluator<'input, 'cache, 'prev, 's
}
}
/// Reads data from `R` passing each line to an [`Evaluator`] to be evaluated.
-#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
#[cfg(feature = "std")]
#[derive(Debug)]
pub struct EvalIter<R> {
@@ -1156,11 +1158,9 @@ pub struct EvalIter<R> {
#[cfg(feature = "rand")]
rng: ThreadRng,
}
-#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
#[cfg(feature = "std")]
impl<R> EvalIter<R> {
/// Creates a new `EvalIter`.
- #[cfg_attr(docsrs, doc(cfg(feature = "rand")))]
#[cfg(feature = "rand")]
#[inline]
pub fn new(reader: R) -> Self {
@@ -1191,7 +1191,6 @@ extern crate std;
#[cfg(feature = "std")]
use std::io::{BufRead, Error};
/// Error returned from [`EvalIter`] when an expression has an error.
-#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
#[cfg(feature = "std")]
#[derive(Debug)]
pub enum E {
@@ -1215,7 +1214,6 @@ impl Display for E {
}
#[cfg(feature = "std")]
use crate::lending_iterator::LendingIterator;
-#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
#[cfg(feature = "std")]
impl<R> LendingIterator for EvalIter<R>
where
@@ -1260,21 +1258,42 @@ where
}
#[cfg(test)]
mod tests {
- use super::*;
+ use super::{
+ BigInt, BigUint, Cache, Evaluator,
+ LangErr::MissingTerm,
+ O::{Empty, Eval, Store},
+ Sign, Vec, vec,
+ };
+ #[cfg(feature = "rand")]
+ use super::{BufRead, E, EvalIter, LangErr, LendingIterator as _};
+ #[cfg(not(feature = "rand"))]
+ use super::{
+ LangErr::{
+ DivByZero, ExpDivByZero, ExpIsNotIntOrOneHalf, InvalidAbs, InvalidDec, InvalidPar,
+ InvalidQuit, InvalidRound, InvalidStore, ModIsNotInt, ModZero, NotEnoughPrevResults,
+ NotNonNegIntFact, SqrtDoesNotExist, TrailingSyms,
+ },
+ O::Exit,
+ Ratio,
+ };
+ #[cfg(not(feature = "rand"))]
+ use alloc::{borrow::ToOwned as _, string::ToString as _};
+ #[cfg(not(feature = "rand"))]
+ use num_traits::Pow as _;
+ #[cfg(feature = "rand")]
+ use num_traits::ToPrimitive as _;
+ #[cfg(feature = "rand")]
+ use std::io::{self, Error, Read};
+ #[expect(clippy::too_many_lines, reason = "a lot to test")]
#[cfg(not(feature = "rand"))]
#[test]
fn empty() {
// Empty expressions without a previous result return nothing.
- assert!(
- match Evaluator::new(b"\n", &mut Cache::new(), &mut None, &mut Vec::new())
- .evaluate()
- .unwrap()
- {
- Empty(o) => o.is_none(),
- _ => false,
- }
+ assert_eq!(
+ Evaluator::new(b"\n", &mut Cache::new(), &mut None, &mut Vec::new()).evaluate(),
+ Ok(Empty(&None))
);
- assert!(
+ assert_eq!(
Evaluator::new(
b" \t \t \n",
&mut Cache::new(),
@@ -1285,11 +1304,10 @@ mod tests {
&mut Vec::new()
)
.evaluate()
- .unwrap()
- .to_string()
- == "> -12"
+ .map(|a| a.to_string()),
+ Ok("> -12".to_owned())
);
- assert!(
+ assert_eq!(
Evaluator::new(
b"\t\n",
&mut Cache::new(),
@@ -1300,41 +1318,38 @@ mod tests {
&mut Vec::new()
)
.evaluate()
- .unwrap()
- .to_string()
- == "> -0.666666667"
+ .map(|a| a.to_string()),
+ Ok("> -0.666666667".to_owned())
);
- assert!(
+ assert_eq!(
Evaluator::new(
b"\t\n",
&mut Cache::new(),
&mut Some(Ratio::new(
BigInt::from_biguint(Sign::Plus, BigUint::new(vec![1])),
- BigInt::from_biguint(Sign::Plus, BigUint::new(vec![4230196224, 6]))
+ BigInt::from_biguint(Sign::Plus, BigUint::new(vec![4_230_196_224, 6]))
)),
&mut Vec::new()
)
.evaluate()
- .unwrap()
- .to_string()
- == "> 0.000000000"
+ .map(|a| a.to_string()),
+ Ok("> 0.000000000".to_owned())
);
- assert!(
+ assert_eq!(
Evaluator::new(
b"\t\n",
&mut Cache::new(),
&mut Some(Ratio::new(
BigInt::from_biguint(Sign::Plus, BigUint::new(vec![17])),
- BigInt::from_biguint(Sign::Plus, BigUint::new(vec![4230196224, 6]))
+ BigInt::from_biguint(Sign::Plus, BigUint::new(vec![4_230_196_224, 6]))
)),
&mut Vec::new()
)
.evaluate()
- .unwrap()
- .to_string()
- == "> 0.000000001"
+ .map(|a| a.to_string()),
+ Ok("> 0.000000001".to_owned())
);
- assert!(
+ assert_eq!(
Evaluator::new(
b"\t\n",
&mut Cache::new(),
@@ -1345,11 +1360,10 @@ mod tests {
&mut Vec::new()
)
.evaluate()
- .unwrap()
- .to_string()
- == "> 0.3"
+ .map(|a| a.to_string()),
+ Ok("> 0.3".to_owned())
);
- assert!(
+ assert_eq!(
Evaluator::new(
b"\t\n",
&mut Cache::new(),
@@ -1360,11 +1374,10 @@ mod tests {
&mut Vec::new()
)
.evaluate()
- .unwrap()
- .to_string()
- == "> -20.3"
+ .map(|a| a.to_string()),
+ Ok("> -20.3".to_owned())
);
- assert!(
+ assert_eq!(
Evaluator::new(
&[0u8; 0],
&mut Cache::new(),
@@ -1375,49 +1388,48 @@ mod tests {
&mut Vec::new()
)
.evaluate()
- .unwrap()
- .to_string()
- == "> -20.3"
+ .map(|a| a.to_string()),
+ Ok("> -20.3".to_owned())
);
}
+ #[expect(clippy::unreachable, reason = "want to crash when there is a bug")]
#[cfg(not(feature = "rand"))]
#[test]
fn number_literal() {
// Normal 0 is fine.
- assert!(
- Evaluator::new(b"0", &mut Cache::new(), &mut None, &mut Vec::new())
- .get_rational()
- .unwrap()
- .unwrap()
- == Ratio::from_integer(BigInt::from_biguint(
- Sign::NoSign,
- BigUint::new(Vec::new())
- ))
+ assert_eq!(
+ Evaluator::new(b"0", &mut Cache::new(), &mut None, &mut Vec::new()).get_rational(),
+ Ok(Some(Ratio::from_integer(BigInt::from_biguint(
+ Sign::NoSign,
+ BigUint::new(Vec::new())
+ ))))
);
// Leading 0s and trailing 0s are fine.
- assert!(
+ assert_eq!(
Evaluator::new(b"0000.00000", &mut Cache::new(), &mut None, &mut Vec::new())
- .get_rational()
- .unwrap()
- .unwrap()
- == Ratio::from_integer(BigInt::from_biguint(
- Sign::NoSign,
- BigUint::new(Vec::new())
- ))
+ .get_rational(),
+ Ok(Some(Ratio::from_integer(BigInt::from_biguint(
+ Sign::NoSign,
+ BigUint::new(Vec::new())
+ ))))
);
// Parsing stops at first non-(digit/period).
- assert!(
- Evaluator::new(b"1 0", &mut Cache::new(), &mut None, &mut Vec::new())
- .get_rational()
- .unwrap()
- .unwrap()
- == Ratio::from_integer(BigInt::from_biguint(Sign::Plus, BigUint::new(vec![1])))
+ assert_eq!(
+ Evaluator::new(b"1 0", &mut Cache::new(), &mut None, &mut Vec::new()).get_rational(),
+ Ok(Some(Ratio::from_integer(BigInt::from_biguint(
+ Sign::Plus,
+ BigUint::new(vec![1])
+ ))))
);
let int = b"3397450981271938475135134759823759835414";
let frac = b"913759810573549872354897210539127530981570";
- let left = Ratio::from_integer(BigInt::parse_bytes(int, 10).unwrap());
+ let left = Ratio::from_integer(
+ BigInt::parse_bytes(int, 10)
+ .unwrap_or_else(|| unreachable!("bug in BigInt::parse_bytes")),
+ );
let right = Ratio::new(
- BigInt::parse_bytes(frac, 10).unwrap(),
+ BigInt::parse_bytes(frac, 10)
+ .unwrap_or_else(|| unreachable!("bug in BigInt::parse_bytes")),
BigInt::from_biguint(Sign::Plus, BigUint::new(vec![10]).pow(frac.len() + 1)),
);
let mut vec = Vec::new();
@@ -1426,381 +1438,310 @@ mod tests {
vec.push(b'0');
vec.extend_from_slice(frac);
// Test a number whose integer and fraction portions are larger than u128::MAX.
- assert!(
+ assert_eq!(
Evaluator::new(
vec.as_slice(),
&mut Cache::new(),
&mut None,
&mut Vec::new()
)
- .get_rational()
- .unwrap()
- .unwrap()
- == left + right
+ .get_rational(),
+ Ok(Some(left + right))
);
// Leading 0s and trailing 0s for a non-zero value are fine.
- assert!(
+ assert_eq!(
Evaluator::new(
b"000000014.0000000000000",
&mut Cache::new(),
&mut None,
&mut Vec::new()
)
- .get_rational()
- .unwrap()
- .unwrap()
- == Ratio::from_integer(BigInt::from_biguint(Sign::Plus, BigUint::new(vec![14])))
+ .get_rational(),
+ Ok(Some(Ratio::from_integer(BigInt::from_biguint(
+ Sign::Plus,
+ BigUint::new(vec![14])
+ ))))
);
// A sequence of digits followed immediately by a decimal point but no digits after is invalid.
- assert!(
- match Evaluator::new(b"1.", &mut Cache::new(), &mut None, &mut Vec::new())
- .get_rational()
- .unwrap_err()
- {
- InvalidDec(i) => i == 2,
- _ => false,
- }
+ assert_eq!(
+ Evaluator::new(b"1.", &mut Cache::new(), &mut None, &mut Vec::new()).get_rational(),
+ Err(InvalidDec(2))
);
// A sequence of digits followed immediately by a decimal point but no digits after is invalid.
// This just shows that spaces are not ignored in number literals.
- assert!(
- match Evaluator::new(b"1. 2", &mut Cache::new(), &mut None, &mut Vec::new())
- .get_rational()
- .unwrap_err()
- {
- InvalidDec(i) => i == 2,
- _ => false,
- }
+ assert_eq!(
+ Evaluator::new(b"1. 2", &mut Cache::new(), &mut None, &mut Vec::new()).get_rational(),
+ Err(InvalidDec(2))
);
// Non-whitespace starting the input is valid but produces no value.
// This also shows that an invalid byte sequence does not produce an error here.
- assert!(
- Evaluator::new(b"a1", &mut Cache::new(), &mut None, &mut Vec::new())
- .get_rational()
- .unwrap()
- .is_none()
+ assert_eq!(
+ Evaluator::new(b"a1", &mut Cache::new(), &mut None, &mut Vec::new()).get_rational(),
+ Ok(None)
);
// A space starting the input is valid but produces no value.
- assert!(
- Evaluator::new(b" 1", &mut Cache::new(), &mut None, &mut Vec::new())
- .get_rational()
- .unwrap()
- .is_none()
+ assert_eq!(
+ Evaluator::new(b" 1", &mut Cache::new(), &mut None, &mut Vec::new()).get_rational(),
+ Ok(None)
);
// A tab starting the input is valid but produces no value.
- assert!(
- Evaluator::new(b"\t1", &mut Cache::new(), &mut None, &mut Vec::new())
- .get_rational()
- .unwrap()
- .is_none()
+ assert_eq!(
+ Evaluator::new(b"\t1", &mut Cache::new(), &mut None, &mut Vec::new()).get_rational(),
+ Ok(None)
);
// Negative literals don't exist, so this should succeed but produce nothing.
- assert!(
- Evaluator::new(b"-1", &mut Cache::new(), &mut None, &mut Vec::new())
- .get_rational()
- .unwrap()
- .is_none()
+ assert_eq!(
+ Evaluator::new(b"-1", &mut Cache::new(), &mut None, &mut Vec::new()).get_rational(),
+ Ok(None)
);
// '/' is division and not part of a number literal so only the "numerator" is parsed.
- assert!(
- Evaluator::new(b"1/2", &mut Cache::new(), &mut None, &mut Vec::new())
- .get_rational()
- .unwrap()
- .unwrap()
- == Ratio::from_integer(BigInt::from_biguint(Sign::Plus, BigUint::new(vec![1])))
+ assert_eq!(
+ Evaluator::new(b"1/2", &mut Cache::new(), &mut None, &mut Vec::new()).get_rational(),
+ Ok(Some(Ratio::from_integer(BigInt::from_biguint(
+ Sign::Plus,
+ BigUint::new(vec![1])
+ ))))
);
// A sequence of digits followed by invalid bytes is valid and produces a number equal to the digits before the invalid bytes.
- assert!(
- Evaluator::new(b"130alj", &mut Cache::new(), &mut None, &mut Vec::new())
- .get_rational()
- .unwrap()
- .unwrap()
- == Ratio::from_integer(BigInt::from_biguint(Sign::Plus, BigUint::new(vec![130])))
+ assert_eq!(
+ Evaluator::new(b"130alj", &mut Cache::new(), &mut None, &mut Vec::new()).get_rational(),
+ Ok(Some(Ratio::from_integer(BigInt::from_biguint(
+ Sign::Plus,
+ BigUint::new(vec![130])
+ ))))
);
}
#[cfg(not(feature = "rand"))]
#[test]
fn par() {
// Missing closing ')'
- assert!(
- match Evaluator::new(b"(1", &mut Cache::new(), &mut None, &mut Vec::new())
- .get_par()
- .unwrap_err()
- {
- InvalidPar(i) => i == 2,
- _ => false,
- }
+ assert_eq!(
+ Evaluator::new(b"(1", &mut Cache::new(), &mut None, &mut Vec::new()).get_par(),
+ Err(InvalidPar(2))
);
- assert!(
- match Evaluator::new(b"((1\t + 2)", &mut Cache::new(), &mut None, &mut Vec::new())
- .get_par()
- .unwrap_err()
- {
- InvalidPar(i) => i == 9,
- _ => false,
- }
+ assert_eq!(
+ Evaluator::new(b"((1\t + 2)", &mut Cache::new(), &mut None, &mut Vec::new()).get_par(),
+ Err(InvalidPar(9))
);
- assert!(
- Evaluator::new(b"( 0 \t )", &mut Cache::new(), &mut None, &mut Vec::new())
- .get_par()
- .unwrap()
- .unwrap()
- == Ratio::from_integer(BigInt::from_biguint(
- Sign::NoSign,
- BigUint::new(Vec::new())
- ))
+ assert_eq!(
+ Evaluator::new(b"( 0 \t )", &mut Cache::new(), &mut None, &mut Vec::new()).get_par(),
+ Ok(Some(Ratio::from_integer(BigInt::from_biguint(
+ Sign::NoSign,
+ BigUint::new(Vec::new())
+ ))))
);
- assert!(
- Evaluator::new(b"( - \t 5 )", &mut Cache::new(), &mut None, &mut Vec::new())
- .get_par()
- .unwrap()
- .unwrap()
- == Ratio::from_integer(BigInt::from_biguint(Sign::Minus, BigUint::new(vec![5])))
+ assert_eq!(
+ Evaluator::new(b"( - \t 5 )", &mut Cache::new(), &mut None, &mut Vec::new()).get_par(),
+ Ok(Some(Ratio::from_integer(BigInt::from_biguint(
+ Sign::Minus,
+ BigUint::new(vec![5])
+ ))))
);
- assert!(
+ assert_eq!(
Evaluator::new(
b"( ( 2 -\t 5) * 9 )",
&mut Cache::new(),
&mut None,
&mut Vec::new()
)
- .get_par()
- .unwrap()
- .unwrap()
- == Ratio::from_integer(BigInt::from_biguint(Sign::Minus, BigUint::new(vec![27])))
+ .get_par(),
+ Ok(Some(Ratio::from_integer(BigInt::from_biguint(
+ Sign::Minus,
+ BigUint::new(vec![27])
+ ))))
);
}
+ #[expect(clippy::too_many_lines, reason = "a lot to test")]
+ #[expect(
+ clippy::indexing_slicing,
+ clippy::unwrap_used,
+ reason = "comments justify correctness"
+ )]
#[cfg(not(feature = "rand"))]
#[test]
fn recall_expression() {
// If the input does not start with '@', then it's valid but produces nothing.
- assert!(
- Evaluator::new(b"1", &mut Cache::new(), &mut None, &mut Vec::new())
- .get_recall()
- .unwrap()
- .is_none()
+ assert_eq!(
+ Evaluator::new(b"1", &mut Cache::new(), &mut None, &mut Vec::new()).get_recall(),
+ Ok(None)
);
- assert!(
- Evaluator::new(b"a", &mut Cache::new(), &mut None, &mut Vec::new())
- .get_recall()
- .unwrap()
- .is_none()
+ assert_eq!(
+ Evaluator::new(b"a", &mut Cache::new(), &mut None, &mut Vec::new()).get_recall(),
+ Ok(None)
);
- assert!(
- Evaluator::new(b" @", &mut Cache::new(), &mut None, &mut Vec::new())
- .get_recall()
- .unwrap()
- .is_none()
+ assert_eq!(
+ Evaluator::new(b" @", &mut Cache::new(), &mut None, &mut Vec::new()).get_recall(),
+ Ok(None)
);
- assert!(
- Evaluator::new(b"\t@", &mut Cache::new(), &mut None, &mut Vec::new())
- .get_recall()
- .unwrap()
- .is_none()
+ assert_eq!(
+ Evaluator::new(b"\t@", &mut Cache::new(), &mut None, &mut Vec::new()).get_recall(),
+ Ok(None)
);
// Invalid recall expression since there are no previous results.
- assert!(
- match Evaluator::new(b"@", &mut Cache::new(), &mut None, &mut Vec::new())
- .get_recall()
- .unwrap_err()
- {
- NotEnoughPrevResults(count) => count == 0,
- _ => false,
- }
+ assert_eq!(
+ Evaluator::new(b"@", &mut Cache::new(), &mut None, &mut Vec::new()).get_recall(),
+ Err(NotEnoughPrevResults(0))
);
// Invalid recall expression since there are no previous results.
- assert!(
- match Evaluator::new(b"@4", &mut Cache::new(), &mut None, &mut Vec::new())
- .get_recall()
- .unwrap_err()
- {
- NotEnoughPrevResults(count) => count == 0,
- _ => false,
- }
+ assert_eq!(
+ Evaluator::new(b"@4", &mut Cache::new(), &mut None, &mut Vec::new()).get_recall(),
+ Err(NotEnoughPrevResults(0))
);
// Invalid recall expression since there are no previous results.
// The input violates our grammar, but this error happens before that.
- assert!(
- match Evaluator::new(b"@0", &mut Cache::new(), &mut None, &mut Vec::new())
- .get_recall()
- .unwrap_err()
- {
- NotEnoughPrevResults(count) => count == 0,
- _ => false,
- }
+ assert_eq!(
+ Evaluator::new(b"@0", &mut Cache::new(), &mut None, &mut Vec::new()).get_recall(),
+ Err(NotEnoughPrevResults(0))
);
// Successfully extract previous expression.
let mut prev = None;
let mut cache = Cache::new();
- drop(
- Evaluator::new(b"1\n", &mut cache, &mut prev, &mut Vec::new())
- .evaluate()
- .unwrap(),
- );
- drop(
- Evaluator::new(b" s \r\n", &mut cache, &mut prev, &mut Vec::new())
- .evaluate()
- .unwrap(),
- );
- assert!(
- Evaluator::new(b"@", &mut cache, &mut prev, &mut Vec::new())
- .get_recall()
- .unwrap()
- .unwrap()
- == Ratio::from_integer(BigInt::from_biguint(Sign::Plus, BigUint::new(vec![1])))
+ // Quick check that `Ok` is returned.
+ _ = Evaluator::new(b"1\n", &mut cache, &mut prev, &mut Vec::new())
+ .evaluate()
+ .unwrap();
+ // Quick check that `Ok` is returned.
+ _ = Evaluator::new(b" s \r\n", &mut cache, &mut prev, &mut Vec::new())
+ .evaluate()
+ .unwrap();
+ assert_eq!(
+ Evaluator::new(b"@", &mut cache, &mut prev, &mut Vec::new()).get_recall(),
+ Ok(Some(Ratio::from_integer(BigInt::from_biguint(
+ Sign::Plus,
+ BigUint::new(vec![1])
+ ))))
);
// Invalid characters are ignored at this stage.
- assert!(
- Evaluator::new(b"@&", &mut cache, &mut prev, &mut Vec::new())
- .get_recall()
- .unwrap()
- .unwrap()
- == Ratio::from_integer(BigInt::from_biguint(Sign::Plus, BigUint::new(vec![1])))
+ assert_eq!(
+ Evaluator::new(b"@&", &mut cache, &mut prev, &mut Vec::new()).get_recall(),
+ Ok(Some(Ratio::from_integer(BigInt::from_biguint(
+ Sign::Plus,
+ BigUint::new(vec![1])
+ ))))
);
// 0 is not a valid stored value only 1-8 are.
- assert!(
- Evaluator::new(b"@0", &mut cache, &mut prev, &mut Vec::new())
- .get_recall()
- .unwrap()
- .unwrap()
- == Ratio::from_integer(BigInt::from_biguint(Sign::Plus, BigUint::new(vec![1])))
+ assert_eq!(
+ Evaluator::new(b"@0", &mut cache, &mut prev, &mut Vec::new()).get_recall(),
+ Ok(Some(Ratio::from_integer(BigInt::from_biguint(
+ Sign::Plus,
+ BigUint::new(vec![1])
+ ))))
);
// 9 is not a valid stored value only 1-8 are.
- assert!(
- Evaluator::new(b"@9", &mut cache, &mut prev, &mut Vec::new())
- .get_recall()
- .unwrap()
- .unwrap()
- == Ratio::from_integer(BigInt::from_biguint(Sign::Plus, BigUint::new(vec![1])))
+ assert_eq!(
+ Evaluator::new(b"@9", &mut cache, &mut prev, &mut Vec::new()).get_recall(),
+ Ok(Some(Ratio::from_integer(BigInt::from_biguint(
+ Sign::Plus,
+ BigUint::new(vec![1])
+ ))))
);
// Spaces are not cleaned; otherwise this would error since we only have 1 stored value.
- assert!(
- Evaluator::new(b"@ 2", &mut cache, &mut prev, &mut Vec::new())
- .get_recall()
- .unwrap()
- .unwrap()
- == Ratio::from_integer(BigInt::from_biguint(Sign::Plus, BigUint::new(vec![1])))
+ assert_eq!(
+ Evaluator::new(b"@ 2", &mut cache, &mut prev, &mut Vec::new()).get_recall(),
+ Ok(Some(Ratio::from_integer(BigInt::from_biguint(
+ Sign::Plus,
+ BigUint::new(vec![1])
+ ))))
);
// Tabs are not cleaned; otherwise this would error since we only have 1 stored value.
- assert!(
- Evaluator::new(b"@\t2", &mut cache, &mut prev, &mut Vec::new())
- .get_recall()
- .unwrap()
- .unwrap()
- == Ratio::from_integer(BigInt::from_biguint(Sign::Plus, BigUint::new(vec![1])))
+ assert_eq!(
+ Evaluator::new(b"@\t2", &mut cache, &mut prev, &mut Vec::new()).get_recall(),
+ Ok(Some(Ratio::from_integer(BigInt::from_biguint(
+ Sign::Plus,
+ BigUint::new(vec![1])
+ ))))
);
// One digits are looked at so this is not @<ten>.
- assert!(
- Evaluator::new(b"@10", &mut cache, &mut prev, &mut Vec::new())
- .get_recall()
- .unwrap()
- .unwrap()
- == Ratio::from_integer(BigInt::from_biguint(Sign::Plus, BigUint::new(vec![1])))
+ assert_eq!(
+ Evaluator::new(b"@10", &mut cache, &mut prev, &mut Vec::new()).get_recall(),
+ Ok(Some(Ratio::from_integer(BigInt::from_biguint(
+ Sign::Plus,
+ BigUint::new(vec![1])
+ ))))
);
// Invalid recall expression since there is only one stored result.
- assert!(
- match Evaluator::new(b"@2", &mut cache, &mut prev, &mut Vec::new())
- .get_recall()
- .unwrap_err()
- {
- NotEnoughPrevResults(count) => count == 1,
- _ => false,
- }
- );
- drop(
- Evaluator::new(b"2\r\n", &mut cache, &mut prev, &mut Vec::new())
- .evaluate()
- .unwrap(),
- );
- drop(
- Evaluator::new(b"s\n", &mut cache, &mut prev, &mut Vec::new())
- .evaluate()
- .unwrap(),
+ assert_eq!(
+ Evaluator::new(b"@2", &mut cache, &mut prev, &mut Vec::new()).get_recall(),
+ Err(NotEnoughPrevResults(1))
);
+ // Quick check that `Ok` is returned.
+ _ = Evaluator::new(b"2\r\n", &mut cache, &mut prev, &mut Vec::new())
+ .evaluate()
+ .unwrap();
+ // Quick check that `Ok` is returned.
+ _ = Evaluator::new(b"s\n", &mut cache, &mut prev, &mut Vec::new())
+ .evaluate()
+ .unwrap();
// Stored values correct.
- assert!(
- Evaluator::new(b"@", &mut cache, &mut prev, &mut Vec::new())
- .get_recall()
- .unwrap()
- .unwrap()
- == Ratio::from_integer(BigInt::from_biguint(Sign::Plus, BigUint::new(vec![2])))
+ assert_eq!(
+ Evaluator::new(b"@", &mut cache, &mut prev, &mut Vec::new()).get_recall(),
+ Ok(Some(Ratio::from_integer(BigInt::from_biguint(
+ Sign::Plus,
+ BigUint::new(vec![2])
+ ))))
);
- assert!(
- Evaluator::new(b"@2", &mut cache, &mut prev, &mut Vec::new())
- .get_recall()
- .unwrap()
- .unwrap()
- == Ratio::from_integer(BigInt::from_biguint(Sign::Plus, BigUint::new(vec![1])))
+ assert_eq!(
+ Evaluator::new(b"@2", &mut cache, &mut prev, &mut Vec::new()).get_recall(),
+ Ok(Some(Ratio::from_integer(BigInt::from_biguint(
+ Sign::Plus,
+ BigUint::new(vec![1])
+ ))))
);
// Invalid recall expression since there are only three stored results.
- assert!(
- match Evaluator::new(b"@3", &mut cache, &mut prev, &mut Vec::new())
- .get_recall()
- .unwrap_err()
- {
- NotEnoughPrevResults(count) => count == 2,
- _ => false,
- }
+ assert_eq!(
+ Evaluator::new(b"@3", &mut cache, &mut prev, &mut Vec::new()).get_recall(),
+ Err(NotEnoughPrevResults(2))
);
let mut v = vec![0, b'\n'];
for i in b'3'..=b'8' {
+ // `v.len() > 0`.
v[0] = i;
- drop(
- Evaluator::new(v.as_slice(), &mut cache, &mut prev, &mut Vec::new())
- .evaluate()
- .unwrap(),
- );
- drop(
- Evaluator::new(b"s\n", &mut cache, &mut prev, &mut Vec::new())
- .evaluate()
- .unwrap(),
- );
+ _ = Evaluator::new(v.as_slice(), &mut cache, &mut prev, &mut Vec::new())
+ .evaluate()
+ .unwrap();
+ _ = Evaluator::new(b"s\n", &mut cache, &mut prev, &mut Vec::new())
+ .evaluate()
+ .unwrap();
}
v[0] = b'@';
for i in b'1'..=b'8' {
+ // `v.len() > 1`.
v[1] = i;
// Cache is filled up correctly storing all previous values.
- assert!(
- Evaluator::new(v.as_slice(), &mut cache, &mut prev, &mut Vec::new())
- .get_recall()
- .unwrap()
- .unwrap()
- == Ratio::from_integer(BigInt::from_biguint(
- Sign::Plus,
- BigUint::new(vec![(b'9' - i) as u32])
- ))
+ assert_eq!(
+ Evaluator::new(v.as_slice(), &mut cache, &mut prev, &mut Vec::new()).get_recall(),
+ Ok(Some(Ratio::from_integer(BigInt::from_biguint(
+ Sign::Plus,
+ BigUint::new(vec![u32::from(b'9' - i)])
+ ))))
);
}
// Only parses the first @ since the second @ is not a digit between 1 and 8.
- assert!(
- Evaluator::new(b"@@", &mut cache, &mut prev, &mut Vec::new())
- .get_recall()
- .unwrap()
- .unwrap()
- == Ratio::from_integer(BigInt::from_biguint(Sign::Plus, BigUint::new(vec![8])))
- );
- drop(
- Evaluator::new(b"9\r\n", &mut cache, &mut prev, &mut Vec::new())
- .evaluate()
- .unwrap(),
- );
- drop(
- Evaluator::new(b"s\n", &mut cache, &mut prev, &mut Vec::new())
- .evaluate()
- .unwrap(),
+ assert_eq!(
+ Evaluator::new(b"@@", &mut cache, &mut prev, &mut Vec::new()).get_recall(),
+ Ok(Some(Ratio::from_integer(BigInt::from_biguint(
+ Sign::Plus,
+ BigUint::new(vec![8])
+ ))))
);
+ // Quick check that `Ok` is returned.
+ _ = Evaluator::new(b"9\r\n", &mut cache, &mut prev, &mut Vec::new())
+ .evaluate()
+ .unwrap();
+ // Quick check that `Ok` is returned.
+ _ = Evaluator::new(b"s\n", &mut cache, &mut prev, &mut Vec::new())
+ .evaluate()
+ .unwrap();
// Oldest value is overwritten; all others remain.
for i in b'1'..=b'8' {
+ // `v.len() > 1`.
v[1] = i;
- assert!(
- Evaluator::new(v.as_slice(), &mut cache, &mut prev, &mut Vec::new())
- .get_recall()
- .unwrap()
- .unwrap()
- == Ratio::from_integer(BigInt::from_biguint(
- Sign::Plus,
- BigUint::new(vec![((b'9' + 1) - i) as u32])
- ))
+ assert_eq!(
+ Evaluator::new(v.as_slice(), &mut cache, &mut prev, &mut Vec::new()).get_recall(),
+ Ok(Some(Ratio::from_integer(BigInt::from_biguint(
+ Sign::Plus,
+ BigUint::new(vec![u32::from((b'9' + 1) - i)])
+ ))))
);
}
}
@@ -1808,229 +1749,182 @@ mod tests {
#[test]
fn abs() {
// Missing closing '|'
- assert!(
- match Evaluator::new(b"|1", &mut Cache::new(), &mut None, &mut Vec::new())
- .get_abs()
- .unwrap_err()
- {
- InvalidAbs(i) => i == 2,
- _ => false,
- }
+ assert_eq!(
+ Evaluator::new(b"|1", &mut Cache::new(), &mut None, &mut Vec::new()).get_abs(),
+ Err(InvalidAbs(2))
);
- assert!(
- match Evaluator::new(b"||1 + 2|", &mut Cache::new(), &mut None, &mut Vec::new())
- .get_abs()
- .unwrap_err()
- {
- InvalidAbs(i) => i == 8,
- _ => false,
- }
+ assert_eq!(
+ Evaluator::new(b"||1 + 2|", &mut Cache::new(), &mut None, &mut Vec::new()).get_abs(),
+ Err(InvalidAbs(8))
);
- assert!(
+ assert_eq!(
Evaluator::new(
b"| 0\t \t |",
&mut Cache::new(),
&mut None,
&mut Vec::new()
)
- .get_abs()
- .unwrap()
- .unwrap()
- == Ratio::from_integer(BigInt::from_biguint(
- Sign::NoSign,
- BigUint::new(Vec::new())
- ))
+ .get_abs(),
+ Ok(Some(Ratio::from_integer(BigInt::from_biguint(
+ Sign::NoSign,
+ BigUint::new(Vec::new())
+ ))))
);
- assert!(
- Evaluator::new(b"| - 5 |", &mut Cache::new(), &mut None, &mut Vec::new())
- .get_abs()
- .unwrap()
- .unwrap()
- == Ratio::from_integer(BigInt::from_biguint(Sign::Plus, BigUint::new(vec![5])))
+ assert_eq!(
+ Evaluator::new(b"| - 5 |", &mut Cache::new(), &mut None, &mut Vec::new()).get_abs(),
+ Ok(Some(Ratio::from_integer(BigInt::from_biguint(
+ Sign::Plus,
+ BigUint::new(vec![5])
+ ))))
);
- assert!(
+ assert_eq!(
Evaluator::new(
b"| \t| 2 - 5| * 9 |",
&mut Cache::new(),
&mut None,
&mut Vec::new()
)
- .get_abs()
- .unwrap()
- .unwrap()
- == Ratio::from_integer(BigInt::from_biguint(Sign::Plus, BigUint::new(vec![27])))
+ .get_abs(),
+ Ok(Some(Ratio::from_integer(BigInt::from_biguint(
+ Sign::Plus,
+ BigUint::new(vec![27])
+ ))))
);
// If the input does not start with '|', then it's valid but produces nothing.
- assert!(
- Evaluator::new(b" \t|9|", &mut Cache::new(), &mut None, &mut Vec::new())
- .get_abs()
- .unwrap()
- .is_none()
+ assert_eq!(
+ Evaluator::new(b" \t|9|", &mut Cache::new(), &mut None, &mut Vec::new()).get_abs(),
+ Ok(None)
);
}
#[cfg(not(feature = "rand"))]
#[test]
fn round() {
// Missing ',<digit>)'
- assert!(
- match Evaluator::new(b"round(1", &mut Cache::new(), &mut None, &mut Vec::new())
- .get_round()
- .unwrap_err()
- {
- InvalidRound(i) => i == 7,
- _ => false,
- }
+ assert_eq!(
+ Evaluator::new(b"round(1", &mut Cache::new(), &mut None, &mut Vec::new()).get_round(),
+ Err(InvalidRound(7))
);
- assert!(
- match Evaluator::new(b"round(1,", &mut Cache::new(), &mut None, &mut Vec::new())
- .get_round()
- .unwrap_err()
- {
- InvalidRound(i) => i == 8,
- _ => false,
- }
+ assert_eq!(
+ Evaluator::new(b"round(1,", &mut Cache::new(), &mut None, &mut Vec::new()).get_round(),
+ Err(InvalidRound(8))
);
- assert!(
- match Evaluator::new(b"round(1,2", &mut Cache::new(), &mut None, &mut Vec::new())
- .get_round()
- .unwrap_err()
- {
- InvalidRound(i) => i == 9,
- _ => false,
- }
+ assert_eq!(
+ Evaluator::new(b"round(1,2", &mut Cache::new(), &mut None, &mut Vec::new()).get_round(),
+ Err(InvalidRound(9))
);
- assert!(match Evaluator::new(
- b"round(1,10)",
- &mut Cache::new(),
- &mut None,
- &mut Vec::new()
- )
- .get_round()
- .unwrap_err()
- {
- InvalidRound(i) => i == 9,
- _ => false,
- });
- assert!(
- match Evaluator::new(b"round(1,a)", &mut Cache::new(), &mut None, &mut Vec::new())
- .get_round()
- .unwrap_err()
- {
- InvalidRound(i) => i == 8,
- _ => false,
- }
+ assert_eq!(
+ Evaluator::new(
+ b"round(1,10)",
+ &mut Cache::new(),
+ &mut None,
+ &mut Vec::new()
+ )
+ .get_round(),
+ Err(InvalidRound(9))
);
- assert!(
+ assert_eq!(
+ Evaluator::new(b"round(1,a)", &mut Cache::new(), &mut None, &mut Vec::new())
+ .get_round(),
+ Err(InvalidRound(8))
+ );
+ assert_eq!(
Evaluator::new(
b"round(2, 7)",
&mut Cache::new(),
&mut None,
&mut Vec::new()
)
- .get_round()
- .unwrap()
- == Some(Ratio::from_integer(BigInt::from_biguint(
- Sign::Plus,
- BigUint::new(vec![2])
- )))
+ .get_round(),
+ Ok(Some(Ratio::from_integer(BigInt::from_biguint(
+ Sign::Plus,
+ BigUint::new(vec![2])
+ ))))
);
- assert!(
+ assert_eq!(
Evaluator::new(
b"round(2.677, 1)",
&mut Cache::new(),
&mut None,
&mut Vec::new()
)
- .get_round()
- .unwrap()
- == Some(Ratio::new(
- BigInt::from_biguint(Sign::Plus, BigUint::new(vec![27])),
- BigInt::from_biguint(Sign::Plus, BigUint::new(vec![10]))
- ))
+ .get_round(),
+ Ok(Some(Ratio::new(
+ BigInt::from_biguint(Sign::Plus, BigUint::new(vec![27])),
+ BigInt::from_biguint(Sign::Plus, BigUint::new(vec![10]))
+ )))
);
}
+ #[expect(clippy::too_many_lines, reason = "a lot to test")]
#[cfg(feature = "rand")]
#[test]
fn rand() {
- assert!(match Evaluator::new(
- b"rand(1",
- &mut Cache::new(),
- &mut None,
- &mut Vec::new(),
- &mut rand::rng()
- )
- .get_rand()
- .unwrap_err()
- {
- LangErr::InvalidRand(i) => i == 6,
- _ => false,
- });
- assert!(match Evaluator::new(
- b"rand(1,2",
- &mut Cache::new(),
- &mut None,
- &mut Vec::new(),
- &mut rand::rng()
- )
- .get_rand()
- .unwrap_err()
- {
- LangErr::InvalidRand(i) => i == 8,
- _ => false,
- });
- assert!(match Evaluator::new(
- b"rand(1/2,3/4)",
- &mut Cache::new(),
- &mut None,
- &mut Vec::new(),
- &mut rand::rng(),
- )
- .get_rand()
- .unwrap_err()
- {
- LangErr::RandNoInts(i) => i == 13,
- _ => false,
- });
- assert!(match Evaluator::new(
- b"rand(-100000000000000000000000,-1000000000000000000000)",
- &mut Cache::new(),
- &mut None,
- &mut Vec::new(),
- &mut rand::rng(),
- )
- .get_rand()
- .unwrap_err()
- {
- LangErr::RandNoInts(i) => i == 55,
- _ => false,
- });
- assert!(match Evaluator::new(
- b"rand(2/3,1/3)",
- &mut Cache::new(),
- &mut None,
- &mut Vec::new(),
- &mut rand::rng(),
- )
- .get_rand()
- .unwrap_err()
- {
- LangErr::RandInvalidArgs(i) => i == 13,
- _ => false,
- });
+ assert_eq!(
+ Evaluator::new(
+ b"rand(1",
+ &mut Cache::new(),
+ &mut None,
+ &mut Vec::new(),
+ &mut rand::rng()
+ )
+ .get_rand(),
+ Err(LangErr::InvalidRand(6))
+ );
+ assert_eq!(
+ Evaluator::new(
+ b"rand(1,2",
+ &mut Cache::new(),
+ &mut None,
+ &mut Vec::new(),
+ &mut rand::rng()
+ )
+ .get_rand(),
+ Err(LangErr::InvalidRand(8))
+ );
+ assert_eq!(
+ Evaluator::new(
+ b"rand(1/2,3/4)",
+ &mut Cache::new(),
+ &mut None,
+ &mut Vec::new(),
+ &mut rand::rng(),
+ )
+ .get_rand(),
+ Err(LangErr::RandNoInts(13))
+ );
+ assert_eq!(
+ Evaluator::new(
+ b"rand(-100000000000000000000000,-1000000000000000000000)",
+ &mut Cache::new(),
+ &mut None,
+ &mut Vec::new(),
+ &mut rand::rng(),
+ )
+ .get_rand(),
+ Err(LangErr::RandNoInts(55))
+ );
+ assert_eq!(
+ Evaluator::new(
+ b"rand(2/3,1/3)",
+ &mut Cache::new(),
+ &mut None,
+ &mut Vec::new(),
+ &mut rand::rng(),
+ )
+ .get_rand(),
+ Err(LangErr::RandInvalidArgs(13))
+ );
// If the input does not start with 'rand(', then it's invalid since get_rand must only be called as the last terminal expression which means whitespace must be consumed already.
- assert!(match Evaluator::new(
- b" rand(2/3,2)",
- &mut Cache::new(),
- &mut None,
- &mut Vec::new(),
- &mut rand::rng(),
- )
- .get_rand()
- .unwrap_err()
- {
- MissingTerm(i) => i == 0,
- _ => false,
- });
+ assert_eq!(
+ Evaluator::new(
+ b" rand(2/3,2)",
+ &mut Cache::new(),
+ &mut None,
+ &mut Vec::new(),
+ &mut rand::rng(),
+ )
+ .get_rand(),
+ Err(MissingTerm(0))
+ );
assert!(
Evaluator::new(
b"rand(2, 7)",
@@ -2040,12 +1934,11 @@ mod tests {
&mut rand::rng()
)
.get_rand()
- .map(|r| {
+ .is_ok_and(|r| {
let int = r.numer();
int >= &BigInt::from_biguint(Sign::Plus, BigUint::new(vec![2]))
&& *int <= BigInt::from_biguint(Sign::Plus, BigUint::new(vec![7]))
})
- .unwrap()
);
assert!(
Evaluator::new(
@@ -2056,13 +1949,12 @@ mod tests {
&mut rand::rng()
)
.get_rand()
- .map(|r| {
+ .is_ok_and(|r| {
let int = r.numer();
int >= &BigInt::from(i64::MIN) && *int <= BigInt::from(i64::MAX)
})
- .unwrap()
);
- for _ in 0..100 {
+ for _ in 0..100u8 {
assert!(
Evaluator::new(
b"rand(2, 2)",
@@ -2072,98 +1964,122 @@ mod tests {
&mut rand::rng()
)
.get_rand()
- .map(|r| *r.numer() == BigInt::from_biguint(Sign::Plus, BigUint::new(vec![2])))
- .unwrap()
+ .is_ok_and(
+ |r| *r.numer() == BigInt::from_biguint(Sign::Plus, BigUint::new(vec![2]))
+ )
);
}
}
+ #[expect(
+ clippy::indexing_slicing,
+ clippy::unwrap_used,
+ reason = "comment justifies correctness"
+ )]
#[cfg(feature = "rand")]
#[test]
- #[ignore]
+ #[ignore = "slow"]
fn rand_uni() {
+ const COUNT: u32 = 999_999;
+ #[expect(
+ clippy::integer_division,
+ clippy::integer_division_remainder_used,
+ reason = "correct"
+ )]
+ const LOWER: u32 = COUNT * 33 / 100;
+ #[expect(
+ clippy::integer_division,
+ clippy::integer_division_remainder_used,
+ reason = "correct"
+ )]
+ const UPPER: u32 = COUNT * 101 / 300;
// Test rand on an interval that is not a power of 2 in size.
// This causes rand to adjust the interval to enforce uniformity.
let mut vals = [0u32; 3];
let mut vec = Vec::new();
let mut cache = Cache::new();
let mut none = None;
- const COUNT: u32 = 999999;
for _ in 1..COUNT {
- vals[(Evaluator::new(
- b"rand(-1, 1)",
- &mut cache,
- &mut none,
- &mut vec,
- &mut rand::rng(),
+ // We want to `panic` if `rand` does not work correctly.
+ vals[usize::try_from(
+ Evaluator::new(
+ b"rand(-1, 1)",
+ &mut cache,
+ &mut none,
+ &mut vec,
+ &mut rand::rng(),
+ )
+ .get_rand()
+ .unwrap()
+ .numer()
+ .to_i32()
+ .unwrap()
+ + 1i32,
)
- .get_rand()
- .unwrap()
- .numer()
- .to_i32()
- .unwrap()
- + 1) as usize] += 1;
+ .unwrap()] += 1;
}
// Test that the distribution is within 1% of what is expected.
- assert!(
- vals.into_iter()
- .try_fold(false, |_, r| {
- if r < COUNT * 33 / 100 || r > COUNT * 101 / 300 {
- Err(false)
- } else {
- Ok(true)
- }
- })
- .unwrap()
+ assert_eq!(
+ vals.into_iter().try_fold(false, |_, r| {
+ if (LOWER..=UPPER).contains(&r) {
+ Ok(true)
+ } else {
+ Err(false)
+ }
+ }),
+ Ok(true)
);
}
+ #[allow(
+ clippy::allow_attributes,
+ reason = "unwrap_used only fires when rand is not enabled"
+ )]
+ #[allow(clippy::unwrap_used, reason = "comments justify correctness")]
#[test]
fn term() {
#[cfg(not(feature = "rand"))]
- assert!(
- Evaluator::new(b"0000.00000", &mut Cache::new(), &mut None, &mut Vec::new())
- .get_term()
- .unwrap()
- == Ratio::from_integer(BigInt::from_biguint(
- Sign::NoSign,
- BigUint::new(Vec::new())
- ))
+ assert_eq!(
+ Evaluator::new(b"0000.00000", &mut Cache::new(), &mut None, &mut Vec::new()).get_term(),
+ Ok(Ratio::from_integer(BigInt::from_biguint(
+ Sign::NoSign,
+ BigUint::new(Vec::new())
+ )))
);
#[cfg(not(feature = "rand"))]
- assert!(
- Evaluator::new(b"(4)", &mut Cache::new(), &mut None, &mut Vec::new())
- .get_term()
- .unwrap()
- == Ratio::from_integer(BigInt::from_biguint(Sign::Plus, BigUint::new(vec![4])))
+ assert_eq!(
+ Evaluator::new(b"(4)", &mut Cache::new(), &mut None, &mut Vec::new()).get_term(),
+ Ok(Ratio::from_integer(BigInt::from_biguint(
+ Sign::Plus,
+ BigUint::new(vec![4])
+ )))
);
#[cfg(not(feature = "rand"))]
- assert!(
+ assert_eq!(
Evaluator::new(
b"round(-2/3,2)",
&mut Cache::new(),
&mut None,
&mut Vec::new()
)
- .get_term()
- .unwrap()
- == Ratio::new(
- BigInt::from_biguint(Sign::Minus, BigUint::new(vec![67])),
- BigInt::from_biguint(Sign::Plus, BigUint::new(vec![100]))
- )
+ .get_term(),
+ Ok(Ratio::new(
+ BigInt::from_biguint(Sign::Minus, BigUint::new(vec![67])),
+ BigInt::from_biguint(Sign::Plus, BigUint::new(vec![100]))
+ ))
);
#[cfg(feature = "rand")]
- assert!(
+ drop(
Evaluator::new(
b"rand()",
&mut Cache::new(),
&mut None,
&mut Vec::new(),
- &mut rand::rng()
+ &mut rand::rng(),
)
.get_term()
- .is_ok()
+ .unwrap(),
);
#[cfg(feature = "rand")]
- assert!(
+ drop(
Evaluator::new(
b"rand(-13/93, 833)",
&mut Cache::new(),
@@ -2172,1181 +2088,1023 @@ mod tests {
&mut rand::rng(),
)
.get_term()
- .is_ok()
+ .unwrap(),
);
#[cfg(not(feature = "rand"))]
- assert!(
- match Evaluator::new(b"rand()", &mut Cache::new(), &mut None, &mut Vec::new())
- .get_term()
- .unwrap_err()
- {
- MissingTerm(i) => i == 0,
- _ => false,
- }
+ assert_eq!(
+ Evaluator::new(b"rand()", &mut Cache::new(), &mut None, &mut Vec::new()).get_term(),
+ Err(MissingTerm(0))
);
#[cfg(not(feature = "rand"))]
- assert!(
- Evaluator::new(b"|4|", &mut Cache::new(), &mut None, &mut Vec::new())
- .get_term()
- .unwrap()
- == Ratio::from_integer(BigInt::from_biguint(Sign::Plus, BigUint::new(vec![4])))
+ assert_eq!(
+ Evaluator::new(b"|4|", &mut Cache::new(), &mut None, &mut Vec::new()).get_term(),
+ Ok(Ratio::from_integer(BigInt::from_biguint(
+ Sign::Plus,
+ BigUint::new(vec![4])
+ )))
);
// Terminal expressions do no clean up before or after.
#[cfg(not(feature = "rand"))]
- assert!(
- match Evaluator::new(b" 2", &mut Cache::new(), &mut None, &mut Vec::new())
- .get_term()
- .unwrap_err()
- {
- MissingTerm(i) => i == 0,
- _ => false,
- }
+ assert_eq!(
+ Evaluator::new(b" 2", &mut Cache::new(), &mut None, &mut Vec::new()).get_term(),
+ Err(MissingTerm(0))
);
#[cfg(not(feature = "rand"))]
let mut prev = None;
#[cfg(not(feature = "rand"))]
let mut cache = Cache::new();
#[cfg(not(feature = "rand"))]
- drop(
- Evaluator::new(b"1\n", &mut cache, &mut prev, &mut Vec::new())
+ {
+ // Quick check that `Ok` is returned.
+ _ = Evaluator::new(b"1\n", &mut cache, &mut prev, &mut Vec::new())
.evaluate()
- .unwrap(),
- );
- #[cfg(not(feature = "rand"))]
- drop(
- Evaluator::new(b"s\n", &mut cache, &mut prev, &mut Vec::new())
+ .unwrap();
+ // Quick check that `Ok` is returned.
+ _ = Evaluator::new(b"s\n", &mut cache, &mut prev, &mut Vec::new())
.evaluate()
- .unwrap(),
- );
+ .unwrap();
+ }
#[cfg(not(feature = "rand"))]
- assert!(
- Evaluator::new(b"@", &mut cache, &mut prev, &mut Vec::new())
- .get_term()
- .unwrap()
- == Ratio::from_integer(BigInt::from_biguint(Sign::Plus, BigUint::new(vec![1])))
+ assert_eq!(
+ Evaluator::new(b"@", &mut cache, &mut prev, &mut Vec::new()).get_term(),
+ Ok(Ratio::from_integer(BigInt::from_biguint(
+ Sign::Plus,
+ BigUint::new(vec![1])
+ )))
);
}
+ #[expect(clippy::unwrap_used, reason = "comments justify correctness")]
#[cfg(not(feature = "rand"))]
#[test]
fn factorial() {
// Negative integer is not allowed.
- assert!(
- match Evaluator::new(b"(-1)!", &mut Cache::new(), &mut None, &mut Vec::new())
- .get_fact()
- .unwrap_err()
- {
- NotNonNegIntFact(i) => i == 5,
- _ => false,
- }
+ assert_eq!(
+ Evaluator::new(b"(-1)!", &mut Cache::new(), &mut None, &mut Vec::new()).get_fact(),
+ Err(NotNonNegIntFact(5))
);
// Non-integer is not allowed.
- assert!(
- match Evaluator::new(b"2.5!", &mut Cache::new(), &mut None, &mut Vec::new())
- .get_fact()
- .unwrap_err()
- {
- NotNonNegIntFact(i) => i == 4,
- _ => false,
- }
+ assert_eq!(
+ Evaluator::new(b"2.5!", &mut Cache::new(), &mut None, &mut Vec::new()).get_fact(),
+ Err(NotNonNegIntFact(4))
);
// factorials always become terminal expressions eventually.
- assert!(
- Evaluator::new(b"7", &mut Cache::new(), &mut None, &mut Vec::new())
- .get_fact()
- .unwrap()
- == Ratio::from_integer(BigInt::from_biguint(Sign::Plus, BigUint::new(vec![7])))
+ assert_eq!(
+ Evaluator::new(b"7", &mut Cache::new(), &mut None, &mut Vec::new()).get_fact(),
+ Ok(Ratio::from_integer(BigInt::from_biguint(
+ Sign::Plus,
+ BigUint::new(vec![7])
+ )))
);
- assert!(
- Evaluator::new(b"(7)", &mut Cache::new(), &mut None, &mut Vec::new())
- .get_fact()
- .unwrap()
- == Ratio::from_integer(BigInt::from_biguint(Sign::Plus, BigUint::new(vec![7])))
+ assert_eq!(
+ Evaluator::new(b"(7)", &mut Cache::new(), &mut None, &mut Vec::new()).get_fact(),
+ Ok(Ratio::from_integer(BigInt::from_biguint(
+ Sign::Plus,
+ BigUint::new(vec![7])
+ )))
);
- assert!(
- Evaluator::new(b"|7|", &mut Cache::new(), &mut None, &mut Vec::new())
- .get_fact()
- .unwrap()
- == Ratio::from_integer(BigInt::from_biguint(Sign::Plus, BigUint::new(vec![7])))
+ assert_eq!(
+ Evaluator::new(b"|7|", &mut Cache::new(), &mut None, &mut Vec::new()).get_fact(),
+ Ok(Ratio::from_integer(BigInt::from_biguint(
+ Sign::Plus,
+ BigUint::new(vec![7])
+ )))
);
let mut prev = None;
let mut cache = Cache::new();
- drop(
- Evaluator::new(b"3\n", &mut cache, &mut prev, &mut Vec::new())
- .evaluate()
- .unwrap(),
- );
- drop(
- Evaluator::new(b"s\n", &mut cache, &mut prev, &mut Vec::new())
- .evaluate()
- .unwrap(),
- );
- assert!(
- Evaluator::new(b"@!", &mut cache, &mut prev, &mut Vec::new())
- .get_fact()
- .unwrap()
- == Ratio::from_integer(BigInt::from_biguint(Sign::Plus, BigUint::new(vec![6])))
+ // Quick check that `Ok` is returned.
+ _ = Evaluator::new(b"3\n", &mut cache, &mut prev, &mut Vec::new())
+ .evaluate()
+ .unwrap();
+ // Quick check that `Ok` is returned.
+ _ = Evaluator::new(b"s\n", &mut cache, &mut prev, &mut Vec::new())
+ .evaluate()
+ .unwrap();
+ assert_eq!(
+ Evaluator::new(b"@!", &mut cache, &mut prev, &mut Vec::new()).get_fact(),
+ Ok(Ratio::from_integer(BigInt::from_biguint(
+ Sign::Plus,
+ BigUint::new(vec![6])
+ )))
);
- assert!(
- Evaluator::new(b"@", &mut cache, &mut prev, &mut Vec::new())
- .get_fact()
- .unwrap()
- == Ratio::from_integer(BigInt::from_biguint(Sign::Plus, BigUint::new(vec![3])))
+ assert_eq!(
+ Evaluator::new(b"@", &mut cache, &mut prev, &mut Vec::new()).get_fact(),
+ Ok(Ratio::from_integer(BigInt::from_biguint(
+ Sign::Plus,
+ BigUint::new(vec![3])
+ )))
);
// 0! = 1.
- assert!(
- Evaluator::new(b"0.0!", &mut Cache::new(), &mut None, &mut Vec::new())
- .get_fact()
- .unwrap()
- == Ratio::from_integer(BigInt::from_biguint(Sign::Plus, BigUint::new(vec![1])))
+ assert_eq!(
+ Evaluator::new(b"0.0!", &mut Cache::new(), &mut None, &mut Vec::new()).get_fact(),
+ Ok(Ratio::from_integer(BigInt::from_biguint(
+ Sign::Plus,
+ BigUint::new(vec![1])
+ )))
);
// 1! = 1.
- assert!(
- Evaluator::new(b"1!", &mut Cache::new(), &mut None, &mut Vec::new())
- .get_fact()
- .unwrap()
- == Ratio::from_integer(BigInt::from_biguint(Sign::Plus, BigUint::new(vec![1])))
+ assert_eq!(
+ Evaluator::new(b"1!", &mut Cache::new(), &mut None, &mut Vec::new()).get_fact(),
+ Ok(Ratio::from_integer(BigInt::from_biguint(
+ Sign::Plus,
+ BigUint::new(vec![1])
+ )))
);
// 4! = 24, and whitespace is not consumed.
- assert!(
- Evaluator::new(b"4! \t", &mut Cache::new(), &mut None, &mut Vec::new())
- .get_fact()
- .unwrap()
- == Ratio::from_integer(BigInt::from_biguint(Sign::Plus, BigUint::new(vec![24])))
+ assert_eq!(
+ Evaluator::new(b"4! \t", &mut Cache::new(), &mut None, &mut Vec::new()).get_fact(),
+ Ok(Ratio::from_integer(BigInt::from_biguint(
+ Sign::Plus,
+ BigUint::new(vec![24])
+ )))
);
// Factorials can be chained.
- assert!(
- Evaluator::new(b"3!! ", &mut Cache::new(), &mut None, &mut Vec::new())
- .get_fact()
- .unwrap()
- == Ratio::from_integer(BigInt::from_biguint(Sign::Plus, BigUint::new(vec![720])))
+ assert_eq!(
+ Evaluator::new(b"3!! ", &mut Cache::new(), &mut None, &mut Vec::new()).get_fact(),
+ Ok(Ratio::from_integer(BigInt::from_biguint(
+ Sign::Plus,
+ BigUint::new(vec![720])
+ )))
);
// only factorial is consumed.
- assert!(
- Evaluator::new(b"2!+3", &mut Cache::new(), &mut None, &mut Vec::new())
- .get_fact()
- .unwrap()
- == Ratio::from_integer(BigInt::from_biguint(Sign::Plus, BigUint::new(vec![2])))
+ assert_eq!(
+ Evaluator::new(b"2!+3", &mut Cache::new(), &mut None, &mut Vec::new()).get_fact(),
+ Ok(Ratio::from_integer(BigInt::from_biguint(
+ Sign::Plus,
+ BigUint::new(vec![2])
+ )))
);
// Error since leading/trailing whitespace is not consumed by factorial or higher precedence expressions.
- assert!(
- match Evaluator::new(b" 2!", &mut Cache::new(), &mut None, &mut Vec::new())
- .get_fact()
- .unwrap_err()
- {
- MissingTerm(i) => i == 0,
- _ => false,
- }
+ assert_eq!(
+ Evaluator::new(b" 2!", &mut Cache::new(), &mut None, &mut Vec::new()).get_fact(),
+ Err(MissingTerm(0))
);
- assert!(
- match Evaluator::new(b"\t2!", &mut Cache::new(), &mut None, &mut Vec::new())
- .get_fact()
- .unwrap_err()
- {
- MissingTerm(i) => i == 0,
- _ => false,
- }
+ assert_eq!(
+ Evaluator::new(b"\t2!", &mut Cache::new(), &mut None, &mut Vec::new()).get_fact(),
+ Err(MissingTerm(0))
);
// Error since negation is not consumed by factorial or higher precedence expressions.
- assert!(
- match Evaluator::new(b"-2!", &mut Cache::new(), &mut None, &mut Vec::new())
- .get_fact()
- .unwrap_err()
- {
- MissingTerm(i) => i == 0,
- _ => false,
- }
+ assert_eq!(
+ Evaluator::new(b"-2!", &mut Cache::new(), &mut None, &mut Vec::new()).get_fact(),
+ Err(MissingTerm(0))
);
}
+ #[expect(
+ clippy::cognitive_complexity,
+ clippy::too_many_lines,
+ reason = "a lot to test"
+ )]
#[cfg(not(feature = "rand"))]
#[test]
fn exp() {
// 1 can be raised to anything and return 1.
// Also white space is ignored between operator.
- assert!(
- Evaluator::new(b"1 ^\t 0", &mut Cache::new(), &mut None, &mut Vec::new())
- .get_exps()
- .unwrap()
- == Ratio::from_integer(BigInt::from_biguint(Sign::Plus, BigUint::new(vec![1])))
+ assert_eq!(
+ Evaluator::new(b"1 ^\t 0", &mut Cache::new(), &mut None, &mut Vec::new()).get_exps(),
+ Ok(Ratio::from_integer(BigInt::from_biguint(
+ Sign::Plus,
+ BigUint::new(vec![1])
+ )))
);
- assert!(
- Evaluator::new(b"1^0.5", &mut Cache::new(), &mut None, &mut Vec::new())
- .get_exps()
- .unwrap()
- == Ratio::from_integer(BigInt::from_biguint(Sign::Plus, BigUint::new(vec![1])))
+ assert_eq!(
+ Evaluator::new(b"1^0.5", &mut Cache::new(), &mut None, &mut Vec::new()).get_exps(),
+ Ok(Ratio::from_integer(BigInt::from_biguint(
+ Sign::Plus,
+ BigUint::new(vec![1])
+ )))
);
- assert!(
- Evaluator::new(b"1^(-1/2)", &mut Cache::new(), &mut None, &mut Vec::new())
- .get_exps()
- .unwrap()
- == Ratio::from_integer(BigInt::from_biguint(Sign::Plus, BigUint::new(vec![1])))
+ assert_eq!(
+ Evaluator::new(b"1^(-1/2)", &mut Cache::new(), &mut None, &mut Vec::new()).get_exps(),
+ Ok(Ratio::from_integer(BigInt::from_biguint(
+ Sign::Plus,
+ BigUint::new(vec![1])
+ )))
);
- assert!(
- Evaluator::new(b"1.0^(-2)", &mut Cache::new(), &mut None, &mut Vec::new())
- .get_exps()
- .unwrap()
- == Ratio::from_integer(BigInt::from_biguint(Sign::Plus, BigUint::new(vec![1])))
+ assert_eq!(
+ Evaluator::new(b"1.0^(-2)", &mut Cache::new(), &mut None, &mut Vec::new()).get_exps(),
+ Ok(Ratio::from_integer(BigInt::from_biguint(
+ Sign::Plus,
+ BigUint::new(vec![1])
+ )))
);
// 0 can be raised to any non-negative value and will always return 0 unless raised to 0 which will return 1.
- assert!(
- Evaluator::new(b"0^0", &mut Cache::new(), &mut None, &mut Vec::new())
- .get_exps()
- .unwrap()
- == Ratio::from_integer(BigInt::from_biguint(Sign::Plus, BigUint::new(vec![1])))
+ assert_eq!(
+ Evaluator::new(b"0^0", &mut Cache::new(), &mut None, &mut Vec::new()).get_exps(),
+ Ok(Ratio::from_integer(BigInt::from_biguint(
+ Sign::Plus,
+ BigUint::new(vec![1])
+ )))
);
- assert!(
- Evaluator::new(b"0^1", &mut Cache::new(), &mut None, &mut Vec::new())
- .get_exps()
- .unwrap()
- == Ratio::from_integer(BigInt::from_biguint(Sign::NoSign, BigUint::new(vec![0])))
+ assert_eq!(
+ Evaluator::new(b"0^1", &mut Cache::new(), &mut None, &mut Vec::new()).get_exps(),
+ Ok(Ratio::from_integer(BigInt::from_biguint(
+ Sign::NoSign,
+ BigUint::new(vec![0])
+ )))
);
- assert!(
- Evaluator::new(b"0^0.5", &mut Cache::new(), &mut None, &mut Vec::new())
- .get_exps()
- .unwrap()
- == Ratio::from_integer(BigInt::from_biguint(Sign::NoSign, BigUint::new(vec![0])))
+ assert_eq!(
+ Evaluator::new(b"0^0.5", &mut Cache::new(), &mut None, &mut Vec::new()).get_exps(),
+ Ok(Ratio::from_integer(BigInt::from_biguint(
+ Sign::NoSign,
+ BigUint::new(vec![0])
+ )))
);
// Anything else can only be raised to integers.
- assert!(
- Evaluator::new(b"4^0", &mut Cache::new(), &mut None, &mut Vec::new())
- .get_exps()
- .unwrap()
- == Ratio::from_integer(BigInt::from_biguint(Sign::Plus, BigUint::new(vec![1])))
- );
- assert!(
- Evaluator::new(b"4^1", &mut Cache::new(), &mut None, &mut Vec::new())
- .get_exps()
- .unwrap()
- == Ratio::from_integer(BigInt::from_biguint(Sign::Plus, BigUint::new(vec![4])))
- );
- assert!(
- Evaluator::new(b"4^(-2)", &mut Cache::new(), &mut None, &mut Vec::new())
- .get_exps()
- .unwrap()
- == Ratio::new(
- BigInt::from_biguint(Sign::Plus, BigUint::new(vec![1])),
- BigInt::from_biguint(Sign::Plus, BigUint::new(vec![16]))
- )
- );
- assert!(
- Evaluator::new(b"(-4)^0", &mut Cache::new(), &mut None, &mut Vec::new())
- .get_exps()
- .unwrap()
- == Ratio::from_integer(BigInt::from_biguint(Sign::Plus, BigUint::new(vec![1])))
- );
- assert!(
- Evaluator::new(b"(-4)^1", &mut Cache::new(), &mut None, &mut Vec::new())
- .get_exps()
- .unwrap()
- == Ratio::from_integer(BigInt::from_biguint(Sign::Minus, BigUint::new(vec![4])))
- );
- assert!(
- Evaluator::new(b"(-4)^2", &mut Cache::new(), &mut None, &mut Vec::new())
- .get_exps()
- .unwrap()
- == Ratio::from_integer(BigInt::from_biguint(Sign::Plus, BigUint::new(vec![16])))
- );
- assert!(
- Evaluator::new(b"(-4)^(-2)", &mut Cache::new(), &mut None, &mut Vec::new())
- .get_exps()
- .unwrap()
- == Ratio::new(
- BigInt::from_biguint(Sign::Plus, BigUint::new(vec![1])),
- BigInt::from_biguint(Sign::Plus, BigUint::new(vec![16]))
- )
+ assert_eq!(
+ Evaluator::new(b"4^0", &mut Cache::new(), &mut None, &mut Vec::new()).get_exps(),
+ Ok(Ratio::from_integer(BigInt::from_biguint(
+ Sign::Plus,
+ BigUint::new(vec![1])
+ )))
);
- assert!(
- Evaluator::new(b"(-4)^(-3)", &mut Cache::new(), &mut None, &mut Vec::new())
- .get_exps()
- .unwrap()
- == Ratio::new(
- BigInt::from_biguint(Sign::Minus, BigUint::new(vec![1])),
- BigInt::from_biguint(Sign::Plus, BigUint::new(vec![64]))
- )
+ assert_eq!(
+ Evaluator::new(b"4^1", &mut Cache::new(), &mut None, &mut Vec::new()).get_exps(),
+ Ok(Ratio::from_integer(BigInt::from_biguint(
+ Sign::Plus,
+ BigUint::new(vec![4])
+ )))
);
- assert!(
- Evaluator::new(b"(2/3)^0", &mut Cache::new(), &mut None, &mut Vec::new())
- .get_exps()
- .unwrap()
- == Ratio::from_integer(BigInt::from_biguint(Sign::Plus, BigUint::new(vec![1])))
+ assert_eq!(
+ Evaluator::new(b"4^(-2)", &mut Cache::new(), &mut None, &mut Vec::new()).get_exps(),
+ Ok(Ratio::new(
+ BigInt::from_biguint(Sign::Plus, BigUint::new(vec![1])),
+ BigInt::from_biguint(Sign::Plus, BigUint::new(vec![16]))
+ ))
);
- assert!(
- Evaluator::new(b"(2/3)^(2)", &mut Cache::new(), &mut None, &mut Vec::new())
- .get_exps()
- .unwrap()
- == Ratio::new(
- BigInt::from_biguint(Sign::Plus, BigUint::new(vec![4])),
- BigInt::from_biguint(Sign::Plus, BigUint::new(vec![9]))
- )
+ assert_eq!(
+ Evaluator::new(b"(-4)^0", &mut Cache::new(), &mut None, &mut Vec::new()).get_exps(),
+ Ok(Ratio::from_integer(BigInt::from_biguint(
+ Sign::Plus,
+ BigUint::new(vec![1])
+ )))
);
- assert!(
- Evaluator::new(b"(2/3)^(-3)", &mut Cache::new(), &mut None, &mut Vec::new())
- .get_exps()
- .unwrap()
- == Ratio::new(
- BigInt::from_biguint(Sign::Plus, BigUint::new(vec![27])),
- BigInt::from_biguint(Sign::Plus, BigUint::new(vec![8]))
- )
+ assert_eq!(
+ Evaluator::new(b"(-4)^1", &mut Cache::new(), &mut None, &mut Vec::new()).get_exps(),
+ Ok(Ratio::from_integer(BigInt::from_biguint(
+ Sign::Minus,
+ BigUint::new(vec![4])
+ )))
);
- assert!(
- Evaluator::new(b"(-2/3)^0", &mut Cache::new(), &mut None, &mut Vec::new())
- .get_exps()
- .unwrap()
- == Ratio::from_integer(BigInt::from_biguint(Sign::Plus, BigUint::new(vec![1])))
+ assert_eq!(
+ Evaluator::new(b"(-4)^2", &mut Cache::new(), &mut None, &mut Vec::new()).get_exps(),
+ Ok(Ratio::from_integer(BigInt::from_biguint(
+ Sign::Plus,
+ BigUint::new(vec![16])
+ )))
);
- assert!(
- Evaluator::new(b"(-2/3)^(2)", &mut Cache::new(), &mut None, &mut Vec::new())
- .get_exps()
- .unwrap()
- == Ratio::new(
- BigInt::from_biguint(Sign::Plus, BigUint::new(vec![4])),
- BigInt::from_biguint(Sign::Plus, BigUint::new(vec![9]))
- )
+ assert_eq!(
+ Evaluator::new(b"(-4)^(-2)", &mut Cache::new(), &mut None, &mut Vec::new()).get_exps(),
+ Ok(Ratio::new(
+ BigInt::from_biguint(Sign::Plus, BigUint::new(vec![1])),
+ BigInt::from_biguint(Sign::Plus, BigUint::new(vec![16]))
+ ))
+ );
+ assert_eq!(
+ Evaluator::new(b"(-4)^(-3)", &mut Cache::new(), &mut None, &mut Vec::new()).get_exps(),
+ Ok(Ratio::new(
+ BigInt::from_biguint(Sign::Minus, BigUint::new(vec![1])),
+ BigInt::from_biguint(Sign::Plus, BigUint::new(vec![64]))
+ ))
+ );
+ assert_eq!(
+ Evaluator::new(b"(2/3)^0", &mut Cache::new(), &mut None, &mut Vec::new()).get_exps(),
+ Ok(Ratio::from_integer(BigInt::from_biguint(
+ Sign::Plus,
+ BigUint::new(vec![1])
+ )))
);
- assert!(
- Evaluator::new(b"(-2/3)^(3)", &mut Cache::new(), &mut None, &mut Vec::new())
- .get_exps()
- .unwrap()
- == Ratio::new(
- BigInt::from_biguint(Sign::Minus, BigUint::new(vec![8])),
- BigInt::from_biguint(Sign::Plus, BigUint::new(vec![27]))
- )
+ assert_eq!(
+ Evaluator::new(b"(2/3)^(2)", &mut Cache::new(), &mut None, &mut Vec::new()).get_exps(),
+ Ok(Ratio::new(
+ BigInt::from_biguint(Sign::Plus, BigUint::new(vec![4])),
+ BigInt::from_biguint(Sign::Plus, BigUint::new(vec![9]))
+ ))
+ );
+ assert_eq!(
+ Evaluator::new(b"(2/3)^(-3)", &mut Cache::new(), &mut None, &mut Vec::new()).get_exps(),
+ Ok(Ratio::new(
+ BigInt::from_biguint(Sign::Plus, BigUint::new(vec![27])),
+ BigInt::from_biguint(Sign::Plus, BigUint::new(vec![8]))
+ ))
+ );
+ assert_eq!(
+ Evaluator::new(b"(-2/3)^0", &mut Cache::new(), &mut None, &mut Vec::new()).get_exps(),
+ Ok(Ratio::from_integer(BigInt::from_biguint(
+ Sign::Plus,
+ BigUint::new(vec![1])
+ )))
);
- assert!(
+ assert_eq!(
+ Evaluator::new(b"(-2/3)^(2)", &mut Cache::new(), &mut None, &mut Vec::new()).get_exps(),
+ Ok(Ratio::new(
+ BigInt::from_biguint(Sign::Plus, BigUint::new(vec![4])),
+ BigInt::from_biguint(Sign::Plus, BigUint::new(vec![9]))
+ ))
+ );
+ assert_eq!(
+ Evaluator::new(b"(-2/3)^(3)", &mut Cache::new(), &mut None, &mut Vec::new()).get_exps(),
+ Ok(Ratio::new(
+ BigInt::from_biguint(Sign::Minus, BigUint::new(vec![8])),
+ BigInt::from_biguint(Sign::Plus, BigUint::new(vec![27]))
+ ))
+ );
+ assert_eq!(
Evaluator::new(
b"(-2/3)^(-2)",
&mut Cache::new(),
&mut None,
&mut Vec::new()
)
- .get_exps()
- .unwrap()
- == Ratio::new(
- BigInt::from_biguint(Sign::Plus, BigUint::new(vec![9])),
- BigInt::from_biguint(Sign::Plus, BigUint::new(vec![4]))
- )
+ .get_exps(),
+ Ok(Ratio::new(
+ BigInt::from_biguint(Sign::Plus, BigUint::new(vec![9])),
+ BigInt::from_biguint(Sign::Plus, BigUint::new(vec![4]))
+ ))
);
- assert!(
+ assert_eq!(
Evaluator::new(
b"(-2/3)^(-3)",
&mut Cache::new(),
&mut None,
&mut Vec::new()
)
- .get_exps()
- .unwrap()
- == Ratio::new(
- BigInt::from_biguint(Sign::Minus, BigUint::new(vec![27])),
- BigInt::from_biguint(Sign::Plus, BigUint::new(vec![8]))
- )
+ .get_exps(),
+ Ok(Ratio::new(
+ BigInt::from_biguint(Sign::Minus, BigUint::new(vec![27])),
+ BigInt::from_biguint(Sign::Plus, BigUint::new(vec![8]))
+ ))
);
- assert!(
+ assert_eq!(
Evaluator::new(
b"(4/9)^(-1/2)",
&mut Cache::new(),
&mut None,
&mut Vec::new()
)
- .get_exps()
- .unwrap()
- == Ratio::new(
- BigInt::from_biguint(Sign::Plus, BigUint::new(vec![3])),
- BigInt::from_biguint(Sign::Plus, BigUint::new(vec![2]))
- )
+ .get_exps(),
+ Ok(Ratio::new(
+ BigInt::from_biguint(Sign::Plus, BigUint::new(vec![3])),
+ BigInt::from_biguint(Sign::Plus, BigUint::new(vec![2]))
+ ))
);
// Error since 0 cannot be raised to a negative power.
- assert!(
- match Evaluator::new(b"0^(-1)", &mut Cache::new(), &mut None, &mut Vec::new())
- .get_exps()
- .unwrap_err()
- {
- ExpDivByZero(i) => i == 6,
- _ => false,
- }
+ assert_eq!(
+ Evaluator::new(b"0^(-1)", &mut Cache::new(), &mut None, &mut Vec::new()).get_exps(),
+ Err(ExpDivByZero(6))
);
// Error since anything other than 0 or 1 cannot be raised to a non-integer power or (+/-) 1/2.
- assert!(
- match Evaluator::new(b"2^(1/3)", &mut Cache::new(), &mut None, &mut Vec::new())
- .get_exps()
- .unwrap_err()
- {
- ExpIsNotIntOrOneHalf(i) => i == 7,
- _ => false,
- }
+ assert_eq!(
+ Evaluator::new(b"2^(1/3)", &mut Cache::new(), &mut None, &mut Vec::new()).get_exps(),
+ Err(ExpIsNotIntOrOneHalf(7))
);
// When exponent is (+/-) 1/2, base has to be the square of a rational number.
- assert!(
- match Evaluator::new(b"2^(1/2)", &mut Cache::new(), &mut None, &mut Vec::new())
- .get_exps()
- .unwrap_err()
- {
- SqrtDoesNotExist(i) => i == 7,
- _ => false,
- }
+ assert_eq!(
+ Evaluator::new(b"2^(1/2)", &mut Cache::new(), &mut None, &mut Vec::new()).get_exps(),
+ Err(SqrtDoesNotExist(7))
);
// exps always become factorials eventually.
- assert!(
- Evaluator::new(b"3!", &mut Cache::new(), &mut None, &mut Vec::new())
- .get_exps()
- .unwrap()
- == Ratio::from_integer(BigInt::from_biguint(Sign::Plus, BigUint::new(vec![6])))
+ assert_eq!(
+ Evaluator::new(b"3!", &mut Cache::new(), &mut None, &mut Vec::new()).get_exps(),
+ Ok(Ratio::from_integer(BigInt::from_biguint(
+ Sign::Plus,
+ BigUint::new(vec![6])
+ )))
);
// exponentiation has lower precedence than factorials.
- assert!(
- Evaluator::new(b"2^3!", &mut Cache::new(), &mut None, &mut Vec::new())
- .get_exps()
- .unwrap()
- == Ratio::from_integer(BigInt::from_biguint(Sign::Plus, BigUint::new(vec![64])))
+ assert_eq!(
+ Evaluator::new(b"2^3!", &mut Cache::new(), &mut None, &mut Vec::new()).get_exps(),
+ Ok(Ratio::from_integer(BigInt::from_biguint(
+ Sign::Plus,
+ BigUint::new(vec![64])
+ )))
);
- assert!(
- Evaluator::new(b"3!^2", &mut Cache::new(), &mut None, &mut Vec::new())
- .get_exps()
- .unwrap()
- == Ratio::from_integer(BigInt::from_biguint(Sign::Plus, BigUint::new(vec![36])))
+ assert_eq!(
+ Evaluator::new(b"3!^2", &mut Cache::new(), &mut None, &mut Vec::new()).get_exps(),
+ Ok(Ratio::from_integer(BigInt::from_biguint(
+ Sign::Plus,
+ BigUint::new(vec![36])
+ )))
);
// Error since leading/trailing whitespace is not consumed by exponentiation or higher precedence expressions.
- assert!(
- match Evaluator::new(b" 2^2", &mut Cache::new(), &mut None, &mut Vec::new())
- .get_exps()
- .unwrap_err()
- {
- MissingTerm(i) => i == 0,
- _ => false,
- }
+ assert_eq!(
+ Evaluator::new(b" 2^2", &mut Cache::new(), &mut None, &mut Vec::new()).get_exps(),
+ Err(MissingTerm(0))
);
- assert!(
- match Evaluator::new(b"\t2^2", &mut Cache::new(), &mut None, &mut Vec::new())
- .get_exps()
- .unwrap_err()
- {
- MissingTerm(i) => i == 0,
- _ => false,
- }
+ assert_eq!(
+ Evaluator::new(b"\t2^2", &mut Cache::new(), &mut None, &mut Vec::new()).get_exps(),
+ Err(MissingTerm(0))
);
}
#[cfg(not(feature = "rand"))]
#[test]
fn neg() {
- assert!(
- Evaluator::new(b"-1", &mut Cache::new(), &mut None, &mut Vec::new())
- .get_neg()
- .unwrap()
- == Ratio::from_integer(BigInt::from_biguint(Sign::Minus, BigUint::new(vec![1])))
+ assert_eq!(
+ Evaluator::new(b"-1", &mut Cache::new(), &mut None, &mut Vec::new()).get_neg(),
+ Ok(Ratio::from_integer(BigInt::from_biguint(
+ Sign::Minus,
+ BigUint::new(vec![1])
+ )))
);
- assert!(
- Evaluator::new(b"- \t - 1", &mut Cache::new(), &mut None, &mut Vec::new())
- .get_neg()
- .unwrap()
- == Ratio::from_integer(BigInt::from_biguint(Sign::Plus, BigUint::new(vec![1])))
+ assert_eq!(
+ Evaluator::new(b"- \t - 1", &mut Cache::new(), &mut None, &mut Vec::new()).get_neg(),
+ Ok(Ratio::from_integer(BigInt::from_biguint(
+ Sign::Plus,
+ BigUint::new(vec![1])
+ )))
);
- assert!(
- Evaluator::new(b"-0", &mut Cache::new(), &mut None, &mut Vec::new())
- .get_neg()
- .unwrap()
- == Ratio::from_integer(BigInt::from_biguint(
- Sign::NoSign,
- BigUint::new(Vec::new())
- ))
+ assert_eq!(
+ Evaluator::new(b"-0", &mut Cache::new(), &mut None, &mut Vec::new()).get_neg(),
+ Ok(Ratio::from_integer(BigInt::from_biguint(
+ Sign::NoSign,
+ BigUint::new(Vec::new())
+ )))
);
// negation has lower precedence than exponentiation.
- assert!(
- Evaluator::new(b"-2^2", &mut Cache::new(), &mut None, &mut Vec::new())
- .get_neg()
- .unwrap()
- == Ratio::from_integer(BigInt::from_biguint(Sign::Minus, BigUint::new(vec![4])))
+ assert_eq!(
+ Evaluator::new(b"-2^2", &mut Cache::new(), &mut None, &mut Vec::new()).get_neg(),
+ Ok(Ratio::from_integer(BigInt::from_biguint(
+ Sign::Minus,
+ BigUint::new(vec![4])
+ )))
);
// negation always becomes exponentiation eventually.
- assert!(
- Evaluator::new(b"2.0^2.0", &mut Cache::new(), &mut None, &mut Vec::new())
- .get_neg()
- .unwrap()
- == Ratio::from_integer(BigInt::from_biguint(Sign::Plus, BigUint::new(vec![4])))
+ assert_eq!(
+ Evaluator::new(b"2.0^2.0", &mut Cache::new(), &mut None, &mut Vec::new()).get_neg(),
+ Ok(Ratio::from_integer(BigInt::from_biguint(
+ Sign::Plus,
+ BigUint::new(vec![4])
+ )))
);
// Error since leading/trailing whitespace is not consumed by exponentiation or higher precedence expressions.
- assert!(
- match Evaluator::new(b" -2", &mut Cache::new(), &mut None, &mut Vec::new())
- .get_neg()
- .unwrap_err()
- {
- MissingTerm(i) => i == 0,
- _ => false,
- }
+ assert_eq!(
+ Evaluator::new(b" -2", &mut Cache::new(), &mut None, &mut Vec::new()).get_neg(),
+ Err(MissingTerm(0))
);
- assert!(
- match Evaluator::new(b"\t-2", &mut Cache::new(), &mut None, &mut Vec::new())
- .get_neg()
- .unwrap_err()
- {
- MissingTerm(i) => i == 0,
- _ => false,
- }
+ assert_eq!(
+ Evaluator::new(b"\t-2", &mut Cache::new(), &mut None, &mut Vec::new()).get_neg(),
+ Err(MissingTerm(0))
);
}
+ #[expect(
+ clippy::cognitive_complexity,
+ clippy::too_many_lines,
+ reason = "a lot to test"
+ )]
#[cfg(not(feature = "rand"))]
#[test]
fn mult() {
- assert!(
- Evaluator::new(b"2 * 3", &mut Cache::new(), &mut None, &mut Vec::new())
- .get_mults()
- .unwrap()
- == Ratio::from_integer(BigInt::from_biguint(Sign::Plus, BigUint::new(vec![6])))
+ assert_eq!(
+ Evaluator::new(b"2 * 3", &mut Cache::new(), &mut None, &mut Vec::new()).get_mults(),
+ Ok(Ratio::from_integer(BigInt::from_biguint(
+ Sign::Plus,
+ BigUint::new(vec![6])
+ )))
);
- assert!(
+ assert_eq!(
Evaluator::new(
b"-2 * \t 3",
&mut Cache::new(),
&mut None,
&mut Vec::new()
)
- .get_mults()
- .unwrap()
- == Ratio::from_integer(BigInt::from_biguint(Sign::Minus, BigUint::new(vec![6])))
+ .get_mults(),
+ Ok(Ratio::from_integer(BigInt::from_biguint(
+ Sign::Minus,
+ BigUint::new(vec![6])
+ )))
);
- assert!(
+ assert_eq!(
Evaluator::new(
b"2\t * -3.0",
&mut Cache::new(),
&mut None,
&mut Vec::new()
)
- .get_mults()
- .unwrap()
- == Ratio::from_integer(BigInt::from_biguint(Sign::Minus, BigUint::new(vec![6])))
+ .get_mults(),
+ Ok(Ratio::from_integer(BigInt::from_biguint(
+ Sign::Minus,
+ BigUint::new(vec![6])
+ )))
);
- assert!(
- Evaluator::new(b"-2.5*-3.5", &mut Cache::new(), &mut None, &mut Vec::new())
- .get_mults()
- .unwrap()
- == Ratio::new(
- BigInt::from_biguint(Sign::Plus, BigUint::new(vec![35])),
- BigInt::from_biguint(Sign::Plus, BigUint::new(vec![4]))
- )
+ assert_eq!(
+ Evaluator::new(b"-2.5*-3.5", &mut Cache::new(), &mut None, &mut Vec::new()).get_mults(),
+ Ok(Ratio::new(
+ BigInt::from_biguint(Sign::Plus, BigUint::new(vec![35])),
+ BigInt::from_biguint(Sign::Plus, BigUint::new(vec![4]))
+ ))
);
- assert!(
+ assert_eq!(
Evaluator::new(b"4.0\t / 6", &mut Cache::new(), &mut None, &mut Vec::new())
- .get_mults()
- .unwrap()
- == Ratio::new(
- BigInt::from_biguint(Sign::Plus, BigUint::new(vec![2])),
- BigInt::from_biguint(Sign::Plus, BigUint::new(vec![3]))
- )
- );
- assert!(
- Evaluator::new(b"6/3", &mut Cache::new(), &mut None, &mut Vec::new())
- .get_mults()
- .unwrap()
- == Ratio::from_integer(BigInt::from_biguint(Sign::Plus, BigUint::new(vec![2])))
+ .get_mults(),
+ Ok(Ratio::new(
+ BigInt::from_biguint(Sign::Plus, BigUint::new(vec![2])),
+ BigInt::from_biguint(Sign::Plus, BigUint::new(vec![3]))
+ ))
+ );
+ assert_eq!(
+ Evaluator::new(b"6/3", &mut Cache::new(), &mut None, &mut Vec::new()).get_mults(),
+ Ok(Ratio::from_integer(BigInt::from_biguint(
+ Sign::Plus,
+ BigUint::new(vec![2])
+ )))
);
- assert!(
- Evaluator::new(b"-6/3", &mut Cache::new(), &mut None, &mut Vec::new())
- .get_mults()
- .unwrap()
- == Ratio::from_integer(BigInt::from_biguint(Sign::Minus, BigUint::new(vec![2])))
+ assert_eq!(
+ Evaluator::new(b"-6/3", &mut Cache::new(), &mut None, &mut Vec::new()).get_mults(),
+ Ok(Ratio::from_integer(BigInt::from_biguint(
+ Sign::Minus,
+ BigUint::new(vec![2])
+ )))
);
- assert!(
- Evaluator::new(b"6/-3", &mut Cache::new(), &mut None, &mut Vec::new())
- .get_mults()
- .unwrap()
- == Ratio::from_integer(BigInt::from_biguint(Sign::Minus, BigUint::new(vec![2])))
+ assert_eq!(
+ Evaluator::new(b"6/-3", &mut Cache::new(), &mut None, &mut Vec::new()).get_mults(),
+ Ok(Ratio::from_integer(BigInt::from_biguint(
+ Sign::Minus,
+ BigUint::new(vec![2])
+ )))
);
- assert!(
+ assert_eq!(
Evaluator::new(
b"- 6 /\t - 3",
&mut Cache::new(),
&mut None,
&mut Vec::new()
)
- .get_mults()
- .unwrap()
- == Ratio::from_integer(BigInt::from_biguint(Sign::Plus, BigUint::new(vec![2])))
+ .get_mults(),
+ Ok(Ratio::from_integer(BigInt::from_biguint(
+ Sign::Plus,
+ BigUint::new(vec![2])
+ )))
);
// Number literals are not strictly equivalent to "ratios" as "ratios" don't exist (i.e., 2/3 is not the ratio of 2 to 3 but is the rational number two divided by the rational number 3).
assert!(
Evaluator::new(b"1/1.5", &mut Cache::new(), &mut None, &mut Vec::new())
.get_mults()
- .unwrap()
- != Evaluator::new(b"1/3/2", &mut Cache::new(), &mut None, &mut Vec::new())
- .get_mults()
- .unwrap()
+ .is_ok_and(|r| {
+ Evaluator::new(b"1/3/2", &mut Cache::new(), &mut None, &mut Vec::new())
+ .get_mults()
+ .is_ok_and(|r2| r != r2)
+ })
);
assert!(
Evaluator::new(b"1/1.5", &mut Cache::new(), &mut None, &mut Vec::new())
.get_mults()
- .unwrap()
- == Evaluator::new(b"1/(3/2)", &mut Cache::new(), &mut None, &mut Vec::new())
- .get_mults()
- .unwrap()
+ .is_ok_and(|r| {
+ Evaluator::new(b"1/(3/2)", &mut Cache::new(), &mut None, &mut Vec::new())
+ .get_mults()
+ .is_ok_and(|r2| r == r2)
+ })
);
// multiplication always becomes negation eventually.
- assert!(
- Evaluator::new(b"-2.0", &mut Cache::new(), &mut None, &mut Vec::new())
- .get_mults()
- .unwrap()
- == Ratio::from_integer(BigInt::from_biguint(Sign::Minus, BigUint::new(vec![2])))
+ assert_eq!(
+ Evaluator::new(b"-2.0", &mut Cache::new(), &mut None, &mut Vec::new()).get_mults(),
+ Ok(Ratio::from_integer(BigInt::from_biguint(
+ Sign::Minus,
+ BigUint::new(vec![2])
+ )))
);
// Error since leading/trailing whitespace is not consumed by multiplication or higher precedence expressions.
- assert!(
- match Evaluator::new(b" 2*2", &mut Cache::new(), &mut None, &mut Vec::new())
- .get_mults()
- .unwrap_err()
- {
- MissingTerm(i) => i == 0,
- _ => false,
- }
+ assert_eq!(
+ Evaluator::new(b" 2*2", &mut Cache::new(), &mut None, &mut Vec::new()).get_mults(),
+ Err(MissingTerm(0))
);
- assert!(
- match Evaluator::new(b"\t2/2", &mut Cache::new(), &mut None, &mut Vec::new())
- .get_mults()
- .unwrap_err()
- {
- MissingTerm(i) => i == 0,
- _ => false,
- }
+ assert_eq!(
+ Evaluator::new(b"\t2/2", &mut Cache::new(), &mut None, &mut Vec::new()).get_mults(),
+ Err(MissingTerm(0))
);
- assert!(
+ assert_eq!(
Evaluator::new(
b"4.0\t mod 6",
&mut Cache::new(),
&mut None,
&mut Vec::new()
)
- .get_mults()
- .unwrap()
- == Ratio::from_integer(BigInt::from_biguint(Sign::Plus, BigUint::new(vec![4])),)
+ .get_mults(),
+ Ok(Ratio::from_integer(BigInt::from_biguint(
+ Sign::Plus,
+ BigUint::new(vec![4])
+ ),))
);
- assert!(
- Evaluator::new(b"5 mod 3", &mut Cache::new(), &mut None, &mut Vec::new())
- .get_mults()
- .unwrap()
- == Ratio::from_integer(BigInt::from_biguint(Sign::Plus, BigUint::new(vec![2])))
+ assert_eq!(
+ Evaluator::new(b"5 mod 3", &mut Cache::new(), &mut None, &mut Vec::new()).get_mults(),
+ Ok(Ratio::from_integer(BigInt::from_biguint(
+ Sign::Plus,
+ BigUint::new(vec![2])
+ )))
);
- assert!(
- Evaluator::new(b"-5 mod 3", &mut Cache::new(), &mut None, &mut Vec::new())
- .get_mults()
- .unwrap()
- == Ratio::from_integer(BigInt::from_biguint(Sign::Plus, BigUint::new(vec![1])))
+ assert_eq!(
+ Evaluator::new(b"-5 mod 3", &mut Cache::new(), &mut None, &mut Vec::new()).get_mults(),
+ Ok(Ratio::from_integer(BigInt::from_biguint(
+ Sign::Plus,
+ BigUint::new(vec![1])
+ )))
);
- assert!(
- Evaluator::new(b"5 mod -3", &mut Cache::new(), &mut None, &mut Vec::new())
- .get_mults()
- .unwrap()
- == Ratio::from_integer(BigInt::from_biguint(Sign::Plus, BigUint::new(vec![2])))
+ assert_eq!(
+ Evaluator::new(b"5 mod -3", &mut Cache::new(), &mut None, &mut Vec::new()).get_mults(),
+ Ok(Ratio::from_integer(BigInt::from_biguint(
+ Sign::Plus,
+ BigUint::new(vec![2])
+ )))
);
- assert!(
+ assert_eq!(
Evaluator::new(
b"-5 mod\t -3",
&mut Cache::new(),
&mut None,
&mut Vec::new()
)
- .get_mults()
- .unwrap()
- == Ratio::from_integer(BigInt::from_biguint(Sign::Plus, BigUint::new(vec![1])))
+ .get_mults(),
+ Ok(Ratio::from_integer(BigInt::from_biguint(
+ Sign::Plus,
+ BigUint::new(vec![1])
+ )))
);
// Cannot divide by 0.
- assert!(
- match Evaluator::new(b"2/0", &mut Cache::new(), &mut None, &mut Vec::new())
- .get_mults()
- .unwrap_err()
- {
- DivByZero(i) => i == 3,
- _ => false,
- }
+ assert_eq!(
+ Evaluator::new(b"2/0", &mut Cache::new(), &mut None, &mut Vec::new()).get_mults(),
+ Err(DivByZero(3))
);
- assert!(
- match Evaluator::new(b"2 mod 0", &mut Cache::new(), &mut None, &mut Vec::new())
- .get_mults()
- .unwrap_err()
- {
- ModZero(i) => i == 7,
- _ => false,
- }
+ assert_eq!(
+ Evaluator::new(b"2 mod 0", &mut Cache::new(), &mut None, &mut Vec::new()).get_mults(),
+ Err(ModZero(7))
);
// Right and left operands of mod must be integers.
- assert!(
- match Evaluator::new(b"3.2 mod 1", &mut Cache::new(), &mut None, &mut Vec::new())
- .get_mults()
- .unwrap_err()
- {
- ModIsNotInt(i) => i == 4,
- _ => false,
- }
+ assert_eq!(
+ Evaluator::new(b"3.2 mod 1", &mut Cache::new(), &mut None, &mut Vec::new()).get_mults(),
+ Err(ModIsNotInt(4))
);
- assert!(
- match Evaluator::new(b"3 mod 3.2", &mut Cache::new(), &mut None, &mut Vec::new())
- .get_mults()
- .unwrap_err()
- {
- ModIsNotInt(i) => i == 9,
- _ => false,
- }
+ assert_eq!(
+ Evaluator::new(b"3 mod 3.2", &mut Cache::new(), &mut None, &mut Vec::new()).get_mults(),
+ Err(ModIsNotInt(9))
);
// multiplication has lower precedence than exponentiation.
- assert!(
- Evaluator::new(b"2*2^2", &mut Cache::new(), &mut None, &mut Vec::new())
- .get_mults()
- .unwrap()
- == Ratio::from_integer(BigInt::from_biguint(Sign::Plus, BigUint::new(vec![8])))
+ assert_eq!(
+ Evaluator::new(b"2*2^2", &mut Cache::new(), &mut None, &mut Vec::new()).get_mults(),
+ Ok(Ratio::from_integer(BigInt::from_biguint(
+ Sign::Plus,
+ BigUint::new(vec![8])
+ )))
);
- assert!(
- Evaluator::new(b"8/2^2", &mut Cache::new(), &mut None, &mut Vec::new())
- .get_mults()
- .unwrap()
- == Ratio::from_integer(BigInt::from_biguint(Sign::Plus, BigUint::new(vec![2])))
+ assert_eq!(
+ Evaluator::new(b"8/2^2", &mut Cache::new(), &mut None, &mut Vec::new()).get_mults(),
+ Ok(Ratio::from_integer(BigInt::from_biguint(
+ Sign::Plus,
+ BigUint::new(vec![2])
+ )))
);
- assert!(
- Evaluator::new(b"8 mod 3^2", &mut Cache::new(), &mut None, &mut Vec::new())
- .get_mults()
- .unwrap()
- == Ratio::from_integer(BigInt::from_biguint(Sign::Plus, BigUint::new(vec![8])))
+ assert_eq!(
+ Evaluator::new(b"8 mod 3^2", &mut Cache::new(), &mut None, &mut Vec::new()).get_mults(),
+ Ok(Ratio::from_integer(BigInt::from_biguint(
+ Sign::Plus,
+ BigUint::new(vec![8])
+ )))
);
}
+ #[expect(clippy::too_many_lines, reason = "a lot to test")]
#[cfg(not(feature = "rand"))]
#[test]
fn add() {
- assert!(
- Evaluator::new(b"2 + 3", &mut Cache::new(), &mut None, &mut Vec::new())
- .get_adds()
- .unwrap()
- == Ratio::from_integer(BigInt::from_biguint(Sign::Plus, BigUint::new(vec![5])))
+ assert_eq!(
+ Evaluator::new(b"2 + 3", &mut Cache::new(), &mut None, &mut Vec::new()).get_adds(),
+ Ok(Ratio::from_integer(BigInt::from_biguint(
+ Sign::Plus,
+ BigUint::new(vec![5])
+ )))
);
- assert!(
- Evaluator::new(b"-2 + 3", &mut Cache::new(), &mut None, &mut Vec::new())
- .get_adds()
- .unwrap()
- == Ratio::from_integer(BigInt::from_biguint(Sign::Plus, BigUint::new(vec![1])))
+ assert_eq!(
+ Evaluator::new(b"-2 + 3", &mut Cache::new(), &mut None, &mut Vec::new()).get_adds(),
+ Ok(Ratio::from_integer(BigInt::from_biguint(
+ Sign::Plus,
+ BigUint::new(vec![1])
+ )))
);
- assert!(
+ assert_eq!(
Evaluator::new(
b"2 + \t -3.0",
&mut Cache::new(),
&mut None,
&mut Vec::new()
)
- .get_adds()
- .unwrap()
- == Ratio::from_integer(BigInt::from_biguint(Sign::Minus, BigUint::new(vec![1])))
+ .get_adds(),
+ Ok(Ratio::from_integer(BigInt::from_biguint(
+ Sign::Minus,
+ BigUint::new(vec![1])
+ )))
);
- assert!(
- Evaluator::new(b"-2.5+-3.5", &mut Cache::new(), &mut None, &mut Vec::new())
- .get_adds()
- .unwrap()
- == Ratio::from_integer(BigInt::from_biguint(Sign::Minus, BigUint::new(vec![6])))
+ assert_eq!(
+ Evaluator::new(b"-2.5+-3.5", &mut Cache::new(), &mut None, &mut Vec::new()).get_adds(),
+ Ok(Ratio::from_integer(BigInt::from_biguint(
+ Sign::Minus,
+ BigUint::new(vec![6])
+ )))
);
- assert!(
- Evaluator::new(b"4.0\t - 6", &mut Cache::new(), &mut None, &mut Vec::new())
- .get_adds()
- .unwrap()
- == Ratio::from_integer(BigInt::from_biguint(Sign::Minus, BigUint::new(vec![2])))
+ assert_eq!(
+ Evaluator::new(b"4.0\t - 6", &mut Cache::new(), &mut None, &mut Vec::new()).get_adds(),
+ Ok(Ratio::from_integer(BigInt::from_biguint(
+ Sign::Minus,
+ BigUint::new(vec![2])
+ )))
);
- assert!(
- Evaluator::new(b"6-3", &mut Cache::new(), &mut None, &mut Vec::new())
- .get_adds()
- .unwrap()
- == Ratio::from_integer(BigInt::from_biguint(Sign::Plus, BigUint::new(vec![3])))
+ assert_eq!(
+ Evaluator::new(b"6-3", &mut Cache::new(), &mut None, &mut Vec::new()).get_adds(),
+ Ok(Ratio::from_integer(BigInt::from_biguint(
+ Sign::Plus,
+ BigUint::new(vec![3])
+ )))
);
- assert!(
- Evaluator::new(b"-6-3", &mut Cache::new(), &mut None, &mut Vec::new())
- .get_adds()
- .unwrap()
- == Ratio::from_integer(BigInt::from_biguint(Sign::Minus, BigUint::new(vec![9])))
+ assert_eq!(
+ Evaluator::new(b"-6-3", &mut Cache::new(), &mut None, &mut Vec::new()).get_adds(),
+ Ok(Ratio::from_integer(BigInt::from_biguint(
+ Sign::Minus,
+ BigUint::new(vec![9])
+ )))
);
- assert!(
- Evaluator::new(b"6--3", &mut Cache::new(), &mut None, &mut Vec::new())
- .get_adds()
- .unwrap()
- == Ratio::from_integer(BigInt::from_biguint(Sign::Plus, BigUint::new(vec![9])))
+ assert_eq!(
+ Evaluator::new(b"6--3", &mut Cache::new(), &mut None, &mut Vec::new()).get_adds(),
+ Ok(Ratio::from_integer(BigInt::from_biguint(
+ Sign::Plus,
+ BigUint::new(vec![9])
+ )))
);
- assert!(
+ assert_eq!(
Evaluator::new(
b"- 6 -\t - 3",
&mut Cache::new(),
&mut None,
&mut Vec::new()
)
- .get_adds()
- .unwrap()
- == Ratio::from_integer(BigInt::from_biguint(Sign::Minus, BigUint::new(vec![3])))
+ .get_adds(),
+ Ok(Ratio::from_integer(BigInt::from_biguint(
+ Sign::Minus,
+ BigUint::new(vec![3])
+ )))
);
// addition always becomes multiplication eventually.
- assert!(
- Evaluator::new(b"2 * 8", &mut Cache::new(), &mut None, &mut Vec::new())
- .get_adds()
- .unwrap()
- == Ratio::from_integer(BigInt::from_biguint(Sign::Plus, BigUint::new(vec![16])))
+ assert_eq!(
+ Evaluator::new(b"2 * 8", &mut Cache::new(), &mut None, &mut Vec::new()).get_adds(),
+ Ok(Ratio::from_integer(BigInt::from_biguint(
+ Sign::Plus,
+ BigUint::new(vec![16])
+ )))
);
- assert!(
- Evaluator::new(b"8 /\t 2", &mut Cache::new(), &mut None, &mut Vec::new())
- .get_adds()
- .unwrap()
- == Ratio::from_integer(BigInt::from_biguint(Sign::Plus, BigUint::new(vec![4])))
+ assert_eq!(
+ Evaluator::new(b"8 /\t 2", &mut Cache::new(), &mut None, &mut Vec::new()).get_adds(),
+ Ok(Ratio::from_integer(BigInt::from_biguint(
+ Sign::Plus,
+ BigUint::new(vec![4])
+ )))
);
// Error since leading/trailing whitespace is not consumed by addition or higher precedence expressions.
- assert!(
- match Evaluator::new(b" 2+2", &mut Cache::new(), &mut None, &mut Vec::new())
- .get_adds()
- .unwrap_err()
- {
- MissingTerm(i) => i == 0,
- _ => false,
- }
+ assert_eq!(
+ Evaluator::new(b" 2+2", &mut Cache::new(), &mut None, &mut Vec::new()).get_adds(),
+ Err(MissingTerm(0))
);
- assert!(
- match Evaluator::new(b" 2-2", &mut Cache::new(), &mut None, &mut Vec::new())
- .get_adds()
- .unwrap_err()
- {
- MissingTerm(i) => i == 0,
- _ => false,
- }
+ assert_eq!(
+ Evaluator::new(b" 2-2", &mut Cache::new(), &mut None, &mut Vec::new()).get_adds(),
+ Err(MissingTerm(0))
);
// addition has lower precedence than multiplication.
- assert!(
- Evaluator::new(b"2+2*2", &mut Cache::new(), &mut None, &mut Vec::new())
- .get_adds()
- .unwrap()
- == Ratio::from_integer(BigInt::from_biguint(Sign::Plus, BigUint::new(vec![6])))
+ assert_eq!(
+ Evaluator::new(b"2+2*2", &mut Cache::new(), &mut None, &mut Vec::new()).get_adds(),
+ Ok(Ratio::from_integer(BigInt::from_biguint(
+ Sign::Plus,
+ BigUint::new(vec![6])
+ )))
);
- assert!(
- Evaluator::new(b"2+2/2", &mut Cache::new(), &mut None, &mut Vec::new())
- .get_adds()
- .unwrap()
- == Ratio::from_integer(BigInt::from_biguint(Sign::Plus, BigUint::new(vec![3])))
+ assert_eq!(
+ Evaluator::new(b"2+2/2", &mut Cache::new(), &mut None, &mut Vec::new()).get_adds(),
+ Ok(Ratio::from_integer(BigInt::from_biguint(
+ Sign::Plus,
+ BigUint::new(vec![3])
+ )))
);
- assert!(
- Evaluator::new(b"2-2*2", &mut Cache::new(), &mut None, &mut Vec::new())
- .get_adds()
- .unwrap()
- == Ratio::from_integer(BigInt::from_biguint(Sign::Minus, BigUint::new(vec![2])))
+ assert_eq!(
+ Evaluator::new(b"2-2*2", &mut Cache::new(), &mut None, &mut Vec::new()).get_adds(),
+ Ok(Ratio::from_integer(BigInt::from_biguint(
+ Sign::Minus,
+ BigUint::new(vec![2])
+ )))
);
- assert!(
- Evaluator::new(b"2-2/2", &mut Cache::new(), &mut None, &mut Vec::new())
- .get_adds()
- .unwrap()
- == Ratio::from_integer(BigInt::from_biguint(Sign::Plus, BigUint::new(vec![1])))
+ assert_eq!(
+ Evaluator::new(b"2-2/2", &mut Cache::new(), &mut None, &mut Vec::new()).get_adds(),
+ Ok(Ratio::from_integer(BigInt::from_biguint(
+ Sign::Plus,
+ BigUint::new(vec![1])
+ )))
);
}
#[cfg(not(feature = "rand"))]
#[test]
fn exit() {
- assert!(
- match Evaluator::new(b" q \n", &mut Cache::new(), &mut None, &mut Vec::new())
- .evaluate()
- .unwrap()
- {
- Exit => true,
- _ => false,
- }
+ assert_eq!(
+ Evaluator::new(b" q \n", &mut Cache::new(), &mut None, &mut Vec::new()).evaluate(),
+ Ok(Exit)
);
- assert!(match Evaluator::new(
- b" q \r\n",
- &mut Cache::new(),
- &mut None,
- &mut Vec::new()
- )
- .evaluate()
- .unwrap()
- {
- Exit => true,
- _ => false,
- });
- assert!(
- match Evaluator::new(b"q\n", &mut Cache::new(), &mut None, &mut Vec::new())
- .evaluate()
- .unwrap()
- {
- Exit => true,
- _ => false,
- }
+ assert_eq!(
+ Evaluator::new(
+ b" q \r\n",
+ &mut Cache::new(),
+ &mut None,
+ &mut Vec::new()
+ )
+ .evaluate(),
+ Ok(Exit)
);
- assert!(
- match Evaluator::new(b"q\r\n", &mut Cache::new(), &mut None, &mut Vec::new())
- .evaluate()
- .unwrap()
- {
- Exit => true,
- _ => false,
- }
+ assert_eq!(
+ Evaluator::new(b"q\n", &mut Cache::new(), &mut None, &mut Vec::new()).evaluate(),
+ Ok(Exit)
);
- assert!(
- match Evaluator::new(b"\rq\n", &mut Cache::new(), &mut None, &mut Vec::new())
- .evaluate()
- .unwrap_err()
- {
- MissingTerm(i) => i == 0,
- _ => false,
- }
+ assert_eq!(
+ Evaluator::new(b"q\r\n", &mut Cache::new(), &mut None, &mut Vec::new()).evaluate(),
+ Ok(Exit)
);
- assert!(
- match Evaluator::new(b"\tq\n", &mut Cache::new(), &mut None, &mut Vec::new())
- .evaluate()
- .unwrap()
- {
- Exit => true,
- _ => false,
- }
+ assert_eq!(
+ Evaluator::new(b"\rq\n", &mut Cache::new(), &mut None, &mut Vec::new()).evaluate(),
+ Err(MissingTerm(0))
);
- assert!(
- match Evaluator::new(b"q\n\n", &mut Cache::new(), &mut None, &mut Vec::new())
- .evaluate()
- .unwrap_err()
- {
- InvalidQuit => true,
- _ => false,
- }
+ assert_eq!(
+ Evaluator::new(b"\tq\n", &mut Cache::new(), &mut None, &mut Vec::new()).evaluate(),
+ Ok(Exit)
);
- assert!(
- match Evaluator::new(b"\nq\n", &mut Cache::new(), &mut None, &mut Vec::new())
- .evaluate()
- .unwrap_err()
- {
- MissingTerm(i) => i == 0,
- _ => false,
- }
+ assert_eq!(
+ Evaluator::new(b"q\n\n", &mut Cache::new(), &mut None, &mut Vec::new()).evaluate(),
+ Err(InvalidQuit)
);
- assert!(
- match Evaluator::new(b"q", &mut Cache::new(), &mut None, &mut Vec::new())
- .evaluate()
- .unwrap()
- {
- Exit => true,
- _ => false,
- }
+ assert_eq!(
+ Evaluator::new(b"\nq\n", &mut Cache::new(), &mut None, &mut Vec::new()).evaluate(),
+ Err(MissingTerm(0))
+ );
+ assert_eq!(
+ Evaluator::new(b"q", &mut Cache::new(), &mut None, &mut Vec::new()).evaluate(),
+ Ok(Exit)
);
}
+ #[expect(clippy::unwrap_used, reason = "comment justifies correctness")]
#[cfg(not(feature = "rand"))]
#[test]
fn store() {
let mut prev = None;
let mut cache = Cache::new();
- drop(
- Evaluator::new(b"1\n", &mut cache, &mut prev, &mut Vec::new())
- .evaluate()
- .unwrap(),
- );
+ // Quick check that `Ok` is returned.
+ _ = Evaluator::new(b"1\n", &mut cache, &mut prev, &mut Vec::new())
+ .evaluate()
+ .unwrap();
assert!(cache.is_empty());
- assert!(
- match Evaluator::new(b"s\n", &mut cache, &mut prev, &mut Vec::new())
- .evaluate()
- .unwrap()
- {
- Store(o) =>
- o.as_ref().unwrap()
- == &Ratio::from_integer(BigInt::from_biguint(
- Sign::Plus,
- BigUint::new(vec![1])
- )),
- _ => false,
- }
+ assert_eq!(
+ Evaluator::new(b"s\n", &mut cache, &mut prev, &mut Vec::new()).evaluate(),
+ Ok(Store(&Some(Ratio::from_integer(BigInt::from_biguint(
+ Sign::Plus,
+ BigUint::new(vec![1])
+ )))))
+ );
+ assert_eq!(cache.len(), 1);
+ assert_eq!(
+ Evaluator::new(b"s2\n", &mut Cache::new(), &mut None, &mut Vec::new()).evaluate(),
+ Err(InvalidStore)
);
- assert!(cache.len() == 1);
}
+ #[expect(clippy::too_many_lines, reason = "a lot to test")]
#[cfg(not(feature = "rand"))]
#[test]
fn eval() {
- use core::str::FromStr;
+ use core::str::FromStr as _;
let mut prev = None;
let mut cache = Cache::new();
let mut exp = Vec::new();
- assert!(
- match Evaluator::new(b"1+2\n", &mut cache, &mut prev, &mut exp)
- .evaluate()
- .unwrap()
- {
- Eval(i) =>
- i == &Ratio::from_integer(BigInt::from_biguint(
- Sign::Plus,
- BigUint::new(vec![3])
- )),
- _ => false,
- }
- );
- assert!(
- match Evaluator::new(b"\t s \n", &mut cache, &mut prev, &mut exp)
- .evaluate()
- .unwrap()
- {
- Store(o) =>
- o.as_ref().unwrap()
- == &Ratio::from_integer(BigInt::from_biguint(
- Sign::Plus,
- BigUint::new(vec![3])
- )),
- _ => false,
- }
+ assert_eq!(
+ Evaluator::new(b"1+2\n", &mut cache, &mut prev, &mut exp).evaluate(),
+ Ok(Eval(&Ratio::from_integer(BigInt::from_biguint(
+ Sign::Plus,
+ BigUint::new(vec![3])
+ ))))
);
- assert!(
- match Evaluator::new(b"-1/2+2*@\n", &mut cache, &mut prev, &mut exp)
- .evaluate()
- .unwrap()
- {
- Eval(i) =>
- i == &Ratio::new(
- BigInt::from_biguint(Sign::Plus, BigUint::new(vec![11])),
- BigInt::from_biguint(Sign::Plus, BigUint::new(vec![2]))
- ),
- _ => false,
- }
+ assert_eq!(
+ Evaluator::new(b"\t s \n", &mut cache, &mut prev, &mut exp).evaluate(),
+ Ok(Store(&Some(Ratio::from_integer(BigInt::from_biguint(
+ Sign::Plus,
+ BigUint::new(vec![3])
+ )))))
+ );
+ assert_eq!(
+ Evaluator::new(b"-1/2+2*@\n", &mut cache, &mut prev, &mut exp).evaluate(),
+ Ok(Eval(&Ratio::new(
+ BigInt::from_biguint(Sign::Plus, BigUint::new(vec![11])),
+ BigInt::from_biguint(Sign::Plus, BigUint::new(vec![2]))
+ )))
);
- assert!(
- match Evaluator::new(b"s\n", &mut cache, &mut prev, &mut exp)
- .evaluate()
- .unwrap()
- {
- Store(o) =>
- o == &Some(Ratio::new(
- BigInt::from_biguint(Sign::Plus, BigUint::new(vec![11])),
- BigInt::from_biguint(Sign::Plus, BigUint::new(vec![2]))
- )),
- _ => false,
- }
+ assert_eq!(
+ Evaluator::new(b"s\n", &mut cache, &mut prev, &mut exp).evaluate(),
+ Ok(Store(&Some(Ratio::new(
+ BigInt::from_biguint(Sign::Plus, BigUint::new(vec![11])),
+ BigInt::from_biguint(Sign::Plus, BigUint::new(vec![2]))
+ ))))
);
- assert!(
- match Evaluator::new(b"@^@2!\r\n", &mut cache, &mut prev, &mut exp)
- .evaluate()
- .unwrap()
- {
- Eval(i) =>
- i == &Ratio::new(
- BigInt::from_biguint(Sign::Plus, BigUint::new(vec![1771561])),
- BigInt::from_biguint(Sign::Plus, BigUint::new(vec![64]))
- ),
- _ => false,
- }
+ assert_eq!(
+ Evaluator::new(b"@^@2!\r\n", &mut cache, &mut prev, &mut exp).evaluate(),
+ Ok(Eval(&Ratio::new(
+ BigInt::from_biguint(Sign::Plus, BigUint::new(vec![1_771_561])),
+ BigInt::from_biguint(Sign::Plus, BigUint::new(vec![64]))
+ )))
);
- assert!(
- match Evaluator::new(b"s\n", &mut cache, &mut prev, &mut exp)
- .evaluate()
- .unwrap()
- {
- Store(o) =>
- o == &Some(Ratio::new(
- BigInt::from_biguint(Sign::Plus, BigUint::new(vec![1771561])),
- BigInt::from_biguint(Sign::Plus, BigUint::new(vec![64]))
- )),
- _ => false,
- }
+ assert_eq!(
+ Evaluator::new(b"s\n", &mut cache, &mut prev, &mut exp).evaluate(),
+ Ok(Store(&Some(Ratio::new(
+ BigInt::from_biguint(Sign::Plus, BigUint::new(vec![1_771_561])),
+ BigInt::from_biguint(Sign::Plus, BigUint::new(vec![64]))
+ ))))
);
// Verified with Wolfram Alpha.
- assert!(match Evaluator::new(b" \t 1 + (2 * |(7.98\t - 12/7)|) / 4!^@3!^|1-3|\t \n", &mut cache, &mut prev, &mut exp).evaluate().unwrap() {
- Eval(i) => i == &Ratio::from_str("2841328814244153299237884950647090899374680152474331/2841328814244153299237884950647090899374680152473600").unwrap(),
- _ => false,
- });
- assert!(match Evaluator::new(
- b" \t round(19/6,0)!\t \r\n",
- &mut cache,
- &mut prev,
- &mut exp
- )
- .evaluate()
- .unwrap()
- {
- Eval(i) =>
- i == &Ratio::from_integer(BigInt::from_biguint(Sign::Plus, BigUint::new(vec![6]))),
- _ => false,
- });
- assert!(match Evaluator::new(
- b" \t 2^round(19/6,0)!\t \r\n",
- &mut cache,
- &mut prev,
- &mut exp
- )
- .evaluate()
- .unwrap()
- {
- Eval(i) =>
- i == &Ratio::from_integer(BigInt::from_biguint(Sign::Plus, BigUint::new(vec![64]))),
- _ => false,
- });
assert!(
- match Evaluator::new(b"round(19/6,0)^2\t\n", &mut cache, &mut prev, &mut exp)
- .evaluate()
- .unwrap()
- {
- Eval(i) =>
- i == &Ratio::from_integer(BigInt::from_biguint(
- Sign::Plus,
- BigUint::new(vec![9])
- )),
- _ => false,
- }
+ Evaluator::new(
+ b" \t 1 + (2 * |(7.98\t - 12/7)|) / 4!^@3!^|1-3|\t \n",
+ &mut cache,
+ &mut prev,
+ &mut exp
+ )
+ .evaluate().is_ok_and(|r| {
+ Ratio::from_str("2841328814244153299237884950647090899374680152474331/2841328814244153299237884950647090899374680152473600").is_ok_and(|r2| {
+ r == Eval(&r2)
+ })
+ })
+ );
+ assert_eq!(
+ Evaluator::new(
+ b" \t round(19/6,0)!\t \r\n",
+ &mut cache,
+ &mut prev,
+ &mut exp
+ )
+ .evaluate(),
+ Ok(Eval(&Ratio::from_integer(BigInt::from_biguint(
+ Sign::Plus,
+ BigUint::new(vec![6])
+ ))))
+ );
+ assert_eq!(
+ Evaluator::new(
+ b" \t 2^round(19/6,0)!\t \r\n",
+ &mut cache,
+ &mut prev,
+ &mut exp
+ )
+ .evaluate(),
+ Ok(Eval(&Ratio::from_integer(BigInt::from_biguint(
+ Sign::Plus,
+ BigUint::new(vec![64])
+ ))))
+ );
+ assert_eq!(
+ Evaluator::new(b"round(19/6,0)^2\t\n", &mut cache, &mut prev, &mut exp).evaluate(),
+ Ok(Eval(&Ratio::from_integer(BigInt::from_biguint(
+ Sign::Plus,
+ BigUint::new(vec![9])
+ ))))
);
// Invalid UTF-8 does not cause a panic!.
- assert!(
- match Evaluator::new(&[255, 255, 255, b'\n'], &mut cache, &mut prev, &mut exp)
- .evaluate()
- .unwrap_err()
- {
- MissingTerm(i) => i == 0,
- _ => false,
- }
+ assert_eq!(
+ Evaluator::new(&[255, 255, 255, b'\n'], &mut cache, &mut prev, &mut exp).evaluate(),
+ Err(MissingTerm(0))
);
- assert!(
- match Evaluator::new(&[b'2', 255, b'\n'], &mut cache, &mut prev, &mut exp)
- .evaluate()
- .unwrap_err()
- {
- TrailingSyms(i) => i == 1,
- _ => false,
- }
+ assert_eq!(
+ Evaluator::new(&[b'2', 255, b'\n'], &mut cache, &mut prev, &mut exp).evaluate(),
+ Err(TrailingSyms(1))
);
// Exactly one newline is required.
- assert!(
- match Evaluator::new(b"2\n\n", &mut cache, &mut prev, &mut exp)
- .evaluate()
- .unwrap_err()
- {
- TrailingSyms(i) => i == 1,
- _ => false,
- }
+ assert_eq!(
+ Evaluator::new(b"2\n\n", &mut cache, &mut prev, &mut exp).evaluate(),
+ Err(TrailingSyms(1))
);
- assert!(
- prev == Some(Ratio::from_integer(BigInt::from_biguint(
+ assert_eq!(
+ prev,
+ Some(Ratio::from_integer(BigInt::from_biguint(
Sign::Plus,
BigUint::new(vec![9])
)))
);
- assert!(match Evaluator::new(b"\n", &mut cache, &mut prev, &mut exp)
- .evaluate()
- .unwrap()
- {
- Empty(o) =>
- o == &Some(Ratio::from_integer(BigInt::from_biguint(
- Sign::Plus,
- BigUint::new(vec![9])
- ))),
- _ => false,
- });
- assert!(
- prev == Some(Ratio::from_integer(BigInt::from_biguint(
+ assert_eq!(
+ Evaluator::new(b"\n", &mut cache, &mut prev.clone(), &mut exp).evaluate(),
+ Ok(Empty(&Some(Ratio::from_integer(BigInt::from_biguint(
+ Sign::Plus,
+ BigUint::new(vec![9])
+ )))))
+ );
+ assert_eq!(
+ prev,
+ Some(Ratio::from_integer(BigInt::from_biguint(
Sign::Plus,
BigUint::new(vec![9])
)))
);
- assert!(
- match Evaluator::new(b"\r\n", &mut cache, &mut prev.clone(), &mut exp)
- .evaluate()
- .unwrap()
- {
- Empty(o) => *o == prev,
- _ => false,
- }
+ assert_eq!(
+ Evaluator::new(b"\r\n", &mut cache, &mut prev.clone(), &mut exp).evaluate(),
+ Ok(Empty(&prev))
);
- assert!(
- match Evaluator::new(&[0u8; 0], &mut cache, &mut prev.clone(), &mut exp)
- .evaluate()
- .unwrap()
- {
- Empty(o) => *o == prev,
- _ => false,
- }
+ assert_eq!(
+ Evaluator::new(&[0u8; 0], &mut cache, &mut prev.clone(), &mut exp).evaluate(),
+ Ok(Empty(&prev))
);
}
#[cfg(feature = "rand")]
#[test]
fn eval_iter() {
- use super::*;
- use num_traits::ToPrimitive;
- use std::io::{self, BufRead, Error, ErrorKind, Read};
struct Reader<'a> {
data: &'a [u8],
err: bool,
@@ -3357,12 +3115,14 @@ mod tests {
}
}
impl Read for Reader<'_> {
+ #[expect(clippy::indexing_slicing, reason = "comment justifies correctness")]
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
if self.err {
self.err = false;
- Err(Error::new(ErrorKind::Other, ""))
+ Err(Error::other(""))
} else {
let len = usize::min(buf.len(), self.data.len());
+ // `len <= buf.len()` and `len <= `self.data.len()`.
buf[..len].copy_from_slice(&self.data[..len]);
Ok(len)
}
@@ -3372,54 +3132,51 @@ mod tests {
fn fill_buf(&mut self) -> io::Result<&[u8]> {
if self.err {
self.err = false;
- Err(Error::new(ErrorKind::Other, ""))
+ Err(Error::other(""))
} else {
Ok(self.data)
}
}
- fn consume(&mut self, amt: usize) {
- self.data = &self.data[amt..];
+ #[expect(clippy::indexing_slicing, reason = "comment justifies correctness")]
+ fn consume(&mut self, amount: usize) {
+ // This is just a test, so calling code passing in an invalid `amount` is fine.
+ self.data = &self.data[amount..];
}
}
let mut iter = EvalIter::new(Reader::new(
b"1+2\n4\n\nq\n5\ns\nrand() + rand(-139/@, 2984/134)\nab",
));
- assert!(match iter.lend_next().unwrap().unwrap_err() {
- E::Error(_) => true,
- _ => false,
- });
- assert!(match iter.lend_next().unwrap().unwrap() {
- Eval(r) => r.numer().to_i32().unwrap() == 3,
- _ => false,
- });
- assert!(match iter.lend_next().unwrap().unwrap() {
- Eval(r) => r.numer().to_i32().unwrap() == 4,
- _ => false,
- });
- assert!(match iter.lend_next().unwrap().unwrap() {
- Empty(r) => r.as_ref().unwrap().numer().to_i32().unwrap() == 4,
- _ => false,
- });
+ assert!(
+ iter.lend_next()
+ .is_some_and(|res| res.map_or_else(|e| matches!(e, E::Error(_)), |_| false))
+ );
+ assert!(iter.lend_next().is_some_and(|res| {
+ res.is_ok_and(|e| matches!(e, Eval(r) if r.numer().to_i32() == Some(3i32)))
+ }));
+ assert!(iter.lend_next().is_some_and(|res| {
+ res.is_ok_and(|e| matches!(e, Eval(r) if r.numer().to_i32() == Some(4i32)))
+ }));
+ assert!(iter.lend_next().is_some_and(|res| {
+ res.is_ok_and(
+ |e| matches!(e, Empty(r) if r.as_ref().is_some_and(|val| val.numer().to_i32() == Some(4i32))),
+ )
+ }));
assert!(iter.lend_next().is_none());
- assert!(match iter.lend_next().unwrap().unwrap() {
- Eval(r) => r.numer().to_i32().unwrap() == 5,
- _ => false,
- });
- assert!(match iter.lend_next().unwrap().unwrap() {
- Store(r) => r.as_ref().unwrap().numer().to_i32().unwrap() == 5,
- _ => false,
- });
- assert!(match iter.lend_next().unwrap().unwrap() {
- Eval(r) => r.is_integer(),
- _ => false,
- });
- assert!(match iter.lend_next().unwrap().unwrap_err() {
- E::LangErr(e) => match e {
- MissingTerm(_) => true,
- _ => false,
- },
- _ => false,
- });
+ assert!(iter.lend_next().is_some_and(|res| {
+ res.is_ok_and(|e| matches!(e, Eval(r) if r.numer().to_i32() == Some(5i32)))
+ }));
+ assert!(iter.lend_next().is_some_and(|res| {
+ res.is_ok_and(
+ |e| matches!(e, Store(r) if r.as_ref().is_some_and(|val| val.numer().to_i32() == Some(5i32))),
+ )
+ }));
+ assert!(
+ iter.lend_next()
+ .is_some_and(|res| res.is_ok_and(|e| matches!(e, Eval(r) if r.is_integer())))
+ );
+ assert!(iter.lend_next().is_some_and(|res| {
+ res.is_err_and(|err| matches!(err, E::LangErr(ref e) if matches!(*e, MissingTerm(_))))
+ }));
assert!(iter.lend_next().is_none());
assert!(iter.lend_next().is_none());
assert!(iter.lend_next().is_none());
diff --git a/src/main.rs b/src/main.rs
@@ -11,10 +11,8 @@ use num_bigint as _;
use num_integer as _;
use num_rational as _;
use num_traits as _;
-#[cfg(all(feature = "priv_sep", not(target_os = "openbsd")))]
-use priv_sep as _;
-#[cfg(all(feature = "priv_sep", target_os = "openbsd"))]
-use priv_sep::{Promise, Promises};
+#[cfg(target_os = "openbsd")]
+use priv_sep::{Errno, Promise, Promises};
#[cfg(feature = "rand")]
use rand as _;
#[cfg(feature = "std")]
@@ -28,16 +26,16 @@ use std::{
enum Err {
/// Error returned from [`writeln`].
Io(Error),
- #[cfg(all(feature = "priv_sep", target_os = "openbsd"))]
/// Error returned from `pledge`.
- Pledge(Error),
+ #[cfg(target_os = "openbsd")]
+ Pledge(Errno),
}
#[cfg(feature = "std")]
impl Display for Err {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
match *self {
Self::Io(ref e) => e.fmt(f),
- #[cfg(all(feature = "priv_sep", target_os = "openbsd"))]
+ #[cfg(target_os = "openbsd")]
Self::Pledge(ref e) => write!(f, "pledge(2)ing 'stdio' failed with {e}"),
}
}
@@ -58,7 +56,7 @@ fn main() {}
#[cfg(feature = "std")]
fn main() -> Result<(), Err> {
/// Calls `pledge(2)` with the "stdio" promise.
- #[cfg(all(feature = "priv_sep", target_os = "openbsd"))]
+ #[cfg(target_os = "openbsd")]
fn privsep() -> Result<(), Err> {
Promises::new([Promise::Stdio])
.pledge()
@@ -69,7 +67,7 @@ fn main() -> Result<(), Err> {
clippy::unnecessary_wraps,
reason = "consistent return type with priv_sep feature"
)]
- #[cfg(not(all(feature = "priv_sep", target_os = "openbsd")))]
+ #[cfg(not(target_os = "openbsd"))]
const fn privsep() -> Result<(), Err> {
Ok(())
}