blob: c1a6f7fc36904b0842c480e42dd04495f2a483bb [file] [log] [blame]
use std::prelude::v1::*;
use std::fmt::{Debug, Formatter};
use std::borrow::Cow;
use super::function::Function;
use super::executor::Executor;
#[derive(Debug)]
pub struct Program<'a> {
pub functions: Vec<Function>,
pub(super) native_functions: Vec<NativeFunction<'a>>
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct ProgramInfo<'a> {
pub functions: Vec<Function>,
pub native_functions: Vec<Cow<'a, str>>
}
pub struct NativeFunction<'a> {
name: String,
fn_impl: &'a Fn(&Executor)
}
impl<'a> Debug for NativeFunction<'a> {
fn fmt(&self, f: &mut Formatter) -> ::std::fmt::Result {
write!(f, "NativeFunction")
}
}
impl<'a> NativeFunction<'a> {
pub fn new<T: ToString>(name: T, f: &'a Fn(&Executor)) -> NativeFunction<'a> {
NativeFunction {
fn_impl: f,
name: name.to_string()
}
}
pub fn invoke(&self, executor: &Executor) {
(self.fn_impl)(executor);
}
}
impl<'a> Program<'a> {
pub fn from_functions(fns: Vec<Function>) -> Program<'a> {
Program {
functions: fns,
native_functions: Vec::new()
}
}
pub fn append_native_function(&mut self, f: NativeFunction<'a>) -> usize {
self.native_functions.push(f);
self.native_functions.len() - 1
}
pub fn resolve_native_functions<T, F>(
&mut self,
function_list: &[T],
resolver: F
) -> bool
where
F: Fn(&str) -> Option<NativeFunction<'a>>,
T: AsRef<str>
{
let mut nf_list: Vec<NativeFunction<'a>> = Vec::new();
for name in function_list {
let nf = if let Some(v) = resolver(name.as_ref()) {
v
} else {
return false;
};
nf_list.push(nf);
}
self.native_functions = nf_list;
true
}
pub fn dump(&self) -> ProgramInfo {
ProgramInfo {
functions: self.functions.clone(),
native_functions: self.native_functions.iter().map(|v| Cow::from(v.name.as_str())).collect()
}
}
pub fn load<F>(info: ProgramInfo, resolver: F) -> Option<Program<'a>>
where F: Fn(&str) -> Option<NativeFunction<'a>>
{
let mut program = Self::from_functions(info.functions);
if program.resolve_native_functions(info.native_functions.as_slice(), resolver) == false {
return None;
}
Some(program)
}
}
impl<'a> ProgramInfo<'a> {
pub fn std_serialize(&self) -> Vec<u8> {
::bincode::serialize(self, ::bincode::Infinite).unwrap()
}
pub fn std_deserialize(input: &'a [u8]) -> Option<ProgramInfo<'a>> {
match ::bincode::deserialize(input) {
Ok(v) => Some(v),
Err(_) => None
}
}
}