1use crate as rune;
4use crate::alloc::Vec;
5use crate::runtime::{self, Future, Inline, Repr, SelectFuture, Value, VmError, VmErrorKind};
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) -> Result<Value, VmError>
18where
19 I: IntoIterator<Item = &'a Value>,
20 F: FnOnce(Vec<Value>) -> Result<Value, VmError>,
21{
22 use futures_util::stream::StreamExt as _;
23
24 let mut futures = futures_util::stream::FuturesUnordered::new();
25 let mut results = 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 Err(VmError::from([
31 VmErrorKind::expected::<Future>(value.type_info()),
32 VmErrorKind::bad_argument(index),
33 ]));
34 }
35 Repr::Dynamic(value) => {
36 return Err(VmError::from([
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 = Value::from(value.clone()).into_future()?;
44 futures.push(SelectFuture::new(index, future));
45 results.try_push(Value::empty())?;
46 }
47 _ => {
48 return Err(VmError::from([
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) = 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) -> Result<Value, VmError> {
101 match value.as_ref() {
102 Repr::Inline(value) => match value {
103 Inline::Unit => Ok(Value::unit()),
104 value => Err(VmError::from([
105 VmErrorKind::bad_argument(0),
106 VmErrorKind::expected::<runtime::Vec>(value.type_info()),
107 ])),
108 },
109 Repr::Dynamic(value) => Err(VmError::from([
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 = value.borrow_ref::<runtime::Vec>()?;
116 let result = try_join_impl(vec.iter(), vec.len(), |vec| {
117 Value::vec(vec).map_err(VmError::from)
118 })
119 .await;
120 Ok(result?)
121 }
122 runtime::OwnedTuple::HASH => {
123 let tuple = value.borrow_ref::<runtime::OwnedTuple>()?;
124
125 let result = try_join_impl(tuple.iter(), tuple.len(), |vec| {
126 Value::tuple(vec).map_err(VmError::from)
127 })
128 .await;
129
130 Ok(result?)
131 }
132 _ => Err(VmError::from([
133 VmErrorKind::bad_argument(0),
134 VmErrorKind::expected::<runtime::Vec>(value.type_info()),
135 ])),
136 },
137 }
138}