Skip to content

Commit

Permalink
feat: add array_slice op (#1313)
Browse files Browse the repository at this point in the history
* add array_slice op

* update slice func and call

* update slice func

* update test

* whitespace

* Remove clones, refactor error messages a little

* ci: Sanitize rust-peer image name (#1314)

* Update Rust crate uuid to v1 (#1308)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>

* update tests

* update tests

* merge

* rename op array_slice => array slice; "array length" as alias to op.array_length

* typo

* better errors

Co-authored-by: folex <[email protected]>
Co-authored-by: Anatoly Laskaris <[email protected]>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
  • Loading branch information
4 people authored Nov 1, 2022
1 parent 34b2788 commit 5df4fc8
Show file tree
Hide file tree
Showing 6 changed files with 177 additions and 8 deletions.
4 changes: 2 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,7 @@ exclude = [
[workspace.dependencies]
fluence-app-service = "0.22.2"
avm-server = "0.26.1"
#air-interpreter-wasm = "=0.30.11"
air-interpreter-wasm = { version = "=0.31.4"}
air-interpreter-wasm = { version = "=0.31.10"}
libp2p = "0.48.0"
libp2p-core = { version = "0.36.0", default-features = false, features = [ "secp256k1" ] }
libp2p-metrics = { version = "0.9.0", features = ["kad"] }
Expand All @@ -60,3 +59,4 @@ bs58 = "0.4.0"
fluence-keypair = "0.8.1"
parking_lot = "0.12.1"
async-std = { version = "1.12.0", features = ["unstable"] }
uuid = { version = "1.2.1", features = ["v4"] }
2 changes: 1 addition & 1 deletion crates/uuid-utils/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@ authors = ["Fluence Labs"]
edition = "2018"

[dependencies]
uuid = { version = "1.2.1", features = ["v4"] }
uuid = { workspace = true }
55 changes: 55 additions & 0 deletions particle-builtins/src/builtins.rs
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,8 @@ where
("array", "intersect") => binary(args, |xs: HashSet<String>, ys: HashSet<String>| -> R<Vec<String>, _> { math::intersect(xs, ys) }),
("array", "diff") => binary(args, |xs: HashSet<String>, ys: HashSet<String>| -> R<Vec<String>, _> { math::diff(xs, ys) }),
("array", "sdiff") => binary(args, |xs: HashSet<String>, ys: HashSet<String>| -> R<Vec<String>, _> { math::sdiff(xs, ys) }),
("array", "slice") => wrap(self.array_slice(args.function_args)),
("array", "length") => wrap(self.array_length(args.function_args)),

("sig", "sign") => wrap(self.sign(args)),
("sig", "verify") => wrap(self.verify(args)),
Expand Down Expand Up @@ -595,6 +597,59 @@ where
}
}

/// takes a range of values from an array
/// slice(array: []JValue, start: usize, end: usize) -> []JValue
fn array_slice(&self, args: Vec<serde_json::Value>) -> Result<JValue, JError> {
let (array, start, end) = if let [array, start, end] = &args[..] {
(array, start, end)
} else {
return Err(JError::new(format!(
"invalid number of parameters. need array, start index and end index"
)));
};

let array = match array {
JValue::Array(arr) if arr.is_empty() => return Ok(json!([])),
JValue::Array(arr) => arr,
e => {
return Err(JError::new(format!(
"first argument must be an array, was {}",
e
)));
}
};

let start = match start.as_u64() {
Some(n) => n as usize,
_ => {
return Err(JError::new(format!(
"second argument (start index) must be an unsigned integer, was {}",
start
)));
}
};

let end = match end.as_u64() {
Some(n) => n as usize,
_ => {
return Err(JError::new(format!(
"third argument (end index) must be an unsigned integer, was {}",
end
)));
}
};

if start > end || end > array.len() {
return Err(JError::new(format!(
"slice indexes out of bounds. start index: {:?}, end index: {:?}, array length: {:?}",
start, end, array.len())
));
}

let slice: Vec<JValue> = array[start..end].to_vec();
Ok(JValue::Array(slice))
}

fn add_module(&self, args: Args) -> Result<JValue, JError> {
let mut args = args.function_args.into_iter();
let module_bytes: String = Args::next("module_bytes", &mut args)?;
Expand Down
118 changes: 116 additions & 2 deletions particle-node/tests/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -778,8 +778,6 @@ fn array_length() {
)
.unwrap();

//

assert_eq!(result, vec![
json!(0),
json!(5),
Expand All @@ -789,6 +787,122 @@ fn array_length() {
])
}

#[test]
fn array_slice() {
let result = exec_script(
r#"(call relay ("array" "slice") [ data sidx eidx ] result)"#,
hashmap! {
"data" => json!(vec![1,2,3,4]),
"sidx" => json!(0),
"eidx" => json!(2),
},
"result",
1,
)
.unwrap();

let expected = vec![json!(vec![1, 2])];
assert_eq!(result, expected);

let result = exec_script(
r#"(call relay ("array" "slice") [ empty_data sidx eidx ] result)"#,
hashmap! {
"empty_data" => json!(Vec::<JValue>::new()),
"sidx" => json!(0),
"eidx" => json!(2),
},
"result",
1,
)
.unwrap();
assert_eq!(result[0], json!(Vec::<JValue>::new()));

let result = exec_script(
r#"(call relay ("array" "slice") [ data sidx eidx ] result)"#,
hashmap! {
"data" => json!(1),
"sidx" => json!(0),
"eidx" => json!(2),
},
"result",
1,
);
assert!(result.is_err());
assert!(
format!("{:?}", result).contains("first argument must be an array, was 1"),
"{:?}",
result
);

let result = exec_script(
r#"(call relay ("array" "slice") [ eidx sidx ] result)"#,
hashmap! {
"data" => json!(vec![1,2,3,4]),
"sidx" => json!(0),
"eidx" => json!(2),
},
"result",
1,
);
assert!(result.is_err());
assert!(format!("{:?}", result)
.contains("invalid number of parameters. need array, start index and end index"));

let result = exec_script(
r#"(call relay ("array" "slice") [ data eidx sidx ] result)"#,
hashmap! {
"data" => json!(vec![1,2,3,4]),
"sidx" => json!(0),
"eidx" => json!(2),
},
"result",
1,
);
assert!(result.is_err());
assert!(
format!("{:?}", result)
.contains("slice indexes out of bounds. start index: 2, end index: 0, array length: 4"),
"result is {:?}",
result
);

let result = exec_script(
r#"(call relay ("array" "slice") [ data bad_idx eidx ] result)"#,
hashmap! {
"data" => json!(vec![1,2,3,4]),
"bad_idx" => json!(-1),
"eidx" => json!(2),
},
"result",
1,
);
assert!(result.is_err());
assert!(
format!("{:?}", result)
.contains("second argument (start index) must be an unsigned integer, was -1"),
"{:?}",
result
);

let result = exec_script(
r#"(call relay ("array" "slice") [ data sidx bad_idx] result)"#,
hashmap! {
"data" => json!(vec![1,2,3,4]),
"bad_idx" => json!(-1),
"sidx" => json!(2),
},
"result",
1,
);
assert!(result.is_err());
assert!(
format!("{:?}", result)
.contains("third argument (end index) must be an unsigned integer, was -1"),
"{:?}",
result
);
}

#[test]
fn timeout_race() {
let fast_result = exec_script(
Expand Down
2 changes: 1 addition & 1 deletion particle-services/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ parking_lot = { workspace = true }
serde_json = "1.0.86"
serde = "1.0.145"
log = "0.4.17"
uuid = { version = "1.2.1", features = ["v4"] }
uuid = { workspace = true }
toml = "0.5.9"
thiserror = "1.0.37"
derivative = "2.2.0"
Expand Down

0 comments on commit 5df4fc8

Please sign in to comment.