calc_rational

CLI calculator for rational numbers.
git clone https://git.philomathiclife.com/repos/calc_rational
Log | Files | Refs | README

commit 5b90bd0d9a37c7eecbf9d9bc9236b9248342787d
parent a7cd8f388f7b14d31558ec847fa65e0d0f8c5886
Author: Zack Newman <zack@philomathiclife.com>
Date:   Wed,  7 Feb 2024 09:55:06 -0700

version 1.0.0

Diffstat:
MCargo.toml | 4++--
Msrc/cache.rs | 26+++-----------------------
Msrc/lending_iterator.rs | 25+------------------------
Msrc/lib.rs | 66++++++++++++++++++++++++++++++++++++++++++++++++------------------
Msrc/main.rs | 9+++++----
5 files changed, 59 insertions(+), 71 deletions(-)

diff --git a/Cargo.toml b/Cargo.toml @@ -9,7 +9,7 @@ license = "MIT OR Apache-2.0" name = "calc_rational" readme = "README.md" repository = "https://git.philomathiclife.com/repos/calc_rational/" -version = "0.9.1" +version = "1.0.0" [lib] name = "calc_lib" @@ -27,7 +27,7 @@ num-traits = { version = "0.2.17", default-features = false } rand = { version = "0.8.5", default-features = false, features = ["std", "std_rng"], optional = true } [target.'cfg(target_os = "openbsd")'.dependencies] -priv_sep = { version = "0.8.1", default-features = false, features = ["openbsd"], optional = true } +priv_sep = { version = "1.0.0", default-features = false, features = ["openbsd"], optional = true } [build-dependencies] rustc_version = "0.4.0" diff --git a/src/cache.rs b/src/cache.rs @@ -1,24 +1,3 @@ -#![deny( - unsafe_code, - unused, - warnings, - clippy::all, - clippy::cargo, - clippy::complexity, - clippy::correctness, - clippy::nursery, - clippy::pedantic, - clippy::perf, - clippy::restriction, - clippy::style, - clippy::suspicious -)] -#![allow( - clippy::arithmetic_side_effects, - clippy::blanket_clippy_restriction_lints, - clippy::implicit_return, - clippy::min_ident_chars -)] use core::ops::Index; /// A cache of `N` `T`s. When the cache is filled up, /// a new entry overwrites the oldest entry. `Cache<T, N>` @@ -59,6 +38,7 @@ impl<T> Cache<T, $x> { /// at index `idx`. Indexing begins at the newest /// entry (i.e., `self.get(0)` will return the most recent entry /// iff at least one item has been cached). + #[allow(clippy::arithmetic_side_effects)] #[inline] pub fn get(&self, idx: usize) -> Option<&T> { (idx < self.len).then(|| self.vals.index(self.next_head.wrapping_sub(1).wrapping_sub(idx) & ($x - 1))) @@ -72,14 +52,14 @@ impl<T> Cache<T, $x> { /// /// `idx < self.len()`. #[inline] - #[allow(unsafe_code)] + #[allow(unsafe_code, clippy::arithmetic_side_effects)] pub unsafe fn get_unsafe(&self, idx: usize) -> &T { self.vals.index(self.next_head.wrapping_sub(1).wrapping_sub(idx) & ($x - 1)) } /// Adds `val` to the cache. In the event `N` values have already been cached, /// the oldest entry is overwritten. #[inline] - #[allow(clippy::indexing_slicing)] + #[allow(clippy::arithmetic_side_effects, clippy::indexing_slicing)] pub fn push(&mut self, val: T) { if self.len < $x { self.len += 1; diff --git a/src/lending_iterator.rs b/src/lending_iterator.rs @@ -1,27 +1,3 @@ -#![deny( - unsafe_code, - unused, - warnings, - clippy::all, - clippy::cargo, - clippy::complexity, - clippy::correctness, - clippy::nursery, - clippy::pedantic, - clippy::perf, - clippy::restriction, - clippy::style, - clippy::suspicious -)] -#![allow( - clippy::arithmetic_side_effects, - clippy::blanket_clippy_restriction_lints, - clippy::implicit_return, - clippy::min_ident_chars, - clippy::missing_trait_methods, - clippy::question_mark_used, - clippy::single_char_lifetime_names -)] /// Generalizes [`Iterator`] by allowing one to yield references. pub trait LendingIterator { /// Read [`Iterator::Item`]. @@ -36,6 +12,7 @@ pub trait LendingIterator { (0, None) } /// Read [`Iterator::count`]. + #[allow(clippy::arithmetic_side_effects)] #[inline] fn count(self) -> usize where diff --git a/src/lib.rs b/src/lib.rs @@ -125,26 +125,27 @@ clippy::suspicious )] #![allow( - clippy::arithmetic_side_effects, clippy::blanket_clippy_restriction_lints, clippy::implicit_return, - clippy::into_iter_on_ref, clippy::min_ident_chars, clippy::missing_trait_methods, clippy::question_mark_used, - clippy::ref_patterns, clippy::single_call_fn, clippy::single_char_lifetime_names, clippy::unseparated_literal_suffix )] extern crate alloc; -use alloc::string::{String, ToString}; -use alloc::vec; -use alloc::vec::Vec; +use alloc::{ + string::{String, ToString}, + vec, + vec::Vec, +}; use cache::Cache; -use core::convert; -use core::fmt::{self, Display, Formatter}; -use core::ops::Index; +use core::{ + convert, + fmt::{self, Display, Formatter}, + ops::Index, +}; use num_bigint::{BigInt, BigUint, Sign}; use num_integer::Integer; use num_rational::Ratio; @@ -236,6 +237,7 @@ pub enum LangErr { RandNoInts(usize), } impl Display for LangErr { + #[allow(clippy::ref_patterns)] #[inline] fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { match *self { @@ -288,7 +290,7 @@ pub enum O<'a> { } impl<'a> Display for O<'a> { #[inline] - #[allow(unsafe_code, clippy::indexing_slicing)] + #[allow(unsafe_code, clippy::arithmetic_side_effects, clippy::indexing_slicing)] fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { match *self { Empty(o) => { @@ -426,7 +428,11 @@ impl<'input, 'cache, 'prev, 'scratch> Evaluator<'input, 'cache, 'prev, 'scratch> /// /// Returns a [`LangErr`] iff the input violates the calc language. #[inline] - #[allow(clippy::indexing_slicing)] + #[allow( + clippy::arithmetic_side_effects, + clippy::indexing_slicing, + clippy::ref_patterns + )] pub fn evaluate(mut self) -> Result<O<'prev>, LangErr> { self.utf8 = if self.utf8.last().map_or(true, |b| *b != b'\n') { self.utf8 @@ -473,7 +479,11 @@ impl<'input, 'cache, 'prev, 'scratch> Evaluator<'input, 'cache, 'prev, 'scratch> } /// Reads from the input until the next non-{space/tab} byte value. #[inline] - #[allow(clippy::indexing_slicing)] + #[allow( + clippy::arithmetic_side_effects, + clippy::indexing_slicing, + clippy::into_iter_on_ref + )] fn consume_ws(&mut self) { // ControlFlow makes more sense to use in try_fold; however due to a lack // of a map_or_else function, it is easier to simply return a Result with @@ -489,6 +499,7 @@ impl<'input, 'cache, 'prev, 'scratch> Evaluator<'input, 'cache, 'prev, 'scratch> /// Evaluates addition expressions as defined in the calc language. /// This function is used for both addition and subtraction operations which /// themselves are based on multiplication expressions. + #[allow(clippy::arithmetic_side_effects)] #[inline] fn get_adds(&mut self) -> Result<Ratio<BigInt>, LangErr> { let mut left = self.get_mults()?; @@ -515,7 +526,7 @@ impl<'input, 'cache, 'prev, 'scratch> Evaluator<'input, 'cache, 'prev, 'scratch> /// This function is used for both multiplication and division operations which /// themselves are based on negation expressions. #[inline] - #[allow(clippy::else_if_without_else)] + #[allow(clippy::arithmetic_side_effects, clippy::else_if_without_else)] fn get_mults(&mut self) -> Result<Ratio<BigInt>, LangErr> { let mut left = self.get_neg()?; let mut right; @@ -574,6 +585,7 @@ impl<'input, 'cache, 'prev, 'scratch> Evaluator<'input, 'cache, 'prev, 'scratch> } /// Evaluates negation expressions as defined in the calc language. /// This function is based on exponentiation expressions. + #[allow(clippy::arithmetic_side_effects)] #[inline] fn get_neg(&mut self) -> Result<Ratio<BigInt>, LangErr> { let mut count = 0usize; @@ -591,7 +603,7 @@ impl<'input, 'cache, 'prev, 'scratch> Evaluator<'input, 'cache, 'prev, 'scratch> } /// Gets the square root of value so long as a solution exists. #[inline] - #[allow(clippy::unwrap_used)] + #[allow(clippy::arithmetic_side_effects, clippy::unwrap_used)] fn sqrt(val: Ratio<BigInt>) -> Option<Ratio<BigInt>> { /// Returns the square root of `n` if one exists; otherwise /// returns `None`. @@ -635,6 +647,7 @@ impl<'input, 'cache, 'prev, 'scratch> Evaluator<'input, 'cache, 'prev, 'scratch> } /// Evaluates exponentiation expressions as defined in the calc language. /// This function is based on negation expressions. + #[allow(clippy::arithmetic_side_effects)] #[inline] fn get_exps(&mut self) -> Result<Ratio<BigInt>, LangErr> { let mut t = self.get_fact()?; @@ -713,6 +726,7 @@ impl<'input, 'cache, 'prev, 'scratch> Evaluator<'input, 'cache, 'prev, 'scratch> } /// Evaluates factorial expressions as defined in the calc language. /// This function is based on terminal expressions. + #[allow(clippy::arithmetic_side_effects)] #[inline] fn get_fact(&mut self) -> Result<Ratio<BigInt>, LangErr> { /// Calculates the factorial of `val`. @@ -812,7 +826,11 @@ impl<'input, 'cache, 'prev, 'scratch> Evaluator<'input, 'cache, 'prev, 'scratch> /// a terminal expression; as a result, it is the only terminal expression /// that does not return an `Option`. #[cfg(feature = "rand")] - #[allow(clippy::host_endian_bytes)] + #[allow( + clippy::arithmetic_side_effects, + clippy::host_endian_bytes, + clippy::too_many_lines + )] #[inline] fn get_rand(&mut self) -> Result<Ratio<BigInt>, LangErr> { /// Generates a random 64-bit integer. @@ -823,8 +841,8 @@ impl<'input, 'cache, 'prev, 'scratch> Evaluator<'input, 'cache, 'prev, 'scratch> .map(|()| i64::from_ne_bytes(bytes)) } /// Generates a random 64-bit integer inclusively between the passed arguments. - #[inline] #[allow( + clippy::arithmetic_side_effects, clippy::as_conversions, clippy::cast_lossless, clippy::cast_possible_truncation, @@ -832,6 +850,7 @@ impl<'input, 'cache, 'prev, 'scratch> Evaluator<'input, 'cache, 'prev, 'scratch> clippy::cast_sign_loss, clippy::needless_pass_by_value )] + #[inline] fn rand_range( rng: &mut ThreadRng, lower: Ratio<BigInt>, @@ -934,6 +953,7 @@ impl<'input, 'cache, 'prev, 'scratch> Evaluator<'input, 'cache, 'prev, 'scratch> } /// Rounds a value to the specified number of fractional digits. /// This function is based on add expressions. + #[allow(clippy::arithmetic_side_effects)] #[inline] fn get_round(&mut self) -> Result<Option<Ratio<BigInt>>, LangErr> { let Some(b) = self.utf8.get(self.i..self.i.saturating_add(6)) else { @@ -984,6 +1004,7 @@ impl<'input, 'cache, 'prev, 'scratch> Evaluator<'input, 'cache, 'prev, 'scratch> } /// Evaluates absolute value expressions as defined in the calc language. /// This function is based on add expressions. + #[allow(clippy::arithmetic_side_effects)] #[inline] fn get_abs(&mut self) -> Result<Option<Ratio<BigInt>>, LangErr> { let Some(b) = self.utf8.get(self.i) else { @@ -1018,7 +1039,11 @@ impl<'input, 'cache, 'prev, 'scratch> Evaluator<'input, 'cache, 'prev, 'scratch> // would end up needing to clone the Ratio anyway. By not forcing // get_term to clone, it can rely on map_or_else over match expressions. #[inline] - #[allow(clippy::as_conversions, clippy::cast_possible_truncation)] + #[allow( + clippy::arithmetic_side_effects, + clippy::as_conversions, + clippy::cast_possible_truncation + )] fn get_recall(&mut self) -> Result<Option<Ratio<BigInt>>, LangErr> { let Some(b) = self.utf8.get(self.i) else { return Ok(None); @@ -1044,6 +1069,7 @@ impl<'input, 'cache, 'prev, 'scratch> Evaluator<'input, 'cache, 'prev, 'scratch> } /// Evaluates parenthetical expressions as defined in the calc language. /// This function is based on add expressions. + #[allow(clippy::arithmetic_side_effects)] #[inline] fn get_par(&mut self) -> Result<Option<Ratio<BigInt>>, LangErr> { let Some(b) = self.utf8.get(self.i) else { @@ -1071,21 +1097,24 @@ impl<'input, 'cache, 'prev, 'scratch> Evaluator<'input, 'cache, 'prev, 'scratch> /// Evaluates number literal expressions as defined in the calc language. #[inline] #[allow( + clippy::arithmetic_side_effects, clippy::as_conversions, clippy::cast_lossless, clippy::indexing_slicing )] fn get_rational(&mut self) -> Result<Option<Ratio<BigInt>>, LangErr> { - #[inline] // ControlFlow makes more sense to use in try_fold; however due to a lack // of a map_or_else function, it is easier to simply return a Result with // Err taking the role of ControlFlow::Break. /// Used to parse a sequence of digits into an unsigned integer. + #[allow(clippy::arithmetic_side_effects, clippy::into_iter_on_ref)] + #[inline] fn to_biguint(v: &[u8]) -> (BigUint, usize) { v.into_iter() .try_fold((BigUint::new(Vec::new()), 0), |mut prev, d| { if d.is_ascii_digit() { prev.1 += 1; + // `*d - b'0'` is guaranteed to return a integer between 0 and 9. prev.0 = prev.0 * 10u8 + (*d - b'0'); Ok(prev) } else { @@ -1195,6 +1224,7 @@ pub enum E { } #[cfg(feature = "std")] impl Display for E { + #[allow(clippy::ref_patterns)] #[inline] fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { match *self { diff --git a/src/main.rs b/src/main.rs @@ -25,13 +25,14 @@ clippy::question_mark_used, clippy::single_call_fn )] -use calc_lib::lending_iterator::LendingIterator; -use calc_lib::EvalIter; +use calc_lib::{lending_iterator::LendingIterator, EvalIter}; use core::fmt::{self, Display, Formatter}; #[cfg(all(feature = "priv_sep", target_os = "openbsd"))] use priv_sep::{Promise, Promises}; -use std::error; -use std::io::{self, Error, Write}; +use std::{ + error, + io::{self, Error, Write}, +}; /// Error returned by [`main`]. #[allow(clippy::exhaustive_enums)] #[derive(Debug)]