diff --git a/interpreter/benches/file_parse.rs b/interpreter/benches/file_parse.rs index 484cba7..002b395 100644 --- a/interpreter/benches/file_parse.rs +++ b/interpreter/benches/file_parse.rs @@ -1,4 +1,4 @@ -use mps_interpreter::MpsFaye; +use muss_interpreter::Interpreter; //use mps_interpreter::MpsRunner; use std::fs::File; use std::io::{BufReader, Read, Seek}; @@ -35,12 +35,12 @@ fn faye_benchmark(c: &mut Criterion) { let mut buf = Vec::with_capacity(1024 * 1024); reader.read_to_end(&mut buf).unwrap(); drop(buf); - c.bench_function("mps-faye lots_of_empty.mps", |b| { + c.bench_function("muss-faye lots_of_empty.mps", |b| { b.iter(|| { //let f = File::open("benches/lots_of_empty.mps").unwrap(); //let mut reader = BufReader::new(f); reader.rewind().unwrap(); - let mps = MpsFaye::with_stream(&mut reader); + let mps = Interpreter::with_stream(&mut reader); for item in mps { match item { Err(e) => panic!("{}", e), diff --git a/interpreter/fuzz/Cargo.lock b/interpreter/fuzz/Cargo.lock index 3a9a116..711d069 100644 --- a/interpreter/fuzz/Cargo.lock +++ b/interpreter/fuzz/Cargo.lock @@ -83,7 +83,7 @@ dependencies = [ [[package]] name = "bliss-audio-symphonia" -version = "0.4.6" +version = "0.5.0" dependencies = [ "bliss-audio-aubio-rs", "crossbeam", @@ -96,6 +96,7 @@ dependencies = [ "noisy_float", "num_cpus", "rayon", + "rcue", "ripemd160", "rustfft", "strum", @@ -567,7 +568,7 @@ dependencies = [ [[package]] name = "muss-interpreter" -version = "0.8.0" +version = "0.9.0" dependencies = [ "bliss-audio-symphonia", "dirs", @@ -871,6 +872,12 @@ dependencies = [ "num_cpus", ] +[[package]] +name = "rcue" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fca1481d62f18158646de2ec552dd63f8bdc5be6448389b192ba95c939df997e" + [[package]] name = "redox_syscall" version = "0.2.13" diff --git a/interpreter/src/debug.rs b/interpreter/src/debug.rs index 3e1c5ac..4f76d3e 100644 --- a/interpreter/src/debug.rs +++ b/interpreter/src/debug.rs @@ -48,7 +48,6 @@ where fn next(&mut self) -> Option { let next_item = self.interpreter.next(); - let transmuted_next = (self.transmuter)(&mut self.interpreter, next_item); - transmuted_next + (self.transmuter)(&mut self.interpreter, next_item) } } diff --git a/interpreter/src/faye.rs b/interpreter/src/faye.rs index e8cbb62..66ef982 100644 --- a/interpreter/src/faye.rs +++ b/interpreter/src/faye.rs @@ -29,8 +29,8 @@ where } #[inline] -fn empty_callback<'a, T: TokenReader>( - _s: &mut Interpreter<'a, T>, +fn empty_callback( + _s: &mut Interpreter<'_, T>, _d: InterpreterEvent, ) -> Result<(), InterpreterError> { Ok(()) diff --git a/interpreter/src/interpretor.rs b/interpreter/src/interpretor.rs index 9d0a657..a4cc186 100644 --- a/interpreter/src/interpretor.rs +++ b/interpreter/src/interpretor.rs @@ -23,26 +23,26 @@ pub(crate) fn standard_vocab(vocabulary: &mut LanguageDictionary) { // iter blocks .add( crate::lang::ItemBlockFactory::new() - .add(crate::lang::vocabulary::item_ops::ConstantItemOpFactory) - .add(crate::lang::vocabulary::item_ops::VariableAssignItemOpFactory) - .add(crate::lang::vocabulary::item_ops::FieldAssignItemOpFactory) - .add(crate::lang::vocabulary::item_ops::FileItemOpFactory) - .add(crate::lang::vocabulary::item_ops::VariableDeclareItemOpFactory) - .add(crate::lang::vocabulary::item_ops::InterpolateStringItemOpFactory) - .add(crate::lang::vocabulary::item_ops::BranchItemOpFactory) - .add(crate::lang::vocabulary::item_ops::IterItemOpFactory) - .add(crate::lang::vocabulary::item_ops::ConstructorItemOpFactory) - .add(crate::lang::vocabulary::item_ops::EmptyItemOpFactory) - .add(crate::lang::vocabulary::item_ops::RemoveItemOpFactory) - .add(crate::lang::vocabulary::item_ops::VariableRetrieveItemOpFactory) - .add(crate::lang::vocabulary::item_ops::NegateItemOpFactory) - .add(crate::lang::vocabulary::item_ops::NotItemOpFactory) - .add(crate::lang::vocabulary::item_ops::CompareItemOpFactory) - .add(crate::lang::vocabulary::item_ops::AddItemOpFactory) - .add(crate::lang::vocabulary::item_ops::SubtractItemOpFactory) - .add(crate::lang::vocabulary::item_ops::OrItemOpFactory) - .add(crate::lang::vocabulary::item_ops::AndItemOpFactory) - .add(crate::lang::vocabulary::item_ops::BracketsItemOpFactory), + .push(crate::lang::vocabulary::item_ops::ConstantItemOpFactory) + .push(crate::lang::vocabulary::item_ops::VariableAssignItemOpFactory) + .push(crate::lang::vocabulary::item_ops::FieldAssignItemOpFactory) + .push(crate::lang::vocabulary::item_ops::FileItemOpFactory) + .push(crate::lang::vocabulary::item_ops::VariableDeclareItemOpFactory) + .push(crate::lang::vocabulary::item_ops::InterpolateStringItemOpFactory) + .push(crate::lang::vocabulary::item_ops::BranchItemOpFactory) + .push(crate::lang::vocabulary::item_ops::IterItemOpFactory) + .push(crate::lang::vocabulary::item_ops::ConstructorItemOpFactory) + .push(crate::lang::vocabulary::item_ops::EmptyItemOpFactory) + .push(crate::lang::vocabulary::item_ops::RemoveItemOpFactory) + .push(crate::lang::vocabulary::item_ops::VariableRetrieveItemOpFactory) + .push(crate::lang::vocabulary::item_ops::NegateItemOpFactory) + .push(crate::lang::vocabulary::item_ops::NotItemOpFactory) + .push(crate::lang::vocabulary::item_ops::CompareItemOpFactory) + .push(crate::lang::vocabulary::item_ops::AddItemOpFactory) + .push(crate::lang::vocabulary::item_ops::SubtractItemOpFactory) + .push(crate::lang::vocabulary::item_ops::OrItemOpFactory) + .push(crate::lang::vocabulary::item_ops::AndItemOpFactory) + .push(crate::lang::vocabulary::item_ops::BracketsItemOpFactory), ) // functions and misc // functions don't enforce bracket coherence diff --git a/interpreter/src/item.rs b/interpreter/src/item.rs index a69492d..2a0dab1 100644 --- a/interpreter/src/item.rs +++ b/interpreter/src/item.rs @@ -45,6 +45,10 @@ impl Item { pub fn len(&self) -> usize { self.fields.len() } + + pub fn is_empty(&self) -> bool { + self.fields.is_empty() + } } impl Display for Item { diff --git a/interpreter/src/lang/dictionary.rs b/interpreter/src/lang/dictionary.rs index 3304f25..2b83280 100644 --- a/interpreter/src/lang/dictionary.rs +++ b/interpreter/src/lang/dictionary.rs @@ -53,6 +53,7 @@ impl LanguageDictionary { } } +#[allow(clippy::derivable_impls)] impl Default for LanguageDictionary { fn default() -> Self { Self { diff --git a/interpreter/src/lang/filter.rs b/interpreter/src/lang/filter.rs index f878b4f..90bcec6 100644 --- a/interpreter/src/lang/filter.rs +++ b/interpreter/src/lang/filter.rs @@ -227,7 +227,7 @@ impl Iterator for FilterStatement

