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}