Enforce cargo clippy strict mode

This commit is contained in:
Austen Adler 2021-05-19 20:08:50 -04:00
parent 9f0ca9d276
commit 17e74b0f52
6 changed files with 96 additions and 82 deletions

View File

@ -1,19 +1,19 @@
pub mod constants;
pub mod errors;
pub mod operations;
pub mod types;
use confy::{load, store};
use constants::{
CalculatorAlignment, CalculatorAngleMode, CalculatorConstant, CalculatorConstants,
CalculatorDisplayMode, CalculatorMacro, CalculatorMacros, CalculatorRegisters, CalculatorState,
RegisterState,
};
use errors::{CalculatorError, CalculatorResult};
use operations::{CalculatorOperation, CalculatorStateChange, MacroState, OpArgs};
use serde::ser::Serializer;
use serde::{Deserialize, Serialize};
use std::collections::{BTreeMap, HashMap};
use std::collections::{HashSet, VecDeque};
use types::{
CalculatorAlignment, CalculatorAngleMode, CalculatorConstant, CalculatorConstants,
CalculatorDisplayMode, CalculatorMacro, CalculatorMacros, CalculatorRegisters, CalculatorState,
RegisterState,
};
const MAX_PRECISION: usize = 20;
const APP_NAME: &str = "rpn_rs";
@ -66,7 +66,7 @@ where
impl Default for Calculator {
fn default() -> Self {
Calculator {
Self {
l: String::new(),
redo_buf: vec![],
undo_buf: vec![],
@ -136,13 +136,15 @@ impl Calculator {
}
}
pub fn load_config() -> CalculatorResult<Calculator> {
pub fn load_config() -> CalculatorResult<Self> {
load(APP_NAME).map_err(|e| CalculatorError::LoadError(Some(e)))
}
pub fn save_config(&self) -> CalculatorResult<()> {
store(APP_NAME, self).map_err(|e| CalculatorError::SaveError(Some(e)))
}
// This maps chars to operations. Not sure I can make this shorter
#[allow(clippy::too_many_lines)]
pub fn take_input(&mut self, c: char) -> CalculatorResult<()> {
match &self.state {
CalculatorState::Normal => match c {
@ -274,12 +276,8 @@ impl Calculator {
}
}
'S' => {
let precision = self.checked_get(0)? as usize;
if precision > MAX_PRECISION {
return Err(CalculatorError::PrecisionTooHigh);
}
self.display_mode = CalculatorDisplayMode::Scientific {
precision: self.pop_usize()?,
precision: self.pop_precision()?,
}
}
'e' => {
@ -288,12 +286,8 @@ impl Calculator {
}
}
'E' => {
let precision = self.checked_get(0)? as usize;
if precision > MAX_PRECISION {
return Err(CalculatorError::PrecisionTooHigh);
}
self.display_mode = CalculatorDisplayMode::Engineering {
precision: self.pop_usize()?,
precision: self.pop_precision()?,
}
}
'f' => {
@ -303,7 +297,7 @@ impl Calculator {
}
'F' => {
self.display_mode = CalculatorDisplayMode::Fixed {
precision: self.pop_usize()?,
precision: self.pop_precision()?,
}
}
'w' => self.save_on_close = false,
@ -405,24 +399,36 @@ impl Calculator {
push: OpArgs::Unary(f),
})
}
pub fn pop(&mut self) -> CalculatorResult<f64> {
pub fn peek(&mut self) -> CalculatorResult<f64> {
self.flush_l()?;
let f = self.checked_get(0)?;
self.checked_get(0)
}
pub fn pop(&mut self) -> CalculatorResult<f64> {
let f = self.peek()?;
self.direct_state_change(CalculatorStateChange {
pop: OpArgs::Unary(f),
push: OpArgs::None,
})?;
Ok(f)
}
pub fn pop_usize(&mut self) -> CalculatorResult<usize> {
self.flush_l()?;
let f = self.checked_get(0)?;
let ret = f as usize;
pub fn pop_precision(&mut self) -> CalculatorResult<usize> {
let f = self.peek()?;
// Ensure this can be cast to a usize
if !f.is_finite() || f.is_sign_negative() {
return Err(CalculatorError::ArithmeticError);
}
#[allow(clippy::cast_sign_loss)]
let u = f as usize;
if u > MAX_PRECISION {
return Err(CalculatorError::PrecisionTooHigh);
}
self.direct_state_change(CalculatorStateChange {
pop: OpArgs::Unary(f),
push: OpArgs::None,
})?;
Ok(ret)
Ok(u)
}
pub fn op(&mut self, op: CalculatorOperation) -> CalculatorResult<()> {
// Dup is special -- don't actually run it if l needs to be flushed
@ -441,7 +447,7 @@ impl Calculator {
}
CalculatorOperation::Negate => self.unary_op(|a| OpArgs::Unary(-a)),
CalculatorOperation::AbsoluteValue => self.unary_op(|a| OpArgs::Unary(a.abs())),
CalculatorOperation::Inverse => self.unary_op(|a| OpArgs::Unary(1.0 / a)),
CalculatorOperation::Inverse => self.unary_op(|a| OpArgs::Unary(a.recip())),
CalculatorOperation::Modulo => self.binary_op(|[a, b]| OpArgs::Unary(b % a)),
//CalculatorOperation::Remainder => self.binary_op(|[a, b]| OpArgs::Unary(b.rem_euclid(a))),
CalculatorOperation::Dup => self.unary_op(|a| OpArgs::Binary([a, a])),
@ -493,7 +499,7 @@ impl Calculator {
CalculatorOperation::Log => self.unary_op(|a| OpArgs::Unary(a.log10())),
CalculatorOperation::Ln => self.unary_op(|a| OpArgs::Unary(a.ln())),
CalculatorOperation::Pow => self.binary_op(|[a, b]| OpArgs::Unary(b.powf(a))),
CalculatorOperation::E => self.binary_op(|[a, b]| OpArgs::Unary(b * 10.0f64.powf(a))),
CalculatorOperation::E => self.binary_op(|[a, b]| OpArgs::Unary(b * 10.0_f64.powf(a))),
CalculatorOperation::Undo => return self.history_op(false),
CalculatorOperation::Redo => return self.history_op(true),
// Macros are a no-op operator; need to insert for undo/redo

View File

@ -27,30 +27,30 @@ impl error::Error for CalculatorError {}
impl fmt::Display for CalculatorError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
CalculatorError::ArithmeticError => write!(f, "Arithmetic Error"),
CalculatorError::NotEnoughStackEntries => write!(f, "Not enough items in the stack"),
CalculatorError::CorruptStateChange(msg) => {
Self::ArithmeticError => write!(f, "Arithmetic Error"),
Self::NotEnoughStackEntries => write!(f, "Not enough items in the stack"),
Self::CorruptStateChange(msg) => {
write!(f, "Corrupt state change: {}", msg)
}
CalculatorError::EmptyHistory(msg) => write!(f, "No history to {}", msg),
CalculatorError::NoSuchOperator(c) => write!(f, "No such operator '{}'", c),
CalculatorError::NoSuchConstant(c) => write!(f, "No such constant '{}'", c),
CalculatorError::NoSuchRegister(c) => write!(f, "No such register '{}'", c),
CalculatorError::NoSuchMacro(c) => write!(f, "No such macro '{}'", c),
CalculatorError::NoSuchSetting(c) => write!(f, "No such setting '{}'", c),
CalculatorError::RecursiveMacro(c) => write!(f, "Recursive macro '{}'", c),
CalculatorError::ParseError => write!(f, "Parse error"),
CalculatorError::PrecisionTooHigh => write!(f, "Precision too high"),
CalculatorError::SaveError(None) => write!(f, "Could not save"),
CalculatorError::SaveError(Some(ConfyError::SerializeTomlError(e))) => {
Self::EmptyHistory(msg) => write!(f, "No history to {}", msg),
Self::NoSuchOperator(c) => write!(f, "No such operator '{}'", c),
Self::NoSuchConstant(c) => write!(f, "No such constant '{}'", c),
Self::NoSuchRegister(c) => write!(f, "No such register '{}'", c),
Self::NoSuchMacro(c) => write!(f, "No such macro '{}'", c),
Self::NoSuchSetting(c) => write!(f, "No such setting '{}'", c),
Self::RecursiveMacro(c) => write!(f, "Recursive macro '{}'", c),
Self::ParseError => write!(f, "Parse error"),
Self::PrecisionTooHigh => write!(f, "Precision too high"),
Self::SaveError(None) => write!(f, "Could not save"),
Self::SaveError(Some(ConfyError::SerializeTomlError(e))) => {
write!(f, "Save serialization error: {}", e)
}
CalculatorError::SaveError(Some(e)) => write!(f, "Could not save: {}", e),
CalculatorError::LoadError(None) => write!(f, "Could not load"),
CalculatorError::LoadError(Some(ConfyError::SerializeTomlError(e))) => {
Self::SaveError(Some(e)) => write!(f, "Could not save: {}", e),
Self::LoadError(None) => write!(f, "Could not load"),
Self::LoadError(Some(ConfyError::SerializeTomlError(e))) => {
write!(f, "Load serialization error: {}", e)
}
CalculatorError::LoadError(Some(e)) => write!(f, "Could not load: {}", e),
Self::LoadError(Some(e)) => write!(f, "Could not load: {}", e),
}
}
}

View File

@ -19,7 +19,7 @@ pub enum CalculatorState {
impl Default for CalculatorState {
fn default() -> Self {
CalculatorState::Normal
Self::Normal
}
}
@ -53,16 +53,16 @@ pub enum CalculatorAngleMode {
impl Default for CalculatorAngleMode {
fn default() -> Self {
CalculatorAngleMode::Degrees
Self::Degrees
}
}
impl fmt::Display for CalculatorAngleMode {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
CalculatorAngleMode::Degrees => write!(f, "DEG"),
CalculatorAngleMode::Radians => write!(f, "RAD"),
CalculatorAngleMode::Grads => write!(f, "GRD"),
Self::Degrees => write!(f, "DEG"),
Self::Radians => write!(f, "RAD"),
Self::Grads => write!(f, "GRD"),
}
}
}
@ -81,18 +81,18 @@ pub enum CalculatorDisplayMode {
impl fmt::Display for CalculatorDisplayMode {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
CalculatorDisplayMode::Default => write!(f, "DEF"),
CalculatorDisplayMode::Separated { separator } => write!(f, "SEP({})", separator),
CalculatorDisplayMode::Scientific { precision } => write!(f, "SCI({})", precision),
CalculatorDisplayMode::Engineering { precision } => write!(f, "ENG({})", precision),
CalculatorDisplayMode::Fixed { precision } => write!(f, "FIX({})", precision),
Self::Default => write!(f, "DEF"),
Self::Separated { separator } => write!(f, "SEP({})", separator),
Self::Scientific { precision } => write!(f, "SCI({})", precision),
Self::Engineering { precision } => write!(f, "ENG({})", precision),
Self::Fixed { precision } => write!(f, "FIX({})", precision),
}
}
}
impl Default for CalculatorDisplayMode {
fn default() -> Self {
CalculatorDisplayMode::Default
Self::Default
}
}
@ -104,15 +104,15 @@ pub enum CalculatorAlignment {
impl Default for CalculatorAlignment {
fn default() -> Self {
CalculatorAlignment::Left
Self::Left
}
}
impl fmt::Display for CalculatorAlignment {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
CalculatorAlignment::Left => write!(f, "L"),
CalculatorAlignment::Right => write!(f, "R"),
Self::Left => write!(f, "L"),
Self::Right => write!(f, "R"),
}
}
}

View File

@ -19,7 +19,7 @@ pub struct Events {
}
impl Events {
pub fn new(tick_rate: u64) -> Events {
pub fn new(tick_rate: u64) -> Self {
let (tx, rx) = mpsc::channel();
let tick_handle = {
let tx = tx.clone();
@ -44,14 +44,14 @@ impl Events {
}
})
};
Events {
Self {
tx,
rx,
tick_handle,
}
}
/// Returns a chain of the next element (blocking) and a TryIter of everything after it.
/// Returns a chain of the next element (blocking) and a `TryIter` of everything after it.
/// Useful for reading a single Iterator of all elements once after blocking, so there are not too many UI redraws.
pub fn blocking_iter(
&self,

View File

@ -2,13 +2,11 @@
pub fn scientific(f: f64, precision: usize) -> String {
let mut ret = format!("{:.precision$E}", f, precision = precision);
let exp = ret.split_off(ret.find('E').unwrap_or(0));
let (exp_sign, exp) = if let Some(stripped) = exp.strip_prefix("E-") {
('-', stripped)
} else {
('+', &exp[1..])
};
let (exp_sign, exp) = exp
.strip_prefix("E-")
.map_or_else(|| ('+', &exp[1..]), |stripped| ('-', stripped));
let sign = if !ret.starts_with('-') { " " } else { "" };
let sign = if ret.starts_with('-') { "" } else { " " };
format!("{}{} E{}{:0>pad$}", sign, ret, exp_sign, exp, pad = 2)
}
@ -48,9 +46,9 @@ pub fn engineering(f: f64, precision: usize) -> String {
// Whole portion of number. Slice is safe because the num_whole_digits is always 3 and the num_str will always have length >= 3 since precision in all=2 (+original whole digit)
// Original number is 1,000 => whole will be 1, if original is 0.01, whole will be 10
let whole = &num_str[0..(num_whole_digits + 1)];
let whole = &num_str[0..=num_whole_digits];
// Decimal portion of the number. Sliced from the number of whole digits to the *requested* precision. Precision generated in all will be requested precision + 2
let decimal = &num_str[(num_whole_digits + 1)..(precision + num_whole_digits + 1)];
let decimal = &num_str[(num_whole_digits + 1)..=(precision + num_whole_digits)];
// Right align whole portion, always have decimal point
format!(
"{: >4}.{} E{}{:0>pad$}",

View File

@ -1,10 +1,16 @@
#![warn(clippy::all, clippy::pedantic, clippy::nursery, clippy::cargo)]
// This is intended behavior
#![allow(clippy::cast_possible_truncation)]
// Cannot fix this, so don't warn me about it
#![allow(clippy::multiple_crate_versions)]
mod calc;
mod event;
mod format;
use calc::{
constants::{CalculatorAlignment, CalculatorDisplayMode, CalculatorState, RegisterState},
errors::CalculatorResult,
types::{CalculatorAlignment, CalculatorDisplayMode, CalculatorState, RegisterState},
Calculator,
};
use crossterm::{
@ -53,7 +59,7 @@ impl Default for App {
Ok(c) => (c, None),
Err(e) => (Calculator::default(), Some(format!("{}", e))),
};
App {
Self {
calculator,
error_msg,
state: AppState::Calculator,
@ -61,11 +67,13 @@ impl Default for App {
}
}
impl App {
fn draw_clippy_dialogs<T: std::io::Write>(&mut self, f: &mut Frame<CrosstermBackend<T>>) {
// This function is long because it contains help text
#[allow(clippy::too_many_lines)]
fn draw_clippy_dialogs<T: Write>(&mut self, f: &mut Frame<CrosstermBackend<T>>) {
match (&self.state, &self.calculator.state) {
(AppState::Help, _) => {
draw_clippy_rect(
ClippyRectangle {
&ClippyRectangle {
title: "Help",
msg: "\
+ => Add s => Sin\n\
@ -92,7 +100,7 @@ impl App {
}
(AppState::Calculator, CalculatorState::WaitingForConstant) => {
draw_clippy_rect(
ClippyRectangle {
&ClippyRectangle {
title: "Constants",
msg: self
.calculator
@ -113,7 +121,7 @@ impl App {
RegisterState::Load => "Registers",
};
draw_clippy_rect(
ClippyRectangle {
&ClippyRectangle {
title,
msg: self
.calculator
@ -128,7 +136,7 @@ impl App {
}
(AppState::Calculator, CalculatorState::WaitingForMacro) => {
draw_clippy_rect(
ClippyRectangle {
&ClippyRectangle {
title: "Macros",
msg: self
.calculator
@ -143,7 +151,7 @@ impl App {
}
(AppState::Calculator, CalculatorState::WaitingForSetting) => {
draw_clippy_rect(
ClippyRectangle {
&ClippyRectangle {
title: "Settings",
msg: "\
d => Degrees\n\
@ -170,7 +178,7 @@ impl App {
}
}
pub fn terminal_draw_func<T: std::io::Write>(&mut self, f: &mut Frame<CrosstermBackend<T>>) {
pub fn terminal_draw_func<T: Write>(&mut self, f: &mut Frame<CrosstermBackend<T>>) {
let chunks = Layout::default()
.direction(Direction::Vertical)
.margin(2)
@ -304,7 +312,7 @@ fn main() -> Result<(), Box<dyn Error>> {
Err(e) => Some(format!("{}", e)),
};
}
_ => continue,
Event::Tick => continue,
}
}
}
@ -318,6 +326,8 @@ fn main() -> Result<(), Box<dyn Error>> {
app.calculator.close().map_err(|e| e.into())
}
// This function is long since it maps keys to their proper value
#[allow(clippy::too_many_lines)]
fn handle_key(app: &mut App, key: KeyEvent) -> CalculatorResult<CalculatorResponse> {
match (&app.state, &app.calculator.state) {
(AppState::Calculator, CalculatorState::Normal) => match key {
@ -452,7 +462,7 @@ impl ClippyRectangle<'_> {
}
}
fn draw_clippy_rect<T: std::io::Write>(c: ClippyRectangle, f: &mut Frame<CrosstermBackend<T>>) {
fn draw_clippy_rect<T: Write>(c: &ClippyRectangle, f: &mut Frame<CrosstermBackend<T>>) {
// let block = Block::default().title(c.title).borders(Borders::ALL);
let dimensions = c.size();
let popup_layout = Layout::default()