Enforce thread safety to allow for multithread interpreter
This commit is contained in:
parent
8910d9df18
commit
13ac120ebc
688
Cargo.lock
generated
688
Cargo.lock
generated
File diff suppressed because it is too large
Load diff
125
interpreter/fuzz/Cargo.lock
generated
125
interpreter/fuzz/Cargo.lock
generated
|
@ -8,17 +8,6 @@ version = "1.0.2"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
|
||||
|
||||
[[package]]
|
||||
name = "ahash"
|
||||
version = "0.7.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47"
|
||||
dependencies = [
|
||||
"getrandom",
|
||||
"once_cell",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "aho-corasick"
|
||||
version = "0.7.18"
|
||||
|
@ -57,6 +46,12 @@ version = "1.1.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
|
||||
|
||||
[[package]]
|
||||
name = "base64"
|
||||
version = "0.13.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "1.3.2"
|
||||
|
@ -345,18 +340,6 @@ version = "0.1.2"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed"
|
||||
|
||||
[[package]]
|
||||
name = "fallible-iterator"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7"
|
||||
|
||||
[[package]]
|
||||
name = "fallible-streaming-iterator"
|
||||
version = "0.1.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a"
|
||||
|
||||
[[package]]
|
||||
name = "flate2"
|
||||
version = "1.0.24"
|
||||
|
@ -397,30 +380,12 @@ dependencies = [
|
|||
"wasi 0.11.0+wasi-snapshot-preview1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.11.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e"
|
||||
dependencies = [
|
||||
"ahash",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.12.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "db0d4cf898abf0081f964436dc980e96670a0f36863e4b83aaacdb65c9d7ccc3"
|
||||
|
||||
[[package]]
|
||||
name = "hashlink"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7249a3129cbc1ffccd74857f81464a323a152173cdb134e0fd81bc803b29facf"
|
||||
dependencies = [
|
||||
"hashbrown 0.11.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "heck"
|
||||
version = "0.3.3"
|
||||
|
@ -452,7 +417,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "10a35a97730320ffe8e2d410b5d3b69279b98d2c14bdb8b70ea89ecf7888d41e"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"hashbrown 0.12.1",
|
||||
"hashbrown",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -496,17 +461,6 @@ dependencies = [
|
|||
"once_cell",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libsqlite3-sys"
|
||||
version = "0.23.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d2cafc7c74096c336d9d27145f7ebd4f4b6f95ba16aa5a282387267e6925cb58"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"pkg-config",
|
||||
"vcpkg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.17"
|
||||
|
@ -516,6 +470,15 @@ dependencies = [
|
|||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "m3u8-rs"
|
||||
version = "3.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "50fe05791a7f418b59d6cddebdc293d77c9c1f652adbff855c071d4507cd883b"
|
||||
dependencies = [
|
||||
"nom",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "maplit"
|
||||
version = "1.0.2"
|
||||
|
@ -546,6 +509,12 @@ dependencies = [
|
|||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "minimal-lexical"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
|
||||
|
||||
[[package]]
|
||||
name = "miniz_oxide"
|
||||
version = "0.5.3"
|
||||
|
@ -570,13 +539,15 @@ dependencies = [
|
|||
name = "muss-interpreter"
|
||||
version = "0.9.0"
|
||||
dependencies = [
|
||||
"base64",
|
||||
"bliss-audio-symphonia",
|
||||
"dirs",
|
||||
"m3u8-rs",
|
||||
"mpd",
|
||||
"rand",
|
||||
"regex",
|
||||
"rusqlite",
|
||||
"shellexpand",
|
||||
"sqlparser",
|
||||
"symphonia",
|
||||
"unidecode",
|
||||
]
|
||||
|
@ -641,6 +612,16 @@ dependencies = [
|
|||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nom"
|
||||
version = "7.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a8903e5a29a317527874d0402f867152a3d21c908bb0b933e416c65e301d4c36"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
"minimal-lexical",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-bigint"
|
||||
version = "0.4.3"
|
||||
|
@ -760,12 +741,6 @@ dependencies = [
|
|||
"sha-1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pkg-config"
|
||||
version = "0.3.25"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1df8c4ec4b0627e53bdf214615ad287367e482558cf84b109250b37464dc03ae"
|
||||
|
||||
[[package]]
|
||||
name = "ppv-lite86"
|
||||
version = "0.2.16"
|
||||
|
@ -926,21 +901,6 @@ dependencies = [
|
|||
"opaque-debug 0.3.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rusqlite"
|
||||
version = "0.26.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4ba4d3462c8b2e4d7f4fcfcf2b296dc6b65404fbbc7b63daa37fd485c149daf7"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"fallible-iterator",
|
||||
"fallible-streaming-iterator",
|
||||
"hashlink",
|
||||
"libsqlite3-sys",
|
||||
"memchr",
|
||||
"smallvec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc-serialize"
|
||||
version = "0.3.24"
|
||||
|
@ -989,10 +949,13 @@ dependencies = [
|
|||
]
|
||||
|
||||
[[package]]
|
||||
name = "smallvec"
|
||||
version = "1.8.1"
|
||||
name = "sqlparser"
|
||||
version = "0.23.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cc88c725d61fc6c3132893370cac4a0200e3fedf5da8331c570664b1987f5ca2"
|
||||
checksum = "0beb13adabbdda01b63d595f38c8bfd19a361e697fd94ce0098a634077bc5b25"
|
||||
dependencies = [
|
||||
"log",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "strength_reduce"
|
||||
|
@ -1281,12 +1244,6 @@ version = "0.3.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "402bb19d8e03f1d1a7450e2bd613980869438e0666331be3e073089124aa1adc"
|
||||
|
||||
[[package]]
|
||||
name = "vcpkg"
|
||||
version = "0.2.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
|
||||
|
||||
[[package]]
|
||||
name = "version_check"
|
||||
version = "0.9.4"
|
||||
|
|
|
@ -16,7 +16,7 @@ use crate::Item;
|
|||
|
||||
const INNER_VARIABLE_NAME: &str = "[inner variable]";
|
||||
|
||||
pub trait FilterPredicate: Clone + Debug + Display {
|
||||
pub trait FilterPredicate: Clone + Debug + Display + Send {
|
||||
fn matches(&mut self, item: &Item, ctx: &mut Context) -> Result<bool, RuntimeMsg>;
|
||||
|
||||
fn is_complete(&self) -> bool;
|
||||
|
@ -24,7 +24,7 @@ pub trait FilterPredicate: Clone + Debug + Display {
|
|||
fn reset(&mut self) -> Result<(), RuntimeMsg>;
|
||||
}
|
||||
|
||||
pub trait FilterFactory<P: FilterPredicate + 'static> {
|
||||
pub trait FilterFactory<P: FilterPredicate + 'static>: Send + Sync {
|
||||
fn is_filter(&self, tokens: &VecDeque<&Token>) -> bool;
|
||||
|
||||
fn build_filter(
|
||||
|
|
|
@ -8,7 +8,7 @@ use crate::lang::SyntaxError;
|
|||
use crate::lang::{BoxedOpFactory, Op};
|
||||
use crate::tokens::Token;
|
||||
|
||||
pub trait FunctionFactory<O: Op + 'static> {
|
||||
pub trait FunctionFactory<O: Op + 'static>: Send + Sync {
|
||||
fn is_function(&self, name: &str) -> bool;
|
||||
|
||||
fn build_function_params(
|
||||
|
|
|
@ -8,11 +8,11 @@ use crate::Item;
|
|||
|
||||
pub struct GeneratorOp {
|
||||
context: Option<Context>,
|
||||
generator: Box<dyn FnMut(&mut Context) -> Option<Result<Item, RuntimeMsg>>>,
|
||||
generator: Box<dyn (FnMut(&mut Context) -> Option<Result<Item, RuntimeMsg>>) + Send>,
|
||||
}
|
||||
|
||||
impl GeneratorOp {
|
||||
pub fn new<F: FnMut(&mut Context) -> Option<Result<Item, RuntimeMsg>> + 'static>(generator_fn: F) -> Self {
|
||||
pub fn new<F: (FnMut(&mut Context) -> Option<Result<Item, RuntimeMsg>>) + Send + 'static>(generator_fn: F) -> Self {
|
||||
Self {
|
||||
context: None,
|
||||
generator: Box::new(generator_fn),
|
||||
|
|
|
@ -17,11 +17,11 @@ use crate::Context;
|
|||
|
||||
const ITEM_VARIABLE_NAME: &str = "item";
|
||||
|
||||
pub trait ItemOp: Debug + Display {
|
||||
pub trait ItemOp: Debug + Display + Send + Sync {
|
||||
fn execute(&self, context: &mut Context) -> Result<Type, RuntimeMsg>;
|
||||
}
|
||||
|
||||
pub trait ItemOpFactory<T: Deref<Target = dyn ItemOp> + 'static> {
|
||||
pub trait ItemOpFactory<T: Deref<Target = dyn ItemOp> + 'static>: Send + Sync {
|
||||
fn is_item_op(&self, tokens: &VecDeque<Token>) -> bool;
|
||||
|
||||
fn build_item_op(
|
||||
|
|
|
@ -48,7 +48,7 @@ pub trait OpFactory<T: Op + 'static> {
|
|||
}
|
||||
}
|
||||
|
||||
pub trait BoxedOpFactory {
|
||||
pub trait BoxedOpFactory: Send {
|
||||
fn build_op_boxed(
|
||||
&self,
|
||||
tokens: &mut VecDeque<Token>,
|
||||
|
@ -60,7 +60,7 @@ pub trait BoxedOpFactory {
|
|||
|
||||
pub type IteratorItem = Result<Item, RuntimeError>;
|
||||
|
||||
pub trait Op: Iterator<Item = IteratorItem> + Debug + Display {
|
||||
pub trait Op: Iterator<Item = IteratorItem> + Debug + Display + Send {
|
||||
fn enter(&mut self, ctx: Context);
|
||||
|
||||
fn escape(&mut self) -> Context;
|
||||
|
|
|
@ -12,7 +12,7 @@ use crate::Context;
|
|||
|
||||
const SORTER_ITEM_CACHE_SIZE: usize = 8;
|
||||
|
||||
pub trait Sorter: Clone + Debug + Display {
|
||||
pub trait Sorter: Clone + Debug + Display + Send + Sync {
|
||||
fn sort(
|
||||
&mut self,
|
||||
iterator: &mut dyn Op,
|
||||
|
@ -22,7 +22,7 @@ pub trait Sorter: Clone + Debug + Display {
|
|||
fn reset(&mut self) {}
|
||||
}
|
||||
|
||||
pub trait SorterFactory<S: Sorter + 'static> {
|
||||
pub trait SorterFactory<S: Sorter + 'static>: Send + Sync {
|
||||
fn is_sorter(&self, tokens: &VecDeque<&Token>) -> bool;
|
||||
|
||||
fn build_sorter(
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
use core::ops::Deref;
|
||||
use std::collections::VecDeque;
|
||||
use std::fmt::{Debug, Display, Error, Formatter};
|
||||
use std::sync::Mutex;
|
||||
|
||||
use crate::lang::utility::{assert_name, check_name};
|
||||
use crate::lang::LanguageDictionary;
|
||||
|
@ -12,7 +13,7 @@ use crate::Context;
|
|||
|
||||
#[derive(Debug)]
|
||||
pub struct IterItemOp {
|
||||
inner: Box<dyn Op>,
|
||||
inner: Mutex<Box<dyn Op>>,
|
||||
}
|
||||
|
||||
impl Deref for IterItemOp {
|
||||
|
@ -24,13 +25,19 @@ impl Deref for IterItemOp {
|
|||
|
||||
impl Display for IterItemOp {
|
||||
fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
|
||||
write!(f, "iter {}", self.inner)
|
||||
match self.inner.lock() {
|
||||
Ok(inner) => write!(f, "iter {}", inner),
|
||||
Err(e) => write!(f, "iter !?!? (e:{})", e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ItemOp for IterItemOp {
|
||||
fn execute(&self, _context: &mut Context) -> Result<Type, RuntimeMsg> {
|
||||
Ok(Type::Op(self.inner.dup()))
|
||||
match self.inner.lock() {
|
||||
Ok(inner) => Ok(Type::Op(inner.dup())),
|
||||
Err(e) => Err(RuntimeMsg(format!("IterItemOp lock failed: {}", e)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -49,6 +56,6 @@ impl ItemOpFactory<IterItemOp> for IterItemOpFactory {
|
|||
) -> Result<IterItemOp, SyntaxError> {
|
||||
assert_name("iter", tokens)?;
|
||||
let inner_op = dict.try_build_statement(tokens)?;
|
||||
Ok(IterItemOp { inner: inner_op })
|
||||
Ok(IterItemOp { inner: Mutex::new(inner_op) })
|
||||
}
|
||||
}
|
||||
|
|
|
@ -329,7 +329,7 @@ impl Iterator for FileIter {
|
|||
}
|
||||
}
|
||||
|
||||
pub trait FilesystemQuerier: Debug {
|
||||
pub trait FilesystemQuerier: Debug + Send {
|
||||
fn raw(
|
||||
&mut self,
|
||||
folder: Option<&str>,
|
||||
|
@ -369,7 +369,7 @@ pub struct FilesystemExecutor {}
|
|||
|
||||
impl FilesystemExecutor {
|
||||
#[cfg(feature = "collections")]
|
||||
fn read_m3u8<P: AsRef<Path> + 'static>(&self, path: P) -> Result<GeneratorOp, RuntimeMsg> {
|
||||
fn read_m3u8<P: AsRef<Path> + Send + 'static>(&self, path: P) -> Result<GeneratorOp, RuntimeMsg> {
|
||||
let mut file = std::fs::File::open(&path).map_err(|e| RuntimeMsg(format!("Path read error: {}", e)))?;
|
||||
let mut file_bytes = Vec::new();
|
||||
file.read_to_end(&mut file_bytes).map_err(|e| RuntimeMsg(format!("File read error: {}", e)))?;
|
||||
|
|
|
@ -11,7 +11,7 @@ use crate::lang::TypePrimitive;
|
|||
use crate::Item;
|
||||
|
||||
/// Music Player Daemon interface for interacting with it's database
|
||||
pub trait MpdQuerier: Debug {
|
||||
pub trait MpdQuerier: Debug + Send {
|
||||
fn connect(&mut self, addr: SocketAddr) -> Result<(), RuntimeMsg>;
|
||||
|
||||
fn search(&mut self, params: Vec<(&str, String)>) -> Result<VecDeque<Item>, RuntimeMsg>;
|
||||
|
|
|
@ -23,7 +23,7 @@ use crate::Item;
|
|||
|
||||
const PATH_FIELD: &str = "filename";
|
||||
|
||||
pub trait MusicAnalyzer: Debug {
|
||||
pub trait MusicAnalyzer: Debug + Send {
|
||||
fn prepare_distance(&mut self, from: &Item, to: &Item) -> Result<(), RuntimeMsg>;
|
||||
|
||||
fn prepare_item(&mut self, item: &Item) -> Result<(), RuntimeMsg>;
|
||||
|
|
|
@ -18,7 +18,7 @@ use crate::Item;
|
|||
pub type QueryResult = Result<Box<dyn Op>, RuntimeMsg>;
|
||||
|
||||
/// SQL querying functionality, loosely de-coupled from any specific SQL dialect (excluding raw call)
|
||||
pub trait DatabaseQuerier: Debug {
|
||||
pub trait DatabaseQuerier: Debug + Send {
|
||||
/// raw SQL call, assumed (but not guaranteed) to retrieved music items
|
||||
fn raw(&mut self, query: &str) -> QueryResult;
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@ impl Type {
|
|||
}
|
||||
}
|
||||
|
||||
pub trait VariableStorer: Debug {
|
||||
pub trait VariableStorer: Debug + Send {
|
||||
fn get(&self, name: &str) -> Result<&'_ Type, RuntimeMsg> {
|
||||
match self.get_opt(name) {
|
||||
Some(item) => Ok(item),
|
||||
|
|
26
src/repl.rs
26
src/repl.rs
|
@ -113,13 +113,25 @@ fn pretty_print_item(item: &Item, terminal: &mut Term, args: &CliArgs, verbose:
|
|||
fields.sort();
|
||||
for field in fields {
|
||||
if field != "title" {
|
||||
writeln!(
|
||||
terminal,
|
||||
" {}: `{}`",
|
||||
field,
|
||||
item.field(field).unwrap_or(&TypePrimitive::Empty).as_str()
|
||||
)
|
||||
.expect(TERMINAL_WRITE_ERROR);
|
||||
let field_str = item.field(field).unwrap_or(&TypePrimitive::Empty).as_str();
|
||||
let max_len = terminal.size().1 as usize - (args.prompt.len() + field.len() + 8);
|
||||
if field_str.len() >= max_len {
|
||||
writeln!(
|
||||
terminal,
|
||||
" {}: `{}[...]`",
|
||||
field,
|
||||
&field_str[..max_len-5]
|
||||
)
|
||||
.expect(TERMINAL_WRITE_ERROR);
|
||||
} else {
|
||||
writeln!(
|
||||
terminal,
|
||||
" {}: `{}`",
|
||||
field,
|
||||
field_str
|
||||
)
|
||||
.expect(TERMINAL_WRITE_ERROR);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
|
Loading…
Reference in a new issue