rune/modules/
future.rs
1use crate as rune;
4use crate::alloc::Vec;
5use crate::runtime::{self, Future, Inline, Repr, SelectFuture, Value, VmErrorKind, VmResult};
6use crate::{ContextError, Module, TypeHash};
7
8#[rune::module(::std::future)]
10pub fn module() -> Result<Module, ContextError> {
11 let mut module = Module::from_meta(self::module_meta)?;
12 module.ty::<Future>()?;
13 module.function_meta(join__meta)?;
14 Ok(module)
15}
16
17async fn try_join_impl<'a, I, F>(values: I, len: usize, factory: F) -> VmResult<Value>
18where
19 I: IntoIterator<Item = &'a Value>,
20 F: FnOnce(Vec<Value>) -> VmResult<Value>,
21{
22 use futures_util::stream::StreamExt as _;
23
24 let mut futures = futures_util::stream::FuturesUnordered::new();
25 let mut results = vm_try!(Vec::try_with_capacity(len));
26
27 for (index, value) in values.into_iter().enumerate() {
28 match value.as_ref() {
29 Repr::Inline(value) => {
30 return VmResult::err([
31 VmErrorKind::expected::<Future>(value.type_info()),
32 VmErrorKind::bad_argument(index),
33 ]);
34 }
35 Repr::Dynamic(value) => {
36 return VmResult::err([
37 VmErrorKind::expected::<Future>(value.type_info()),
38 VmErrorKind::bad_argument(index),
39 ]);
40 }
41 Repr::Any(value) => match value.type_hash() {
42 Future::HASH => {
43 let future = vm_try!(Value::from(value.clone()).into_future());
44 futures.push(SelectFuture::new(index, future));
45 vm_try!(results.try_push(Value::empty()));
46 }
47 _ => {
48 return VmResult::err([
49 VmErrorKind::expected::<Future>(value.type_info()),
50 VmErrorKind::bad_argument(index),
51 ]);
52 }
53 },
54 }
55 }
56
57 while !futures.is_empty() {
58 let (index, value) = vm_try!(futures.next().await.unwrap());
59 *results.get_mut(index).unwrap() = value;
60 }
61
62 factory(results)
63}
64
65#[rune::function(keep)]
100async fn join(value: Value) -> VmResult<Value> {
101 match value.as_ref() {
102 Repr::Inline(value) => match value {
103 Inline::Unit => VmResult::Ok(Value::unit()),
104 value => VmResult::err([
105 VmErrorKind::bad_argument(0),
106 VmErrorKind::expected::<runtime::Vec>(value.type_info()),
107 ]),
108 },
109 Repr::Dynamic(value) => VmResult::err([
110 VmErrorKind::bad_argument(0),
111 VmErrorKind::expected::<runtime::Vec>(value.type_info()),
112 ]),
113 Repr::Any(value) => match value.type_hash() {
114 runtime::Vec::HASH => {
115 let vec = vm_try!(value.borrow_ref::<runtime::Vec>());
116 let result = try_join_impl(vec.iter(), vec.len(), |vec| {
117 VmResult::Ok(vm_try!(Value::vec(vec)))
118 })
119 .await;
120 VmResult::Ok(vm_try!(result))
121 }
122 runtime::OwnedTuple::HASH => {
123 let tuple = vm_try!(value.borrow_ref::<runtime::OwnedTuple>());
124
125 let result = try_join_impl(tuple.iter(), tuple.len(), |vec| {
126 VmResult::Ok(vm_try!(Value::tuple(vec)))
127 })
128 .await;
129
130 VmResult::Ok(vm_try!(result))
131 }
132 _ => VmResult::err([
133 VmErrorKind::bad_argument(0),
134 VmErrorKind::expected::<runtime::Vec>(value.type_info()),
135 ]),
136 },
137 }
138}