Fix clippy warnings & errors

This commit is contained in:
NGnius (Graham) 2022-07-30 00:05:03 -04:00
parent 2bec331700
commit 2b6c47f166
52 changed files with 305 additions and 304 deletions

View file

@ -1,4 +1,4 @@
use mps_interpreter::MpsFaye; use muss_interpreter::Interpreter;
//use mps_interpreter::MpsRunner; //use mps_interpreter::MpsRunner;
use std::fs::File; use std::fs::File;
use std::io::{BufReader, Read, Seek}; use std::io::{BufReader, Read, Seek};
@ -35,12 +35,12 @@ fn faye_benchmark(c: &mut Criterion) {
let mut buf = Vec::with_capacity(1024 * 1024); let mut buf = Vec::with_capacity(1024 * 1024);
reader.read_to_end(&mut buf).unwrap(); reader.read_to_end(&mut buf).unwrap();
drop(buf); drop(buf);
c.bench_function("mps-faye lots_of_empty.mps", |b| { c.bench_function("muss-faye lots_of_empty.mps", |b| {
b.iter(|| { b.iter(|| {
//let f = File::open("benches/lots_of_empty.mps").unwrap(); //let f = File::open("benches/lots_of_empty.mps").unwrap();
//let mut reader = BufReader::new(f); //let mut reader = BufReader::new(f);
reader.rewind().unwrap(); reader.rewind().unwrap();
let mps = MpsFaye::with_stream(&mut reader); let mps = Interpreter::with_stream(&mut reader);
for item in mps { for item in mps {
match item { match item {
Err(e) => panic!("{}", e), Err(e) => panic!("{}", e),

View file

@ -83,7 +83,7 @@ dependencies = [
[[package]] [[package]]
name = "bliss-audio-symphonia" name = "bliss-audio-symphonia"
version = "0.4.6" version = "0.5.0"
dependencies = [ dependencies = [
"bliss-audio-aubio-rs", "bliss-audio-aubio-rs",
"crossbeam", "crossbeam",
@ -96,6 +96,7 @@ dependencies = [
"noisy_float", "noisy_float",
"num_cpus", "num_cpus",
"rayon", "rayon",
"rcue",
"ripemd160", "ripemd160",
"rustfft", "rustfft",
"strum", "strum",
@ -567,7 +568,7 @@ dependencies = [
[[package]] [[package]]
name = "muss-interpreter" name = "muss-interpreter"
version = "0.8.0" version = "0.9.0"
dependencies = [ dependencies = [
"bliss-audio-symphonia", "bliss-audio-symphonia",
"dirs", "dirs",
@ -871,6 +872,12 @@ dependencies = [
"num_cpus", "num_cpus",
] ]
[[package]]
name = "rcue"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fca1481d62f18158646de2ec552dd63f8bdc5be6448389b192ba95c939df997e"
[[package]] [[package]]
name = "redox_syscall" name = "redox_syscall"
version = "0.2.13" version = "0.2.13"

View file

@ -48,7 +48,6 @@ where
fn next(&mut self) -> Option<Self::Item> { fn next(&mut self) -> Option<Self::Item> {
let next_item = self.interpreter.next(); let next_item = self.interpreter.next();
let transmuted_next = (self.transmuter)(&mut self.interpreter, next_item); (self.transmuter)(&mut self.interpreter, next_item)
transmuted_next
} }
} }

View file

@ -29,8 +29,8 @@ where
} }
#[inline] #[inline]
fn empty_callback<'a, T: TokenReader>( fn empty_callback<T: TokenReader>(
_s: &mut Interpreter<'a, T>, _s: &mut Interpreter<'_, T>,
_d: InterpreterEvent, _d: InterpreterEvent,
) -> Result<(), InterpreterError> { ) -> Result<(), InterpreterError> {
Ok(()) Ok(())

View file

@ -23,26 +23,26 @@ pub(crate) fn standard_vocab(vocabulary: &mut LanguageDictionary) {
// iter blocks // iter blocks
.add( .add(
crate::lang::ItemBlockFactory::new() crate::lang::ItemBlockFactory::new()
.add(crate::lang::vocabulary::item_ops::ConstantItemOpFactory) .push(crate::lang::vocabulary::item_ops::ConstantItemOpFactory)
.add(crate::lang::vocabulary::item_ops::VariableAssignItemOpFactory) .push(crate::lang::vocabulary::item_ops::VariableAssignItemOpFactory)
.add(crate::lang::vocabulary::item_ops::FieldAssignItemOpFactory) .push(crate::lang::vocabulary::item_ops::FieldAssignItemOpFactory)
.add(crate::lang::vocabulary::item_ops::FileItemOpFactory) .push(crate::lang::vocabulary::item_ops::FileItemOpFactory)
.add(crate::lang::vocabulary::item_ops::VariableDeclareItemOpFactory) .push(crate::lang::vocabulary::item_ops::VariableDeclareItemOpFactory)
.add(crate::lang::vocabulary::item_ops::InterpolateStringItemOpFactory) .push(crate::lang::vocabulary::item_ops::InterpolateStringItemOpFactory)
.add(crate::lang::vocabulary::item_ops::BranchItemOpFactory) .push(crate::lang::vocabulary::item_ops::BranchItemOpFactory)
.add(crate::lang::vocabulary::item_ops::IterItemOpFactory) .push(crate::lang::vocabulary::item_ops::IterItemOpFactory)
.add(crate::lang::vocabulary::item_ops::ConstructorItemOpFactory) .push(crate::lang::vocabulary::item_ops::ConstructorItemOpFactory)
.add(crate::lang::vocabulary::item_ops::EmptyItemOpFactory) .push(crate::lang::vocabulary::item_ops::EmptyItemOpFactory)
.add(crate::lang::vocabulary::item_ops::RemoveItemOpFactory) .push(crate::lang::vocabulary::item_ops::RemoveItemOpFactory)
.add(crate::lang::vocabulary::item_ops::VariableRetrieveItemOpFactory) .push(crate::lang::vocabulary::item_ops::VariableRetrieveItemOpFactory)
.add(crate::lang::vocabulary::item_ops::NegateItemOpFactory) .push(crate::lang::vocabulary::item_ops::NegateItemOpFactory)
.add(crate::lang::vocabulary::item_ops::NotItemOpFactory) .push(crate::lang::vocabulary::item_ops::NotItemOpFactory)
.add(crate::lang::vocabulary::item_ops::CompareItemOpFactory) .push(crate::lang::vocabulary::item_ops::CompareItemOpFactory)
.add(crate::lang::vocabulary::item_ops::AddItemOpFactory) .push(crate::lang::vocabulary::item_ops::AddItemOpFactory)
.add(crate::lang::vocabulary::item_ops::SubtractItemOpFactory) .push(crate::lang::vocabulary::item_ops::SubtractItemOpFactory)
.add(crate::lang::vocabulary::item_ops::OrItemOpFactory) .push(crate::lang::vocabulary::item_ops::OrItemOpFactory)
.add(crate::lang::vocabulary::item_ops::AndItemOpFactory) .push(crate::lang::vocabulary::item_ops::AndItemOpFactory)
.add(crate::lang::vocabulary::item_ops::BracketsItemOpFactory), .push(crate::lang::vocabulary::item_ops::BracketsItemOpFactory),
) )
// functions and misc // functions and misc
// functions don't enforce bracket coherence // functions don't enforce bracket coherence

View file

@ -45,6 +45,10 @@ impl Item {
pub fn len(&self) -> usize { pub fn len(&self) -> usize {
self.fields.len() self.fields.len()
} }
pub fn is_empty(&self) -> bool {
self.fields.is_empty()
}
} }
impl Display for Item { impl Display for Item {

View file

@ -53,6 +53,7 @@ impl LanguageDictionary {
} }
} }
#[allow(clippy::derivable_impls)]
impl Default for LanguageDictionary { impl Default for LanguageDictionary {
fn default() -> Self { fn default() -> Self {
Self { Self {

View file

@ -227,7 +227,7 @@ impl<P: FilterPredicate + 'static> Iterator for FilterStatement<P> {
let matches_result = self.predicate.matches(&item, &mut ctx); let matches_result = self.predicate.matches(&item, &mut ctx);
let matches = match matches_result { let matches = match matches_result {
Err(e) => { Err(e) => {
maybe_result = Some(Err(e.with(RuntimeOp(fake.clone())))); maybe_result = Some(Err(e.with(RuntimeOp(fake))));
self.context = Some(ctx); self.context = Some(ctx);
break; break;
} }
@ -245,7 +245,7 @@ impl<P: FilterPredicate + 'static> Iterator for FilterStatement<P> {
Err(e) => { Err(e) => {
//self.context = Some(op.escape()); //self.context = Some(op.escape());
maybe_result = maybe_result =
Some(Err(e.with(RuntimeOp(fake.clone())))); Some(Err(e.with(RuntimeOp(fake))));
self.context = Some(ctx); self.context = Some(ctx);
break; break;
} }
@ -269,7 +269,7 @@ impl<P: FilterPredicate + 'static> Iterator for FilterStatement<P> {
Err(e) => match maybe_result { Err(e) => match maybe_result {
Some(Ok(_)) => { Some(Ok(_)) => {
maybe_result = Some(Err( 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, Some(Err(e2)) => maybe_result = Some(Err(e2)), // already failing, do not replace error,
@ -286,7 +286,7 @@ impl<P: FilterPredicate + 'static> Iterator for FilterStatement<P> {
Err(e) => { Err(e) => {
//self.context = Some(op.escape()); //self.context = Some(op.escape());
maybe_result = maybe_result =
Some(Err(e.with(RuntimeOp(fake.clone())))); Some(Err(e.with(RuntimeOp(fake))));
self.context = Some(ctx); self.context = Some(ctx);
break; break;
} }
@ -332,7 +332,7 @@ impl<P: FilterPredicate + 'static> Iterator for FilterStatement<P> {
} }
Err(e) => { Err(e) => {
self.is_failing = true; // this is unrecoverable and reproducible, so it shouldn't be tried again (to prevent error spam) 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; let mut maybe_result = None;
@ -434,7 +434,7 @@ impl<P: FilterPredicate + 'static> Iterator for FilterStatement<P> {
.variables .variables
.declare(variable_name, Type::Op(variable)) .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, Ok(_) => maybe_result,
} }
} }
@ -479,6 +479,7 @@ impl<P: FilterPredicate + 'static, F: FilterFactory<P> + 'static>
impl<P: FilterPredicate + 'static, F: FilterFactory<P> + 'static> BoxedOpFactory impl<P: FilterPredicate + 'static, F: FilterFactory<P> + 'static> BoxedOpFactory
for FilterStatementFactory<P, F> for FilterStatementFactory<P, F>
{ {
#[allow(clippy::unnecessary_unwrap)]
fn is_op_boxed(&self, tokens: &VecDeque<Token>) -> bool { fn is_op_boxed(&self, tokens: &VecDeque<Token>) -> bool {
let tokens_len = tokens.len(); let tokens_len = tokens.len();
if is_correct_format(tokens) { if is_correct_format(tokens) {
@ -524,8 +525,7 @@ impl<P: FilterPredicate + 'static, F: FilterFactory<P> + 'static> BoxedOpFactory
dict: &LanguageDictionary, dict: &LanguageDictionary,
) -> Result<Box<dyn Op>, SyntaxError> { ) -> Result<Box<dyn Op>, SyntaxError> {
let start_of_op = last_dot_before_open_bracket(tokens); let start_of_op = last_dot_before_open_bracket(tokens);
let op; let op = if start_of_op == 1 && tokens[0].is_name() {
if start_of_op == 1 && tokens[0].is_name() {
// variable_name.(predicate) // variable_name.(predicate)
let variable_name = assert_token( let variable_name = assert_token(
|t| match t { |t| match t {
@ -535,15 +535,15 @@ impl<P: FilterPredicate + 'static, F: FilterFactory<P> + 'static> BoxedOpFactory
Token::Name("variable_name".into()), Token::Name("variable_name".into()),
tokens, tokens,
)?; )?;
op = VariableOrOp::Variable(variable_name); VariableOrOp::Variable(variable_name)
} else { } else {
// <some other op>.(predicate) // <some other op>.(predicate)
//let mut new_tokens = tokens.range(0..start_of_op).map(|x| x.to_owned()).collect(); //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 end_tokens = tokens.split_off(start_of_op); // don't parse filter in inner statement
let inner_op = dict.try_build_statement(tokens)?; let inner_op = dict.try_build_statement(tokens)?;
tokens.extend(end_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::Dot, tokens)?;
assert_token_raw(Token::OpenBracket, tokens)?; assert_token_raw(Token::OpenBracket, tokens)?;
if !tokens.is_empty() && check_name("if", &tokens[0]) { if !tokens.is_empty() && check_name("if", &tokens[0]) {

View file

@ -190,7 +190,7 @@ impl<P: FilterPredicate + 'static> Iterator for FilterReplaceStatement<P> {
Ok(x) => { Ok(x) => {
return Some(Err(RuntimeError { return Some(Err(RuntimeError {
line: 0, line: 0,
op: fake.clone(), op: fake,
msg: format!( msg: format!(
"Expected operation/iterable type in variable {}, got {}", "Expected operation/iterable type in variable {}, got {}",
&variable_name, x &variable_name, x
@ -203,15 +203,14 @@ impl<P: FilterPredicate + 'static> Iterator for FilterReplaceStatement<P> {
variable.enter(ctx); variable.enter(ctx);
let item = variable.next(); let item = variable.next();
self.context = Some(variable.escape()); self.context = Some(variable.escape());
match self if let Err(e) = self
.context .context
.as_mut() .as_mut()
.unwrap() .unwrap()
.variables .variables
.declare(variable_name, Type::Op(variable)) .declare(variable_name, Type::Op(variable))
{ {
Err(e) => return Some(Err(e.with(RuntimeOp(fake)))), return Some(Err(e.with(RuntimeOp(fake))));
Ok(_) => {}
} }
item item
} }
@ -242,9 +241,8 @@ impl<P: FilterPredicate + 'static> Iterator for FilterReplaceStatement<P> {
// invoke inner op // invoke inner op
real_op.enter(self.context.take().unwrap()); real_op.enter(self.context.take().unwrap());
if real_op.is_resetable() { if real_op.is_resetable() {
match real_op.reset() { if let Err(e) = real_op.reset() {
Err(e) => return Some(Err(e)), return Some(Err(e));
Ok(_) => {}
} }
} }
for item in real_op.by_ref() { for item in real_op.by_ref() {
@ -287,9 +285,8 @@ impl<P: FilterPredicate + 'static> Iterator for FilterReplaceStatement<P> {
// invoke inner operation // invoke inner operation
real_op.enter(self.context.take().unwrap()); real_op.enter(self.context.take().unwrap());
if real_op.is_resetable() { if real_op.is_resetable() {
match real_op.reset() { if let Err(e) = real_op.reset() {
Err(e) => return Some(Err(e)), return Some(Err(e));
Ok(_) => {}
} }
} }
for item in real_op.by_ref() { for item in real_op.by_ref() {
@ -319,7 +316,7 @@ impl<P: FilterPredicate + 'static> Iterator for FilterReplaceStatement<P> {
Some(Ok(item)) 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)), Some(Err(e)) => Some(Err(e)),
@ -347,12 +344,11 @@ fn declare_or_replace_item(
single: SingleItem, single: SingleItem,
ctx: &mut Context, ctx: &mut Context,
) -> Result<Option<Type>, RuntimeMsg> { ) -> Result<Option<Type>, RuntimeMsg> {
let old_item: Option<Type>; let old_item: Option<Type> = if ctx.variables.exists(ITEM_VARIABLE_NAME) {
if ctx.variables.exists(ITEM_VARIABLE_NAME) { Some(ctx.variables.remove(ITEM_VARIABLE_NAME)?)
old_item = Some(ctx.variables.remove(ITEM_VARIABLE_NAME)?);
} else { } else {
old_item = None; None
} };
ctx.variables ctx.variables
.declare(ITEM_VARIABLE_NAME, Type::Op(Box::new(single)))?; .declare(ITEM_VARIABLE_NAME, Type::Op(Box::new(single)))?;
Ok(old_item) Ok(old_item)

View file

@ -1,3 +1,4 @@
#![allow(clippy::new_without_default)]
use core::ops::Deref; use core::ops::Deref;
use std::collections::VecDeque; use std::collections::VecDeque;
use std::fmt::{Debug, Display, Error, Formatter}; use std::fmt::{Debug, Display, Error, Formatter};
@ -67,11 +68,11 @@ pub struct ItemBlockStatement {
impl Display for ItemBlockStatement { impl Display for ItemBlockStatement {
fn fmt(&self, f: &mut Formatter) -> Result<(), Error> { fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
write!(f, "{}.{{", self.iterable)?; write!(f, "{}.{{", self.iterable)?;
if self.statements.len() > 0 { if !self.statements.is_empty() {
write!(f, "\n")?; writeln!(f)?;
} }
for statement in self.statements.iter() { for statement in self.statements.iter() {
write!(f, "{}\n", statement)?; writeln!(f, "{}", statement)?;
} }
write!(f, "}}") write!(f, "}}")
} }
@ -213,7 +214,7 @@ pub struct ItemBlockFactory {
} }
impl ItemBlockFactory { impl ItemBlockFactory {
pub fn add< pub fn push<
T: ItemOpFactory<Y> + 'static, T: ItemOpFactory<Y> + 'static,
Y: Deref<Target = dyn ItemOp> + ItemOp + 'static, Y: Deref<Target = dyn ItemOp> + ItemOp + 'static,
>( >(
@ -317,12 +318,11 @@ fn restore_item_var(
ctx: &mut Context, ctx: &mut Context,
old_var: Option<Type>, old_var: Option<Type>,
) -> Result<Option<Type>, RuntimeMsg> { ) -> Result<Option<Type>, RuntimeMsg> {
let new_var; let new_var = if ctx.variables.exists(ITEM_VARIABLE_NAME) {
if ctx.variables.exists(ITEM_VARIABLE_NAME) { Some(ctx.variables.remove(ITEM_VARIABLE_NAME)?)
new_var = Some(ctx.variables.remove(ITEM_VARIABLE_NAME)?);
} else { } else {
new_var = None; None
} };
if let Some(old_var) = old_var { if let Some(old_var) = old_var {
ctx.variables.declare(ITEM_VARIABLE_NAME, old_var)?; ctx.variables.declare(ITEM_VARIABLE_NAME, old_var)?;
} }

View file

@ -1,3 +1,5 @@
#![allow(clippy::match_like_matches_macro)]
#![allow(clippy::needless_range_loop)]
mod db_items; mod db_items;
mod dictionary; mod dictionary;
mod error; mod error;

View file

@ -1,3 +1,4 @@
#![allow(clippy::borrowed_box)]
use std::fmt::{Debug, Display, Error, Formatter}; use std::fmt::{Debug, Display, Error, Formatter};
use super::Op; use super::Op;

View file

@ -13,7 +13,7 @@ use crate::Context;
const SORTER_ITEM_CACHE_SIZE: usize = 8; const SORTER_ITEM_CACHE_SIZE: usize = 8;
pub trait Sorter: Clone + Debug + Display { pub trait Sorter: Clone + Debug + Display {
fn sort<'a>( fn sort(
&mut self, &mut self,
iterator: &mut dyn Op, iterator: &mut dyn Op,
item_buf: &mut VecDeque<IteratorItem>, item_buf: &mut VecDeque<IteratorItem>,

View file

@ -19,7 +19,7 @@ impl Display for NonEmptyFilter {
impl FilterPredicate for NonEmptyFilter { impl FilterPredicate for NonEmptyFilter {
fn matches(&mut self, item: &Item, _ctx: &mut Context) -> Result<bool, RuntimeMsg> { fn matches(&mut self, item: &Item, _ctx: &mut Context) -> Result<bool, RuntimeMsg> {
if item.len() != 0 { if !item.is_empty() {
if item.len() == 1 && item.field("filename").is_some() { if item.len() == 1 && item.field("filename").is_some() {
Ok(false) // ignore filename field, since that almost always exists Ok(false) // ignore filename field, since that almost always exists
} else { } else {

View file

@ -90,7 +90,7 @@ pub struct UniqueFilterFactory;
impl FilterFactory<UniqueFieldFilter> for UniqueFilterFactory { impl FilterFactory<UniqueFieldFilter> for UniqueFilterFactory {
fn is_filter(&self, tokens: &VecDeque<&Token>) -> bool { 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( fn build_filter(
@ -128,7 +128,7 @@ impl FilterFactory<UniqueFieldFilter> for UniqueFilterFactory {
impl FilterFactory<UniqueFilter> for UniqueFilterFactory { impl FilterFactory<UniqueFilter> for UniqueFilterFactory {
fn is_filter(&self, tokens: &VecDeque<&Token>) -> bool { 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( fn build_filter(

View file

@ -49,7 +49,7 @@ impl Iterator for IntersectionStatement {
type Item = IteratorItem; type Item = IteratorItem;
fn next(&mut self) -> Option<Self::Item> { fn next(&mut self) -> Option<Self::Item> {
if self.ops.len() == 0 { if self.ops.is_empty() {
return None; return None;
} else if self.init_needed { } else if self.init_needed {
self.init_needed = false; self.init_needed = false;

View file

@ -36,7 +36,7 @@ impl ItemOp for AddItemOp {
let rhs = self.rhs.execute(context)?; let rhs = self.rhs.execute(context)?;
if let Type::Primitive(rhs) = &rhs { if let Type::Primitive(rhs) = &rhs {
Ok(Type::Primitive( Ok(Type::Primitive(
lhs.try_add(rhs).map_err(|e| RuntimeMsg(e))?, lhs.try_add(rhs).map_err(RuntimeMsg)?,
)) ))
} else { } else {
Err(RuntimeMsg(format!( Err(RuntimeMsg(format!(

View file

@ -28,29 +28,29 @@ impl Display for BranchItemOp {
fn fmt(&self, f: &mut Formatter) -> Result<(), Error> { fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
write!(f, "if {} {{", self.condition)?; write!(f, "if {} {{", self.condition)?;
if self.inner_ifs.len() > 1 { if self.inner_ifs.len() > 1 {
write!(f, "\n")?; writeln!(f)?;
} }
for i in 0..self.inner_ifs.len() { for i in 0..self.inner_ifs.len() {
write!(f, "{}", self.inner_ifs[i])?; write!(f, "{}", self.inner_ifs[i])?;
if i != self.inner_ifs.len() - 1 { if i != self.inner_ifs.len() - 1 {
write!(f, ",\n")?; writeln!(f, ",")?;
} }
} }
if self.inner_ifs.len() > 1 { if self.inner_ifs.len() > 1 {
write!(f, "\n")?; writeln!(f)?;
} }
write!(f, "}} else {{")?; write!(f, "}} else {{")?;
if self.inner_elses.len() > 1 { if self.inner_elses.len() > 1 {
write!(f, "\n")?; writeln!(f)?;
} }
for i in 0..self.inner_elses.len() { for i in 0..self.inner_elses.len() {
write!(f, "{}", self.inner_elses[i])?; write!(f, "{}", self.inner_elses[i])?;
if i != self.inner_elses.len() - 1 { if i != self.inner_elses.len() - 1 {
write!(f, ",\n")?; writeln!(f, ",")?;
} }
} }
if self.inner_elses.len() > 1 { if self.inner_elses.len() > 1 {
write!(f, "\n")?; writeln!(f)?;
} }
write!(f, "}}") write!(f, "}}")
} }

View file

@ -42,7 +42,7 @@ impl ItemOp for CompareItemOp {
let rhs_val = self.rhs.execute(context)?; let rhs_val = self.rhs.execute(context)?;
if let Type::Primitive(lhs) = lhs_val { if let Type::Primitive(lhs) = lhs_val {
if let Type::Primitive(rhs) = rhs_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; let mut is_match = false;
for comparator in self.comparison { for comparator in self.comparison {
if comparator == compare { if comparator == compare {

View file

@ -35,7 +35,7 @@ impl Display for ConstructorItemOp {
fn fmt(&self, f: &mut Formatter) -> Result<(), Error> { fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
write!(f, "Item(")?; write!(f, "Item(")?;
if self.fields.len() > 1 { if self.fields.len() > 1 {
write!(f, "\n")?; writeln!(f)?;
for i in 0..self.fields.len() - 1 { for i in 0..self.fields.len() - 1 {
let field = &self.fields[i]; let field = &self.fields[i];
write!(f, "{}: {}, ", field.name, field.value)?; write!(f, "{}: {}, ", field.name, field.value)?;

View file

@ -78,11 +78,10 @@ impl ItemOpFactory<FieldAssignItemOp> for FieldAssignItemOpFactory {
factory: &ItemBlockFactory, factory: &ItemBlockFactory,
dict: &LanguageDictionary, dict: &LanguageDictionary,
) -> Result<FieldAssignItemOp, SyntaxError> { ) -> Result<FieldAssignItemOp, SyntaxError> {
let var_name; let var_name =if tokens[0].is_dot() {
if tokens[0].is_dot() { "item".to_string()
var_name = "item".to_string();
} else { } else {
var_name = assert_token( assert_token(
|t| match t { |t| match t {
Token::Name(s) => Some(s), Token::Name(s) => Some(s),
_ => None, _ => None,
@ -90,7 +89,7 @@ impl ItemOpFactory<FieldAssignItemOp> for FieldAssignItemOpFactory {
Token::Name("variable_name".into()), Token::Name("variable_name".into()),
tokens, tokens,
)? )?
} };
assert_token_raw(Token::Dot, tokens)?; assert_token_raw(Token::Dot, tokens)?;
let f_name = assert_token( let f_name = assert_token(
|t| match t { |t| match t {

View file

@ -30,7 +30,7 @@ impl Display for IterItemOp {
impl ItemOp for IterItemOp { impl ItemOp for IterItemOp {
fn execute(&self, _context: &mut Context) -> Result<Type, RuntimeMsg> { fn execute(&self, _context: &mut Context) -> Result<Type, RuntimeMsg> {
Ok(Type::Op(self.inner.dup().into())) Ok(Type::Op(self.inner.dup()))
} }
} }

View file

@ -33,7 +33,7 @@ impl ItemOp for NegateItemOp {
let rhs = self.rhs.execute(context)?; let rhs = self.rhs.execute(context)?;
if let Type::Primitive(rhs) = &rhs { if let Type::Primitive(rhs) = &rhs {
Ok(Type::Primitive( Ok(Type::Primitive(
rhs.try_negate().map_err(|e| RuntimeMsg(e))?, rhs.try_negate().map_err(RuntimeMsg)?,
)) ))
} else { } else {
Err(RuntimeMsg(format!( Err(RuntimeMsg(format!(

View file

@ -33,7 +33,7 @@ impl ItemOp for NotItemOp {
let rhs = self.rhs.execute(context)?; let rhs = self.rhs.execute(context)?;
if let Type::Primitive(rhs) = &rhs { if let Type::Primitive(rhs) = &rhs {
Ok(Type::Primitive( Ok(Type::Primitive(
rhs.try_not().map_err(|e| RuntimeMsg(e))?, rhs.try_not().map_err(RuntimeMsg)?,
)) ))
} else { } else {
Err(RuntimeMsg(format!( Err(RuntimeMsg(format!(

View file

@ -75,20 +75,19 @@ impl ItemOpFactory<RemoveItemOp> for RemoveItemOpFactory {
Token::Name("variable_name".into()), Token::Name("variable_name".into()),
tokens, tokens,
)?; )?;
let field_opt; let field_opt = if tokens.is_empty() {
if tokens.is_empty() { None
field_opt = None;
} else { } else {
assert_token_raw(Token::Dot, tokens)?; assert_token_raw(Token::Dot, tokens)?;
field_opt = Some(assert_token( Some(assert_token(
|t| match t { |t| match t {
Token::Name(s) => Some(s), Token::Name(s) => Some(s),
_ => None, _ => None,
}, },
Token::Name("field_name".into()), Token::Name("field_name".into()),
tokens, tokens,
)?); )?)
} };
Ok(RemoveItemOp { Ok(RemoveItemOp {
variable_name: name, variable_name: name,
field_name: field_opt, field_name: field_opt,

View file

@ -86,20 +86,19 @@ impl ItemOpFactory<VariableRetrieveItemOp> for VariableRetrieveItemOpFactory {
Token::Name("variable_name".into()), Token::Name("variable_name".into()),
tokens, tokens,
)?; )?;
let field_opt; let field_opt = if tokens.is_empty() {
if tokens.is_empty() { None
field_opt = None;
} else { } else {
assert_token_raw(Token::Dot, tokens)?; assert_token_raw(Token::Dot, tokens)?;
field_opt = Some(assert_token( Some(assert_token(
|t| match t { |t| match t {
Token::Name(s) => Some(s), Token::Name(s) => Some(s),
_ => None, _ => None,
}, },
Token::Name("field_name".into()), Token::Name("field_name".into()),
tokens, tokens,
)?); )?)
} };
Ok(VariableRetrieveItemOp { Ok(VariableRetrieveItemOp {
variable_name: var_name, variable_name: var_name,
field_name: field_opt, field_name: field_opt,

View file

@ -39,7 +39,7 @@ impl ItemOp for InterpolateStringItemOp {
} }
Type::Item(item) => { Type::Item(item) => {
let mut result; let mut result;
if item.len() == 0 { if item.is_empty() {
result = self.format.clone(); result = self.format.clone();
} else { } else {
let mut iter = item.iter(); let mut iter = item.iter();

View file

@ -36,7 +36,7 @@ impl ItemOp for SubtractItemOp {
let rhs = self.rhs.execute(context)?; let rhs = self.rhs.execute(context)?;
if let Type::Primitive(rhs) = &rhs { if let Type::Primitive(rhs) = &rhs {
Ok(Type::Primitive( Ok(Type::Primitive(
lhs.try_subtract(rhs).map_err(|e| RuntimeMsg(e))?, lhs.try_subtract(rhs).map_err(RuntimeMsg)?,
)) ))
} else { } else {
Err(RuntimeMsg(format!( Err(RuntimeMsg(format!(

View file

@ -40,12 +40,10 @@ impl ItemOp for VariableDeclareItemOp {
if !context.variables.exists(&self.variable_name) { if !context.variables.exists(&self.variable_name) {
context.variables.declare(&self.variable_name, mps_type)?; context.variables.declare(&self.variable_name, mps_type)?;
} }
} else { } else if !context.variables.exists(&self.variable_name) {
if !context.variables.exists(&self.variable_name) { context
context .variables
.variables .declare(&self.variable_name, Type::empty())?;
.declare(&self.variable_name, Type::empty())?;
}
} }
Ok(Type::empty()) Ok(Type::empty())
} }
@ -74,13 +72,12 @@ impl ItemOpFactory<VariableDeclareItemOp> for VariableDeclareItemOpFactory {
Token::Name("variable_name".into()), Token::Name("variable_name".into()),
tokens, tokens,
)?; )?;
let inner_op: Option<Box<dyn ItemOp>>; let inner_op: Option<Box<dyn ItemOp>> = if !tokens.is_empty() {
if !tokens.is_empty() {
assert_token_raw(Token::Equals, tokens)?; 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 { } else {
inner_op = None; None
} };
Ok(VariableDeclareItemOp { Ok(VariableDeclareItemOp {
variable_name: var_name, variable_name: var_name,
inner: inner_op, inner: inner_op,

View file

@ -1,3 +1,4 @@
#![allow(clippy::while_let_on_iterator)]
mod empties; mod empties;
pub(crate) mod empty; pub(crate) mod empty;
mod files; mod files;

View file

@ -117,7 +117,7 @@ impl Iterator for MpdQueryStatement {
}); });
} }
let results = self.results.as_mut().unwrap(); 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<usize>) { fn size_hint(&self) -> (usize, Option<usize>) {

View file

@ -69,7 +69,7 @@ impl Iterator for RepeatStatement {
} }
if real_op.is_resetable() { if real_op.is_resetable() {
while self.loop_forever || !self.inner_done { while self.loop_forever || !self.inner_done {
for item in real_op.by_ref() { if let Some(item) = real_op.next() {
return Some(item); return Some(item);
} }
if !self.loop_forever { if !self.loop_forever {
@ -79,16 +79,14 @@ impl Iterator for RepeatStatement {
self.context = Some(real_op.escape()); self.context = Some(real_op.escape());
} else { } else {
self.repetitions -= 1; self.repetitions -= 1;
match real_op.reset() { if let Err(e) = real_op.reset() {
Err(e) => return Some(Err(e)), return Some(Err(e));
Ok(_) => {}
} }
} }
} else { } else {
// always reset in infinite loop mode // always reset in infinite loop mode
match real_op.reset() { if let Err(e) = real_op.reset() {
Err(e) => return Some(Err(e)), return Some(Err(e));
Ok(_) => {}
} }
} }
} }

View file

@ -68,18 +68,16 @@ impl Sorter for BlissNextSorter {
let mut ctx = iterator.escape(); let mut ctx = iterator.escape();
for i in 1..self.item_buf.len() { for i in 1..self.item_buf.len() {
let item = &self.item_buf[i]; let item = &self.item_buf[i];
match ctx.analysis.prepare_distance(first, item) { if let Err(e) = ctx.analysis.prepare_distance(first, item) {
Err(e) => { iterator.enter(ctx);
iterator.enter(ctx); return Err(e);
return Err(e);
}
Ok(_) => {}
} }
} }
iterator.enter(ctx); iterator.enter(ctx);
items_out.push_back(Ok(first.to_owned())); items_out.push_back(Ok(first.to_owned()));
} }
} else { } else {
#[allow(clippy::collapsible_else_if)]
if self.item_buf.len() > 2 { if self.item_buf.len() > 2 {
let last = self.item_buf.pop_front().unwrap(); let last = self.item_buf.pop_front().unwrap();
let mut best_index = 0; let mut best_index = 0;
@ -107,12 +105,9 @@ impl Sorter for BlissNextSorter {
let next = &self.item_buf[0]; let next = &self.item_buf[0];
for i in 1..self.item_buf.len() { for i in 1..self.item_buf.len() {
let item = &self.item_buf[i]; let item = &self.item_buf[i];
match ctx.analysis.prepare_distance(next, item) { if let Err(e) = ctx.analysis.prepare_distance(next, item) {
Err(e) => { iterator.enter(ctx);
iterator.enter(ctx); return Err(e);
return Err(e);
}
Ok(_) => {}
} }
} }
iterator.enter(ctx); iterator.enter(ctx);

View file

@ -64,12 +64,7 @@ impl Sorter for BlissSorter {
// when buf_len_old == item_buf.len(), iterator was already complete // 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 // 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() { if self.first_song.is_none() {
for item in item_buf.iter() { self.first_song = item_buf.iter().flatten().next().map(|x| x.to_owned());
if let Ok(item) = item {
self.first_song = Some(item.clone());
break;
}
}
} }
if let Some(first) = &self.first_song { if let Some(first) = &self.first_song {
let mut ctx = iterator.escape(); let mut ctx = iterator.escape();
@ -78,12 +73,9 @@ impl Sorter for BlissSorter {
if item == first { if item == first {
continue; continue;
} }
match ctx.analysis.prepare_distance(first, item) { if let Err(e) = ctx.analysis.prepare_distance(first, item) {
Err(e) => { iterator.enter(ctx);
iterator.enter(ctx); return Err(e);
return Err(e);
}
Ok(_) => {}
} }
} }
} }
@ -115,8 +107,8 @@ impl Sorter for BlissSorter {
item_buf.make_contiguous().sort_by(|a, b| { item_buf.make_contiguous().sort_by(|a, b| {
if let Ok(a) = a { if let Ok(a) = a {
if let Ok(b) = b { if let Ok(b) = b {
let float_a = cache.get(&a).unwrap(); let float_a = cache.get(a).unwrap();
let float_b = cache.get(&b).unwrap(); let float_b = cache.get(b).unwrap();
return float_a.partial_cmp(float_b).unwrap_or(DEFAULT_ORDER); return float_a.partial_cmp(float_b).unwrap_or(DEFAULT_ORDER);
} }
} }

View file

@ -53,10 +53,10 @@ impl Sorter for ShuffleSorter {
} }
} }
// end case: everything is completely empty -- end loop without a new result // end case: everything is completely empty -- end loop without a new result
if item_buf.len() == 0 { if item_buf.is_empty() {
return Ok(()); return Ok(());
} }
random = random % item_buf.len(); random %= item_buf.len();
} }
} }
} }
@ -71,10 +71,10 @@ pub struct ShuffleSorterFactory;
impl SorterFactory<ShuffleSorter> for ShuffleSorterFactory { impl SorterFactory<ShuffleSorter> for ShuffleSorterFactory {
fn is_sorter(&self, tokens: &VecDeque<&Token>) -> bool { 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 || (tokens.len() > 1
&& check_name("random", &tokens[0]) && check_name("random", tokens[0])
&& check_name("shuffle", &tokens[1])) && check_name("shuffle", tokens[1]))
} }
fn build_sorter( fn build_sorter(

View file

@ -65,7 +65,7 @@ impl Iterator for UnionStatement {
Err(e) => return Some(Err(e)), Err(e) => return Some(Err(e)),
}; };
real_op.enter(self.context.take().unwrap()); 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()); self.context = Some(real_op.escape());
return Some(item); return Some(item);
} }

View file

@ -74,22 +74,21 @@ impl Iterator for AssignStatement {
Ok(real) => real, Ok(real) => real,
Err(e) => return Some(Err(e)), Err(e) => return Some(Err(e)),
}; };
let result; let result = if self.is_declaration {
if self.is_declaration { self
result = self
.context .context
.as_mut() .as_mut()
.unwrap() .unwrap()
.variables .variables
.declare(&self.variable_name, Type::Op(real)); .declare(&self.variable_name, Type::Op(real))
} else { } else {
result = self self
.context .context
.as_mut() .as_mut()
.unwrap() .unwrap()
.variables .variables
.assign(&self.variable_name, Type::Op(real)); .assign(&self.variable_name, Type::Op(real))
} };
match result { match result {
Ok(_) => None, Ok(_) => None,
Err(e) => Some(Err(e.with(RuntimeOp(PseudoOp::from_printable(self))))), Err(e) => Some(Err(e.with(RuntimeOp(PseudoOp::from_printable(self))))),
@ -107,22 +106,21 @@ impl Iterator for AssignStatement {
}))*/ }))*/
} else { } else {
let assign_type = self.assign_type.clone().unwrap(); let assign_type = self.assign_type.clone().unwrap();
let result; let result = if self.is_declaration {
if self.is_declaration { self
result = self
.context .context
.as_mut() .as_mut()
.unwrap() .unwrap()
.variables .variables
.declare(&self.variable_name, Type::Primitive(assign_type)); .declare(&self.variable_name, Type::Primitive(assign_type))
} else { } else {
result = self self
.context .context
.as_mut() .as_mut()
.unwrap() .unwrap()
.variables .variables
.assign(&self.variable_name, Type::Primitive(assign_type)); .assign(&self.variable_name, Type::Primitive(assign_type))
} };
match result { match result {
Ok(_) => None, Ok(_) => None,
Err(e) => Some(Err(e.with(RuntimeOp(PseudoOp::from_printable(self))))), Err(e) => Some(Err(e.with(RuntimeOp(PseudoOp::from_printable(self))))),

View file

@ -246,6 +246,8 @@
//! Load an item from file, populating the item with the song's tags. //! Load an item from file, populating the item with the song's tags.
//! //!
#![allow(clippy::redundant_field_names)]
mod context; mod context;
mod debug; mod debug;
mod errors; mod errors;

View file

@ -36,6 +36,10 @@ impl Library {
self.songs.len() self.songs.len()
} }
pub fn is_empty(&self) -> bool {
self.songs.is_empty()
}
pub fn clear_modified(&mut self) { pub fn clear_modified(&mut self) {
self.dirty = false; self.dirty = false;
} }
@ -54,7 +58,7 @@ impl Library {
self.files.contains(&path.as_ref().to_path_buf()) 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() self.songs.values().collect()
} }
@ -67,7 +71,7 @@ impl Library {
self.songs.insert(song.song_id, song); 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() self.metadata.values().collect()
} }
@ -77,7 +81,7 @@ impl Library {
self.metadata.insert(meta.meta_id, meta); 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() self.artists.values().collect()
} }
@ -88,7 +92,7 @@ impl Library {
.insert(Self::sanitise_key(&artist.name), artist); .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() self.albums.values().collect()
} }
@ -98,7 +102,7 @@ impl Library {
self.albums.insert(Self::sanitise_key(&album.title), album); 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() self.genres.values().collect()
} }
@ -236,7 +240,7 @@ impl Library {
} }
#[inline] #[inline]
fn find_or_gen_id<'a, D: DatabaseObj>(map: &'a HashMap<String, D>, key: &str) -> u64 { fn find_or_gen_id<D: DatabaseObj>(map: &HashMap<String, D>, key: &str) -> u64 {
if let Some(obj) = Self::find_by_key(map, key) { if let Some(obj) = Self::find_by_key(map, key) {
obj.id() obj.id()
} else { } else {

View file

@ -49,7 +49,7 @@ impl Tags {
.file_name() .file_name()
.and_then(|file| file.to_str()) .and_then(|file| file.to_str())
.map(|file| file.replacen(&format!(".{}", extension), "", 1)) .map(|file| file.replacen(&format!(".{}", extension), "", 1))
.unwrap_or("Unknown Title".into()) .unwrap_or_else(|| "Unknown Title".into())
} }
#[inline] #[inline]
@ -149,7 +149,7 @@ impl Tags {
pub fn artist(&self, id: u64, genre_id: u64) -> DbArtistItem { pub fn artist(&self, id: u64, genre_id: u64) -> DbArtistItem {
DbArtistItem { DbArtistItem {
artist_id: id, 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, 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 { pub fn album(&self, id: u64, meta_id: u64, artist_id: u64, genre_id: u64) -> DbAlbumItem {
DbAlbumItem { DbAlbumItem {
album_id: id, 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, metadata: meta_id,
artist: artist_id, artist: artist_id,
genre: genre_id, genre: genre_id,
@ -212,7 +212,7 @@ impl Tags {
pub fn genre(&self, id: u64) -> DbGenreItem { pub fn genre(&self, id: u64) -> DbGenreItem {
DbGenreItem { DbGenreItem {
genre_id: id, genre_id: id,
title: self.genre_title().unwrap_or("Unknown Genre".into()), title: self.genre_title().unwrap_or_else(|| "Unknown Genre".into()),
} }
} }
} }

View file

@ -41,10 +41,11 @@ impl Iterator for SortedReadDir {
} }
} }
self.dir_iter_complete = true; 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, b| b.path().to_string_lossy().to_lowercase().cmp(
&a.path().to_string_lossy().to_lowercase()) &a.path().to_string_lossy().to_lowercase())
); );*/
} }
if self.cache.is_empty() { if self.cache.is_empty() {
None None
@ -73,7 +74,7 @@ impl Display for FileIter {
self.pattern self.pattern
.as_ref() .as_ref()
.map(|re| re.to_string()) .map(|re| re.to_string())
.unwrap_or("[none]".to_string()), .unwrap_or_else(|| "[none]".to_string()),
self.recursive self.recursive
) )
} }
@ -224,13 +225,11 @@ impl FileIter {
) { ) {
// populates fields from named capture groups // populates fields from named capture groups
if let Some(captures) = captures { if let Some(captures) = captures {
for name_maybe in capture_names { for name in capture_names.flatten() {
if let Some(name) = name_maybe { if item.field(name).is_some() {
if item.field(name).is_some() {
// do nothing // do nothing
} else if let Some(value) = captures.name(name).map(|m| m.as_str().to_string()) { } else if let Some(value) = captures.name(name).map(|m| m.as_str().to_string()) {
item.set_field(name, TypePrimitive::parse(value)); item.set_field(name, TypePrimitive::parse(value));
}
} }
} }
} }

View file

@ -41,7 +41,7 @@ impl MpdQuerier for MpdExecutor {
query_mut = query_mut.and(str_to_term(term), value); 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)))?; 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<VecDeque<Item>, RuntimeMsg> { fn one_shot_search(&self, addr: SocketAddr, params: Vec<(&str, String)>) -> Result<VecDeque<Item>, RuntimeMsg> {
@ -53,7 +53,7 @@ impl MpdQuerier for MpdExecutor {
query_mut = query_mut.and(str_to_term(term), value); 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)))?; 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] #[inline]
fn str_to_term<'a>(s: &'a str) -> Term<'a> { fn str_to_term(s: &str) -> Term<'_> {
match s { match s {
"any" => Term::Any, "any" => Term::Any,
"file" => Term::File, "file" => Term::File,

View file

@ -208,7 +208,7 @@ enum ResponseType {
}, },
Song { Song {
path: String, path: String,
song: Result<Song, BlissError>, song: Result<Box<Song>, BlissError>,
}, },
UnsupportedSong { UnsupportedSong {
path: String, path: String,
@ -257,13 +257,13 @@ impl CacheThread {
} }
} }
fn insert_song(&mut self, path: String, song_result: Result<Song, BlissError>) { fn insert_song(&mut self, path: String, song_result: Result<Box<Song>, BlissError>) {
self.song_in_progress.remove(&path); self.song_in_progress.remove(&path);
if self.song_cache.len() > MAX_SONG_CACHE_SIZE { if self.song_cache.len() > MAX_SONG_CACHE_SIZE {
// avoid using too much memory -- songs are big memory objects // avoid using too much memory -- songs are big memory objects
self.song_cache.clear(); 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( fn insert_distance(
@ -305,7 +305,7 @@ impl CacheThread {
if result.is_none() && auto_add { if result.is_none() && auto_add {
self.song_in_progress.insert(path.to_owned()); self.song_in_progress.insert(path.to_owned());
} }
return result; return result.map(|x| x.as_ref().to_owned());
} else { } else {
self.insert_song(path2, song); self.insert_song(path2, song);
} }
@ -322,7 +322,7 @@ impl CacheThread {
let result = self let result = self
.song_cache .song_cache
.get(path) .get(path)
.and_then(|r| r.clone().ok().to_owned()); .and_then(|r| r.clone().ok());
if result.is_none() && auto_add { if result.is_none() && auto_add {
self.song_in_progress.insert(path.to_owned()); self.song_in_progress.insert(path.to_owned());
} }
@ -331,7 +331,7 @@ impl CacheThread {
if auto_add { if auto_add {
self.song_in_progress.insert(path.to_owned()); self.song_in_progress.insert(path.to_owned());
} }
return None; None
} }
fn handle_distance_req( fn handle_distance_req(
@ -346,11 +346,11 @@ impl CacheThread {
if let Some(result) = self.distance_cache.get(&key) { if let Some(result) = self.distance_cache.get(&key) {
if ack { if ack {
let result = result.to_owned(); let result = result.to_owned();
if let Err(_) = self.responses.send(ResponseType::Distance { if self.responses.send(ResponseType::Distance {
path1: path1, path1: path1,
path2: path2, path2: path2,
distance: result, distance: result,
}) { }).is_err() {
return true; return true;
} }
} }
@ -360,14 +360,12 @@ impl CacheThread {
// also prevents deadlock in self.get_song_option() // also prevents deadlock in self.get_song_option()
// due to waiting on song that isn't being processed yet // due to waiting on song that isn't being processed yet
// (first call adds it to song_in_progress set, second call just waits) // (first call adds it to song_in_progress set, second call just waits)
if ack { if ack && self.responses.send(ResponseType::Distance {
if let Err(_) = self.responses.send(ResponseType::Distance {
path1: path1, path1: path1,
path2: path2, path2: path2,
distance: Ok(0.0), distance: Ok(0.0),
}) { }).is_err() {
return true; return true;
}
} }
} else if !self.distance_in_progress.contains(&key) { } else if !self.distance_in_progress.contains(&key) {
// distance worker uses 3 threads (it's own thread + 1 extra per song) for 2 songs // distance worker uses 3 threads (it's own thread + 1 extra per song) for 2 songs
@ -433,11 +431,11 @@ impl CacheThread {
distance.clone(), distance.clone(),
); );
if path1_2 == key.0 && path2_2 == key.1 { 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, path1: path1_2,
path2: path2_2, path2: path2_2,
distance: distance, distance: distance,
}) { }).is_err() {
return true; return true;
} }
break 'inner1; break 'inner1;
@ -448,10 +446,10 @@ impl CacheThread {
}, },
ResponseType::UnsupportedSong { path: unsupported_path, msg } => { ResponseType::UnsupportedSong { path: unsupported_path, msg } => {
self.song_in_progress.remove(&unsupported_path); 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(), path: unsupported_path.clone(),
msg: msg msg: msg
}) { }).is_err() {
return true; return true;
} }
if unsupported_path == key.0 || unsupported_path == key.1 { if unsupported_path == key.0 || unsupported_path == key.1 {
@ -478,10 +476,10 @@ impl CacheThread {
} else if !path.contains("://") { } else if !path.contains("://") {
path path
} else { } 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), msg: format!("Song path is not a supported URI, it's `{}`", path),
path: path, path: path,
}) { }).is_err() {
return true; return true;
} }
return false; return false;
@ -489,10 +487,10 @@ impl CacheThread {
if let Some(song) = self.song_cache.get(&path) { if let Some(song) = self.song_cache.get(&path) {
if ack { if ack {
let song = song.to_owned(); let song = song.to_owned();
if let Err(_) = self.responses.send(ResponseType::Song { if self.responses.send(ResponseType::Song {
path: path, path: path,
song: song, song: song.map(Box::new),
}) { }).is_err() {
return true; return true;
} }
} }
@ -539,7 +537,7 @@ impl CacheThread {
results results
.send(ResponseType::Song { .send(ResponseType::Song {
path: path_clone, path: path_clone,
song: song_result, song: song_result.map(Box::new),
}) })
.unwrap_or(()); .unwrap_or(());
}); });
@ -557,10 +555,10 @@ impl CacheThread {
ResponseType::Song { path: path2, song } => { ResponseType::Song { path: path2, song } => {
self.insert_song(path2.clone(), song.clone()); self.insert_song(path2.clone(), song.clone());
if path2 == path { if path2 == path {
if let Err(_) = self.responses.send(ResponseType::Song { if self.responses.send(ResponseType::Song {
path: path, path: path,
song: song, song: song,
}) { }).is_err() {
return true; return true;
} }
break 'inner3; break 'inner3;
@ -569,10 +567,10 @@ impl CacheThread {
ResponseType::UnsupportedSong { path: unsupported_path, msg } => { ResponseType::UnsupportedSong { path: unsupported_path, msg } => {
self.song_in_progress.remove(&unsupported_path); self.song_in_progress.remove(&unsupported_path);
if unsupported_path == path { if unsupported_path == path {
if let Err(_) = self.responses.send(ResponseType::UnsupportedSong { if self.responses.send(ResponseType::UnsupportedSong {
path: unsupported_path, path: unsupported_path,
msg: msg msg: msg
}) { }).is_err() {
return true; return true;
} }
break 'inner3; break 'inner3;
@ -624,7 +622,7 @@ fn worker_distance(
results results
.send(ResponseType::Song { .send(ResponseType::Song {
path: path1.to_string(), path: path1.to_string(),
song: new_song1.clone(), song: new_song1.clone().map(Box::new),
}) })
.unwrap_or(()); .unwrap_or(());
new_song1? new_song1?
@ -637,7 +635,7 @@ fn worker_distance(
results results
.send(ResponseType::Song { .send(ResponseType::Song {
path: path2.to_string(), path: path2.to_string(),
song: new_song2.clone(), song: new_song2.clone().map(Box::new),
}) })
.unwrap_or(()); .unwrap_or(());
if new_song2.is_err() { if new_song2.is_err() {

View file

@ -1,4 +1,5 @@
use core::fmt::Debug; use core::fmt::Debug;
use std::fmt::Write;
use std::collections::{HashMap, HashSet}; use std::collections::{HashMap, HashSet};
use crate::lang::db::*; use crate::lang::db::*;
@ -159,9 +160,11 @@ impl DatabaseQuerier for SQLiteExecutor {
for key in keys.drain() { for key in keys.drain() {
if first { if first {
first = false; first = false;
concat_keys += key; write!(concat_keys, "{}", key).unwrap();
//concat_keys += key;
} else { } else {
concat_keys += &format!("{}, ", key); write!(concat_keys, "{}, ", key).unwrap();
//concat_keys += &format!("{}, ", key);
} }
} }
return Err(RuntimeMsg(format!( return Err(RuntimeMsg(format!(

View file

@ -1,3 +1,4 @@
#![allow(clippy::match_like_matches_macro)]
mod error; mod error;
mod token_enum; mod token_enum;
mod tokenizer; mod tokenizer;

View file

@ -268,7 +268,7 @@ impl ReaderStateMachine {
Self::Escaped { inside } => match inside { Self::Escaped { inside } => match inside {
'`' => Self::InsideTickLiteral { out: input }, '`' => Self::InsideTickLiteral { out: input },
'"' => Self::InsideQuoteLiteral { out: input }, '"' => Self::InsideQuoteLiteral { out: input },
'_' | _ => Self::Regular { out: input }, _ => Self::Regular { out: input },
}, },
Self::StartTickLiteral {} | Self::InsideTickLiteral { .. } => match input_char { Self::StartTickLiteral {} | Self::InsideTickLiteral { .. } => match input_char {
'\\' => Self::Escaped { inside: '`' }, '\\' => Self::Escaped { inside: '`' },

View file

@ -1,5 +1,5 @@
use std::fmt::{Debug, Display, Error, Formatter}; use std::fmt::{Debug, Display, Error, Formatter};
use std::convert::Into; use std::convert::From;
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub enum PlayerError { pub enum PlayerError {
@ -58,9 +58,9 @@ impl Display for PlaybackError {
} }
} }
impl Into<PlayerError> for PlaybackError { impl From<PlaybackError> for PlayerError {
fn into(self) -> PlayerError { fn from(other: PlaybackError) -> Self {
PlayerError::Playback(self) PlayerError::Playback(other)
} }
} }
@ -86,8 +86,8 @@ impl Display for UriError {
} }
} }
impl Into<PlayerError> for UriError { impl From<UriError> for PlayerError {
fn into(self) -> PlayerError { fn from(other: UriError) -> Self {
PlayerError::Uri(self) PlayerError::Uri(other)
} }
} }

View file

@ -3,6 +3,9 @@
//! Music playback and m3u8 playlist generation are implemented in this part of the project. //! 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 controller;
mod errors; mod errors;
pub(crate) mod os_controls; pub(crate) mod os_controls;

View file

@ -165,7 +165,7 @@ impl<I: std::iter::Iterator<Item=Result<Item, InterpreterError>>> PlayerServer<I
pub fn unblocking_timer_loop(ctrl_tx: Sender<ControlAction>, sleep_ms: u64) { pub fn unblocking_timer_loop(ctrl_tx: Sender<ControlAction>, sleep_ms: u64) {
let dur = std::time::Duration::from_millis(sleep_ms); let dur = std::time::Duration::from_millis(sleep_ms);
loop { loop {
if let Err(_) = ctrl_tx.send(ControlAction::NoOp { ack: false }) { if ctrl_tx.send(ControlAction::NoOp { ack: false }).is_err() {
break; break;
} }
thread::sleep(dur); thread::sleep(dur);

View file

@ -15,9 +15,9 @@ impl<'a> Uri<&'a str> {
match self.0.find("//") { match self.0.find("//") {
Some(end) => { Some(end) => {
// proper URI // 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() 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() self.0.get(end+2..frag_start).unwrap()
} else { } else {
self.0.get(end+2..).unwrap() self.0.get(end+2..).unwrap()

View file

@ -80,7 +80,7 @@ fn main() {
} }
// build playback controller // build playback controller
let script_file2 = script_file.clone(); 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() { let mpd = match args.mpd.clone().map(|a| muss_player::mpd_connection(a.parse().unwrap())).transpose() {
Ok(mpd) => mpd, Ok(mpd) => mpd,
Err(e) => panic!("Abort: Cannot connect to MPD: {}", e), Err(e) => panic!("Abort: Cannot connect to MPD: {}", e),

View file

@ -1,4 +1,5 @@
//! Read, Execute, Print Loop functionality //! Read, Execute, Print Loop functionality
#![allow(clippy::single_match)]
use std::sync::{RwLock}; use std::sync::{RwLock};
use std::sync::mpsc::{self, Receiver}; use std::sync::mpsc::{self, Receiver};
use std::io::{self, Write}; 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<T: muss_interpreter::tokens::TokenReader>(_interpreter: &mut Interpreter<'_, T>, event: InterpreterEvent) -> Result<(), InterpreterError> {
match event { match event {
InterpreterEvent::StatementComplete => { InterpreterEvent::StatementComplete => {
if let Ok(mut d_state) = DEBUG_STATE.write() { if let Ok(mut d_state) = DEBUG_STATE.write() {
@ -165,7 +166,7 @@ pub fn repl(args: CliArgs) {
let term = Term::stdout(); let term = Term::stdout();
term.set_title("muss"); term.set_title("muss");
let (writer, reader) = channel_io(); 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() { let mpd = match args.mpd.clone().map(|a| muss_player::mpd_connection(a.parse().unwrap())).transpose() {
Ok(mpd) => mpd, Ok(mpd) => mpd,
Err(e) => { Err(e) => {
@ -187,7 +188,7 @@ pub fn repl(args: CliArgs) {
match flag { match flag {
DebugFlag::Normal => item, DebugFlag::Normal => item,
DebugFlag::Skip => { DebugFlag::Skip => {
while let Some(_) = interpretor.next() { for _ in interpretor.by_ref() {
// NOTE: recursion occurs here // NOTE: recursion occurs here
} }
None None
@ -195,7 +196,7 @@ pub fn repl(args: CliArgs) {
DebugFlag::List => { DebugFlag::List => {
if let Some(x) = item { if let Some(x) = item {
list_tx.send(x.map_err(|e| e.to_string())).unwrap_or(()); 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 // NOTE: recursion occurs here
// in most cases this will never be a case of Some(...) because // in most cases this will never be a case of Some(...) because
// recursive calls to this function intercept it first and return None // 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) { match player.save_m3u8(&mut playlist_writer) {
Ok(_) => {} Ok(_) => {}
Err(e) => { Err(e) => {
error_prompt(e, &args); error_prompt(e, args);
// consume any further errors (this shouldn't actually write anything) // consume any further errors (this shouldn't actually write anything)
while let Err(e) = player.save_m3u8(&mut playlist_writer) { 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 { if args.wait {
match ctrl.wait_for_empty() { match ctrl.wait_for_empty() {
Ok(_) => {} Ok(_) => {}
Err(e) => error_prompt(e, &args), Err(e) => error_prompt(e, args),
} }
} else { } else {
// consume all incoming errors // consume all incoming errors
@ -274,7 +275,7 @@ pub fn repl(args: CliArgs) {
while had_err { while had_err {
let mut new_had_err = false; let mut new_had_err = false;
for e in ctrl.check_ack() { for e in ctrl.check_ack() {
error_prompt(e, &args); error_prompt(e, args);
new_had_err = true; new_had_err = true;
} }
had_err = new_had_err; had_err = new_had_err;
@ -354,7 +355,7 @@ fn read_loop<F: FnMut(&mut ReplState, &CliArgs)>(args: &CliArgs, state: &mut Rep
if !statement_result.starts_with('?') { if !statement_result.starts_with('?') {
state state
.writer .writer
.write(state.statement_buf.iter().collect::<String>().as_bytes()) .write_all(state.statement_buf.iter().collect::<String>().as_bytes())
.expect(INTERPRETER_WRITE_ERROR); .expect(INTERPRETER_WRITE_ERROR);
execute(state, args); execute(state, args);
state.statement_buf.clear(); state.statement_buf.clear();
@ -427,57 +428,55 @@ fn read_loop<F: FnMut(&mut ReplState, &CliArgs)>(args: &CliArgs, state: &mut Rep
} }
} }
} }
} else { } else if state.current_line.len() != state.cursor_rightward_position {
if state.current_line.len() != state.cursor_rightward_position { // if not at start of line
// if not at start of line let removed_char = state
let removed_char = state .current_line
.current_line .remove(state.current_line.len() - state.cursor_rightward_position - 1);
.remove(state.current_line.len() - state.cursor_rightward_position - 1); state.statement_buf.remove(
state.statement_buf.remove( state.statement_buf.len() - state.cursor_rightward_position - 1,
state.statement_buf.len() - state.cursor_rightward_position - 1, );
); // re-sync unclosed syntax tracking
// re-sync unclosed syntax tracking match removed_char {
match removed_char { '"' | '`' => {
'"' | '`' => { if let Some(c2) = state.in_literal {
if let Some(c2) = state.in_literal { if removed_char == c2 {
if removed_char == c2 { state.in_literal = None;
state.in_literal = None;
}
} else {
state.in_literal = Some(removed_char);
} }
} 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 if state.bracket_depth != 0 {
.terminal state.bracket_depth -= 1
.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.bracket_depth += 1,
state '{' => {
.terminal if state.curly_depth != 0 {
.move_cursor_left(state.cursor_rightward_position + 1) 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); .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 => { Key::Del => {
@ -547,7 +546,7 @@ fn read_loop<F: FnMut(&mut ReplState, &CliArgs)>(args: &CliArgs, state: &mut Rep
let complete_statement = state.statement_buf.iter().collect::<String>(); let complete_statement = state.statement_buf.iter().collect::<String>();
state state
.writer .writer
.write(complete_statement.as_bytes()) .write_all(complete_statement.as_bytes())
.expect("Failed to write to MPS interpreter"); .expect("Failed to write to MPS interpreter");
execute(state, args); execute(state, args);
state.statement_buf.clear(); state.statement_buf.clear();
@ -575,23 +574,27 @@ fn read_loop<F: FnMut(&mut ReplState, &CliArgs)>(args: &CliArgs, state: &mut Rep
} }
} }
Key::ArrowDown => { Key::ArrowDown => {
if state.selected_history > 1 { match state.selected_history {
state.selected_history -= 1; 1 => {
display_history_line(state, args); state.selected_history = 0;
} else if state.selected_history == 1 { state.line_number -= 1;
state.selected_history = 0; state
state.line_number -= 1; .terminal
state .clear_line()
.terminal .expect(TERMINAL_WRITE_ERROR);
.clear_line() prompt(state, args);
.expect(TERMINAL_WRITE_ERROR); // clear stale input buffer
prompt(state, args); state.statement_buf.clear();
// clear stale input buffer state.current_line.clear();
state.statement_buf.clear(); state.in_literal = None;
state.current_line.clear(); state.bracket_depth = 0;
state.in_literal = None; state.curly_depth = 0;
state.bracket_depth = 0; },
state.curly_depth = 0; 0 => {},
_ => {
state.selected_history -= 1;
display_history_line(state, args);
},
} }
} }
Key::ArrowLeft => { 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(); let new_statement = state.history[state.history.len() - state.selected_history].trim();
state state
.terminal .terminal
.write(new_statement.as_bytes()) .write_all(new_statement.as_bytes())
.expect(TERMINAL_WRITE_ERROR); .expect(TERMINAL_WRITE_ERROR);
// clear stale input buffer // clear stale input buffer
state.statement_buf.clear(); state.statement_buf.clear();