monty_proto/convert/
mod.rs1mod exception;
18pub(crate) mod limits;
19mod os_call;
20mod os_policy;
21mod resume;
22mod type_checking;
23
24use std::{error, fmt};
25
26use monty_types::{
27 MontyObject, NamedValues,
28 unstable::{self, MontyGraph, NodeId},
29};
30pub use os_call::{os_call_from_proto, os_call_to_proto};
31pub use resume::{
32 ext_result_from_proto, ext_result_to_proto, future_results_from_proto, future_results_to_proto,
33 resume_call_from_proto,
34};
35
36use crate::{
37 BudgetVec, pb,
38 wire::{WireArena, graph_error},
39};
40
41#[derive(Debug)]
47pub enum ProtoConvertError {
48 MissingField(&'static str),
50 UnknownExcType(String),
52 UnknownType(String),
54 UnknownBuiltinFunction(String),
56 InvalidFileMode(String),
58 InvalidTimeCaller(String),
60 InvalidValue {
62 field: &'static str,
64 reason: String,
66 },
67}
68
69impl fmt::Display for ProtoConvertError {
70 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
71 match self {
72 Self::MissingField(field) => write!(f, "missing required field {field}"),
73 Self::UnknownExcType(name) => write!(f, "unknown exception type {name:?}"),
74 Self::UnknownType(name) => write!(f, "unknown type name {name:?}"),
75 Self::UnknownBuiltinFunction(name) => write!(f, "unknown builtin function {name:?}"),
76 Self::InvalidFileMode(mode) => write!(f, "invalid file mode {mode:?}"),
77 Self::InvalidTimeCaller(caller) => write!(f, "invalid time caller {caller:?}"),
78 Self::InvalidValue { field, reason } => write!(f, "invalid value for {field}: {reason}"),
79 }
80 }
81}
82
83impl error::Error for ProtoConvertError {}
84
85impl From<MontyObject> for pb::Complete {
86 fn from(value: MontyObject) -> Self {
87 let (graph, root) = unstable::into_graph_parts(value);
88 Self {
89 value: root.0,
90 values: Some(WireArena::new(graph)),
91 }
92 }
93}
94
95impl TryFrom<pb::Complete> for MontyObject {
96 type Error = ProtoConvertError;
97
98 fn try_from(complete: pb::Complete) -> Result<Self, ProtoConvertError> {
99 root_object(complete.values, complete.value, "Complete.values")
100 }
101}
102
103#[must_use]
105pub fn named_values_to_proto(inputs: NamedValues) -> (BudgetVec<pb::NamedRef>, WireArena) {
106 let (graph, names) = unstable::into_named_values_parts(inputs);
107 let refs = names
108 .into_iter()
109 .map(|(name, id)| pb::NamedRef { name, value: id.0 })
110 .collect();
111 (refs, WireArena::new(graph))
112}
113
114pub fn named_values_from_proto(
116 inputs: impl IntoIterator<Item = pb::NamedRef>,
117 values: Option<WireArena>,
118) -> Result<NamedValues, ProtoConvertError> {
119 let graph = graph_or_empty(values)?;
120 let names = inputs
121 .into_iter()
122 .map(|input| (input.name, NodeId(input.value)))
123 .collect();
124 unstable::named_values_from_parts(graph, names).map_err(|err| graph_error(&err))
125}
126
127pub(crate) fn root_object(
130 values: Option<WireArena>,
131 root: u32,
132 field: &'static str,
133) -> Result<MontyObject, ProtoConvertError> {
134 let graph = values.ok_or(ProtoConvertError::MissingField(field))?.into_graph()?;
135 unstable::object_from_graph(graph, NodeId(root)).map_err(|err| graph_error(&err))
136}
137
138pub(crate) fn graph_or_empty(values: Option<WireArena>) -> Result<MontyGraph, ProtoConvertError> {
141 values.map_or_else(|| Ok(MontyGraph::new()), WireArena::into_graph)
142}