mirror of
https://github.com/fluencelabs/aquavm
synced 2024-12-04 15:20:16 +00:00
fix match behaviour (#61)
This commit is contained in:
parent
7cc248439e
commit
611bee0836
93
Cargo.lock
generated
93
Cargo.lock
generated
@ -230,9 +230,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bumpalo"
|
name = "bumpalo"
|
||||||
version = "3.4.0"
|
version = "3.5.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2e8c087f005730276d1096a652e92a8bacee2e2472bcc9715a74d2bec38b5820"
|
checksum = "f07aa6688c702439a1be0307b6a94dffe1168569e45b9500c1372bc580740d59"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "byte-tools"
|
name = "byte-tools"
|
||||||
@ -392,16 +392,16 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "criterion"
|
name = "criterion"
|
||||||
version = "0.3.3"
|
version = "0.3.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "70daa7ceec6cf143990669a04c7df13391d55fb27bd4079d252fca774ba244d8"
|
checksum = "ab327ed7354547cc2ef43cbe20ef68b988e70b4b593cbd66a2a61733123a3d23"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"atty",
|
"atty",
|
||||||
"cast",
|
"cast",
|
||||||
"clap",
|
"clap",
|
||||||
"criterion-plot",
|
"criterion-plot",
|
||||||
"csv",
|
"csv",
|
||||||
"itertools",
|
"itertools 0.10.0",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
"num-traits",
|
"num-traits",
|
||||||
"oorandom",
|
"oorandom",
|
||||||
@ -423,7 +423,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "e022feadec601fba1649cfa83586381a4ad31c6bf3a9ab7d408118b05dd9889d"
|
checksum = "e022feadec601fba1649cfa83586381a4ad31c6bf3a9ab7d408118b05dd9889d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cast",
|
"cast",
|
||||||
"itertools",
|
"itertools 0.9.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -718,9 +718,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "fluence-app-service"
|
name = "fluence-app-service"
|
||||||
version = "0.1.29"
|
version = "0.1.30"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7efb3d5f011df7b7f84fd80ef116885392ad27f32f934829389bd94945a42085"
|
checksum = "2fb49d32cad551606cc6ef324b93b0079e7f7f8a54be15176a314098028195cb"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"fluence-faas",
|
"fluence-faas",
|
||||||
"log",
|
"log",
|
||||||
@ -742,7 +742,7 @@ dependencies = [
|
|||||||
"fce",
|
"fce",
|
||||||
"fce-utils",
|
"fce-utils",
|
||||||
"fluence-sdk-main",
|
"fluence-sdk-main",
|
||||||
"itertools",
|
"itertools 0.9.0",
|
||||||
"log",
|
"log",
|
||||||
"safe-transmute",
|
"safe-transmute",
|
||||||
"serde",
|
"serde",
|
||||||
@ -871,9 +871,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "getrandom"
|
name = "getrandom"
|
||||||
version = "0.2.1"
|
version = "0.2.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4060f4657be78b8e766215b02b18a2e862d83745545de804638e2b545e81aee6"
|
checksum = "c9495705279e7140bf035dde1f6e750c162df8b625267cd52cc44e0b156732c8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if 1.0.0",
|
"cfg-if 1.0.0",
|
||||||
"libc",
|
"libc",
|
||||||
@ -903,9 +903,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "half"
|
name = "half"
|
||||||
version = "1.6.0"
|
version = "1.7.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d36fab90f82edc3c747f9d438e06cf0a491055896f2a279638bb5beed6c40177"
|
checksum = "62aca2aba2d62b4a7f5b33f3712cb1b0692779a56fb510499d5c0aa594daeaf3"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hashbrown"
|
name = "hashbrown"
|
||||||
@ -924,9 +924,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hermit-abi"
|
name = "hermit-abi"
|
||||||
version = "0.1.17"
|
version = "0.1.18"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5aca5565f760fb5b220e499d72710ed156fdb74e631659e99377d9ebfbd13ae8"
|
checksum = "322f4de77956e22ed0e5032c359a0f1273f1f7f0d79bfa3b8ffbc730d7fbcc5c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
@ -1009,6 +1009,15 @@ dependencies = [
|
|||||||
"either",
|
"either",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "itertools"
|
||||||
|
version = "0.10.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "37d572918e350e82412fe766d24b15e6682fb2ed2bbe018280caa810397cb319"
|
||||||
|
dependencies = [
|
||||||
|
"either",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "itoa"
|
name = "itoa"
|
||||||
version = "0.4.7"
|
version = "0.4.7"
|
||||||
@ -1048,7 +1057,7 @@ dependencies = [
|
|||||||
"diff",
|
"diff",
|
||||||
"docopt",
|
"docopt",
|
||||||
"ena",
|
"ena",
|
||||||
"itertools",
|
"itertools 0.9.0",
|
||||||
"lalrpop-util",
|
"lalrpop-util",
|
||||||
"petgraph",
|
"petgraph",
|
||||||
"regex",
|
"regex",
|
||||||
@ -1096,9 +1105,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libc"
|
name = "libc"
|
||||||
version = "0.2.82"
|
version = "0.2.83"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "89203f3fba0a3795506acaad8ebce3c80c0af93f994d5a1d7a0b1eeb23271929"
|
checksum = "7eb0c4e9c72ee9d69b767adebc5f4788462a3b45624acd919475c92597bcaf4f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lock_api"
|
name = "lock_api"
|
||||||
@ -1120,11 +1129,11 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "log"
|
name = "log"
|
||||||
version = "0.4.13"
|
version = "0.4.14"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "fcf3805d4480bb5b86070dcfeb9e2cb2ebc148adb753c5cca5f884d1d65a42b2"
|
checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if 0.1.10",
|
"cfg-if 1.0.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -1335,16 +1344,32 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "plotters"
|
name = "plotters"
|
||||||
version = "0.2.15"
|
version = "0.3.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0d1685fbe7beba33de0330629da9d955ac75bd54f33d7b79f9a895590124f6bb"
|
checksum = "45ca0ae5f169d0917a7c7f5a9c1a3d3d9598f18f529dd2b8373ed988efea307a"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"js-sys",
|
|
||||||
"num-traits",
|
"num-traits",
|
||||||
|
"plotters-backend",
|
||||||
|
"plotters-svg",
|
||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
"web-sys",
|
"web-sys",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "plotters-backend"
|
||||||
|
version = "0.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b07fffcddc1cb3a1de753caa4e4df03b79922ba43cf882acc1bdd7e8df9f4590"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "plotters-svg"
|
||||||
|
version = "0.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b38a02e23bd9604b842a812063aec4ef702b57989c37b655254bb61c471ad211"
|
||||||
|
dependencies = [
|
||||||
|
"plotters-backend",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "polyplets"
|
name = "polyplets"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
@ -1718,9 +1743,9 @@ checksum = "1e81da0851ada1f3e9d4312c704aa4f8806f0f9d69faaf8df2f3464b4a9437c2"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "1.0.58"
|
version = "1.0.60"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "cc60a3d73ea6594cd712d830cc1f0390fd71542d8c8cd24e70cc54cdfd5e05d5"
|
checksum = "c700597eca8a5a762beb35753ef6b94df201c81cca676604f547495a0d7f0081"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@ -1784,11 +1809,11 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "thread_local"
|
name = "thread_local"
|
||||||
version = "1.1.0"
|
version = "1.1.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "bb9bc092d0d51e76b2b19d9d85534ffc9ec2db959a2523cdae0697e2972cd447"
|
checksum = "d8208a331e1cb318dd5bd76951d2b8fc48ca38a69f5f4e4af1b6a9f8c6236915"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"lazy_static",
|
"once_cell",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -1828,9 +1853,9 @@ checksum = "373c8a200f9e67a0c95e62a4f52fbf80c23b4381c05a17845531982fa99e6b33"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "typetag"
|
name = "typetag"
|
||||||
version = "0.1.6"
|
version = "0.1.7"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "83b97b107d25d29de6879ac4f676ac5bfea92bdd01f206e995794493f1fc2e32"
|
checksum = "422619e1a7299befb977a1f6d8932c499f6151dbcafae715193570860cae8f07"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"erased-serde",
|
"erased-serde",
|
||||||
"inventory",
|
"inventory",
|
||||||
@ -1841,9 +1866,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "typetag-impl"
|
name = "typetag-impl"
|
||||||
version = "0.1.6"
|
version = "0.1.7"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3f2466fc87b07b800a5060f89ba579d6882f7a03ac21363e4737764aaf9f99f9"
|
checksum = "504f9626fe6cc1c376227864781996668e15c1ff251d222f63ef17f310bf1fec"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@ -1874,7 +1899,7 @@ version = "0.8.2"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7"
|
checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"getrandom 0.2.1",
|
"getrandom 0.2.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "stepper-lib"
|
name = "stepper-lib"
|
||||||
version = "0.4.0"
|
version = "0.4.1"
|
||||||
authors = ["Fluence Labs"]
|
authors = ["Fluence Labs"]
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
|
@ -39,16 +39,19 @@ impl<'i> super::ExecutableInstruction<'i> for Match<'i> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
use crate::execution::utils::resolve_to_jvaluable;
|
||||||
|
use crate::JValue;
|
||||||
|
|
||||||
fn compare_matchable<'ctx>(
|
fn compare_matchable<'ctx>(
|
||||||
left: &MatchableValue<'_>,
|
left: &MatchableValue<'_>,
|
||||||
right: &MatchableValue<'_>,
|
right: &MatchableValue<'_>,
|
||||||
exec_ctx: &'ctx ExecutionCtx<'_>,
|
exec_ctx: &'ctx ExecutionCtx<'_>,
|
||||||
) -> ExecutionResult<bool> {
|
) -> ExecutionResult<bool> {
|
||||||
use crate::execution::utils::resolve_to_jvaluable;
|
|
||||||
use MatchableValue::*;
|
use MatchableValue::*;
|
||||||
|
|
||||||
match (left, right) {
|
match (left, right) {
|
||||||
(Literal(left_name), Literal(right_name)) => Ok(left_name == right_name),
|
(Literal(name), matchable) => compare_matchable_and_literal(matchable, name, exec_ctx),
|
||||||
|
(matchable, Literal(name)) => compare_matchable_and_literal(matchable, name, exec_ctx),
|
||||||
(Variable(left_name), Variable(right_name)) => {
|
(Variable(left_name), Variable(right_name)) => {
|
||||||
let left_jvaluable = resolve_to_jvaluable(left_name, exec_ctx)?;
|
let left_jvaluable = resolve_to_jvaluable(left_name, exec_ctx)?;
|
||||||
let left_value = left_jvaluable.as_jvalue();
|
let left_value = left_jvaluable.as_jvalue();
|
||||||
@ -71,6 +74,42 @@ fn compare_matchable<'ctx>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn compare_matchable_and_literal<'ctx>(
|
||||||
|
matchable: &MatchableValue<'_>,
|
||||||
|
string_literal: &str,
|
||||||
|
exec_ctx: &'ctx ExecutionCtx<'_>,
|
||||||
|
) -> ExecutionResult<bool> {
|
||||||
|
use std::borrow::Cow;
|
||||||
|
use MatchableValue::*;
|
||||||
|
|
||||||
|
fn compare_jvalue_and_literal(jvalue: Cow<'_, JValue>, string_literal: &str) -> bool {
|
||||||
|
use std::ops::Deref;
|
||||||
|
|
||||||
|
match jvalue.deref() {
|
||||||
|
JValue::String(value) => value == string_literal,
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
match matchable {
|
||||||
|
Literal(name) => Ok(name == &string_literal),
|
||||||
|
Variable(name) => {
|
||||||
|
let jvaluable = resolve_to_jvaluable(name, exec_ctx)?;
|
||||||
|
let jvalue = jvaluable.as_jvalue();
|
||||||
|
Ok(compare_jvalue_and_literal(jvalue, string_literal))
|
||||||
|
}
|
||||||
|
JsonPath { variable, path } => {
|
||||||
|
let jvaluable = resolve_to_jvaluable(variable, exec_ctx)?;
|
||||||
|
let jvalues = jvaluable.apply_json_path(path)?;
|
||||||
|
if jvalues.len() != 1 {
|
||||||
|
return Ok(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(compare_jvalue_and_literal(Cow::Borrowed(jvalues[0]), string_literal))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::contexts::execution_trace::ExecutionTrace;
|
use crate::contexts::execution_trace::ExecutionTrace;
|
||||||
@ -158,6 +197,41 @@ mod tests {
|
|||||||
assert_eq!(actual_trace[2], expected_executed_call_result);
|
assert_eq!(actual_trace[2], expected_executed_call_result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn match_with_string() {
|
||||||
|
use crate::contexts::execution_trace::CallResult::*;
|
||||||
|
use crate::contexts::execution_trace::ExecutedState::*;
|
||||||
|
|
||||||
|
let set_variable_peer_id = "set_variable_peer_id";
|
||||||
|
let mut set_variable_vm = create_aqua_vm(echo_string_call_service(), set_variable_peer_id);
|
||||||
|
|
||||||
|
let local_peer_id = "local_peer_id";
|
||||||
|
let mut vm = create_aqua_vm(echo_string_call_service(), local_peer_id);
|
||||||
|
|
||||||
|
let script = format!(
|
||||||
|
r#"
|
||||||
|
(seq
|
||||||
|
(call "{0}" ("" "") ["value_1"] value_1)
|
||||||
|
(xor
|
||||||
|
(match value_1 "value_1"
|
||||||
|
(call "{1}" ("service_id_2" "local_fn_name") ["result_1"] result_1)
|
||||||
|
)
|
||||||
|
(call "{1}" ("service_id_2" "local_fn_name") ["result_2"] result_2)
|
||||||
|
)
|
||||||
|
)"#,
|
||||||
|
set_variable_peer_id, local_peer_id
|
||||||
|
);
|
||||||
|
|
||||||
|
let res = call_vm!(set_variable_vm, "asd", script.clone(), "", "");
|
||||||
|
let res = call_vm!(vm, "asd", script, "", res.data);
|
||||||
|
|
||||||
|
let actual_trace: ExecutionTrace = serde_json::from_slice(&res.data).expect("should be valid json");
|
||||||
|
let expected_executed_call_result = Call(Executed(Rc::new(JValue::String(String::from("result_1")))));
|
||||||
|
|
||||||
|
assert_eq!(actual_trace.len(), 2);
|
||||||
|
assert_eq!(actual_trace[1], expected_executed_call_result);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn match_without_xor() {
|
fn match_without_xor() {
|
||||||
let set_variable_peer_id = "set_variable_peer_id";
|
let set_variable_peer_id = "set_variable_peer_id";
|
||||||
|
@ -11,7 +11,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "air-parser"
|
name = "air-parser"
|
||||||
version = "0.2.0"
|
version = "0.3.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"codespan",
|
"codespan",
|
||||||
"codespan-reporting",
|
"codespan-reporting",
|
||||||
@ -672,7 +672,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "stepper-lib"
|
name = "stepper-lib"
|
||||||
version = "0.3.0"
|
version = "0.4.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"air-parser",
|
"air-parser",
|
||||||
"boolinator",
|
"boolinator",
|
||||||
|
@ -11,7 +11,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "air-parser"
|
name = "air-parser"
|
||||||
version = "0.2.0"
|
version = "0.3.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"codespan",
|
"codespan",
|
||||||
"codespan-reporting",
|
"codespan-reporting",
|
||||||
@ -672,7 +672,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "stepper-lib"
|
name = "stepper-lib"
|
||||||
version = "0.3.0"
|
version = "0.4.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"air-parser",
|
"air-parser",
|
||||||
"boolinator",
|
"boolinator",
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "aquamarine"
|
name = "aquamarine"
|
||||||
version = "0.3.0"
|
version = "0.4.1"
|
||||||
authors = ["Fluence Labs"]
|
authors = ["Fluence Labs"]
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user