marine/fluence-faas/src/faas_interface.rs

206 lines
6.4 KiB
Rust
Raw Normal View History

2020-06-10 16:55:18 +03:00
/*
* 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 super::IType;
2020-09-16 01:14:15 +03:00
use super::IRecordType;
2020-10-21 22:21:16 +03:00
use crate::FaaSModuleInterface;
use crate::FaaSFunctionSignature;
2020-08-07 11:54:37 +03:00
2020-11-05 15:18:48 +03:00
use fce::RecordTypes;
2020-08-07 11:54:37 +03:00
use serde::Serialize;
use serde::Serializer;
2020-06-10 16:55:18 +03:00
use std::fmt;
use std::collections::HashMap;
2020-10-21 22:21:16 +03:00
use std::collections::HashSet;
2020-11-05 15:18:48 +03:00
use std::rc::Rc;
2020-09-16 13:46:38 +03:00
use itertools::Itertools;
2020-06-10 16:55:18 +03:00
2020-10-21 22:21:16 +03:00
#[derive(Debug, PartialEq, Eq, Clone)]
pub struct FaaSInterface<'a> {
2020-10-21 22:21:16 +03:00
pub modules: HashMap<&'a str, FaaSModuleInterface<'a>>,
2020-06-10 16:55:18 +03:00
}
impl<'a> fmt::Display for FaaSInterface<'a> {
2020-06-10 16:55:18 +03:00
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2020-11-09 06:14:07 +03:00
fn type_text_view(arg_ty: &IType, record_types: &RecordTypes) -> String {
2020-09-16 01:14:15 +03:00
match arg_ty {
IType::Record(record_type_id) => {
2020-10-21 22:21:16 +03:00
// unwrap is safe because FaaSInterface here is well-formed
2020-09-16 01:14:15 +03:00
// (it was checked on the module startup stage)
2020-10-21 22:21:16 +03:00
let record = record_types.get(record_type_id).unwrap();
2020-09-16 01:14:15 +03:00
record.name.clone()
}
2020-11-09 06:14:07 +03:00
IType::Array(array_ty) => {
format!("Array<{}>", type_text_view(array_ty, record_types))
}
2020-09-16 01:14:15 +03:00
t => format!("{:?}", t),
}
};
2020-10-21 22:21:16 +03:00
let mut printed_record_types: HashSet<&IRecordType> = HashSet::new();
2020-09-16 01:14:15 +03:00
2020-10-21 22:21:16 +03:00
for (_, module_interface) in self.modules.iter() {
for (_, record_type) in module_interface.record_types.iter() {
2020-11-08 19:41:48 +03:00
if !printed_record_types.insert(record_type) {
2020-10-21 22:21:16 +03:00
// do not print record if it has been already printed
continue;
}
writeln!(f, "{} {{", record_type.name)?;
2020-09-16 01:14:15 +03:00
2020-10-21 22:21:16 +03:00
for field in record_type.fields.iter() {
writeln!(
f,
" {}: {}",
field.name,
type_text_view(&field.ty, &module_interface.record_types)
)?;
}
writeln!(f, "}}")?;
}
2020-09-16 01:14:15 +03:00
}
2020-10-21 22:21:16 +03:00
for (name, module_interface) in self.modules.iter() {
2020-09-16 12:31:21 +03:00
writeln!(f, "\n{}:", *name)?;
2020-10-21 22:21:16 +03:00
for function_signature in module_interface.function_signatures.iter() {
write!(f, " fn {}(", function_signature.name)?;
2020-09-16 01:14:15 +03:00
2020-10-21 22:21:16 +03:00
let args = function_signature
2020-09-16 13:46:38 +03:00
.arguments
.iter()
2020-10-21 22:21:16 +03:00
.map(|arg| {
format!(
"{}: {}",
arg.name,
type_text_view(&arg.ty, &module_interface.record_types)
)
})
2020-09-16 13:46:38 +03:00
.join(", ");
2020-11-05 15:18:48 +03:00
let outputs = &function_signature.outputs;
2020-10-21 22:21:16 +03:00
if outputs.is_empty() {
2020-09-16 13:46:38 +03:00
writeln!(f, "{})", args)?;
2020-10-21 22:21:16 +03:00
} else if outputs.len() == 1 {
2020-09-16 13:46:38 +03:00
writeln!(
f,
"{}) -> {}",
args,
2020-10-21 22:21:16 +03:00
type_text_view(&outputs[0], &module_interface.record_types)
2020-09-16 13:46:38 +03:00
)?;
2020-09-16 01:14:15 +03:00
} else {
// At now, multi values aren't supported - only one output type is possible
unimplemented!()
}
}
2020-06-10 16:55:18 +03:00
}
Ok(())
}
}
2020-07-28 16:29:09 +03:00
impl<'a> Serialize for FaaSInterface<'a> {
fn serialize<S>(&self, serializer: S) -> Result<<S as Serializer>::Ok, <S as Serializer>::Error>
where
S: Serializer,
{
#[derive(Serialize)]
2020-10-21 22:21:16 +03:00
pub struct FunctionSignature<'a> {
2020-11-05 15:18:48 +03:00
pub name: &'a Rc<String>,
2020-09-16 01:14:15 +03:00
pub arguments: Vec<(&'a String, &'a IType)>,
2020-11-05 15:18:48 +03:00
pub output_types: &'a Rc<Vec<IType>>,
2020-07-28 16:29:09 +03:00
}
2020-09-16 01:14:15 +03:00
#[derive(Serialize)]
pub struct RecordType<'a> {
pub name: &'a str,
pub id: u64,
pub fields: Vec<(&'a String, &'a IType)>,
}
2020-07-28 16:29:09 +03:00
#[derive(Serialize)]
pub struct Module<'a> {
pub name: &'a str,
2020-10-21 22:21:16 +03:00
pub function_signatures: Vec<FunctionSignature<'a>>,
pub record_types: Vec<RecordType<'a>>,
2020-07-28 16:29:09 +03:00
}
#[derive(Serialize)]
pub struct Interface<'a> {
pub modules: Vec<Module<'a>>,
}
2020-11-05 15:18:48 +03:00
fn serialize_function_signature(
signature: &FaaSFunctionSignature,
) -> FunctionSignature<'_> {
2020-10-21 22:21:16 +03:00
let arguments = signature
.arguments
.iter()
.map(|arg| (&arg.name, &arg.ty))
.collect();
FunctionSignature {
2020-11-05 15:18:48 +03:00
name: &signature.name,
2020-10-21 22:21:16 +03:00
arguments,
2020-11-05 15:18:48 +03:00
output_types: &signature.outputs,
2020-10-21 22:21:16 +03:00
}
}
2020-09-16 01:14:15 +03:00
2020-11-05 15:18:48 +03:00
fn serialize_record_type<'a, 'b>(record: (&'a u64, &'b Rc<IRecordType>)) -> RecordType<'b> {
2020-10-21 22:21:16 +03:00
let fields = record
.1
.fields
.iter()
.map(|field| (&field.name, &field.ty))
.collect::<Vec<_>>();
RecordType {
name: record.1.name.as_str(),
id: *record.0,
fields,
}
}
2020-09-16 01:14:15 +03:00
2020-07-28 16:29:09 +03:00
let modules: Vec<_> = self
.modules
.iter()
2020-10-21 22:21:16 +03:00
.map(|(name, interface)| {
let function_signatures = interface
.function_signatures
.iter()
.map(serialize_function_signature)
.collect();
let record_types: Vec<_> = interface
.record_types
2020-07-28 16:29:09 +03:00
.iter()
2020-10-21 22:21:16 +03:00
.map(serialize_record_type)
2020-07-28 16:29:09 +03:00
.collect();
2020-10-21 22:21:16 +03:00
Module {
name,
function_signatures,
record_types,
}
2020-07-28 16:29:09 +03:00
})
.collect();
2020-10-21 22:21:16 +03:00
Interface { modules }.serialize(serializer)
2020-07-28 16:29:09 +03:00
}
}