rune/runtime/
control_flow.rs
1use core::ops;
2
3use crate as rune;
4use crate::alloc::clone::TryClone;
5use crate::alloc::fmt::TryWrite;
6use crate::Any;
7
8use super::{
9 EnvProtocolCaller, Formatter, FromValue, ProtocolCaller, RuntimeError, ToValue, Value, VmResult,
10};
11
12#[derive(Debug, Clone, TryClone, Any)]
28#[try_clone(crate)]
29#[rune(item = ::std::ops)]
30pub enum ControlFlow {
31 #[rune(constructor)]
33 Continue(#[rune(get, set)] Value),
34 #[rune(constructor)]
36 Break(#[rune(get, set)] Value),
37}
38
39impl ControlFlow {
40 #[rune::function(keep, protocol = PARTIAL_EQ)]
61 pub(crate) fn partial_eq(&self, other: &Self) -> VmResult<bool> {
62 Self::partial_eq_with(self, other, &mut EnvProtocolCaller)
63 }
64
65 pub(crate) fn partial_eq_with(
66 &self,
67 other: &Self,
68 caller: &mut dyn ProtocolCaller,
69 ) -> VmResult<bool> {
70 match (self, other) {
71 (ControlFlow::Continue(a), ControlFlow::Continue(b)) => {
72 Value::partial_eq_with(a, b, caller)
73 }
74 (ControlFlow::Break(a), ControlFlow::Break(b)) => Value::partial_eq_with(a, b, caller),
75 _ => VmResult::Ok(false),
76 }
77 }
78
79 #[rune::function(keep, protocol = EQ)]
100 pub(crate) fn eq(&self, other: &ControlFlow) -> VmResult<bool> {
101 self.eq_with(other, &mut EnvProtocolCaller)
102 }
103
104 pub(crate) fn eq_with(
105 &self,
106 other: &ControlFlow,
107 caller: &mut dyn ProtocolCaller,
108 ) -> VmResult<bool> {
109 match (self, other) {
110 (ControlFlow::Continue(a), ControlFlow::Continue(b)) => Value::eq_with(a, b, caller),
111 (ControlFlow::Break(a), ControlFlow::Break(b)) => Value::eq_with(a, b, caller),
112 _ => VmResult::Ok(false),
113 }
114 }
115
116 #[rune::function(keep, protocol = DEBUG_FMT)]
126 pub(crate) fn debug_fmt(&self, f: &mut Formatter) -> VmResult<()> {
127 Self::debug_fmt_with(self, f, &mut EnvProtocolCaller)
128 }
129
130 pub(crate) fn debug_fmt_with(
131 &self,
132 f: &mut Formatter,
133 caller: &mut dyn ProtocolCaller,
134 ) -> VmResult<()> {
135 match self {
136 ControlFlow::Continue(value) => {
137 vm_try!(vm_write!(f, "Continue("));
138 vm_try!(Value::debug_fmt_with(value, f, caller));
139 vm_try!(vm_write!(f, ")"));
140 }
141 ControlFlow::Break(value) => {
142 vm_try!(vm_write!(f, "Break("));
143 vm_try!(Value::debug_fmt_with(value, f, caller));
144 vm_try!(vm_write!(f, ")"));
145 }
146 }
147
148 VmResult::Ok(())
149 }
150
151 #[rune::function(keep, protocol = CLONE)]
164 pub(crate) fn clone(&self) -> VmResult<Self> {
165 VmResult::Ok(vm_try!(self.try_clone()))
166 }
167}
168
169impl<B, C> ToValue for ops::ControlFlow<B, C>
170where
171 B: ToValue,
172 C: ToValue,
173{
174 #[inline]
175 fn to_value(self) -> Result<Value, RuntimeError> {
176 let value = match self {
177 ops::ControlFlow::Continue(value) => ControlFlow::Continue(C::to_value(value)?),
178 ops::ControlFlow::Break(value) => ControlFlow::Break(B::to_value(value)?),
179 };
180
181 Ok(Value::try_from(value)?)
182 }
183}
184
185impl<B, C> FromValue for ops::ControlFlow<B, C>
186where
187 B: FromValue,
188 C: FromValue,
189{
190 #[inline]
191 fn from_value(value: Value) -> Result<Self, RuntimeError> {
192 Ok(match &*value.borrow_ref::<ControlFlow>()? {
193 ControlFlow::Continue(value) => {
194 ops::ControlFlow::Continue(C::from_value(value.clone())?)
195 }
196 ControlFlow::Break(value) => ops::ControlFlow::Break(B::from_value(value.clone())?),
197 })
198 }
199}