1use crate::alloc::prelude::*;
2use crate::alloc::{self, HashMap};
3use crate::any::AnyMarker;
4
5use super::{AnyObj, Object, RuntimeError, Value, VmError};
6
7pub use rune_macros::ToValue;
40
41pub fn to_value(value: impl ToValue) -> Result<Value, RuntimeError> {
73 value.to_value()
74}
75
76#[diagnostic::on_unimplemented(
108 message = "ToValue is not implemented for `{Self}`",
109 label = "ToValue is not implemented for `{Self}`",
110 note = "This probably means that `{Self}` hasn't derived rune::Any"
111)]
112pub trait ToValue: Sized {
113 fn to_value(self) -> Result<Value, RuntimeError>;
115}
116
117pub trait IntoReturn
119where
120 Self: Sized,
121{
122 fn into_return(self) -> Result<Value, VmError>;
124}
125
126impl<T> IntoReturn for T
127where
128 T: ToValue,
129{
130 #[inline]
131 fn into_return(self) -> Result<Value, VmError> {
132 Ok(T::to_value(self)?)
133 }
134}
135
136impl ToValue for Value {
137 #[inline]
138 fn to_value(self) -> Result<Value, RuntimeError> {
139 Ok(self)
140 }
141}
142
143pub trait UnsafeToValue: Sized {
145 type Guard: 'static;
147
148 unsafe fn unsafe_to_value(self) -> Result<(Value, Self::Guard), RuntimeError>;
155}
156
157impl<T> ToValue for T
158where
159 T: AnyMarker,
160{
161 #[inline]
162 fn to_value(self) -> Result<Value, RuntimeError> {
163 Ok(Value::from(AnyObj::new(self)?))
164 }
165}
166
167impl<T> UnsafeToValue for T
168where
169 T: ToValue,
170{
171 type Guard = ();
172
173 #[inline]
174 unsafe fn unsafe_to_value(self) -> Result<(Value, Self::Guard), RuntimeError> {
175 Ok((self.to_value()?, ()))
176 }
177}
178
179impl ToValue for &Value {
180 #[inline]
181 fn to_value(self) -> Result<Value, RuntimeError> {
182 Ok(self.clone())
183 }
184}
185
186impl<T> ToValue for Option<T>
189where
190 T: ToValue,
191{
192 #[inline]
193 fn to_value(self) -> Result<Value, RuntimeError> {
194 let option = match self {
195 Some(some) => Some(some.to_value()?),
196 None => None,
197 };
198
199 Ok(Value::try_from(option)?)
200 }
201}
202
203impl ToValue for alloc::Box<str> {
206 #[inline]
207 fn to_value(self) -> Result<Value, RuntimeError> {
208 let this = alloc::String::from(self);
209 Ok(Value::new(this)?)
210 }
211}
212
213impl ToValue for &str {
214 #[inline]
215 fn to_value(self) -> Result<Value, RuntimeError> {
216 let this = alloc::String::try_from(self)?;
217 Ok(Value::new(this)?)
218 }
219}
220
221impl ToValue for rust_alloc::boxed::Box<str> {
222 #[inline]
223 fn to_value(self) -> Result<Value, RuntimeError> {
224 let this = self.try_to_string()?;
225 Ok(Value::new(this)?)
226 }
227}
228
229impl ToValue for rust_alloc::string::String {
230 #[inline]
231 fn to_value(self) -> Result<Value, RuntimeError> {
232 let string = alloc::String::try_from(self)?;
233 Ok(Value::new(string)?)
234 }
235}
236
237impl<T, E> ToValue for Result<T, E>
238where
239 T: ToValue,
240 E: ToValue,
241{
242 fn to_value(self) -> Result<Value, RuntimeError> {
243 let result = match self {
244 Ok(ok) => Ok(ok.to_value()?),
245 Err(err) => Err(err.to_value()?),
246 };
247
248 Ok(Value::try_from(result)?)
249 }
250}
251
252macro_rules! impl_map {
255 ($ty:ty) => {
256 impl<T> ToValue for $ty
257 where
258 T: ToValue,
259 {
260 fn to_value(self) -> Result<Value, RuntimeError> {
261 let mut output = Object::with_capacity(self.len())?;
262
263 for (key, value) in self {
264 let key = alloc::String::try_from(key)?;
265 let value = value.to_value()?;
266 output.insert(key, value)?;
267 }
268
269 Ok(Value::try_from(output)?)
270 }
271 }
272 };
273}
274
275impl_map!(HashMap<rust_alloc::string::String, T>);
276impl_map!(HashMap<alloc::String, T>);
277
278cfg_std! {
279 impl_map!(::std::collections::HashMap<rust_alloc::string::String, T>);
280 impl_map!(::std::collections::HashMap<alloc::String, T>);
281}