mirror of
https://github.com/fluencelabs/marine.git
synced 2025-03-15 14:00:50 +00:00
decouple json serde into separate crate, add module and function names to args serde errors
This commit is contained in:
parent
bbd006ed3c
commit
9219339b82
14
Cargo.lock
generated
14
Cargo.lock
generated
@ -832,6 +832,7 @@ dependencies = [
|
|||||||
"bytesize",
|
"bytesize",
|
||||||
"cmd_lib",
|
"cmd_lib",
|
||||||
"env_logger 0.7.1",
|
"env_logger 0.7.1",
|
||||||
|
"it-json-serde",
|
||||||
"itertools 0.9.0",
|
"itertools 0.9.0",
|
||||||
"log",
|
"log",
|
||||||
"marine-module-interface 0.2.0",
|
"marine-module-interface 0.2.0",
|
||||||
@ -1335,6 +1336,18 @@ version = "2.3.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "68f2d64f2edebec4ce84ad108148e67e1064789bee435edc5b60ad398714a3a9"
|
checksum = "68f2d64f2edebec4ce84ad108148e67e1064789bee435edc5b60ad398714a3a9"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "it-json-serde"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"serde",
|
||||||
|
"serde_derive",
|
||||||
|
"serde_json",
|
||||||
|
"serde_with",
|
||||||
|
"thiserror",
|
||||||
|
"wasmer-interface-types-fl 0.21.1",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "it-lilo"
|
name = "it-lilo"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
@ -1871,6 +1884,7 @@ dependencies = [
|
|||||||
"bytesize",
|
"bytesize",
|
||||||
"console_error_panic_hook",
|
"console_error_panic_hook",
|
||||||
"fluence-it-types",
|
"fluence-it-types",
|
||||||
|
"it-json-serde",
|
||||||
"it-lilo 0.2.0",
|
"it-lilo 0.2.0",
|
||||||
"it-memory-traits",
|
"it-memory-traits",
|
||||||
"itertools 0.10.3",
|
"itertools 0.10.3",
|
||||||
|
@ -3,6 +3,7 @@ members = [
|
|||||||
"crates/it-generator",
|
"crates/it-generator",
|
||||||
"crates/it-interfaces",
|
"crates/it-interfaces",
|
||||||
"crates/it-parser",
|
"crates/it-parser",
|
||||||
|
"crates/it-json-serde",
|
||||||
"crates/min-it-version",
|
"crates/min-it-version",
|
||||||
"crates/module-info-parser",
|
"crates/module-info-parser",
|
||||||
"crates/module-interface",
|
"crates/module-interface",
|
||||||
|
20
crates/it-json-serde/Cargo.toml
Normal file
20
crates/it-json-serde/Cargo.toml
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
[package]
|
||||||
|
name = "it-json-serde"
|
||||||
|
description = "Fluence Marine interface-types serde tools"
|
||||||
|
version = "0.1.0"
|
||||||
|
authors = ["Fluence Labs"]
|
||||||
|
license = "Apache-2.0"
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
name = "it_json_serde"
|
||||||
|
path = "src/lib.rs"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
wasmer-it = { package = "wasmer-interface-types-fl", version = "0.21.1" }
|
||||||
|
|
||||||
|
serde = { version = "1.0.118", features = ["derive"] }
|
||||||
|
serde_json = "1.0.53"
|
||||||
|
serde_derive = "1.0.118"
|
||||||
|
serde_with = "1.11.0"
|
||||||
|
thiserror = "1.0.23"
|
@ -14,8 +14,13 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
mod ivalues_to_json;
|
use thiserror::Error;
|
||||||
mod json_to_ivalues;
|
|
||||||
|
|
||||||
pub(crate) use ivalues_to_json::ivalues_to_json;
|
#[derive(Debug, Error)]
|
||||||
pub(crate) use json_to_ivalues::json_to_ivalues;
|
pub enum ItJsonSerdeError {
|
||||||
|
#[error("cannot serialize IValues to Json: {0}")]
|
||||||
|
SerializationError(String),
|
||||||
|
|
||||||
|
#[error("cannot deserialize Json to IValues: {0}")]
|
||||||
|
DeserializationError(String),
|
||||||
|
}
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2020 Fluence Labs Limited
|
* Copyright 2022 Fluence Labs Limited
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -16,19 +16,19 @@
|
|||||||
|
|
||||||
use crate::IValue;
|
use crate::IValue;
|
||||||
use crate::IType;
|
use crate::IType;
|
||||||
use crate::FaaSResult;
|
use crate::ItJsonSerdeError::SerializationError;
|
||||||
use crate::errors::FaaSError::JsonOutputSerializationError as OutputDeError;
|
use crate::JsonResult;
|
||||||
|
|
||||||
use marine::MRecordTypes;
|
use crate::MRecordTypes;
|
||||||
use serde_json::Value as JValue;
|
use serde_json::Value as JValue;
|
||||||
|
|
||||||
pub(crate) fn ivalues_to_json(
|
pub fn ivalues_to_json(
|
||||||
mut ivalues: Vec<IValue>,
|
mut ivalues: Vec<IValue>,
|
||||||
outputs: &[IType],
|
outputs: &[IType],
|
||||||
record_types: &MRecordTypes,
|
record_types: &MRecordTypes,
|
||||||
) -> FaaSResult<JValue> {
|
) -> JsonResult<JValue> {
|
||||||
if outputs.len() != ivalues.len() {
|
if outputs.len() != ivalues.len() {
|
||||||
return Err(OutputDeError(format!(
|
return Err(SerializationError(format!(
|
||||||
"resulted values {:?} and function signature {:?} aren't compatible",
|
"resulted values {:?} and function signature {:?} aren't compatible",
|
||||||
ivalues, outputs
|
ivalues, outputs
|
||||||
)));
|
)));
|
||||||
@ -46,7 +46,7 @@ fn ivalue_to_json(
|
|||||||
ivalue: IValue,
|
ivalue: IValue,
|
||||||
output: &IType,
|
output: &IType,
|
||||||
record_types: &MRecordTypes,
|
record_types: &MRecordTypes,
|
||||||
) -> FaaSResult<JValue> {
|
) -> JsonResult<JValue> {
|
||||||
use serde_json::json;
|
use serde_json::json;
|
||||||
|
|
||||||
// clone here needed because binding by-value and by-ref in the same pattern in unstable
|
// clone here needed because binding by-value and by-ref in the same pattern in unstable
|
||||||
@ -70,7 +70,7 @@ fn ivalue_to_json(
|
|||||||
Ok(JValue::Array(result))
|
Ok(JValue::Array(result))
|
||||||
}
|
}
|
||||||
(IValue::Array(value), IType::ByteArray) => {
|
(IValue::Array(value), IType::ByteArray) => {
|
||||||
let result: FaaSResult<Vec<_>> = value
|
let result: JsonResult<Vec<_>> = value
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|v| ivalue_to_json(v, &IType::U8, record_types))
|
.map(|v| ivalue_to_json(v, &IType::U8, record_types))
|
||||||
.collect();
|
.collect();
|
||||||
@ -78,7 +78,7 @@ fn ivalue_to_json(
|
|||||||
Ok(JValue::Array(result?))
|
Ok(JValue::Array(result?))
|
||||||
}
|
}
|
||||||
(IValue::ByteArray(value), IType::Array(array_ty)) => {
|
(IValue::ByteArray(value), IType::Array(array_ty)) => {
|
||||||
let result: FaaSResult<Vec<_>> = value
|
let result: JsonResult<Vec<_>> = value
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|v| ivalue_to_json(IValue::U8(v), &array_ty, record_types))
|
.map(|v| ivalue_to_json(IValue::U8(v), &array_ty, record_types))
|
||||||
.collect();
|
.collect();
|
||||||
@ -86,7 +86,7 @@ fn ivalue_to_json(
|
|||||||
Ok(JValue::Array(result?))
|
Ok(JValue::Array(result?))
|
||||||
}
|
}
|
||||||
(IValue::Array(value), IType::Array(array_ty)) => {
|
(IValue::Array(value), IType::Array(array_ty)) => {
|
||||||
let result: FaaSResult<Vec<_>> = value
|
let result: JsonResult<Vec<_>> = value
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|v| ivalue_to_json(v, &array_ty, record_types))
|
.map(|v| ivalue_to_json(v, &array_ty, record_types))
|
||||||
.collect();
|
.collect();
|
||||||
@ -95,7 +95,7 @@ fn ivalue_to_json(
|
|||||||
}
|
}
|
||||||
(IValue::Record(field_values), IType::Record(record_id)) => {
|
(IValue::Record(field_values), IType::Record(record_id)) => {
|
||||||
let record_type = record_types.get(&record_id).ok_or_else(|| {
|
let record_type = record_types.get(&record_id).ok_or_else(|| {
|
||||||
OutputDeError(format!(
|
SerializationError(format!(
|
||||||
"record id {} wasn't found in module record types",
|
"record id {} wasn't found in module record types",
|
||||||
record_id
|
record_id
|
||||||
))
|
))
|
||||||
@ -103,7 +103,7 @@ fn ivalue_to_json(
|
|||||||
let field_types = &record_type.fields;
|
let field_types = &record_type.fields;
|
||||||
|
|
||||||
if field_values.len() != field_types.len() {
|
if field_values.len() != field_types.len() {
|
||||||
return Err(OutputDeError(format!(
|
return Err(SerializationError(format!(
|
||||||
"output record {:?} isn't compatible to output record fields {:?}",
|
"output record {:?} isn't compatible to output record fields {:?}",
|
||||||
field_values, field_types
|
field_values, field_types
|
||||||
)));
|
)));
|
||||||
@ -119,7 +119,7 @@ fn ivalue_to_json(
|
|||||||
|
|
||||||
Ok(JValue::Object(result))
|
Ok(JValue::Object(result))
|
||||||
}
|
}
|
||||||
(ivalue, itype) => Err(OutputDeError(format!(
|
(ivalue, itype) => Err(SerializationError(format!(
|
||||||
"value {:?} is incompatible to type {:?}",
|
"value {:?} is incompatible to type {:?}",
|
||||||
ivalue, itype
|
ivalue, itype
|
||||||
))),
|
))),
|
@ -16,22 +16,22 @@
|
|||||||
|
|
||||||
use crate::IValue;
|
use crate::IValue;
|
||||||
use crate::IType;
|
use crate::IType;
|
||||||
use crate::faas::Result;
|
use super::ItJsonSerdeError::DeserializationError;
|
||||||
use crate::faas::FaaSError::JsonArgumentsDeserializationError as ArgDeError;
|
use super::JsonResult;
|
||||||
use crate::MRecordTypes;
|
|
||||||
|
|
||||||
|
use crate::MRecordTypes;
|
||||||
|
use serde_json::Value as JValue;
|
||||||
use wasmer_it::NEVec;
|
use wasmer_it::NEVec;
|
||||||
|
|
||||||
use serde_json::Value as JValue;
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::iter::ExactSizeIterator;
|
use std::iter::ExactSizeIterator;
|
||||||
|
|
||||||
/// Convert json to an array of ivalues according to the supplied argument types.
|
/// Convert json to an array of ivalues according to the supplied argument types.
|
||||||
pub(crate) fn json_to_ivalues<'a, 'b>(
|
pub fn json_to_ivalues<'a, 'b>(
|
||||||
json_args: JValue,
|
json_args: JValue,
|
||||||
arg_types: impl Iterator<Item = (&'a String, &'a IType)> + ExactSizeIterator,
|
arg_types: impl Iterator<Item = (&'a String, &'a IType)> + ExactSizeIterator,
|
||||||
record_types: &'b MRecordTypes,
|
record_types: &'b MRecordTypes,
|
||||||
) -> Result<Vec<IValue>> {
|
) -> JsonResult<Vec<IValue>> {
|
||||||
let ivalues = match json_args {
|
let ivalues = match json_args {
|
||||||
JValue::Object(json_map) => json_map_to_ivalues(json_map, arg_types, record_types)?,
|
JValue::Object(json_map) => json_map_to_ivalues(json_map, arg_types, record_types)?,
|
||||||
JValue::Array(json_array) => {
|
JValue::Array(json_array) => {
|
||||||
@ -49,19 +49,19 @@ fn json_map_to_ivalues<'a, 'b>(
|
|||||||
mut json_map: serde_json::Map<String, JValue>,
|
mut json_map: serde_json::Map<String, JValue>,
|
||||||
arg_types: impl Iterator<Item = (&'a String, &'a IType)>,
|
arg_types: impl Iterator<Item = (&'a String, &'a IType)>,
|
||||||
record_types: &'b MRecordTypes,
|
record_types: &'b MRecordTypes,
|
||||||
) -> Result<Vec<IValue>> {
|
) -> JsonResult<Vec<IValue>> {
|
||||||
let mut iargs = Vec::new();
|
let mut iargs = Vec::new();
|
||||||
|
|
||||||
for (arg_name, arg_type) in arg_types {
|
for (arg_name, arg_type) in arg_types {
|
||||||
let json_value = json_map
|
let json_value = json_map.remove(arg_name).ok_or_else(|| {
|
||||||
.remove(arg_name)
|
DeserializationError(format!("missing argument with name {}", arg_name))
|
||||||
.ok_or_else(|| ArgDeError(format!("missing argument with name {}", arg_name)))?;
|
})?;
|
||||||
let iarg = jvalue_to_ivalue(json_value, arg_type, record_types)?;
|
let iarg = jvalue_to_ivalue(json_value, arg_type, record_types)?;
|
||||||
iargs.push(iarg);
|
iargs.push(iarg);
|
||||||
}
|
}
|
||||||
|
|
||||||
if !json_map.is_empty() {
|
if !json_map.is_empty() {
|
||||||
return Err(ArgDeError(format!(
|
return Err(DeserializationError(format!(
|
||||||
"function requires {} arguments, {} provided",
|
"function requires {} arguments, {} provided",
|
||||||
iargs.len(),
|
iargs.len(),
|
||||||
iargs.len() + json_map.len()
|
iargs.len() + json_map.len()
|
||||||
@ -76,9 +76,9 @@ fn json_array_to_ivalues<'a, 'b>(
|
|||||||
json_array: Vec<JValue>,
|
json_array: Vec<JValue>,
|
||||||
arg_types: impl Iterator<Item = &'a IType> + ExactSizeIterator,
|
arg_types: impl Iterator<Item = &'a IType> + ExactSizeIterator,
|
||||||
record_types: &'b MRecordTypes,
|
record_types: &'b MRecordTypes,
|
||||||
) -> Result<Vec<IValue>> {
|
) -> JsonResult<Vec<IValue>> {
|
||||||
if json_array.len() != arg_types.len() {
|
if json_array.len() != arg_types.len() {
|
||||||
return Err(ArgDeError(format!(
|
return Err(DeserializationError(format!(
|
||||||
"function requires {} arguments, {} provided",
|
"function requires {} arguments, {} provided",
|
||||||
arg_types.len(),
|
arg_types.len(),
|
||||||
json_array.len()
|
json_array.len()
|
||||||
@ -89,7 +89,7 @@ fn json_array_to_ivalues<'a, 'b>(
|
|||||||
.into_iter()
|
.into_iter()
|
||||||
.zip(arg_types)
|
.zip(arg_types)
|
||||||
.map(|(json_value, arg_type)| jvalue_to_ivalue(json_value, arg_type, record_types))
|
.map(|(json_value, arg_type)| jvalue_to_ivalue(json_value, arg_type, record_types))
|
||||||
.collect::<Result<Vec<_>>>()?;
|
.collect::<JsonResult<Vec<_>>>()?;
|
||||||
|
|
||||||
Ok(iargs)
|
Ok(iargs)
|
||||||
}
|
}
|
||||||
@ -98,9 +98,9 @@ fn json_array_to_ivalues<'a, 'b>(
|
|||||||
fn json_value_to_ivalues<'a>(
|
fn json_value_to_ivalues<'a>(
|
||||||
json_value: JValue,
|
json_value: JValue,
|
||||||
mut arg_types: impl Iterator<Item = (&'a String, &'a IType)> + ExactSizeIterator,
|
mut arg_types: impl Iterator<Item = (&'a String, &'a IType)> + ExactSizeIterator,
|
||||||
) -> Result<Vec<IValue>> {
|
) -> JsonResult<Vec<IValue>> {
|
||||||
if arg_types.len() != 1 {
|
if arg_types.len() != 1 {
|
||||||
return Err(ArgDeError(format!(
|
return Err(DeserializationError(format!(
|
||||||
"called function has the following signature: '{:?}', and it isn't suitable for an argument '{:?}' provided",
|
"called function has the following signature: '{:?}', and it isn't suitable for an argument '{:?}' provided",
|
||||||
arg_types.collect::<Vec<_>>(),
|
arg_types.collect::<Vec<_>>(),
|
||||||
json_value,
|
json_value,
|
||||||
@ -117,9 +117,9 @@ fn json_value_to_ivalues<'a>(
|
|||||||
/// Convert json Null to an empty array of ivalues.
|
/// Convert json Null to an empty array of ivalues.
|
||||||
fn json_null_to_ivalues<'a>(
|
fn json_null_to_ivalues<'a>(
|
||||||
arg_types: impl Iterator<Item = (&'a String, &'a IType)> + ExactSizeIterator,
|
arg_types: impl Iterator<Item = (&'a String, &'a IType)> + ExactSizeIterator,
|
||||||
) -> Result<Vec<IValue>> {
|
) -> JsonResult<Vec<IValue>> {
|
||||||
if arg_types.len() != 0 {
|
if arg_types.len() != 0 {
|
||||||
return Err(ArgDeError(format!(
|
return Err(DeserializationError(format!(
|
||||||
"the called function has the following signature: {:?}, but no arguments is provided",
|
"the called function has the following signature: {:?}, but no arguments is provided",
|
||||||
arg_types.collect::<Vec<_>>()
|
arg_types.collect::<Vec<_>>()
|
||||||
)));
|
)));
|
||||||
@ -129,7 +129,7 @@ fn json_null_to_ivalues<'a>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Convert one JValue to an array of ivalues according to the supplied argument type.
|
/// Convert one JValue to an array of ivalues according to the supplied argument type.
|
||||||
fn jvalue_to_ivalue(jvalue: JValue, ty: &IType, record_types: &MRecordTypes) -> Result<IValue> {
|
fn jvalue_to_ivalue(jvalue: JValue, ty: &IType, record_types: &MRecordTypes) -> JsonResult<IValue> {
|
||||||
macro_rules! to_ivalue(
|
macro_rules! to_ivalue(
|
||||||
($json_value:expr, $ty:ident) => {
|
($json_value:expr, $ty:ident) => {
|
||||||
{
|
{
|
||||||
@ -142,7 +142,7 @@ fn jvalue_to_ivalue(jvalue: JValue, ty: &IType, record_types: &MRecordTypes) ->
|
|||||||
},
|
},
|
||||||
jvalue => serde_json::from_value(jvalue),
|
jvalue => serde_json::from_value(jvalue),
|
||||||
}.map_err(|e|
|
}.map_err(|e|
|
||||||
ArgDeError(format!("error {:?} occurred while deserialize output result to a json value",e))
|
DeserializationError(format!("error {:?} occurred while deserialize output result to a json value",e))
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
Ok(IValue::$ty(value))
|
Ok(IValue::$ty(value))
|
||||||
@ -169,11 +169,14 @@ fn jvalue_to_ivalue(jvalue: JValue, ty: &IType, record_types: &MRecordTypes) ->
|
|||||||
let iargs = json_array
|
let iargs = json_array
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|json_value| jvalue_to_ivalue(json_value, &IType::U8, record_types))
|
.map(|json_value| jvalue_to_ivalue(json_value, &IType::U8, record_types))
|
||||||
.collect::<Result<Vec<_>>>()?;
|
.collect::<JsonResult<Vec<_>>>()?;
|
||||||
|
|
||||||
Ok(iargs)
|
Ok(iargs)
|
||||||
}
|
}
|
||||||
_ => Err(ArgDeError(format!("expected bytearray, got {:?}", jvalue))),
|
_ => Err(DeserializationError(format!(
|
||||||
|
"expected bytearray, got {:?}",
|
||||||
|
jvalue
|
||||||
|
))),
|
||||||
}?;
|
}?;
|
||||||
|
|
||||||
Ok(IValue::Array(value))
|
Ok(IValue::Array(value))
|
||||||
@ -184,11 +187,11 @@ fn jvalue_to_ivalue(jvalue: JValue, ty: &IType, record_types: &MRecordTypes) ->
|
|||||||
let iargs = json_array
|
let iargs = json_array
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|json_value| jvalue_to_ivalue(json_value, value_type, record_types))
|
.map(|json_value| jvalue_to_ivalue(json_value, value_type, record_types))
|
||||||
.collect::<Result<Vec<_>>>()?;
|
.collect::<JsonResult<Vec<_>>>()?;
|
||||||
|
|
||||||
Ok(iargs)
|
Ok(iargs)
|
||||||
}
|
}
|
||||||
_ => Err(ArgDeError(format!(
|
_ => Err(DeserializationError(format!(
|
||||||
"expected array of {:?} types, got {:?}",
|
"expected array of {:?} types, got {:?}",
|
||||||
value_type, jvalue
|
value_type, jvalue
|
||||||
))),
|
))),
|
||||||
@ -212,9 +215,9 @@ fn json_record_type_to_ivalue(
|
|||||||
json_value: JValue,
|
json_value: JValue,
|
||||||
record_type_id: &u64,
|
record_type_id: &u64,
|
||||||
record_types: &MRecordTypes,
|
record_types: &MRecordTypes,
|
||||||
) -> Result<NEVec<IValue>> {
|
) -> JsonResult<NEVec<IValue>> {
|
||||||
let record_type = record_types.get(record_type_id).ok_or_else(|| {
|
let record_type = record_types.get(record_type_id).ok_or_else(|| {
|
||||||
ArgDeError(format!(
|
DeserializationError(format!(
|
||||||
"record with type id `{}` wasn't found",
|
"record with type id `{}` wasn't found",
|
||||||
record_type_id
|
record_type_id
|
||||||
))
|
))
|
||||||
@ -236,7 +239,7 @@ fn json_record_type_to_ivalue(
|
|||||||
record_types,
|
record_types,
|
||||||
)?)
|
)?)
|
||||||
.unwrap()),
|
.unwrap()),
|
||||||
_ => Err(ArgDeError(format!(
|
_ => Err(DeserializationError(format!(
|
||||||
"record with type id `{}` should be encoded as array or map of fields",
|
"record with type id `{}` should be encoded as array or map of fields",
|
||||||
record_type_id
|
record_type_id
|
||||||
))),
|
))),
|
41
crates/it-json-serde/src/lib.rs
Normal file
41
crates/it-json-serde/src/lib.rs
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2022 Fluence Labs Limited
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
#![warn(rust_2018_idioms)]
|
||||||
|
#![deny(
|
||||||
|
dead_code,
|
||||||
|
nonstandard_style,
|
||||||
|
unused_imports,
|
||||||
|
unused_mut,
|
||||||
|
unused_variables,
|
||||||
|
unused_unsafe,
|
||||||
|
unreachable_patterns
|
||||||
|
)]
|
||||||
|
mod ivalues_to_json;
|
||||||
|
mod json_to_ivalues;
|
||||||
|
mod errors;
|
||||||
|
|
||||||
|
pub type JsonResult<T> = Result<T, ItJsonSerdeError>;
|
||||||
|
pub use errors::ItJsonSerdeError;
|
||||||
|
pub use ivalues_to_json::ivalues_to_json;
|
||||||
|
pub use json_to_ivalues::json_to_ivalues;
|
||||||
|
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
|
pub(crate) use wasmer_it::IValue;
|
||||||
|
pub(crate) use wasmer_it::IType;
|
||||||
|
pub(crate) use wasmer_it::IRecordType;
|
||||||
|
pub(crate) type MRecordTypes = HashMap<u64, Rc<IRecordType>>;
|
@ -12,6 +12,7 @@ marine-module-interface = { path = "../crates/module-interface", version = "0.2.
|
|||||||
marine-utils = { path = "../crates/utils", version = "0.4.0" }
|
marine-utils = { path = "../crates/utils", version = "0.4.0" }
|
||||||
marine-rs-sdk-main = { version = "0.6.15", features = ["logger"] }
|
marine-rs-sdk-main = { version = "0.6.15", features = ["logger"] }
|
||||||
marine-rs-sdk = { version = "0.6.15", features = ["logger"] }
|
marine-rs-sdk = { version = "0.6.15", features = ["logger"] }
|
||||||
|
it-json-serde = { path = "../crates/it-json-serde", version = "0.1.0" }
|
||||||
|
|
||||||
wasmer-runtime = { package = "wasmer-runtime-fl", version = "=0.17.1" }
|
wasmer-runtime = { package = "wasmer-runtime-fl", version = "=0.17.1" }
|
||||||
# dynamicfunc-fat-closures allows using state inside DynamicFunc
|
# dynamicfunc-fat-closures allows using state inside DynamicFunc
|
||||||
|
@ -54,12 +54,20 @@ pub enum FaaSError {
|
|||||||
NoSuchModule(String),
|
NoSuchModule(String),
|
||||||
|
|
||||||
/// Provided arguments aren't compatible with a called function signature.
|
/// Provided arguments aren't compatible with a called function signature.
|
||||||
#[error("arguments from json deserialization error: {0}")]
|
#[error("arguments from json deserialization error in module {module_name}, function {function_name}: {message}")]
|
||||||
JsonArgumentsDeserializationError(String),
|
JsonArgumentsDeserializationError {
|
||||||
|
module_name: String,
|
||||||
|
function_name: String,
|
||||||
|
message: String,
|
||||||
|
},
|
||||||
|
|
||||||
/// Returned outputs aren't compatible with a called function signature.
|
/// Returned outputs aren't compatible with a called function signature.
|
||||||
#[error("output to json serialization error: {0}")]
|
#[error("output to json serialization error in module {module_name}, function {function_name}: {message}")]
|
||||||
JsonOutputSerializationError(String),
|
JsonOutputSerializationError {
|
||||||
|
module_name: String,
|
||||||
|
function_name: String,
|
||||||
|
message: String,
|
||||||
|
},
|
||||||
|
|
||||||
/// Errors related to invalid config.
|
/// Errors related to invalid config.
|
||||||
#[error("parsing config error: {0}")]
|
#[error("parsing config error: {0}")]
|
||||||
@ -90,3 +98,25 @@ impl From<std::convert::Infallible> for FaaSError {
|
|||||||
unreachable!()
|
unreachable!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! json_to_faas_err {
|
||||||
|
($json_expr:expr, $module_name:expr, $function_name:expr) => {
|
||||||
|
$json_expr.map_err(|e| match e {
|
||||||
|
it_json_serde::ItJsonSerdeError::SerializationError(message) => {
|
||||||
|
FaaSError::JsonArgumentsDeserializationError {
|
||||||
|
module_name: $module_name,
|
||||||
|
function_name: $function_name,
|
||||||
|
message,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
it_json_serde::ItJsonSerdeError::DeserializationError(message) => {
|
||||||
|
FaaSError::JsonOutputSerializationError {
|
||||||
|
module_name: $module_name,
|
||||||
|
function_name: $function_name,
|
||||||
|
message,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
};
|
||||||
|
}
|
||||||
|
@ -25,6 +25,7 @@ use crate::module_loading::load_modules_from_fs;
|
|||||||
use crate::module_loading::ModulesLoadStrategy;
|
use crate::module_loading::ModulesLoadStrategy;
|
||||||
use crate::host_imports::logger::LoggerFilter;
|
use crate::host_imports::logger::LoggerFilter;
|
||||||
use crate::host_imports::logger::WASM_LOG_ENV_NAME;
|
use crate::host_imports::logger::WASM_LOG_ENV_NAME;
|
||||||
|
use crate::json_to_faas_err;
|
||||||
|
|
||||||
use marine::Marine;
|
use marine::Marine;
|
||||||
use marine::IFunctionArg;
|
use marine::IFunctionArg;
|
||||||
@ -158,24 +159,32 @@ impl FluenceFaaS {
|
|||||||
json_args: JValue,
|
json_args: JValue,
|
||||||
call_parameters: marine_rs_sdk::CallParameters,
|
call_parameters: marine_rs_sdk::CallParameters,
|
||||||
) -> FaaSResult<JValue> {
|
) -> FaaSResult<JValue> {
|
||||||
use crate::json::json_to_ivalues;
|
use it_json_serde::json_to_ivalues;
|
||||||
use crate::json::ivalues_to_json;
|
use it_json_serde::ivalues_to_json;
|
||||||
|
|
||||||
let module_name = module_name.as_ref();
|
let module_name = module_name.as_ref();
|
||||||
let func_name = func_name.as_ref();
|
let func_name = func_name.as_ref();
|
||||||
|
|
||||||
let (func_signature, output_types, record_types) =
|
let (func_signature, output_types, record_types) =
|
||||||
self.lookup_module_interface(module_name, func_name)?;
|
self.lookup_module_interface(module_name, func_name)?;
|
||||||
let iargs = json_to_ivalues(
|
let iargs = json_to_faas_err!(
|
||||||
|
json_to_ivalues(
|
||||||
json_args,
|
json_args,
|
||||||
func_signature.iter().map(|arg| (&arg.name, &arg.ty)),
|
func_signature.iter().map(|arg| (&arg.name, &arg.ty)),
|
||||||
&record_types,
|
&record_types,
|
||||||
|
),
|
||||||
|
module_name.to_string(),
|
||||||
|
func_name.to_string()
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
self.call_parameters.replace(call_parameters);
|
self.call_parameters.replace(call_parameters);
|
||||||
let result = self.marine.call(module_name, func_name, &iargs)?;
|
let result = self.marine.call(module_name, func_name, &iargs)?;
|
||||||
|
|
||||||
ivalues_to_json(result, &output_types, &record_types)
|
json_to_faas_err!(
|
||||||
|
ivalues_to_json(result, &output_types, &record_types),
|
||||||
|
module_name.to_string(),
|
||||||
|
func_name.to_string()
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return all export functions (name and signatures) of loaded modules.
|
/// Return all export functions (name and signatures) of loaded modules.
|
||||||
|
@ -1,244 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2020 Fluence Labs Limited
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
use crate::IValue;
|
|
||||||
use crate::IType;
|
|
||||||
use crate::FaaSResult;
|
|
||||||
use crate::FaaSError::JsonArgumentsDeserializationError as ArgDeError;
|
|
||||||
|
|
||||||
use marine::MRecordTypes;
|
|
||||||
use serde_json::Value as JValue;
|
|
||||||
use wasmer_it::NEVec;
|
|
||||||
|
|
||||||
use std::collections::HashMap;
|
|
||||||
use std::iter::ExactSizeIterator;
|
|
||||||
|
|
||||||
/// Convert json to an array of ivalues according to the supplied argument types.
|
|
||||||
pub(crate) fn json_to_ivalues<'a, 'b>(
|
|
||||||
json_args: JValue,
|
|
||||||
arg_types: impl Iterator<Item = (&'a String, &'a IType)> + ExactSizeIterator,
|
|
||||||
record_types: &'b MRecordTypes,
|
|
||||||
) -> FaaSResult<Vec<IValue>> {
|
|
||||||
let ivalues = match json_args {
|
|
||||||
JValue::Object(json_map) => json_map_to_ivalues(json_map, arg_types, record_types)?,
|
|
||||||
JValue::Array(json_array) => {
|
|
||||||
json_array_to_ivalues(json_array, arg_types.map(|arg| arg.1), record_types)?
|
|
||||||
}
|
|
||||||
JValue::Null => json_null_to_ivalues(arg_types)?,
|
|
||||||
json_value => json_value_to_ivalues(json_value, arg_types)?,
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(ivalues)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Convert json map to an array of ivalues according to the supplied argument types.
|
|
||||||
fn json_map_to_ivalues<'a, 'b>(
|
|
||||||
mut json_map: serde_json::Map<String, JValue>,
|
|
||||||
arg_types: impl Iterator<Item = (&'a String, &'a IType)>,
|
|
||||||
record_types: &'b MRecordTypes,
|
|
||||||
) -> FaaSResult<Vec<IValue>> {
|
|
||||||
let mut iargs = Vec::new();
|
|
||||||
|
|
||||||
for (arg_name, arg_type) in arg_types {
|
|
||||||
let json_value = json_map
|
|
||||||
.remove(arg_name)
|
|
||||||
.ok_or_else(|| ArgDeError(format!("missing argument with name {}", arg_name)))?;
|
|
||||||
let iarg = jvalue_to_ivalue(json_value, arg_type, record_types)?;
|
|
||||||
iargs.push(iarg);
|
|
||||||
}
|
|
||||||
|
|
||||||
if !json_map.is_empty() {
|
|
||||||
return Err(ArgDeError(format!(
|
|
||||||
"function requires {} arguments, {} provided",
|
|
||||||
iargs.len(),
|
|
||||||
iargs.len() + json_map.len()
|
|
||||||
)));
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(iargs)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Convert json array to an array of ivalues according to the supplied argument types.
|
|
||||||
fn json_array_to_ivalues<'a, 'b>(
|
|
||||||
json_array: Vec<JValue>,
|
|
||||||
arg_types: impl Iterator<Item = &'a IType> + ExactSizeIterator,
|
|
||||||
record_types: &'b MRecordTypes,
|
|
||||||
) -> FaaSResult<Vec<IValue>> {
|
|
||||||
if json_array.len() != arg_types.len() {
|
|
||||||
return Err(ArgDeError(format!(
|
|
||||||
"function requires {} arguments, {} provided",
|
|
||||||
arg_types.len(),
|
|
||||||
json_array.len()
|
|
||||||
)));
|
|
||||||
}
|
|
||||||
|
|
||||||
let iargs = json_array
|
|
||||||
.into_iter()
|
|
||||||
.zip(arg_types)
|
|
||||||
.map(|(json_value, arg_type)| jvalue_to_ivalue(json_value, arg_type, record_types))
|
|
||||||
.collect::<FaaSResult<Vec<_>>>()?;
|
|
||||||
|
|
||||||
Ok(iargs)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Convert json value (Number, String or Bool) to an array of ivalues according to the supplied argument types.
|
|
||||||
fn json_value_to_ivalues<'a>(
|
|
||||||
json_value: JValue,
|
|
||||||
mut arg_types: impl Iterator<Item = (&'a String, &'a IType)> + ExactSizeIterator,
|
|
||||||
) -> FaaSResult<Vec<IValue>> {
|
|
||||||
if arg_types.len() != 1 {
|
|
||||||
return Err(ArgDeError(format!(
|
|
||||||
"called function has the following signature: '{:?}', and it isn't suitable for an argument '{:?}' provided",
|
|
||||||
arg_types.collect::<Vec<_>>(),
|
|
||||||
json_value,
|
|
||||||
)));
|
|
||||||
}
|
|
||||||
|
|
||||||
// unwrap is safe here because iterator size's been checked
|
|
||||||
let arg_type = arg_types.next().unwrap().1;
|
|
||||||
let ivalue = jvalue_to_ivalue(json_value, arg_type, &HashMap::new())?;
|
|
||||||
|
|
||||||
Ok(vec![ivalue])
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Convert json Null to an empty array of ivalues.
|
|
||||||
fn json_null_to_ivalues<'a>(
|
|
||||||
arg_types: impl Iterator<Item = (&'a String, &'a IType)> + ExactSizeIterator,
|
|
||||||
) -> FaaSResult<Vec<IValue>> {
|
|
||||||
if arg_types.len() != 0 {
|
|
||||||
return Err(ArgDeError(format!(
|
|
||||||
"the called function has the following signature: {:?}, but no arguments is provided",
|
|
||||||
arg_types.collect::<Vec<_>>()
|
|
||||||
)));
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(vec![])
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Convert one JValue to an array of ivalues according to the supplied argument type.
|
|
||||||
fn jvalue_to_ivalue(jvalue: JValue, ty: &IType, record_types: &MRecordTypes) -> FaaSResult<IValue> {
|
|
||||||
macro_rules! to_ivalue(
|
|
||||||
($json_value:expr, $ty:ident) => {
|
|
||||||
{
|
|
||||||
let value = match $json_value {
|
|
||||||
// if there is an array with only one element try to implicitly flatten it,
|
|
||||||
// this is needed mostly because jsonpath lib returns Vec<&JValue> and
|
|
||||||
// could be changed in future
|
|
||||||
JValue::Array(mut json_array) if json_array.len() == 1 => {
|
|
||||||
serde_json::from_value(json_array.remove(0))
|
|
||||||
},
|
|
||||||
jvalue => serde_json::from_value(jvalue),
|
|
||||||
}.map_err(|e|
|
|
||||||
ArgDeError(format!("error {:?} occurred while deserialize output result to a json value",e))
|
|
||||||
)?;
|
|
||||||
|
|
||||||
Ok(IValue::$ty(value))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
match ty {
|
|
||||||
IType::Boolean => to_ivalue!(jvalue, Boolean),
|
|
||||||
IType::S8 => to_ivalue!(jvalue, S8),
|
|
||||||
IType::S16 => to_ivalue!(jvalue, S16),
|
|
||||||
IType::S32 => to_ivalue!(jvalue, S32),
|
|
||||||
IType::S64 => to_ivalue!(jvalue, S64),
|
|
||||||
IType::U8 => to_ivalue!(jvalue, U8),
|
|
||||||
IType::U16 => to_ivalue!(jvalue, U16),
|
|
||||||
IType::U32 => to_ivalue!(jvalue, U32),
|
|
||||||
IType::U64 => to_ivalue!(jvalue, U64),
|
|
||||||
IType::F32 => to_ivalue!(jvalue, F32),
|
|
||||||
IType::F64 => to_ivalue!(jvalue, F64),
|
|
||||||
IType::String => to_ivalue!(jvalue, String),
|
|
||||||
IType::ByteArray => {
|
|
||||||
let value = match jvalue {
|
|
||||||
JValue::Array(json_array) => {
|
|
||||||
let iargs = json_array
|
|
||||||
.into_iter()
|
|
||||||
.map(|json_value| jvalue_to_ivalue(json_value, &IType::U8, record_types))
|
|
||||||
.collect::<FaaSResult<Vec<_>>>()?;
|
|
||||||
|
|
||||||
Ok(iargs)
|
|
||||||
}
|
|
||||||
_ => Err(ArgDeError(format!("expected bytearray, got {:?}", jvalue))),
|
|
||||||
}?;
|
|
||||||
|
|
||||||
Ok(IValue::Array(value))
|
|
||||||
}
|
|
||||||
IType::Array(value_type) => {
|
|
||||||
let value = match jvalue {
|
|
||||||
JValue::Array(json_array) => {
|
|
||||||
let iargs = json_array
|
|
||||||
.into_iter()
|
|
||||||
.map(|json_value| jvalue_to_ivalue(json_value, value_type, record_types))
|
|
||||||
.collect::<FaaSResult<Vec<_>>>()?;
|
|
||||||
|
|
||||||
Ok(iargs)
|
|
||||||
}
|
|
||||||
_ => Err(ArgDeError(format!(
|
|
||||||
"expected array of {:?} types, got {:?}",
|
|
||||||
value_type, jvalue
|
|
||||||
))),
|
|
||||||
}?;
|
|
||||||
|
|
||||||
Ok(IValue::Array(value))
|
|
||||||
}
|
|
||||||
IType::I32 => to_ivalue!(jvalue, I32),
|
|
||||||
IType::I64 => to_ivalue!(jvalue, I64),
|
|
||||||
IType::Record(record_type_id) => {
|
|
||||||
let value = json_record_type_to_ivalue(jvalue, record_type_id, record_types)?;
|
|
||||||
Ok(IValue::Record(value))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(clippy::ptr_arg)]
|
|
||||||
/// Convert JValue of array or object types to an IValue record type.
|
|
||||||
// TODO: after introducing new Record type wrapper change the result type
|
|
||||||
fn json_record_type_to_ivalue(
|
|
||||||
json_value: JValue,
|
|
||||||
record_type_id: &u64,
|
|
||||||
record_types: &MRecordTypes,
|
|
||||||
) -> FaaSResult<NEVec<IValue>> {
|
|
||||||
let record_type = record_types.get(record_type_id).ok_or_else(|| {
|
|
||||||
ArgDeError(format!(
|
|
||||||
"record with type id `{}` wasn't found",
|
|
||||||
record_type_id
|
|
||||||
))
|
|
||||||
})?;
|
|
||||||
|
|
||||||
match json_value {
|
|
||||||
JValue::Object(json_map) => Ok(NEVec::new(json_map_to_ivalues(
|
|
||||||
json_map,
|
|
||||||
record_type
|
|
||||||
.fields
|
|
||||||
.iter()
|
|
||||||
.map(|field| (&field.name, &field.ty)),
|
|
||||||
record_types,
|
|
||||||
)?)
|
|
||||||
.unwrap()),
|
|
||||||
JValue::Array(json_array) => Ok(NEVec::new(json_array_to_ivalues(
|
|
||||||
json_array,
|
|
||||||
record_type.fields.iter().map(|field| (&field.ty)),
|
|
||||||
record_types,
|
|
||||||
)?)
|
|
||||||
.unwrap()),
|
|
||||||
_ => Err(ArgDeError(format!(
|
|
||||||
"record with type id `{}` should be encoded as array or map of fields",
|
|
||||||
record_type_id
|
|
||||||
))),
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,21 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2020 Fluence Labs Limited
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
mod ivalues_to_json;
|
|
||||||
mod json_to_ivalues;
|
|
||||||
|
|
||||||
pub(crate) use ivalues_to_json::ivalues_to_json;
|
|
||||||
pub(crate) use json_to_ivalues::json_to_ivalues;
|
|
@ -26,7 +26,6 @@
|
|||||||
|
|
||||||
mod config;
|
mod config;
|
||||||
mod host_imports;
|
mod host_imports;
|
||||||
mod json;
|
|
||||||
mod errors;
|
mod errors;
|
||||||
mod faas;
|
mod faas;
|
||||||
mod faas_interface;
|
mod faas_interface;
|
||||||
|
@ -20,6 +20,7 @@ wasmer-it = { package = "wasmer-interface-types-fl", version = "0.21.1" }
|
|||||||
fluence-it-types = {version = "0.3.1", features = ["impls"] }
|
fluence-it-types = {version = "0.3.1", features = ["impls"] }
|
||||||
it-lilo = "0.2.0"
|
it-lilo = "0.2.0"
|
||||||
it-memory-traits = "0.1.0"
|
it-memory-traits = "0.1.0"
|
||||||
|
it-json-serde = { path = "../crates/it-json-serde", version = "0.1.0" }
|
||||||
|
|
||||||
wasm-bindgen = "0.2"
|
wasm-bindgen = "0.2"
|
||||||
nom = "5.1"
|
nom = "5.1"
|
||||||
|
@ -34,12 +34,20 @@ pub enum FaaSError {
|
|||||||
NoSuchModule(String),
|
NoSuchModule(String),
|
||||||
|
|
||||||
/// Provided arguments aren't compatible with a called function signature.
|
/// Provided arguments aren't compatible with a called function signature.
|
||||||
#[error("arguments from json deserialization error: {0}")]
|
#[error("arguments from json deserialization error in module {module_name}, function {function_name}: {message}")]
|
||||||
JsonArgumentsDeserializationError(String),
|
JsonArgumentsDeserializationError {
|
||||||
|
module_name: String,
|
||||||
|
function_name: String,
|
||||||
|
message: String,
|
||||||
|
},
|
||||||
|
|
||||||
/// Returned outputs aren't compatible with a called function signature.
|
/// Returned outputs aren't compatible with a called function signature.
|
||||||
#[error("output to json serialization error: {0}")]
|
#[error("output to json serialization error in module {module_name}, function {function_name}: {message}")]
|
||||||
JsonOutputSerializationError(String),
|
JsonOutputSerializationError {
|
||||||
|
module_name: String,
|
||||||
|
function_name: String,
|
||||||
|
message: String,
|
||||||
|
},
|
||||||
|
|
||||||
/// Errors related to invalid config.
|
/// Errors related to invalid config.
|
||||||
#[error("parsing config error: {0}")]
|
#[error("parsing config error: {0}")]
|
||||||
@ -61,3 +69,25 @@ impl From<std::convert::Infallible> for FaaSError {
|
|||||||
unreachable!()
|
unreachable!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! json_to_faas_err {
|
||||||
|
($json_expr:expr, $module_name:expr, $function_name:expr) => {
|
||||||
|
$json_expr.map_err(|e| match e {
|
||||||
|
it_json_serde::ItJsonSerdeError::SerializationError(message) => {
|
||||||
|
FaaSError::JsonArgumentsDeserializationError {
|
||||||
|
module_name: $module_name,
|
||||||
|
function_name: $function_name,
|
||||||
|
message,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
it_json_serde::ItJsonSerdeError::DeserializationError(message) => {
|
||||||
|
FaaSError::JsonOutputSerializationError {
|
||||||
|
module_name: $module_name,
|
||||||
|
function_name: $function_name,
|
||||||
|
message,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
};
|
||||||
|
}
|
||||||
|
@ -22,6 +22,7 @@ use crate::IType;
|
|||||||
use crate::Marine;
|
use crate::Marine;
|
||||||
use crate::IFunctionArg;
|
use crate::IFunctionArg;
|
||||||
use crate::MRecordTypes;
|
use crate::MRecordTypes;
|
||||||
|
use crate::json_to_faas_err;
|
||||||
|
|
||||||
//use marine_utils::SharedString;
|
//use marine_utils::SharedString;
|
||||||
use marine_rs_sdk::CallParameters;
|
use marine_rs_sdk::CallParameters;
|
||||||
@ -95,24 +96,32 @@ impl FluenceFaaS {
|
|||||||
json_args: JValue,
|
json_args: JValue,
|
||||||
call_parameters: marine_rs_sdk::CallParameters,
|
call_parameters: marine_rs_sdk::CallParameters,
|
||||||
) -> Result<JValue> {
|
) -> Result<JValue> {
|
||||||
use crate::faas::json::json_to_ivalues;
|
use it_json_serde::json_to_ivalues;
|
||||||
use crate::faas::json::ivalues_to_json;
|
use it_json_serde::ivalues_to_json;
|
||||||
|
|
||||||
let module_name = module_name.as_ref();
|
let module_name = module_name.as_ref();
|
||||||
let func_name = func_name.as_ref();
|
let func_name = func_name.as_ref();
|
||||||
|
|
||||||
let (func_signature, output_types, record_types) =
|
let (func_signature, output_types, record_types) =
|
||||||
self.lookup_module_interface(module_name, func_name)?;
|
self.lookup_module_interface(module_name, func_name)?;
|
||||||
let iargs = json_to_ivalues(
|
let iargs = json_to_faas_err!(
|
||||||
|
json_to_ivalues(
|
||||||
json_args,
|
json_args,
|
||||||
func_signature.iter().map(|arg| (&arg.name, &arg.ty)),
|
func_signature.iter().map(|arg| (&arg.name, &arg.ty)),
|
||||||
&record_types,
|
&record_types,
|
||||||
|
),
|
||||||
|
module_name.to_string(),
|
||||||
|
func_name.to_string()
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
self.call_parameters.replace(call_parameters);
|
self.call_parameters.replace(call_parameters);
|
||||||
let result = self.marine.call(module_name, func_name, &iargs)?;
|
let result = self.marine.call(module_name, func_name, &iargs)?;
|
||||||
|
|
||||||
ivalues_to_json(result, &output_types, &record_types)
|
json_to_faas_err!(
|
||||||
|
ivalues_to_json(result, &output_types, &record_types),
|
||||||
|
module_name.to_string(),
|
||||||
|
func_name.to_string()
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return all export functions (name and signatures) of loaded modules.
|
/// Return all export functions (name and signatures) of loaded modules.
|
||||||
|
@ -1,123 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2022 Fluence Labs Limited
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
use crate::IValue;
|
|
||||||
use crate::IType;
|
|
||||||
use crate::faas::Result;
|
|
||||||
use crate::faas::errors::FaaSError::JsonOutputSerializationError as OutputDeError;
|
|
||||||
use crate::MRecordTypes;
|
|
||||||
|
|
||||||
use serde_json::Value as JValue;
|
|
||||||
|
|
||||||
pub(crate) fn ivalues_to_json(
|
|
||||||
mut ivalues: Vec<IValue>,
|
|
||||||
outputs: &[IType],
|
|
||||||
record_types: &MRecordTypes,
|
|
||||||
) -> Result<JValue> {
|
|
||||||
if outputs.len() != ivalues.len() {
|
|
||||||
return Err(OutputDeError(format!(
|
|
||||||
"resulted values {:?} and function signature {:?} aren't compatible",
|
|
||||||
ivalues, outputs
|
|
||||||
)));
|
|
||||||
}
|
|
||||||
match ivalues.len() {
|
|
||||||
0 => Ok(JValue::Null),
|
|
||||||
1 => ivalue_to_json(ivalues.remove(0), outputs.first().unwrap(), record_types),
|
|
||||||
_ => unimplemented!(
|
|
||||||
"multi-values aren't supported now - more then one result values aren't possible"
|
|
||||||
),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn ivalue_to_json(ivalue: IValue, output: &IType, record_types: &MRecordTypes) -> Result<JValue> {
|
|
||||||
use serde_json::json;
|
|
||||||
|
|
||||||
// clone here needed because binding by-value and by-ref in the same pattern in unstable
|
|
||||||
match (ivalue, output.clone()) {
|
|
||||||
(IValue::Boolean(value), IType::Boolean) => Ok(json!(value)),
|
|
||||||
(IValue::S8(value), IType::S8) => Ok(json!(value)),
|
|
||||||
(IValue::S16(value), IType::S16) => Ok(json!(value)),
|
|
||||||
(IValue::S32(value), IType::S32) => Ok(json!(value)),
|
|
||||||
(IValue::S64(value), IType::S64) => Ok(json!(value)),
|
|
||||||
(IValue::U8(value), IType::U8) => Ok(json!(value)),
|
|
||||||
(IValue::U16(value), IType::U16) => Ok(json!(value)),
|
|
||||||
(IValue::U32(value), IType::U32) => Ok(json!(value)),
|
|
||||||
(IValue::U64(value), IType::U64) => Ok(json!(value)),
|
|
||||||
(IValue::I32(value), IType::I32) => Ok(json!(value)),
|
|
||||||
(IValue::I64(value), IType::I64) => Ok(json!(value)),
|
|
||||||
(IValue::F32(value), IType::F32) => Ok(json!(value)),
|
|
||||||
(IValue::F64(value), IType::F64) => Ok(json!(value)),
|
|
||||||
(IValue::String(value), IType::String) => Ok(json!(value)),
|
|
||||||
(IValue::ByteArray(value), IType::ByteArray) => {
|
|
||||||
let result = value.into_iter().map(|v| json!(v)).collect();
|
|
||||||
Ok(JValue::Array(result))
|
|
||||||
}
|
|
||||||
(IValue::Array(value), IType::ByteArray) => {
|
|
||||||
let result: Result<Vec<_>> = value
|
|
||||||
.into_iter()
|
|
||||||
.map(|v| ivalue_to_json(v, &IType::U8, record_types))
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
Ok(JValue::Array(result?))
|
|
||||||
}
|
|
||||||
(IValue::ByteArray(value), IType::Array(array_ty)) => {
|
|
||||||
let result: Result<Vec<_>> = value
|
|
||||||
.into_iter()
|
|
||||||
.map(|v| ivalue_to_json(IValue::U8(v), &array_ty, record_types))
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
Ok(JValue::Array(result?))
|
|
||||||
}
|
|
||||||
(IValue::Array(value), IType::Array(array_ty)) => {
|
|
||||||
let result: Result<Vec<_>> = value
|
|
||||||
.into_iter()
|
|
||||||
.map(|v| ivalue_to_json(v, &array_ty, record_types))
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
Ok(JValue::Array(result?))
|
|
||||||
}
|
|
||||||
(IValue::Record(field_values), IType::Record(record_id)) => {
|
|
||||||
let record_type = record_types.get(&record_id).ok_or_else(|| {
|
|
||||||
OutputDeError(format!(
|
|
||||||
"record id {} wasn't found in module record types",
|
|
||||||
record_id
|
|
||||||
))
|
|
||||||
})?;
|
|
||||||
let field_types = &record_type.fields;
|
|
||||||
|
|
||||||
if field_values.len() != field_types.len() {
|
|
||||||
return Err(OutputDeError(format!(
|
|
||||||
"output record {:?} isn't compatible to output record fields {:?}",
|
|
||||||
field_values, field_types
|
|
||||||
)));
|
|
||||||
}
|
|
||||||
|
|
||||||
let field_values = field_values.into_vec();
|
|
||||||
let mut result = serde_json::Map::with_capacity(field_values.len());
|
|
||||||
|
|
||||||
for (field_value, field_type) in field_values.into_iter().zip(field_types.iter()) {
|
|
||||||
let json_field_value = ivalue_to_json(field_value, &field_type.ty, record_types)?;
|
|
||||||
result.insert(field_type.name.clone(), json_field_value);
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(JValue::Object(result))
|
|
||||||
}
|
|
||||||
(ivalue, itype) => Err(OutputDeError(format!(
|
|
||||||
"value {:?} is incompatible to type {:?}",
|
|
||||||
ivalue, itype
|
|
||||||
))),
|
|
||||||
}
|
|
||||||
}
|
|
@ -14,7 +14,6 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
mod json;
|
|
||||||
mod errors;
|
mod errors;
|
||||||
mod faas;
|
mod faas;
|
||||||
mod faas_interface;
|
mod faas_interface;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user