{ let matches_result = self.predicate.matches(&item, &mut ctx); let matches = match matches_result { Err(e) => { - maybe_result = Some(Err(e.with(RuntimeOp(fake.clone())))); + maybe_result = Some(Err(e.with(RuntimeOp(fake)))); self.context = Some(ctx); break; } @@ -245,7 +245,7 @@ impl Iterator for FilterStatement

{ Err(e) => { //self.context = Some(op.escape()); maybe_result = - Some(Err(e.with(RuntimeOp(fake.clone())))); + Some(Err(e.with(RuntimeOp(fake)))); self.context = Some(ctx); break; } @@ -269,7 +269,7 @@ impl Iterator for FilterStatement

{ Err(e) => match maybe_result { Some(Ok(_)) => { maybe_result = Some(Err( - e.with(RuntimeOp(fake.clone())) + e.with(RuntimeOp(fake)) )) } Some(Err(e2)) => maybe_result = Some(Err(e2)), // already failing, do not replace error, @@ -286,7 +286,7 @@ impl Iterator for FilterStatement

{ Err(e) => { //self.context = Some(op.escape()); maybe_result = - Some(Err(e.with(RuntimeOp(fake.clone())))); + Some(Err(e.with(RuntimeOp(fake)))); self.context = Some(ctx); break; } @@ -332,7 +332,7 @@ impl Iterator for FilterStatement

{ } Err(e) => { self.is_failing = true; // this is unrecoverable and reproducible, so it shouldn't be tried again (to prevent error spam) - return Some(Err(e.with(RuntimeOp(fake.clone())))) + return Some(Err(e.with(RuntimeOp(fake)))) }, }; let mut maybe_result = None; @@ -434,7 +434,7 @@ impl Iterator for FilterStatement

{ .variables .declare(variable_name, Type::Op(variable)) { - Err(e) => Some(Err(e.with(RuntimeOp(fake.clone())))), + Err(e) => Some(Err(e.with(RuntimeOp(fake)))), Ok(_) => maybe_result, } } @@ -479,6 +479,7 @@ impl + 'static> impl + 'static> BoxedOpFactory for FilterStatementFactory { + #[allow(clippy::unnecessary_unwrap)] fn is_op_boxed(&self, tokens: &VecDeque) -> bool { let tokens_len = tokens.len(); if is_correct_format(tokens) { @@ -524,8 +525,7 @@ impl + 'static> BoxedOpFactory dict: &LanguageDictionary, ) -> Result, SyntaxError> { let start_of_op = last_dot_before_open_bracket(tokens); - let op; - if start_of_op == 1 && tokens[0].is_name() { + let op = if start_of_op == 1 && tokens[0].is_name() { // variable_name.(predicate) let variable_name = assert_token( |t| match t { @@ -535,15 +535,15 @@ impl + 'static> BoxedOpFactory Token::Name("variable_name".into()), tokens, )?; - op = VariableOrOp::Variable(variable_name); + VariableOrOp::Variable(variable_name) } else { // .(predicate) //let mut new_tokens = tokens.range(0..start_of_op).map(|x| x.to_owned()).collect(); let end_tokens = tokens.split_off(start_of_op); // don't parse filter in inner statement let inner_op = dict.try_build_statement(tokens)?; tokens.extend(end_tokens); - op = VariableOrOp::Op(inner_op.into()); - } + VariableOrOp::Op(inner_op.into()) + }; assert_token_raw(Token::Dot, tokens)?; assert_token_raw(Token::OpenBracket, tokens)?; if !tokens.is_empty() && check_name("if", &tokens[0]) { diff --git a/interpreter/src/lang/filter_replace.rs b/interpreter/src/lang/filter_replace.rs index 5510d69..cc24aee 100644 --- a/interpreter/src/lang/filter_replace.rs +++ b/interpreter/src/lang/filter_replace.rs @@ -190,7 +190,7 @@ impl Iterator for FilterReplaceStatement

{ Ok(x) => { return Some(Err(RuntimeError { line: 0, - op: fake.clone(), + op: fake, msg: format!( "Expected operation/iterable type in variable {}, got {}", &variable_name, x @@ -203,15 +203,14 @@ impl Iterator for FilterReplaceStatement

{ variable.enter(ctx); let item = variable.next(); self.context = Some(variable.escape()); - match self + if let Err(e) = self .context .as_mut() .unwrap() .variables .declare(variable_name, Type::Op(variable)) { - Err(e) => return Some(Err(e.with(RuntimeOp(fake)))), - Ok(_) => {} + return Some(Err(e.with(RuntimeOp(fake)))); } item } @@ -242,9 +241,8 @@ impl Iterator for FilterReplaceStatement

{ // invoke inner op real_op.enter(self.context.take().unwrap()); if real_op.is_resetable() { - match real_op.reset() { - Err(e) => return Some(Err(e)), - Ok(_) => {} + if let Err(e) = real_op.reset() { + return Some(Err(e)); } } for item in real_op.by_ref() { @@ -287,9 +285,8 @@ impl Iterator for FilterReplaceStatement

{ // invoke inner operation real_op.enter(self.context.take().unwrap()); if real_op.is_resetable() { - match real_op.reset() { - Err(e) => return Some(Err(e)), - Ok(_) => {} + if let Err(e) = real_op.reset() { + return Some(Err(e)); } } for item in real_op.by_ref() { @@ -319,7 +316,7 @@ impl Iterator for FilterReplaceStatement

{ Some(Ok(item)) } } - Err(e) => Some(Err(e.with(RuntimeOp(fake.clone())))), + Err(e) => Some(Err(e.with(RuntimeOp(fake)))), } } Some(Err(e)) => Some(Err(e)), @@ -347,12 +344,11 @@ fn declare_or_replace_item( single: SingleItem, ctx: &mut Context, ) -> Result, RuntimeMsg> { - let old_item: Option; - if ctx.variables.exists(ITEM_VARIABLE_NAME) { - old_item = Some(ctx.variables.remove(ITEM_VARIABLE_NAME)?); + let old_item: Option = if ctx.variables.exists(ITEM_VARIABLE_NAME) { + Some(ctx.variables.remove(ITEM_VARIABLE_NAME)?) } else { - old_item = None; - } + None + }; ctx.variables .declare(ITEM_VARIABLE_NAME, Type::Op(Box::new(single)))?; Ok(old_item) diff --git a/interpreter/src/lang/iter_block.rs b/interpreter/src/lang/iter_block.rs index ca6fe21..6d476e2 100644 --- a/interpreter/src/lang/iter_block.rs +++ b/interpreter/src/lang/iter_block.rs @@ -1,3 +1,4 @@ +#![allow(clippy::new_without_default)] use core::ops::Deref; use std::collections::VecDeque; use std::fmt::{Debug, Display, Error, Formatter}; @@ -67,11 +68,11 @@ pub struct ItemBlockStatement { impl Display for ItemBlockStatement { fn fmt(&self, f: &mut Formatter) -> Result<(), Error> { write!(f, "{}.{{", self.iterable)?; - if self.statements.len() > 0 { - write!(f, "\n")?; + if !self.statements.is_empty() { + writeln!(f)?; } for statement in self.statements.iter() { - write!(f, "{}\n", statement)?; + writeln!(f, "{}", statement)?; } write!(f, "}}") } @@ -213,7 +214,7 @@ pub struct ItemBlockFactory { } impl ItemBlockFactory { - pub fn add< + pub fn push< T: ItemOpFactory + 'static, Y: Deref + ItemOp + 'static, >( @@ -317,12 +318,11 @@ fn restore_item_var( ctx: &mut Context, old_var: Option, ) -> Result, RuntimeMsg> { - let new_var; - if ctx.variables.exists(ITEM_VARIABLE_NAME) { - new_var = Some(ctx.variables.remove(ITEM_VARIABLE_NAME)?); + let new_var = if ctx.variables.exists(ITEM_VARIABLE_NAME) { + Some(ctx.variables.remove(ITEM_VARIABLE_NAME)?) } else { - new_var = None; - } + None + }; if let Some(old_var) = old_var { ctx.variables.declare(ITEM_VARIABLE_NAME, old_var)?; } diff --git a/interpreter/src/lang/mod.rs b/interpreter/src/lang/mod.rs index b0e8757..2cd4ee8 100644 --- a/interpreter/src/lang/mod.rs +++ b/interpreter/src/lang/mod.rs @@ -1,3 +1,5 @@ +#![allow(clippy::match_like_matches_macro)] +#![allow(clippy::needless_range_loop)] mod db_items; mod dictionary; mod error; diff --git a/interpreter/src/lang/pseudo_op.rs b/interpreter/src/lang/pseudo_op.rs index c0bbad3..1e9d612 100644 --- a/interpreter/src/lang/pseudo_op.rs +++ b/interpreter/src/lang/pseudo_op.rs @@ -1,3 +1,4 @@ +#![allow(clippy::borrowed_box)] use std::fmt::{Debug, Display, Error, Formatter}; use super::Op; diff --git a/interpreter/src/lang/sorter.rs b/interpreter/src/lang/sorter.rs index d33858d..bbbc757 100644 --- a/interpreter/src/lang/sorter.rs +++ b/interpreter/src/lang/sorter.rs @@ -13,7 +13,7 @@ use crate::Context; const SORTER_ITEM_CACHE_SIZE: usize = 8; pub trait Sorter: Clone + Debug + Display { - fn sort<'a>( + fn sort( &mut self, iterator: &mut dyn Op, item_buf: &mut VecDeque, diff --git a/interpreter/src/lang/vocabulary/filters/nonempty_filter.rs b/interpreter/src/lang/vocabulary/filters/nonempty_filter.rs index 29f730f..e7278e6 100644 --- a/interpreter/src/lang/vocabulary/filters/nonempty_filter.rs +++ b/interpreter/src/lang/vocabulary/filters/nonempty_filter.rs @@ -19,7 +19,7 @@ impl Display for NonEmptyFilter { impl FilterPredicate for NonEmptyFilter { fn matches(&mut self, item: &Item, _ctx: &mut Context) -> Result { - if item.len() != 0 { + if !item.is_empty() { if item.len() == 1 && item.field("filename").is_some() { Ok(false) // ignore filename field, since that almost always exists } else { diff --git a/interpreter/src/lang/vocabulary/filters/unique.rs b/interpreter/src/lang/vocabulary/filters/unique.rs index 92b4972..766a648 100644 --- a/interpreter/src/lang/vocabulary/filters/unique.rs +++ b/interpreter/src/lang/vocabulary/filters/unique.rs @@ -90,7 +90,7 @@ pub struct UniqueFilterFactory; impl FilterFactory for UniqueFilterFactory { fn is_filter(&self, tokens: &VecDeque<&Token>) -> bool { - tokens.len() >= 2 && check_name("unique", &tokens[0]) + tokens.len() >= 2 && check_name("unique", tokens[0]) } fn build_filter( @@ -128,7 +128,7 @@ impl FilterFactory for UniqueFilterFactory { impl FilterFactory for UniqueFilterFactory { fn is_filter(&self, tokens: &VecDeque<&Token>) -> bool { - tokens.len() == 1 && check_name("unique", &tokens[0]) + tokens.len() == 1 && check_name("unique", tokens[0]) } fn build_filter( diff --git a/interpreter/src/lang/vocabulary/intersection.rs b/interpreter/src/lang/vocabulary/intersection.rs index 596dc01..441ccc4 100644 --- a/interpreter/src/lang/vocabulary/intersection.rs +++ b/interpreter/src/lang/vocabulary/intersection.rs @@ -49,7 +49,7 @@ impl Iterator for IntersectionStatement { type Item = IteratorItem; fn next(&mut self) -> Option { - if self.ops.len() == 0 { + if self.ops.is_empty() { return None; } else if self.init_needed { self.init_needed = false; diff --git a/interpreter/src/lang/vocabulary/item_ops/add.rs b/interpreter/src/lang/vocabulary/item_ops/add.rs index b7dbd73..36fbb7e 100644 --- a/interpreter/src/lang/vocabulary/item_ops/add.rs +++ b/interpreter/src/lang/vocabulary/item_ops/add.rs @@ -36,7 +36,7 @@ impl ItemOp for AddItemOp { let rhs = self.rhs.execute(context)?; if let Type::Primitive(rhs) = &rhs { Ok(Type::Primitive( - lhs.try_add(rhs).map_err(|e| RuntimeMsg(e))?, + lhs.try_add(rhs).map_err(RuntimeMsg)?, )) } else { Err(RuntimeMsg(format!( diff --git a/interpreter/src/lang/vocabulary/item_ops/branch.rs b/interpreter/src/lang/vocabulary/item_ops/branch.rs index f31f9c6..72fab86 100644 --- a/interpreter/src/lang/vocabulary/item_ops/branch.rs +++ b/interpreter/src/lang/vocabulary/item_ops/branch.rs @@ -28,29 +28,29 @@ impl Display for BranchItemOp { fn fmt(&self, f: &mut Formatter) -> Result<(), Error> { write!(f, "if {} {{", self.condition)?; if self.inner_ifs.len() > 1 { - write!(f, "\n")?; + writeln!(f)?; } for i in 0..self.inner_ifs.len() { write!(f, "{}", self.inner_ifs[i])?; if i != self.inner_ifs.len() - 1 { - write!(f, ",\n")?; + writeln!(f, ",")?; } } if self.inner_ifs.len() > 1 { - write!(f, "\n")?; + writeln!(f)?; } write!(f, "}} else {{")?; if self.inner_elses.len() > 1 { - write!(f, "\n")?; + writeln!(f)?; } for i in 0..self.inner_elses.len() { write!(f, "{}", self.inner_elses[i])?; if i != self.inner_elses.len() - 1 { - write!(f, ",\n")?; + writeln!(f, ",")?; } } if self.inner_elses.len() > 1 { - write!(f, "\n")?; + writeln!(f)?; } write!(f, "}}") } diff --git a/interpreter/src/lang/vocabulary/item_ops/compare.rs b/interpreter/src/lang/vocabulary/item_ops/compare.rs index 9a52a35..f03fd4f 100644 --- a/interpreter/src/lang/vocabulary/item_ops/compare.rs +++ b/interpreter/src/lang/vocabulary/item_ops/compare.rs @@ -42,7 +42,7 @@ impl ItemOp for CompareItemOp { let rhs_val = self.rhs.execute(context)?; if let Type::Primitive(lhs) = lhs_val { if let Type::Primitive(rhs) = rhs_val { - let compare = lhs.compare(&rhs).map_err(|e| RuntimeMsg(e))?; + let compare = lhs.compare(&rhs).map_err(RuntimeMsg)?; let mut is_match = false; for comparator in self.comparison { if comparator == compare { diff --git a/interpreter/src/lang/vocabulary/item_ops/constructor.rs b/interpreter/src/lang/vocabulary/item_ops/constructor.rs index f99e65a..1376e54 100644 --- a/interpreter/src/lang/vocabulary/item_ops/constructor.rs +++ b/interpreter/src/lang/vocabulary/item_ops/constructor.rs @@ -35,7 +35,7 @@ impl Display for ConstructorItemOp { fn fmt(&self, f: &mut Formatter) -> Result<(), Error> { write!(f, "Item(")?; if self.fields.len() > 1 { - write!(f, "\n")?; + writeln!(f)?; for i in 0..self.fields.len() - 1 { let field = &self.fields[i]; write!(f, "{}: {}, ", field.name, field.value)?; diff --git a/interpreter/src/lang/vocabulary/item_ops/field_assign.rs b/interpreter/src/lang/vocabulary/item_ops/field_assign.rs index 54a24d6..29546fb 100644 --- a/interpreter/src/lang/vocabulary/item_ops/field_assign.rs +++ b/interpreter/src/lang/vocabulary/item_ops/field_assign.rs @@ -78,11 +78,10 @@ impl ItemOpFactory for FieldAssignItemOpFactory { factory: &ItemBlockFactory, dict: &LanguageDictionary, ) -> Result { - let var_name; - if tokens[0].is_dot() { - var_name = "item".to_string(); + let var_name =if tokens[0].is_dot() { + "item".to_string() } else { - var_name = assert_token( + assert_token( |t| match t { Token::Name(s) => Some(s), _ => None, @@ -90,7 +89,7 @@ impl ItemOpFactory for FieldAssignItemOpFactory { Token::Name("variable_name".into()), tokens, )? - } + }; assert_token_raw(Token::Dot, tokens)?; let f_name = assert_token( |t| match t { diff --git a/interpreter/src/lang/vocabulary/item_ops/iter_op.rs b/interpreter/src/lang/vocabulary/item_ops/iter_op.rs index e403dd2..3a5f02e 100644 --- a/interpreter/src/lang/vocabulary/item_ops/iter_op.rs +++ b/interpreter/src/lang/vocabulary/item_ops/iter_op.rs @@ -30,7 +30,7 @@ impl Display for IterItemOp { impl ItemOp for IterItemOp { fn execute(&self, _context: &mut Context) -> Result { - Ok(Type::Op(self.inner.dup().into())) + Ok(Type::Op(self.inner.dup())) } } diff --git a/interpreter/src/lang/vocabulary/item_ops/negate.rs b/interpreter/src/lang/vocabulary/item_ops/negate.rs index 3ebe35a..0e0b450 100644 --- a/interpreter/src/lang/vocabulary/item_ops/negate.rs +++ b/interpreter/src/lang/vocabulary/item_ops/negate.rs @@ -33,7 +33,7 @@ impl ItemOp for NegateItemOp { let rhs = self.rhs.execute(context)?; if let Type::Primitive(rhs) = &rhs { Ok(Type::Primitive( - rhs.try_negate().map_err(|e| RuntimeMsg(e))?, + rhs.try_negate().map_err(RuntimeMsg)?, )) } else { Err(RuntimeMsg(format!( diff --git a/interpreter/src/lang/vocabulary/item_ops/not.rs b/interpreter/src/lang/vocabulary/item_ops/not.rs index 6f9b855..e2a6b59 100644 --- a/interpreter/src/lang/vocabulary/item_ops/not.rs +++ b/interpreter/src/lang/vocabulary/item_ops/not.rs @@ -33,7 +33,7 @@ impl ItemOp for NotItemOp { let rhs = self.rhs.execute(context)?; if let Type::Primitive(rhs) = &rhs { Ok(Type::Primitive( - rhs.try_not().map_err(|e| RuntimeMsg(e))?, + rhs.try_not().map_err(RuntimeMsg)?, )) } else { Err(RuntimeMsg(format!( diff --git a/interpreter/src/lang/vocabulary/item_ops/remove_variable.rs b/interpreter/src/lang/vocabulary/item_ops/remove_variable.rs index 0cb3919..718fa83 100644 --- a/interpreter/src/lang/vocabulary/item_ops/remove_variable.rs +++ b/interpreter/src/lang/vocabulary/item_ops/remove_variable.rs @@ -75,20 +75,19 @@ impl ItemOpFactory for RemoveItemOpFactory { Token::Name("variable_name".into()), tokens, )?; - let field_opt; - if tokens.is_empty() { - field_opt = None; + let field_opt = if tokens.is_empty() { + None } else { assert_token_raw(Token::Dot, tokens)?; - field_opt = Some(assert_token( + Some(assert_token( |t| match t { Token::Name(s) => Some(s), _ => None, }, Token::Name("field_name".into()), tokens, - )?); - } + )?) + }; Ok(RemoveItemOp { variable_name: name, field_name: field_opt, diff --git a/interpreter/src/lang/vocabulary/item_ops/retrieve_variable.rs b/interpreter/src/lang/vocabulary/item_ops/retrieve_variable.rs index 2116d66..9cf3cdf 100644 --- a/interpreter/src/lang/vocabulary/item_ops/retrieve_variable.rs +++ b/interpreter/src/lang/vocabulary/item_ops/retrieve_variable.rs @@ -86,20 +86,19 @@ impl ItemOpFactory for VariableRetrieveItemOpFactory { Token::Name("variable_name".into()), tokens, )?; - let field_opt; - if tokens.is_empty() { - field_opt = None; + let field_opt = if tokens.is_empty() { + None } else { assert_token_raw(Token::Dot, tokens)?; - field_opt = Some(assert_token( + Some(assert_token( |t| match t { Token::Name(s) => Some(s), _ => None, }, Token::Name("field_name".into()), tokens, - )?); - } + )?) + }; Ok(VariableRetrieveItemOp { variable_name: var_name, field_name: field_opt, diff --git a/interpreter/src/lang/vocabulary/item_ops/string_interpolate.rs b/interpreter/src/lang/vocabulary/item_ops/string_interpolate.rs index b5b9a88..582e62f 100644 --- a/interpreter/src/lang/vocabulary/item_ops/string_interpolate.rs +++ b/interpreter/src/lang/vocabulary/item_ops/string_interpolate.rs @@ -39,7 +39,7 @@ impl ItemOp for InterpolateStringItemOp { } Type::Item(item) => { let mut result; - if item.len() == 0 { + if item.is_empty() { result = self.format.clone(); } else { let mut iter = item.iter(); diff --git a/interpreter/src/lang/vocabulary/item_ops/subtract.rs b/interpreter/src/lang/vocabulary/item_ops/subtract.rs index ca0b3cc..d57b24a 100644 --- a/interpreter/src/lang/vocabulary/item_ops/subtract.rs +++ b/interpreter/src/lang/vocabulary/item_ops/subtract.rs @@ -36,7 +36,7 @@ impl ItemOp for SubtractItemOp { let rhs = self.rhs.execute(context)?; if let Type::Primitive(rhs) = &rhs { Ok(Type::Primitive( - lhs.try_subtract(rhs).map_err(|e| RuntimeMsg(e))?, + lhs.try_subtract(rhs).map_err(RuntimeMsg)?, )) } else { Err(RuntimeMsg(format!( diff --git a/interpreter/src/lang/vocabulary/item_ops/variable_declare.rs b/interpreter/src/lang/vocabulary/item_ops/variable_declare.rs index 0664368..ba30a3c 100644 --- a/interpreter/src/lang/vocabulary/item_ops/variable_declare.rs +++ b/interpreter/src/lang/vocabulary/item_ops/variable_declare.rs @@ -40,12 +40,10 @@ impl ItemOp for VariableDeclareItemOp { if !context.variables.exists(&self.variable_name) { context.variables.declare(&self.variable_name, mps_type)?; } - } else { - if !context.variables.exists(&self.variable_name) { - context - .variables - .declare(&self.variable_name, Type::empty())?; - } + } else if !context.variables.exists(&self.variable_name) { + context + .variables + .declare(&self.variable_name, Type::empty())?; } Ok(Type::empty()) } @@ -74,13 +72,12 @@ impl ItemOpFactory for VariableDeclareItemOpFactory { Token::Name("variable_name".into()), tokens, )?; - let inner_op: Option>; - if !tokens.is_empty() { + let inner_op: Option> = if !tokens.is_empty() { assert_token_raw(Token::Equals, tokens)?; - inner_op = Some(factory.try_build_item_statement(tokens, dict)?); + Some(factory.try_build_item_statement(tokens, dict)?) } else { - inner_op = None; - } + None + }; Ok(VariableDeclareItemOp { variable_name: var_name, inner: inner_op, diff --git a/interpreter/src/lang/vocabulary/mod.rs b/interpreter/src/lang/vocabulary/mod.rs index b89b224..fb1c6d2 100644 --- a/interpreter/src/lang/vocabulary/mod.rs +++ b/interpreter/src/lang/vocabulary/mod.rs @@ -1,3 +1,4 @@ +#![allow(clippy::while_let_on_iterator)] mod empties; pub(crate) mod empty; mod files; diff --git a/interpreter/src/lang/vocabulary/mpd_query.rs b/interpreter/src/lang/vocabulary/mpd_query.rs index 165879c..699b93e 100644 --- a/interpreter/src/lang/vocabulary/mpd_query.rs +++ b/interpreter/src/lang/vocabulary/mpd_query.rs @@ -117,7 +117,7 @@ impl Iterator for MpdQueryStatement { }); } let results = self.results.as_mut().unwrap(); - results.pop_front().map(|x| Ok(x)) + results.pop_front().map(Ok) } fn size_hint(&self) -> (usize, Option) { diff --git a/interpreter/src/lang/vocabulary/repeat.rs b/interpreter/src/lang/vocabulary/repeat.rs index def0350..d87aeb2 100644 --- a/interpreter/src/lang/vocabulary/repeat.rs +++ b/interpreter/src/lang/vocabulary/repeat.rs @@ -69,7 +69,7 @@ impl Iterator for RepeatStatement { } if real_op.is_resetable() { while self.loop_forever || !self.inner_done { - for item in real_op.by_ref() { + if let Some(item) = real_op.next() { return Some(item); } if !self.loop_forever { @@ -79,16 +79,14 @@ impl Iterator for RepeatStatement { self.context = Some(real_op.escape()); } else { self.repetitions -= 1; - match real_op.reset() { - Err(e) => return Some(Err(e)), - Ok(_) => {} + if let Err(e) = real_op.reset() { + return Some(Err(e)); } } } else { // always reset in infinite loop mode - match real_op.reset() { - Err(e) => return Some(Err(e)), - Ok(_) => {} + if let Err(e) = real_op.reset() { + return Some(Err(e)); } } } diff --git a/interpreter/src/lang/vocabulary/sorters/bliss_next_sorter.rs b/interpreter/src/lang/vocabulary/sorters/bliss_next_sorter.rs index a17e9c1..0ef4652 100644 --- a/interpreter/src/lang/vocabulary/sorters/bliss_next_sorter.rs +++ b/interpreter/src/lang/vocabulary/sorters/bliss_next_sorter.rs @@ -68,18 +68,16 @@ impl Sorter for BlissNextSorter { let mut ctx = iterator.escape(); for i in 1..self.item_buf.len() { let item = &self.item_buf[i]; - match ctx.analysis.prepare_distance(first, item) { - Err(e) => { - iterator.enter(ctx); - return Err(e); - } - Ok(_) => {} + if let Err(e) = ctx.analysis.prepare_distance(first, item) { + iterator.enter(ctx); + return Err(e); } } iterator.enter(ctx); items_out.push_back(Ok(first.to_owned())); } } else { + #[allow(clippy::collapsible_else_if)] if self.item_buf.len() > 2 { let last = self.item_buf.pop_front().unwrap(); let mut best_index = 0; @@ -107,12 +105,9 @@ impl Sorter for BlissNextSorter { let next = &self.item_buf[0]; for i in 1..self.item_buf.len() { let item = &self.item_buf[i]; - match ctx.analysis.prepare_distance(next, item) { - Err(e) => { - iterator.enter(ctx); - return Err(e); - } - Ok(_) => {} + if let Err(e) = ctx.analysis.prepare_distance(next, item) { + iterator.enter(ctx); + return Err(e); } } iterator.enter(ctx); diff --git a/interpreter/src/lang/vocabulary/sorters/bliss_sorter.rs b/interpreter/src/lang/vocabulary/sorters/bliss_sorter.rs index 59b5316..7eb8cf9 100644 --- a/interpreter/src/lang/vocabulary/sorters/bliss_sorter.rs +++ b/interpreter/src/lang/vocabulary/sorters/bliss_sorter.rs @@ -64,12 +64,7 @@ impl Sorter for BlissSorter { // when buf_len_old == item_buf.len(), iterator was already complete // no need to sort in that case, since buffer was sorted in last call to sort or buffer never had any items to sort if self.first_song.is_none() { - for item in item_buf.iter() { - if let Ok(item) = item { - self.first_song = Some(item.clone()); - break; - } - } + self.first_song = item_buf.iter().flatten().next().map(|x| x.to_owned()); } if let Some(first) = &self.first_song { let mut ctx = iterator.escape(); @@ -78,12 +73,9 @@ impl Sorter for BlissSorter { if item == first { continue; } - match ctx.analysis.prepare_distance(first, item) { - Err(e) => { - iterator.enter(ctx); - return Err(e); - } - Ok(_) => {} + if let Err(e) = ctx.analysis.prepare_distance(first, item) { + iterator.enter(ctx); + return Err(e); } } } @@ -115,8 +107,8 @@ impl Sorter for BlissSorter { item_buf.make_contiguous().sort_by(|a, b| { if let Ok(a) = a { if let Ok(b) = b { - let float_a = cache.get(&a).unwrap(); - let float_b = cache.get(&b).unwrap(); + let float_a = cache.get(a).unwrap(); + let float_b = cache.get(b).unwrap(); return float_a.partial_cmp(float_b).unwrap_or(DEFAULT_ORDER); } } diff --git a/interpreter/src/lang/vocabulary/sorters/shuffle.rs b/interpreter/src/lang/vocabulary/sorters/shuffle.rs index cf996be..074c0e6 100644 --- a/interpreter/src/lang/vocabulary/sorters/shuffle.rs +++ b/interpreter/src/lang/vocabulary/sorters/shuffle.rs @@ -53,10 +53,10 @@ impl Sorter for ShuffleSorter { } } // end case: everything is completely empty -- end loop without a new result - if item_buf.len() == 0 { + if item_buf.is_empty() { return Ok(()); } - random = random % item_buf.len(); + random %= item_buf.len(); } } } @@ -71,10 +71,10 @@ pub struct ShuffleSorterFactory; impl SorterFactory for ShuffleSorterFactory { fn is_sorter(&self, tokens: &VecDeque<&Token>) -> bool { - (!tokens.is_empty() && check_name("shuffle", &tokens[0])) + (!tokens.is_empty() && check_name("shuffle", tokens[0])) || (tokens.len() > 1 - && check_name("random", &tokens[0]) - && check_name("shuffle", &tokens[1])) + && check_name("random", tokens[0]) + && check_name("shuffle", tokens[1])) } fn build_sorter( diff --git a/interpreter/src/lang/vocabulary/union.rs b/interpreter/src/lang/vocabulary/union.rs index 1cd240d..8740511 100644 --- a/interpreter/src/lang/vocabulary/union.rs +++ b/interpreter/src/lang/vocabulary/union.rs @@ -65,7 +65,7 @@ impl Iterator for UnionStatement { Err(e) => return Some(Err(e)), }; real_op.enter(self.context.take().unwrap()); - while let Some(item) = real_op.next() { + if let Some(item) = real_op.next() { self.context = Some(real_op.escape()); return Some(item); } diff --git a/interpreter/src/lang/vocabulary/variable_assign.rs b/interpreter/src/lang/vocabulary/variable_assign.rs index 06e66af..e9021ec 100644 --- a/interpreter/src/lang/vocabulary/variable_assign.rs +++ b/interpreter/src/lang/vocabulary/variable_assign.rs @@ -74,22 +74,21 @@ impl Iterator for AssignStatement { Ok(real) => real, Err(e) => return Some(Err(e)), }; - let result; - if self.is_declaration { - result = self + let result = if self.is_declaration { + self .context .as_mut() .unwrap() .variables - .declare(&self.variable_name, Type::Op(real)); + .declare(&self.variable_name, Type::Op(real)) } else { - result = self + self .context .as_mut() .unwrap() .variables - .assign(&self.variable_name, Type::Op(real)); - } + .assign(&self.variable_name, Type::Op(real)) + }; match result { Ok(_) => None, Err(e) => Some(Err(e.with(RuntimeOp(PseudoOp::from_printable(self))))), @@ -107,22 +106,21 @@ impl Iterator for AssignStatement { }))*/ } else { let assign_type = self.assign_type.clone().unwrap(); - let result; - if self.is_declaration { - result = self + let result = if self.is_declaration { + self .context .as_mut() .unwrap() .variables - .declare(&self.variable_name, Type::Primitive(assign_type)); + .declare(&self.variable_name, Type::Primitive(assign_type)) } else { - result = self + self .context .as_mut() .unwrap() .variables - .assign(&self.variable_name, Type::Primitive(assign_type)); - } + .assign(&self.variable_name, Type::Primitive(assign_type)) + }; match result { Ok(_) => None, Err(e) => Some(Err(e.with(RuntimeOp(PseudoOp::from_printable(self))))), diff --git a/interpreter/src/lib.rs b/interpreter/src/lib.rs index b8f22ff..460f617 100644 --- a/interpreter/src/lib.rs +++ b/interpreter/src/lib.rs @@ -246,6 +246,8 @@ //! Load an item from file, populating the item with the song's tags. //! +#![allow(clippy::redundant_field_names)] + mod context; mod debug; mod errors; diff --git a/interpreter/src/music/library.rs b/interpreter/src/music/library.rs index 91d3f22..2a23e5a 100644 --- a/interpreter/src/music/library.rs +++ b/interpreter/src/music/library.rs @@ -36,6 +36,10 @@ impl Library { self.songs.len() } + pub fn is_empty(&self) -> bool { + self.songs.is_empty() + } + pub fn clear_modified(&mut self) { self.dirty = false; } @@ -54,7 +58,7 @@ impl Library { self.files.contains(&path.as_ref().to_path_buf()) } - pub fn all_songs<'a>(&'a self) -> Vec<&'a DbMusicItem> { + pub fn all_songs(&self) -> Vec<&'_ DbMusicItem> { self.songs.values().collect() } @@ -67,7 +71,7 @@ impl Library { self.songs.insert(song.song_id, song); } - pub fn all_metadata<'a>(&'a self) -> Vec<&'a DbMetaItem> { + pub fn all_metadata(& self) -> Vec<&'_ DbMetaItem> { self.metadata.values().collect() } @@ -77,7 +81,7 @@ impl Library { self.metadata.insert(meta.meta_id, meta); } - pub fn all_artists<'a>(&'a self) -> Vec<&'a DbArtistItem> { + pub fn all_artists(&self) -> Vec<&'_ DbArtistItem> { self.artists.values().collect() } @@ -88,7 +92,7 @@ impl Library { .insert(Self::sanitise_key(&artist.name), artist); } - pub fn all_albums<'a>(&'a self) -> Vec<&'a DbAlbumItem> { + pub fn all_albums(&self) -> Vec<&'_ DbAlbumItem> { self.albums.values().collect() } @@ -98,7 +102,7 @@ impl Library { self.albums.insert(Self::sanitise_key(&album.title), album); } - pub fn all_genres<'a>(&'a self) -> Vec<&'a DbGenreItem> { + pub fn all_genres(&self) -> Vec<&'_ DbGenreItem> { self.genres.values().collect() } @@ -236,7 +240,7 @@ impl Library { } #[inline] - fn find_or_gen_id<'a, D: DatabaseObj>(map: &'a HashMap, key: &str) -> u64 { + fn find_or_gen_id(map: &HashMap, key: &str) -> u64 { if let Some(obj) = Self::find_by_key(map, key) { obj.id() } else { diff --git a/interpreter/src/music/tag.rs b/interpreter/src/music/tag.rs index f471471..fc3440d 100644 --- a/interpreter/src/music/tag.rs +++ b/interpreter/src/music/tag.rs @@ -49,7 +49,7 @@ impl Tags { .file_name() .and_then(|file| file.to_str()) .map(|file| file.replacen(&format!(".{}", extension), "", 1)) - .unwrap_or("Unknown Title".into()) + .unwrap_or_else(|| "Unknown Title".into()) } #[inline] @@ -149,7 +149,7 @@ impl Tags { pub fn artist(&self, id: u64, genre_id: u64) -> DbArtistItem { DbArtistItem { artist_id: id, - name: self.artist_name().unwrap_or("Unknown Artist".into()), + name: self.artist_name().unwrap_or_else(|| "Unknown Artist".into()), genre: genre_id, } } @@ -171,7 +171,7 @@ impl Tags { pub fn album(&self, id: u64, meta_id: u64, artist_id: u64, genre_id: u64) -> DbAlbumItem { DbAlbumItem { album_id: id, - title: self.album_title().unwrap_or("Unknown Album".into()), + title: self.album_title().unwrap_or_else(|| "Unknown Album".into()), metadata: meta_id, artist: artist_id, genre: genre_id, @@ -212,7 +212,7 @@ impl Tags { pub fn genre(&self, id: u64) -> DbGenreItem { DbGenreItem { genre_id: id, - title: self.genre_title().unwrap_or("Unknown Genre".into()), + title: self.genre_title().unwrap_or_else(|| "Unknown Genre".into()), } } } diff --git a/interpreter/src/processing/filesystem.rs b/interpreter/src/processing/filesystem.rs index db67222..a9642d6 100644 --- a/interpreter/src/processing/filesystem.rs +++ b/interpreter/src/processing/filesystem.rs @@ -41,10 +41,11 @@ impl Iterator for SortedReadDir { } } self.dir_iter_complete = true; - self.cache.sort_by( + self.cache.sort_by_key(|b| std::cmp::Reverse(b.path().to_string_lossy().to_lowercase())); + /*self.cache.sort_by( |a, b| b.path().to_string_lossy().to_lowercase().cmp( &a.path().to_string_lossy().to_lowercase()) - ); + );*/ } if self.cache.is_empty() { None @@ -73,7 +74,7 @@ impl Display for FileIter { self.pattern .as_ref() .map(|re| re.to_string()) - .unwrap_or("[none]".to_string()), + .unwrap_or_else(|| "[none]".to_string()), self.recursive ) } @@ -224,13 +225,11 @@ impl FileIter { ) { // populates fields from named capture groups if let Some(captures) = captures { - for name_maybe in capture_names { - if let Some(name) = name_maybe { - if item.field(name).is_some() { + for name in capture_names.flatten() { + if item.field(name).is_some() { // do nothing - } else if let Some(value) = captures.name(name).map(|m| m.as_str().to_string()) { - item.set_field(name, TypePrimitive::parse(value)); - } + } else if let Some(value) = captures.name(name).map(|m| m.as_str().to_string()) { + item.set_field(name, TypePrimitive::parse(value)); } } } diff --git a/interpreter/src/processing/mpd.rs b/interpreter/src/processing/mpd.rs index 774eb54..0fccc5f 100644 --- a/interpreter/src/processing/mpd.rs +++ b/interpreter/src/processing/mpd.rs @@ -41,7 +41,7 @@ impl MpdQuerier for MpdExecutor { query_mut = query_mut.and(str_to_term(term), value); } let songs = self.connection.as_mut().unwrap().search(query_mut, None).map_err(|e| RuntimeMsg(format!("MPD search error: {}", e)))?; - Ok(songs.into_iter().map(|x| song_to_item(x)).collect()) + Ok(songs.into_iter().map(song_to_item).collect()) } fn one_shot_search(&self, addr: SocketAddr, params: Vec<(&str, String)>) -> Result, RuntimeMsg> { @@ -53,7 +53,7 @@ impl MpdQuerier for MpdExecutor { query_mut = query_mut.and(str_to_term(term), value); } let songs = connection.search(query_mut, None).map_err(|e| RuntimeMsg(format!("MPD search error: {}", e)))?; - Ok(songs.into_iter().map(|x| song_to_item(x)).collect()) + Ok(songs.into_iter().map(song_to_item).collect()) } } @@ -95,7 +95,7 @@ fn song_to_item(song: Song) -> Item { } #[inline] -fn str_to_term<'a>(s: &'a str) -> Term<'a> { +fn str_to_term(s: &str) -> Term<'_> { match s { "any" => Term::Any, "file" => Term::File, diff --git a/interpreter/src/processing/music_analysis.rs b/interpreter/src/processing/music_analysis.rs index d9f79b9..7e80764 100644 --- a/interpreter/src/processing/music_analysis.rs +++ b/interpreter/src/processing/music_analysis.rs @@ -208,7 +208,7 @@ enum ResponseType { }, Song { path: String, - song: Result, + song: Result, BlissError>, }, UnsupportedSong { path: String, @@ -257,13 +257,13 @@ impl CacheThread { } } - fn insert_song(&mut self, path: String, song_result: Result) { + fn insert_song(&mut self, path: String, song_result: Result, BlissError>) { self.song_in_progress.remove(&path); if self.song_cache.len() > MAX_SONG_CACHE_SIZE { // avoid using too much memory -- songs are big memory objects self.song_cache.clear(); } - self.song_cache.insert(path, song_result); + self.song_cache.insert(path, song_result.map(|x| x.as_ref().to_owned())); } fn insert_distance( @@ -305,7 +305,7 @@ impl CacheThread { if result.is_none() && auto_add { self.song_in_progress.insert(path.to_owned()); } - return result; + return result.map(|x| x.as_ref().to_owned()); } else { self.insert_song(path2, song); } @@ -322,7 +322,7 @@ impl CacheThread { let result = self .song_cache .get(path) - .and_then(|r| r.clone().ok().to_owned()); + .and_then(|r| r.clone().ok()); if result.is_none() && auto_add { self.song_in_progress.insert(path.to_owned()); } @@ -331,7 +331,7 @@ impl CacheThread { if auto_add { self.song_in_progress.insert(path.to_owned()); } - return None; + None } fn handle_distance_req( @@ -346,11 +346,11 @@ impl CacheThread { if let Some(result) = self.distance_cache.get(&key) { if ack { let result = result.to_owned(); - if let Err(_) = self.responses.send(ResponseType::Distance { + if self.responses.send(ResponseType::Distance { path1: path1, path2: path2, distance: result, - }) { + }).is_err() { return true; } } @@ -360,14 +360,12 @@ impl CacheThread { // also prevents deadlock in self.get_song_option() // due to waiting on song that isn't being processed yet // (first call adds it to song_in_progress set, second call just waits) - if ack { - if let Err(_) = self.responses.send(ResponseType::Distance { + if ack && self.responses.send(ResponseType::Distance { path1: path1, path2: path2, distance: Ok(0.0), - }) { - return true; - } + }).is_err() { + return true; } } else if !self.distance_in_progress.contains(&key) { // distance worker uses 3 threads (it's own thread + 1 extra per song) for 2 songs @@ -433,11 +431,11 @@ impl CacheThread { distance.clone(), ); if path1_2 == key.0 && path2_2 == key.1 { - if let Err(_) = self.responses.send(ResponseType::Distance { + if self.responses.send(ResponseType::Distance { path1: path1_2, path2: path2_2, distance: distance, - }) { + }).is_err() { return true; } break 'inner1; @@ -448,10 +446,10 @@ impl CacheThread { }, ResponseType::UnsupportedSong { path: unsupported_path, msg } => { self.song_in_progress.remove(&unsupported_path); - if let Err(_) = self.responses.send(ResponseType::UnsupportedSong { + if self.responses.send(ResponseType::UnsupportedSong { path: unsupported_path.clone(), msg: msg - }) { + }).is_err() { return true; } if unsupported_path == key.0 || unsupported_path == key.1 { @@ -478,10 +476,10 @@ impl CacheThread { } else if !path.contains("://") { path } else { - if let Err(_) = self.responses.send(ResponseType::UnsupportedSong { + if self.responses.send(ResponseType::UnsupportedSong { msg: format!("Song path is not a supported URI, it's `{}`", path), path: path, - }) { + }).is_err() { return true; } return false; @@ -489,10 +487,10 @@ impl CacheThread { if let Some(song) = self.song_cache.get(&path) { if ack { let song = song.to_owned(); - if let Err(_) = self.responses.send(ResponseType::Song { + if self.responses.send(ResponseType::Song { path: path, - song: song, - }) { + song: song.map(Box::new), + }).is_err() { return true; } } @@ -539,7 +537,7 @@ impl CacheThread { results .send(ResponseType::Song { path: path_clone, - song: song_result, + song: song_result.map(Box::new), }) .unwrap_or(()); }); @@ -557,10 +555,10 @@ impl CacheThread { ResponseType::Song { path: path2, song } => { self.insert_song(path2.clone(), song.clone()); if path2 == path { - if let Err(_) = self.responses.send(ResponseType::Song { + if self.responses.send(ResponseType::Song { path: path, song: song, - }) { + }).is_err() { return true; } break 'inner3; @@ -569,10 +567,10 @@ impl CacheThread { ResponseType::UnsupportedSong { path: unsupported_path, msg } => { self.song_in_progress.remove(&unsupported_path); if unsupported_path == path { - if let Err(_) = self.responses.send(ResponseType::UnsupportedSong { + if self.responses.send(ResponseType::UnsupportedSong { path: unsupported_path, msg: msg - }) { + }).is_err() { return true; } break 'inner3; @@ -624,7 +622,7 @@ fn worker_distance( results .send(ResponseType::Song { path: path1.to_string(), - song: new_song1.clone(), + song: new_song1.clone().map(Box::new), }) .unwrap_or(()); new_song1? @@ -637,7 +635,7 @@ fn worker_distance( results .send(ResponseType::Song { path: path2.to_string(), - song: new_song2.clone(), + song: new_song2.clone().map(Box::new), }) .unwrap_or(()); if new_song2.is_err() { diff --git a/interpreter/src/processing/sql.rs b/interpreter/src/processing/sql.rs index f167ab5..7a53528 100644 --- a/interpreter/src/processing/sql.rs +++ b/interpreter/src/processing/sql.rs @@ -1,4 +1,5 @@ use core::fmt::Debug; +use std::fmt::Write; use std::collections::{HashMap, HashSet}; use crate::lang::db::*; @@ -159,9 +160,11 @@ impl DatabaseQuerier for SQLiteExecutor { for key in keys.drain() { if first { first = false; - concat_keys += key; + write!(concat_keys, "{}", key).unwrap(); + //concat_keys += key; } else { - concat_keys += &format!("{}, ", key); + write!(concat_keys, "{}, ", key).unwrap(); + //concat_keys += &format!("{}, ", key); } } return Err(RuntimeMsg(format!( diff --git a/interpreter/src/tokens/mod.rs b/interpreter/src/tokens/mod.rs index e6d008c..6629581 100644 --- a/interpreter/src/tokens/mod.rs +++ b/interpreter/src/tokens/mod.rs @@ -1,3 +1,4 @@ +#![allow(clippy::match_like_matches_macro)] mod error; mod token_enum; mod tokenizer; diff --git a/interpreter/src/tokens/tokenizer.rs b/interpreter/src/tokens/tokenizer.rs index dbbf5d6..c00a16c 100644 --- a/interpreter/src/tokens/tokenizer.rs +++ b/interpreter/src/tokens/tokenizer.rs @@ -268,7 +268,7 @@ impl ReaderStateMachine { Self::Escaped { inside } => match inside { '`' => Self::InsideTickLiteral { out: input }, '"' => Self::InsideQuoteLiteral { out: input }, - '_' | _ => Self::Regular { out: input }, + _ => Self::Regular { out: input }, }, Self::StartTickLiteral {} | Self::InsideTickLiteral { .. } => match input_char { '\\' => Self::Escaped { inside: '`' }, diff --git a/player/src/errors.rs b/player/src/errors.rs index 08a29ab..6640a84 100644 --- a/player/src/errors.rs +++ b/player/src/errors.rs @@ -1,5 +1,5 @@ use std::fmt::{Debug, Display, Error, Formatter}; -use std::convert::Into; +use std::convert::From; #[derive(Debug, Clone)] pub enum PlayerError { @@ -58,9 +58,9 @@ impl Display for PlaybackError { } } -impl Into for PlaybackError { - fn into(self) -> PlayerError { - PlayerError::Playback(self) +impl From for PlayerError { + fn from(other: PlaybackError) -> Self { + PlayerError::Playback(other) } } @@ -86,8 +86,8 @@ impl Display for UriError { } } -impl Into for UriError { - fn into(self) -> PlayerError { - PlayerError::Uri(self) +impl From for PlayerError { + fn from(other: UriError) -> Self { + PlayerError::Uri(other) } } diff --git a/player/src/lib.rs b/player/src/lib.rs index e1da6bb..6cbf25f 100644 --- a/player/src/lib.rs +++ b/player/src/lib.rs @@ -3,6 +3,9 @@ //! Music playback and m3u8 playlist generation are implemented in this part of the project. //! +#![allow(clippy::match_like_matches_macro)] +#![allow(clippy::redundant_field_names)] + mod controller; mod errors; pub(crate) mod os_controls; diff --git a/player/src/player_wrapper.rs b/player/src/player_wrapper.rs index 3abb42b..7aa601b 100644 --- a/player/src/player_wrapper.rs +++ b/player/src/player_wrapper.rs @@ -165,7 +165,7 @@ impl>> PlayerServer, sleep_ms: u64) { let dur = std::time::Duration::from_millis(sleep_ms); loop { - if let Err(_) = ctrl_tx.send(ControlAction::NoOp { ack: false }) { + if ctrl_tx.send(ControlAction::NoOp { ack: false }).is_err() { break; } thread::sleep(dur); diff --git a/player/src/uri.rs b/player/src/uri.rs index 612de22..5b2f43f 100644 --- a/player/src/uri.rs +++ b/player/src/uri.rs @@ -15,9 +15,9 @@ impl<'a> Uri<&'a str> { match self.0.find("//") { Some(end) => { // proper URI - if let Some(query_start) = self.0.find("?") { + if let Some(query_start) = self.0.find('?') { self.0.get(end+2..query_start).unwrap() - } else if let Some(frag_start) = self.0.find("#") { + } else if let Some(frag_start) = self.0.find('#') { self.0.get(end+2..frag_start).unwrap() } else { self.0.get(end+2..).unwrap() diff --git a/src/main.rs b/src/main.rs index 04d8e3e..86f387a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -80,7 +80,7 @@ fn main() { } // build playback controller let script_file2 = script_file.clone(); - let volume = args.volume.clone(); + let volume = args.volume; let mpd = match args.mpd.clone().map(|a| muss_player::mpd_connection(a.parse().unwrap())).transpose() { Ok(mpd) => mpd, Err(e) => panic!("Abort: Cannot connect to MPD: {}", e), diff --git a/src/repl.rs b/src/repl.rs index 3399264..9d6c87c 100644 --- a/src/repl.rs +++ b/src/repl.rs @@ -1,4 +1,5 @@ //! Read, Execute, Print Loop functionality +#![allow(clippy::single_match)] use std::sync::{RwLock}; use std::sync::mpsc::{self, Receiver}; use std::io::{self, Write}; @@ -79,7 +80,7 @@ impl ReplState { } } -fn interpreter_event_callback<'a, T: muss_interpreter::tokens::TokenReader>(_interpreter: &mut Interpreter<'a, T>, event: InterpreterEvent) -> Result<(), InterpreterError> { +fn interpreter_event_callback(_interpreter: &mut Interpreter<'_, T>, event: InterpreterEvent) -> Result<(), InterpreterError> { match event { InterpreterEvent::StatementComplete => { if let Ok(mut d_state) = DEBUG_STATE.write() { @@ -165,7 +166,7 @@ pub fn repl(args: CliArgs) { let term = Term::stdout(); term.set_title("muss"); let (writer, reader) = channel_io(); - let volume = args.volume.clone(); + let volume = args.volume; let mpd = match args.mpd.clone().map(|a| muss_player::mpd_connection(a.parse().unwrap())).transpose() { Ok(mpd) => mpd, Err(e) => { @@ -187,7 +188,7 @@ pub fn repl(args: CliArgs) { match flag { DebugFlag::Normal => item, DebugFlag::Skip => { - while let Some(_) = interpretor.next() { + for _ in interpretor.by_ref() { // NOTE: recursion occurs here } None @@ -195,7 +196,7 @@ pub fn repl(args: CliArgs) { DebugFlag::List => { if let Some(x) = item { list_tx.send(x.map_err(|e| e.to_string())).unwrap_or(()); - while let Some(x) = interpretor.next() { + for x in interpretor.by_ref() { // NOTE: recursion occurs here // in most cases this will never be a case of Some(...) because // recursive calls to this function intercept it first and return None @@ -241,10 +242,10 @@ pub fn repl(args: CliArgs) { match player.save_m3u8(&mut playlist_writer) { Ok(_) => {} Err(e) => { - error_prompt(e, &args); + error_prompt(e, args); // consume any further errors (this shouldn't actually write anything) while let Err(e) = player.save_m3u8(&mut playlist_writer) { - error_prompt(e, &args); + error_prompt(e, args); } } } @@ -266,7 +267,7 @@ pub fn repl(args: CliArgs) { if args.wait { match ctrl.wait_for_empty() { Ok(_) => {} - Err(e) => error_prompt(e, &args), + Err(e) => error_prompt(e, args), } } else { // consume all incoming errors @@ -274,7 +275,7 @@ pub fn repl(args: CliArgs) { while had_err { let mut new_had_err = false; for e in ctrl.check_ack() { - error_prompt(e, &args); + error_prompt(e, args); new_had_err = true; } had_err = new_had_err; @@ -354,7 +355,7 @@ fn read_loop(args: &CliArgs, state: &mut Rep if !statement_result.starts_with('?') { state .writer - .write(state.statement_buf.iter().collect::().as_bytes()) + .write_all(state.statement_buf.iter().collect::().as_bytes()) .expect(INTERPRETER_WRITE_ERROR); execute(state, args); state.statement_buf.clear(); @@ -427,57 +428,55 @@ fn read_loop(args: &CliArgs, state: &mut Rep } } } - } else { - if state.current_line.len() != state.cursor_rightward_position { - // if not at start of line - let removed_char = state - .current_line - .remove(state.current_line.len() - state.cursor_rightward_position - 1); - state.statement_buf.remove( - state.statement_buf.len() - state.cursor_rightward_position - 1, - ); - // re-sync unclosed syntax tracking - match removed_char { - '"' | '`' => { - if let Some(c2) = state.in_literal { - if removed_char == c2 { - state.in_literal = None; - } - } else { - state.in_literal = Some(removed_char); + } else if state.current_line.len() != state.cursor_rightward_position { + // if not at start of line + let removed_char = state + .current_line + .remove(state.current_line.len() - state.cursor_rightward_position - 1); + state.statement_buf.remove( + state.statement_buf.len() - state.cursor_rightward_position - 1, + ); + // re-sync unclosed syntax tracking + match removed_char { + '"' | '`' => { + if let Some(c2) = state.in_literal { + if removed_char == c2 { + state.in_literal = None; } + } else { + state.in_literal = Some(removed_char); } - '(' => { - if state.bracket_depth != 0 { - state.bracket_depth -= 1 - } - } - ')' => state.bracket_depth += 1, - '{' => { - if state.curly_depth != 0 { - state.curly_depth -= 1 - } - } - '}' => state.curly_depth += 1, - _ => {} } - // re-print end of line to remove character in middle - state - .terminal - .move_cursor_left(1) - .expect(TERMINAL_WRITE_ERROR); - for i in state.current_line.len() - state.cursor_rightward_position - ..state.current_line.len() - { - write!(state.terminal, "{}", state.current_line[i]) - .expect(TERMINAL_WRITE_ERROR); + '(' => { + if state.bracket_depth != 0 { + state.bracket_depth -= 1 + } } - write!(state.terminal, " ").expect(TERMINAL_WRITE_ERROR); - state - .terminal - .move_cursor_left(state.cursor_rightward_position + 1) + ')' => state.bracket_depth += 1, + '{' => { + if state.curly_depth != 0 { + state.curly_depth -= 1 + } + } + '}' => state.curly_depth += 1, + _ => {} + } + // re-print end of line to remove character in middle + state + .terminal + .move_cursor_left(1) + .expect(TERMINAL_WRITE_ERROR); + for i in state.current_line.len() - state.cursor_rightward_position + ..state.current_line.len() + { + write!(state.terminal, "{}", state.current_line[i]) .expect(TERMINAL_WRITE_ERROR); } + write!(state.terminal, " ").expect(TERMINAL_WRITE_ERROR); + state + .terminal + .move_cursor_left(state.cursor_rightward_position + 1) + .expect(TERMINAL_WRITE_ERROR); } } Key::Del => { @@ -547,7 +546,7 @@ fn read_loop(args: &CliArgs, state: &mut Rep let complete_statement = state.statement_buf.iter().collect::(); state .writer - .write(complete_statement.as_bytes()) + .write_all(complete_statement.as_bytes()) .expect("Failed to write to MPS interpreter"); execute(state, args); state.statement_buf.clear(); @@ -575,23 +574,27 @@ fn read_loop(args: &CliArgs, state: &mut Rep } } Key::ArrowDown => { - if state.selected_history > 1 { - state.selected_history -= 1; - display_history_line(state, args); - } else if state.selected_history == 1 { - state.selected_history = 0; - state.line_number -= 1; - state - .terminal - .clear_line() - .expect(TERMINAL_WRITE_ERROR); - prompt(state, args); - // clear stale input buffer - state.statement_buf.clear(); - state.current_line.clear(); - state.in_literal = None; - state.bracket_depth = 0; - state.curly_depth = 0; + match state.selected_history { + 1 => { + state.selected_history = 0; + state.line_number -= 1; + state + .terminal + .clear_line() + .expect(TERMINAL_WRITE_ERROR); + prompt(state, args); + // clear stale input buffer + state.statement_buf.clear(); + state.current_line.clear(); + state.in_literal = None; + state.bracket_depth = 0; + state.curly_depth = 0; + }, + 0 => {}, + _ => { + state.selected_history -= 1; + display_history_line(state, args); + }, } } Key::ArrowLeft => { @@ -642,7 +645,7 @@ fn display_history_line(state: &mut ReplState, args: &CliArgs) { let new_statement = state.history[state.history.len() - state.selected_history].trim(); state .terminal - .write(new_statement.as_bytes()) + .write_all(new_statement.as_bytes()) .expect(TERMINAL_WRITE_ERROR); // clear stale input buffer state.statement_buf.clear();