Skip to main content

harn_vm/value/
isolate.rs

1use super::{VmError, VmValue};
2
3/// A data value proven safe to instantiate in independent VM isolates.
4///
5/// The wrapped representation stays private so callers cannot bypass the
6/// one-time graph validation. Cloning an instance is O(1) at this boundary;
7/// Harn collections preserve isolation with copy-on-write mutation.
8#[derive(Clone)]
9pub struct IsolateValue(VmValue);
10
11impl IsolateValue {
12    /// Create one copy-on-write instance for a fresh VM.
13    pub fn instantiate(&self) -> VmValue {
14        self.0.clone()
15    }
16}
17
18impl VmValue {
19    /// Validate this value as reusable data for fresh VM isolates.
20    ///
21    /// The complete value graph is validated once, rejecting execution-bound
22    /// handles whose clone would retain source-VM state. The returned opaque
23    /// seed can then instantiate isolated values without rescanning the graph.
24    ///
25    /// Validation is iterative so adversarially deep data cannot overflow the
26    /// native stack.
27    pub fn try_into_isolate_value(self) -> Result<IsolateValue, VmError> {
28        let mut pending = vec![&self];
29        while let Some(value) = pending.pop() {
30            match value {
31                Self::List(items) => pending.extend(items.iter()),
32                Self::Dict(entries) => pending.extend(entries.values()),
33                Self::EnumVariant(variant) => pending.extend(variant.fields.iter()),
34                Self::StructInstance(instance) => {
35                    pending.extend(instance.fields.iter().filter_map(Option::as_ref));
36                }
37                Self::Set(set) => pending.extend(set.iter()),
38                Self::Pair(pair) => {
39                    pending.push(&pair.0);
40                    pending.push(&pair.1);
41                }
42                Self::Closure(_)
43                | Self::TaskHandle(_)
44                | Self::Channel(_)
45                | Self::Atomic(_)
46                | Self::Rng(_)
47                | Self::SyncPermit(_)
48                | Self::Resource(_)
49                | Self::ResourceGuard(_)
50                | Self::McpClient(_)
51                | Self::VerdictReceipt(_)
52                | Self::Generator(_)
53                | Self::Stream(_)
54                | Self::Iter(_)
55                | Self::Harness(_) => {
56                    return Err(VmError::Runtime(format!(
57                        "{} values retain execution state and cannot cross a VM isolate",
58                        value.type_name()
59                    )));
60                }
61                Self::Int(_)
62                | Self::Float(_)
63                | Self::Decimal(_)
64                | Self::String(_)
65                | Self::Bytes(_)
66                | Self::Bool(_)
67                | Self::Nil
68                | Self::BuiltinRef(_)
69                | Self::BuiltinRefId(_)
70                | Self::Duration(_)
71                | Self::Range(_) => {}
72            }
73        }
74        Ok(IsolateValue(self))
75    }
76}