mod exception;
pub(crate) mod limits;
mod os_call;
mod os_policy;
mod resume;
mod type_checking;
use std::{error, fmt};
use monty_types::{
MontyObject, NamedValues,
unstable::{self, MontyGraph, NodeId},
};
pub use os_call::{os_call_from_proto, os_call_to_proto};
pub use resume::{
ext_result_from_proto, ext_result_to_proto, future_results_from_proto, future_results_to_proto,
resume_call_from_proto,
};
use crate::{
BudgetVec, pb,
wire::{WireArena, graph_error},
};
#[derive(Debug)]
pub enum ProtoConvertError {
MissingField(&'static str),
UnknownExcType(String),
UnknownType(String),
UnknownBuiltinFunction(String),
InvalidFileMode(String),
InvalidTimeCaller(String),
InvalidValue {
field: &'static str,
reason: String,
},
}
impl fmt::Display for ProtoConvertError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::MissingField(field) => write!(f, "missing required field {field}"),
Self::UnknownExcType(name) => write!(f, "unknown exception type {name:?}"),
Self::UnknownType(name) => write!(f, "unknown type name {name:?}"),
Self::UnknownBuiltinFunction(name) => write!(f, "unknown builtin function {name:?}"),
Self::InvalidFileMode(mode) => write!(f, "invalid file mode {mode:?}"),
Self::InvalidTimeCaller(caller) => write!(f, "invalid time caller {caller:?}"),
Self::InvalidValue { field, reason } => write!(f, "invalid value for {field}: {reason}"),
}
}
}
impl error::Error for ProtoConvertError {}
impl From<MontyObject> for pb::Complete {
fn from(value: MontyObject) -> Self {
let (graph, root) = unstable::into_graph_parts(value);
Self {
value: root.0,
values: Some(WireArena::new(graph)),
}
}
}
impl TryFrom<pb::Complete> for MontyObject {
type Error = ProtoConvertError;
fn try_from(complete: pb::Complete) -> Result<Self, ProtoConvertError> {
root_object(complete.values, complete.value, "Complete.values")
}
}
#[must_use]
pub fn named_values_to_proto(inputs: NamedValues) -> (BudgetVec<pb::NamedRef>, WireArena) {
let (graph, names) = unstable::into_named_values_parts(inputs);
let refs = names
.into_iter()
.map(|(name, id)| pb::NamedRef { name, value: id.0 })
.collect();
(refs, WireArena::new(graph))
}
pub fn named_values_from_proto(
inputs: impl IntoIterator<Item = pb::NamedRef>,
values: Option<WireArena>,
) -> Result<NamedValues, ProtoConvertError> {
let graph = graph_or_empty(values)?;
let names = inputs
.into_iter()
.map(|input| (input.name, NodeId(input.value)))
.collect();
unstable::named_values_from_parts(graph, names).map_err(|err| graph_error(&err))
}
pub(crate) fn root_object(
values: Option<WireArena>,
root: u32,
field: &'static str,
) -> Result<MontyObject, ProtoConvertError> {
let graph = values.ok_or(ProtoConvertError::MissingField(field))?.into_graph()?;
unstable::object_from_graph(graph, NodeId(root)).map_err(|err| graph_error(&err))
}
pub(crate) fn graph_or_empty(values: Option<WireArena>) -> Result<MontyGraph, ProtoConvertError> {
values.map_or_else(|| Ok(MontyGraph::new()), WireArena::into_graph)
}