mirror of
https://github.com/leptos-rs/leptos
synced 2024-09-20 14:32:00 +00:00
get types working with nested ErrorBoundary/Suspense
This commit is contained in:
parent
e11eea1af1
commit
851e1f73fd
32 changed files with 270 additions and 363 deletions
Binary file not shown.
|
@ -31,30 +31,30 @@ pub fn ErrorTemplate(
|
|||
|
||||
// Only the response code for the first error is actually sent from the server
|
||||
// this may be customized by the specific application
|
||||
#[cfg(feature = "ssr")]
|
||||
/*#[cfg(feature = "ssr")]
|
||||
{
|
||||
let response = use_context::<ResponseOptions>();
|
||||
if let Some(response) = response {
|
||||
response.set_status(errors[0].status_code());
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
view! {
|
||||
<h1>"Errors"</h1>
|
||||
<For
|
||||
// a function that returns the items we're iterating over; a signal is fine
|
||||
each= move || {errors.clone().into_iter().enumerate()}
|
||||
// a unique key for each item as a reference
|
||||
key=|(index, _error)| *index
|
||||
// renders each item to a view
|
||||
children=move |error| {
|
||||
let error_string = error.1.to_string();
|
||||
let error_code= error.1.status_code();
|
||||
view! {
|
||||
<h2>{error_code.to_string()}</h2>
|
||||
<p>"Error: " {error_string}</p>
|
||||
}
|
||||
}
|
||||
/>
|
||||
<h1>"Errors"</h1>
|
||||
<For
|
||||
// a function that returns the items we're iterating over; a signal is fine
|
||||
each=move || { errors.clone().into_iter().enumerate() }
|
||||
// a unique key for each item as a reference
|
||||
key=|(index, _error)| *index
|
||||
// renders each item to a view
|
||||
children=move |error| {
|
||||
let error_string = error.1.to_string();
|
||||
let error_code = error.1.status_code();
|
||||
view! {
|
||||
<h2>{error_code.to_string()}</h2>
|
||||
<p>"Error: " {error_string}</p>
|
||||
}
|
||||
}
|
||||
/>
|
||||
}
|
||||
}
|
||||
|
|
|
@ -120,9 +120,39 @@ pub fn Todos() -> impl IntoView {
|
|||
<div>
|
||||
|
||||
// fallback=move || view! { <p>"Loading..."</p> }>
|
||||
<Suspense>
|
||||
<Suspense fallback=move || view! { <p>"Loading..."</p> }>
|
||||
<ErrorBoundary fallback=|errors| view! { <ErrorTemplate errors/> }>
|
||||
<ul>"foo"// {existing_todos}
|
||||
// {existing_todos}
|
||||
<ul>
|
||||
{move || {
|
||||
async move {
|
||||
todos
|
||||
.await
|
||||
.map(|todos| {
|
||||
if todos.is_empty() {
|
||||
Either::Left(view! { <p>"No tasks were found."</p> })
|
||||
} else {
|
||||
Either::Right(
|
||||
todos
|
||||
.into_iter()
|
||||
.map(move |todo| {
|
||||
view! {
|
||||
<li>
|
||||
{todo.title} <ActionForm action=delete_todo>
|
||||
<input type="hidden" name="id" value=todo.id/>
|
||||
<input type="submit" value="X"/>
|
||||
</ActionForm>
|
||||
</li>
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>(),
|
||||
)
|
||||
}
|
||||
})
|
||||
}
|
||||
.wait()
|
||||
}}
|
||||
|
||||
// {pending_todos}
|
||||
</ul>
|
||||
</ErrorBoundary>
|
||||
|
|
|
@ -194,15 +194,30 @@ where
|
|||
impl<Chil, Fal, Rndr> RenderHtml<Rndr> for ErrorBoundaryView<Chil, Fal, Rndr>
|
||||
where
|
||||
Chil: RenderHtml<Rndr>,
|
||||
Fal: RenderHtml<Rndr>,
|
||||
Fal: RenderHtml<Rndr> + Send,
|
||||
Rndr: Renderer,
|
||||
{
|
||||
type AsyncOutput = std::future::Ready<()>; //ErrorBoundaryView<Chil::AsyncOutput, Fal, Rndr>;
|
||||
type AsyncOutput = ErrorBoundaryView<Chil::AsyncOutput, Fal, Rndr>;
|
||||
|
||||
const MIN_LENGTH: usize = Chil::MIN_LENGTH;
|
||||
|
||||
fn resolve(self) -> Self::AsyncOutput {
|
||||
todo!()
|
||||
async fn resolve(self) -> Self::AsyncOutput {
|
||||
let ErrorBoundaryView {
|
||||
errors_empty,
|
||||
children,
|
||||
fallback,
|
||||
..
|
||||
} = self;
|
||||
let children = match children {
|
||||
None => None,
|
||||
Some(children) => Some(children.resolve().await),
|
||||
};
|
||||
ErrorBoundaryView {
|
||||
errors_empty,
|
||||
children,
|
||||
fallback,
|
||||
rndr: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
fn to_html_with_buf(self, buf: &mut String, position: &mut Position) {
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
use crate::into_view::IntoView;
|
||||
use leptos_macro::component;
|
||||
use reactive_graph::owner::Owner;
|
||||
use std::{hash::Hash, marker::PhantomData};
|
||||
|
@ -44,7 +45,6 @@ use tachys::{
|
|||
/// }
|
||||
/// ```
|
||||
#[cfg_attr(feature = "tracing", tracing::instrument(level = "trace", skip_all))]
|
||||
#[component(transparent)]
|
||||
pub fn For<Rndr, IF, I, T, EF, N, KF, K>(
|
||||
/// Items over which the component should iterate.
|
||||
each: IF,
|
||||
|
@ -52,17 +52,15 @@ pub fn For<Rndr, IF, I, T, EF, N, KF, K>(
|
|||
key: KF,
|
||||
/// A function that takes the item, and returns the view that will be displayed for each item.
|
||||
children: EF,
|
||||
#[prop(optional)] _rndr: PhantomData<Rndr>,
|
||||
) -> impl RenderHtml<Rndr>
|
||||
) -> impl IntoView
|
||||
where
|
||||
IF: Fn() -> I + 'static,
|
||||
I: IntoIterator<Item = T>,
|
||||
EF: Fn(T) -> N + Clone + 'static,
|
||||
N: RenderHtml<Rndr> + 'static,
|
||||
KF: Fn(&T) -> K + Clone + 'static,
|
||||
IF: Fn() -> I + Send + 'static,
|
||||
I: IntoIterator<Item = T> + Send,
|
||||
EF: Fn(T) -> N + Send + Clone + 'static,
|
||||
N: IntoView + 'static,
|
||||
KF: Fn(&T) -> K + Send + Clone + 'static,
|
||||
K: Eq + Hash + 'static,
|
||||
T: 'static,
|
||||
Rndr: Renderer + 'static,
|
||||
T: Send + 'static,
|
||||
{
|
||||
// this takes the owner of the For itself
|
||||
// this will end up with N + 1 children
|
||||
|
@ -72,13 +70,14 @@ where
|
|||
// this means
|
||||
// a) the reactive owner for each row will not be cleared when the whole list updates
|
||||
// b) context provided in each row will not wipe out the others
|
||||
let parent = Owner::current().expect("no reactive owner");
|
||||
/*let parent = Owner::current().expect("no reactive owner");
|
||||
let children = move |child| {
|
||||
let owner = parent.with(Owner::new);
|
||||
let view = owner.with(|| children(child));
|
||||
OwnedView::new_with_owner(view, owner)
|
||||
};
|
||||
move || keyed(each(), key.clone(), children.clone())
|
||||
move || keyed(each(), key.clone(), children.clone())*/
|
||||
"todo"
|
||||
}
|
||||
|
||||
#[component]
|
||||
|
@ -90,7 +89,7 @@ pub fn FlatFor<Rndr, IF, I, T, EF, N, KF, K>(
|
|||
/// A function that takes the item, and returns the view that will be displayed for each item.
|
||||
children: EF,
|
||||
#[prop(optional)] _rndr: PhantomData<Rndr>,
|
||||
) -> impl RenderHtml<Rndr>
|
||||
) -> impl IntoView
|
||||
where
|
||||
IF: Fn() -> I + 'static,
|
||||
I: IntoIterator<Item = T>,
|
||||
|
@ -101,7 +100,8 @@ where
|
|||
T: 'static,
|
||||
Rndr: Renderer + 'static,
|
||||
{
|
||||
move || keyed(each(), key.clone(), children.clone())
|
||||
//move || keyed(each(), key.clone(), children.clone())
|
||||
"bar"
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
@ -119,11 +119,7 @@ mod tests {
|
|||
let values = RwSignal::new(vec![1, 2, 3, 4, 5]);
|
||||
let list: HtmlElement<_, _, _, MockDom> = view! {
|
||||
<ol>
|
||||
<For
|
||||
each=move || values.get()
|
||||
key=|i| *i
|
||||
let:i
|
||||
>
|
||||
<For each=move || values.get() key=|i| *i let:i>
|
||||
<li>{i}</li>
|
||||
</For>
|
||||
</ol>
|
||||
|
|
|
@ -24,7 +24,6 @@ impl<T> View<T> {
|
|||
pub trait IntoView
|
||||
where
|
||||
Self: Sized + Render<Dom> + RenderHtml<Dom> + Send,
|
||||
<Self::AsyncOutput as Future>::Output: RenderHtml<Dom>,
|
||||
{
|
||||
fn into_view(self) -> View<Self>;
|
||||
}
|
||||
|
@ -32,8 +31,6 @@ where
|
|||
impl<T> IntoView for T
|
||||
where
|
||||
T: Sized + Render<Dom> + RenderHtml<Dom> + Send, //+ AddAnyAttr<Dom>,
|
||||
T::AsyncOutput: Send,
|
||||
<T::AsyncOutput as Future>::Output: RenderHtml<Dom>,
|
||||
{
|
||||
fn into_view(self) -> View<Self> {
|
||||
View(self)
|
||||
|
@ -69,8 +66,8 @@ impl<T: IntoView> RenderHtml<Dom> for View<T> {
|
|||
|
||||
const MIN_LENGTH: usize = <T as RenderHtml<Dom>>::MIN_LENGTH;
|
||||
|
||||
fn resolve(self) -> Self::AsyncOutput {
|
||||
self.0.resolve()
|
||||
async fn resolve(self) -> Self::AsyncOutput {
|
||||
self.0.resolve().await
|
||||
}
|
||||
|
||||
fn to_html_with_buf(self, buf: &mut String, position: &mut Position) {
|
||||
|
|
|
@ -1,22 +1,27 @@
|
|||
use crate::children::{ChildrenFnMut, ViewFn};
|
||||
use crate::{
|
||||
children::{TypedChildrenMut, ViewFn},
|
||||
IntoView,
|
||||
};
|
||||
use leptos_macro::component;
|
||||
use reactive_graph::{computed::ArcMemo, traits::Get};
|
||||
use tachys::{either::Either, renderer::dom::Dom, view::RenderHtml};
|
||||
|
||||
#[component]
|
||||
pub fn Show<W>(
|
||||
pub fn Show<W, C>(
|
||||
/// The children will be shown whenever the condition in the `when` closure returns `true`.
|
||||
mut children: ChildrenFnMut,
|
||||
children: TypedChildrenMut<C>,
|
||||
/// A closure that returns a bool that determines whether this thing runs
|
||||
when: W,
|
||||
/// A closure that returns what gets rendered if the when statement is false. By default this is the empty view.
|
||||
#[prop(optional, into)]
|
||||
fallback: ViewFn,
|
||||
) -> impl RenderHtml<Dom>
|
||||
) -> impl IntoView
|
||||
where
|
||||
W: Fn() -> bool + Send + Sync + 'static,
|
||||
C: IntoView + 'static,
|
||||
{
|
||||
let memoized_when = ArcMemo::new(move |_| when());
|
||||
let mut children = children.into_inner();
|
||||
|
||||
move || match memoized_when.get() {
|
||||
true => Either::Left(children()),
|
||||
|
|
|
@ -116,18 +116,16 @@ impl<const TRANSITION: bool, Fal, Chil, Rndr> RenderHtml<Rndr>
|
|||
where
|
||||
Fal: RenderHtml<Rndr> + Send + 'static,
|
||||
Chil: RenderHtml<Rndr> + Send + 'static,
|
||||
Chil::AsyncOutput: Send + 'static,
|
||||
<Chil::AsyncOutput as Future>::Output: RenderHtml<Rndr>,
|
||||
Rndr: Renderer + 'static,
|
||||
{
|
||||
// i.e., if this is the child of another Suspense during SSR, don't wait for it: it will handle
|
||||
// itself
|
||||
type AsyncOutput = Ready<Self>;
|
||||
type AsyncOutput = Self;
|
||||
|
||||
const MIN_LENGTH: usize = Chil::MIN_LENGTH;
|
||||
|
||||
fn resolve(self) -> Self::AsyncOutput {
|
||||
ready(self)
|
||||
async fn resolve(self) -> Self::AsyncOutput {
|
||||
self
|
||||
}
|
||||
|
||||
fn to_html_with_buf(self, buf: &mut String, position: &mut Position) {
|
||||
|
@ -371,7 +369,7 @@ where
|
|||
Fut::Output: RenderHtml<Rndr>,
|
||||
Rndr: Renderer + 'static,
|
||||
{
|
||||
type AsyncOutput = Fut;
|
||||
type AsyncOutput = Fut::Output;
|
||||
|
||||
const MIN_LENGTH: usize = Fut::Output::MIN_LENGTH;
|
||||
|
||||
|
@ -425,7 +423,7 @@ where
|
|||
SuspendState { inner }
|
||||
}
|
||||
|
||||
fn resolve(self) -> Self::AsyncOutput {
|
||||
self.fut
|
||||
async fn resolve(self) -> Self::AsyncOutput {
|
||||
self.fut.await
|
||||
}
|
||||
}
|
||||
|
|
|
@ -125,12 +125,12 @@ impl Render<Dom> for BodyView {
|
|||
}
|
||||
|
||||
impl RenderHtml<Dom> for BodyView {
|
||||
type AsyncOutput = Ready<Self>;
|
||||
type AsyncOutput = Self;
|
||||
|
||||
const MIN_LENGTH: usize = 0;
|
||||
|
||||
fn resolve(self) -> Self::AsyncOutput {
|
||||
ready(self)
|
||||
async fn resolve(self) -> Self::AsyncOutput {
|
||||
self
|
||||
}
|
||||
|
||||
fn to_html_with_buf(self, buf: &mut String, position: &mut Position) {}
|
||||
|
|
|
@ -138,12 +138,12 @@ impl Render<Dom> for HtmlView {
|
|||
}
|
||||
|
||||
impl RenderHtml<Dom> for HtmlView {
|
||||
type AsyncOutput = Ready<Self>;
|
||||
type AsyncOutput = Self;
|
||||
|
||||
const MIN_LENGTH: usize = 0;
|
||||
|
||||
fn resolve(self) -> Self::AsyncOutput {
|
||||
ready(self)
|
||||
async fn resolve(self) -> Self::AsyncOutput {
|
||||
self
|
||||
}
|
||||
|
||||
fn to_html_with_buf(self, _buf: &mut String, _position: &mut Position) {
|
||||
|
|
|
@ -354,12 +354,12 @@ where
|
|||
At: Attribute<Dom>,
|
||||
Ch: RenderHtml<Dom> + Send,
|
||||
{
|
||||
type AsyncOutput = Ready<Self>;
|
||||
type AsyncOutput = Self;
|
||||
|
||||
const MIN_LENGTH: usize = 0;
|
||||
|
||||
fn resolve(self) -> Self::AsyncOutput {
|
||||
ready(self)
|
||||
async fn resolve(self) -> Self::AsyncOutput {
|
||||
self
|
||||
}
|
||||
|
||||
fn to_html_with_buf(self, _buf: &mut String, _position: &mut Position) {
|
||||
|
@ -460,12 +460,12 @@ impl Render<Dom> for MetaTagsView {
|
|||
}
|
||||
|
||||
impl RenderHtml<Dom> for MetaTagsView {
|
||||
type AsyncOutput = Ready<Self>;
|
||||
type AsyncOutput = Self;
|
||||
|
||||
const MIN_LENGTH: usize = 0;
|
||||
|
||||
fn resolve(self) -> Self::AsyncOutput {
|
||||
ready(self)
|
||||
async fn resolve(self) -> Self::AsyncOutput {
|
||||
self
|
||||
}
|
||||
|
||||
fn to_html_with_buf(self, buf: &mut String, position: &mut Position) {
|
||||
|
|
|
@ -233,12 +233,12 @@ impl Render<Dom> for TitleView {
|
|||
}
|
||||
|
||||
impl RenderHtml<Dom> for TitleView {
|
||||
type AsyncOutput = Ready<Self>;
|
||||
type AsyncOutput = Self;
|
||||
|
||||
const MIN_LENGTH: usize = 0;
|
||||
|
||||
fn resolve(self) -> Self::AsyncOutput {
|
||||
ready(self)
|
||||
async fn resolve(self) -> Self::AsyncOutput {
|
||||
self
|
||||
}
|
||||
|
||||
fn to_html_with_buf(self, buf: &mut String, position: &mut Position) {
|
||||
|
|
|
@ -207,13 +207,13 @@ where
|
|||
Children::Match: std::fmt::Debug,
|
||||
<Children::Match as MatchInterface<Rndr>>::Child: std::fmt::Debug,
|
||||
{
|
||||
type AsyncOutput = Ready<Self>;
|
||||
type AsyncOutput = Self;
|
||||
|
||||
// TODO probably pick a max length here
|
||||
const MIN_LENGTH: usize = Children::View::MIN_LENGTH;
|
||||
|
||||
fn resolve(self) -> Self::AsyncOutput {
|
||||
ready(self)
|
||||
async fn resolve(self) -> Self::AsyncOutput {
|
||||
self
|
||||
}
|
||||
|
||||
fn to_html_with_buf(self, buf: &mut String, position: &mut Position) {
|
||||
|
@ -666,12 +666,12 @@ impl<R> RenderHtml<R> for Outlet<R>
|
|||
where
|
||||
R: Renderer + 'static,
|
||||
{
|
||||
type AsyncOutput = Ready<Self>;
|
||||
type AsyncOutput = Self;
|
||||
|
||||
const MIN_LENGTH: usize = 0; // TODO
|
||||
|
||||
fn resolve(self) -> Self::AsyncOutput {
|
||||
ready(self)
|
||||
async fn resolve(self) -> Self::AsyncOutput {
|
||||
self
|
||||
}
|
||||
|
||||
fn html_len(&self) -> usize {
|
||||
|
@ -949,12 +949,12 @@ where
|
|||
Matcher::View: Sized + 'static,
|
||||
R: Renderer + 'static,
|
||||
{
|
||||
type AsyncOutput = Ready<Self>;
|
||||
type AsyncOutput = Self;
|
||||
|
||||
const MIN_LENGTH: usize = Matcher::View::MIN_LENGTH;
|
||||
|
||||
fn resolve(self) -> Self::AsyncOutput {
|
||||
ready(self)
|
||||
async fn resolve(self) -> Self::AsyncOutput {
|
||||
self
|
||||
}
|
||||
|
||||
fn html_len(&self) -> usize {
|
||||
|
@ -1225,13 +1225,13 @@ where
|
|||
Fallback::State: 'static,
|
||||
Rndr: Renderer + 'static,
|
||||
{
|
||||
type AsyncOutput = Ready<Self>;
|
||||
type AsyncOutput = Self;
|
||||
|
||||
const MIN_LENGTH: usize =
|
||||
<Children::Match as MatchInterface<Rndr>>::View::MIN_LENGTH;
|
||||
|
||||
fn resolve(self) -> Self::AsyncOutput {
|
||||
ready(self)
|
||||
async fn resolve(self) -> Self::AsyncOutput {
|
||||
self
|
||||
}
|
||||
|
||||
fn to_html_with_buf(self, buf: &mut String, position: &mut Position) {
|
||||
|
|
|
@ -166,11 +166,11 @@ where
|
|||
Fut::Output: RenderHtml<Rndr> + Send,
|
||||
Rndr: Renderer + 'static,
|
||||
{
|
||||
type AsyncOutput = Fut;
|
||||
type AsyncOutput = Fut::Output;
|
||||
|
||||
const MIN_LENGTH: usize = Fal::MIN_LENGTH;
|
||||
|
||||
fn resolve(self) -> Self::AsyncOutput {
|
||||
fn resolve(self) -> impl Future<Output = Self::AsyncOutput> + Send {
|
||||
self.fut
|
||||
}
|
||||
|
||||
|
|
|
@ -98,9 +98,9 @@ where
|
|||
|
||||
impl<E, At, Ch, Rndr> AddAnyAttr<Rndr> for HtmlElement<E, At, Ch, Rndr>
|
||||
where
|
||||
E: ElementType + CreateElement<Rndr>,
|
||||
At: Attribute<Rndr>,
|
||||
Ch: RenderHtml<Rndr>,
|
||||
E: ElementType + CreateElement<Rndr> + Send,
|
||||
At: Attribute<Rndr> + Send,
|
||||
Ch: RenderHtml<Rndr> + Send,
|
||||
Rndr: Renderer,
|
||||
{
|
||||
type Output<SomeNewAttr: Attribute<Rndr>> = HtmlElement<
|
||||
|
@ -218,49 +218,15 @@ where
|
|||
Ok(())
|
||||
}
|
||||
}
|
||||
pin_project_lite::pin_project! {
|
||||
pub struct HtmlElementFuture<E, At, Ch, Rndr> {
|
||||
sync_fields: Option<(E, At)>,
|
||||
#[pin]
|
||||
children_fut: Ch,
|
||||
rndr: PhantomData<Rndr>,
|
||||
}
|
||||
}
|
||||
|
||||
impl<E, At, Ch, Rndr> Future for HtmlElementFuture<E, At, Ch, Rndr>
|
||||
where
|
||||
Ch: Future,
|
||||
{
|
||||
type Output = HtmlElement<E, At, Ch::Output, Rndr>;
|
||||
|
||||
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
let this = self.project();
|
||||
match this.children_fut.poll(cx) {
|
||||
Poll::Ready(children) => {
|
||||
let (tag, attributes) = this.sync_fields.take().expect(
|
||||
"tried to take synchronous fields from HtmlElementFuture \
|
||||
more than once",
|
||||
);
|
||||
Poll::Ready(HtmlElement {
|
||||
tag,
|
||||
attributes,
|
||||
children,
|
||||
rndr: PhantomData,
|
||||
})
|
||||
}
|
||||
Poll::Pending => Poll::Pending,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<E, At, Ch, Rndr> RenderHtml<Rndr> for HtmlElement<E, At, Ch, Rndr>
|
||||
where
|
||||
E: ElementType + CreateElement<Rndr>,
|
||||
At: Attribute<Rndr>,
|
||||
Ch: RenderHtml<Rndr>,
|
||||
E: ElementType + CreateElement<Rndr> + Send,
|
||||
At: Attribute<Rndr> + Send,
|
||||
Ch: RenderHtml<Rndr> + Send,
|
||||
Rndr: Renderer,
|
||||
{
|
||||
type AsyncOutput = HtmlElementFuture<E, At, Ch::AsyncOutput, Rndr>;
|
||||
type AsyncOutput = HtmlElement<E, At, Ch::AsyncOutput, Rndr>;
|
||||
|
||||
const MIN_LENGTH: usize = if E::SELF_CLOSING {
|
||||
3 // < ... />
|
||||
|
@ -275,11 +241,12 @@ where
|
|||
+ E::TAG.len()
|
||||
};
|
||||
|
||||
fn resolve(self) -> Self::AsyncOutput {
|
||||
HtmlElementFuture {
|
||||
sync_fields: Some((self.tag, self.attributes)),
|
||||
children_fut: self.children.resolve(),
|
||||
rndr: self.rndr,
|
||||
async fn resolve(self) -> Self::AsyncOutput {
|
||||
HtmlElement {
|
||||
tag: self.tag,
|
||||
rndr: PhantomData,
|
||||
attributes: self.attributes,
|
||||
children: self.children.resolve().await,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -83,8 +83,8 @@ where
|
|||
+ "data-component".len()
|
||||
+ View::MIN_LENGTH;
|
||||
|
||||
fn resolve(self) -> Self::AsyncOutput {
|
||||
self.view.resolve()
|
||||
async fn resolve(self) -> Self::AsyncOutput {
|
||||
self.view.resolve().await
|
||||
}
|
||||
|
||||
fn to_html_with_buf(self, buf: &mut String, position: &mut Position) {
|
||||
|
@ -187,9 +187,9 @@ where
|
|||
+ "</>".len()
|
||||
+ View::MIN_LENGTH;
|
||||
|
||||
fn resolve(self) -> Self::AsyncOutput {
|
||||
async fn resolve(self) -> Self::AsyncOutput {
|
||||
// TODO should this be wrapped?
|
||||
self.view.resolve()
|
||||
self.view.resolve().await
|
||||
}
|
||||
|
||||
fn to_html_with_buf(self, buf: &mut String, position: &mut Position) {
|
||||
|
|
|
@ -52,12 +52,12 @@ impl<R> RenderHtml<R> for Doctype<R>
|
|||
where
|
||||
R: Renderer + Send,
|
||||
{
|
||||
type AsyncOutput = Ready<Self>;
|
||||
type AsyncOutput = Self;
|
||||
|
||||
const MIN_LENGTH: usize = "<!DOCTYPE html>".len();
|
||||
|
||||
fn resolve(self) -> Self::AsyncOutput {
|
||||
ready(self)
|
||||
async fn resolve(self) -> Self::AsyncOutput {
|
||||
self
|
||||
}
|
||||
|
||||
fn to_html_with_buf(self, buf: &mut String, _position: &mut Position) {
|
||||
|
|
|
@ -47,12 +47,12 @@ impl<R> RenderHtml<R> for Oco<'static, str>
|
|||
where
|
||||
R: Renderer,
|
||||
{
|
||||
type AsyncOutput = Ready<Self>;
|
||||
type AsyncOutput = Self;
|
||||
|
||||
const MIN_LENGTH: usize = 0;
|
||||
|
||||
fn resolve(self) -> Self::AsyncOutput {
|
||||
ready(self)
|
||||
async fn resolve(self) -> Self::AsyncOutput {
|
||||
self
|
||||
}
|
||||
|
||||
fn to_html_with_buf(self, buf: &mut String, position: &mut Position) {
|
||||
|
|
|
@ -87,7 +87,7 @@ Ok(())
|
|||
R: Renderer,
|
||||
G: Deref<Target = $child_type> + Send
|
||||
{
|
||||
type AsyncOutput = Ready<Self>;
|
||||
type AsyncOutput = Self;
|
||||
|
||||
const MIN_LENGTH: usize = 0;
|
||||
|
||||
|
@ -133,8 +133,8 @@ Ok(())
|
|||
[<ReadGuard $child_type:camel State>](node, *self)
|
||||
}
|
||||
|
||||
fn resolve(self) -> Self::AsyncOutput {
|
||||
ready(self)
|
||||
async fn resolve(self) -> Self::AsyncOutput {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -247,7 +247,7 @@ where
|
|||
|
||||
G: Deref<Target = String> + Send,
|
||||
{
|
||||
type AsyncOutput = Ready<Self>;
|
||||
type AsyncOutput = Self;
|
||||
|
||||
const MIN_LENGTH: usize = 0;
|
||||
|
||||
|
@ -269,8 +269,8 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
fn resolve(self) -> Self::AsyncOutput {
|
||||
ready(self)
|
||||
async fn resolve(self) -> Self::AsyncOutput {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -207,7 +207,7 @@ where
|
|||
|
||||
impl<F, V, R> RenderHtml<R> for F
|
||||
where
|
||||
F: FnMut() -> V + 'static,
|
||||
F: FnMut() -> V + Send + 'static,
|
||||
V: RenderHtml<R>,
|
||||
V::State: 'static,
|
||||
V::FallibleState: 'static,
|
||||
|
@ -217,8 +217,8 @@ where
|
|||
|
||||
const MIN_LENGTH: usize = 0;
|
||||
|
||||
fn resolve(mut self) -> Self::AsyncOutput {
|
||||
self().resolve()
|
||||
async fn resolve(mut self) -> Self::AsyncOutput {
|
||||
self().resolve().await
|
||||
}
|
||||
|
||||
fn html_len(&self) -> usize {
|
||||
|
@ -263,7 +263,7 @@ where
|
|||
|
||||
impl<F, V, R> AddAnyAttr<R> for F
|
||||
where
|
||||
F: FnMut() -> V + 'static,
|
||||
F: FnMut() -> V + Send + 'static,
|
||||
V: RenderHtml<R>,
|
||||
V::State: 'static,
|
||||
V::FallibleState: 'static,
|
||||
|
@ -484,12 +484,12 @@ mod stable {
|
|||
V::FallibleState: 'static,
|
||||
R: Renderer + 'static,
|
||||
{
|
||||
type AsyncOutput = Ready<Self>;
|
||||
type AsyncOutput = Self;
|
||||
|
||||
const MIN_LENGTH: usize = 0;
|
||||
|
||||
fn resolve(self) -> Self::AsyncOutput {
|
||||
ready(self)
|
||||
async fn resolve(self) -> Self::AsyncOutput {
|
||||
self
|
||||
}
|
||||
|
||||
fn html_len(&self) -> usize {
|
||||
|
@ -611,12 +611,12 @@ mod stable {
|
|||
V::FallibleState: 'static,
|
||||
R: Renderer + 'static,
|
||||
{
|
||||
type AsyncOutput = Ready<Self>;
|
||||
type AsyncOutput = Self;
|
||||
|
||||
const MIN_LENGTH: usize = 0;
|
||||
|
||||
fn resolve(self) -> Self::AsyncOutput {
|
||||
ready(self)
|
||||
async fn resolve(self) -> Self::AsyncOutput {
|
||||
self
|
||||
}
|
||||
|
||||
fn html_len(&self) -> usize {
|
||||
|
|
|
@ -99,7 +99,7 @@ where
|
|||
R: Renderer,
|
||||
{
|
||||
// TODO
|
||||
type AsyncOutput = std::future::Ready<OwnedView<T::AsyncOutput, R>>;
|
||||
type AsyncOutput = OwnedView<T::AsyncOutput, R>;
|
||||
|
||||
const MIN_LENGTH: usize = T::MIN_LENGTH;
|
||||
|
||||
|
@ -136,7 +136,7 @@ where
|
|||
OwnedViewState::new(state, self.owner)
|
||||
}
|
||||
|
||||
fn resolve(self) -> Self::AsyncOutput {
|
||||
async fn resolve(self) -> Self::AsyncOutput {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -287,9 +287,9 @@ impl<R> RenderHtml<R> for AnyView<R>
|
|||
where
|
||||
R: Renderer + 'static,
|
||||
{
|
||||
type AsyncOutput = Ready<Self>;
|
||||
type AsyncOutput = Self;
|
||||
|
||||
fn resolve(self) -> Self::AsyncOutput {
|
||||
async fn resolve(self) -> Self::AsyncOutput {
|
||||
// we probably do need a function for this
|
||||
todo!()
|
||||
}
|
||||
|
|
|
@ -136,16 +136,12 @@ where
|
|||
B: RenderHtml<Rndr>,
|
||||
Rndr: Renderer,
|
||||
{
|
||||
type AsyncOutput = EitherFuture<A::AsyncOutput, B::AsyncOutput>;
|
||||
type AsyncOutput = Either<A::AsyncOutput, B::AsyncOutput>;
|
||||
|
||||
fn resolve(self) -> Self::AsyncOutput {
|
||||
async fn resolve(self) -> Self::AsyncOutput {
|
||||
match self {
|
||||
Either::Left(left) => EitherFuture::Left {
|
||||
inner: left.resolve(),
|
||||
},
|
||||
Either::Right(right) => EitherFuture::Right {
|
||||
inner: right.resolve(),
|
||||
},
|
||||
Either::Left(left) => Either::Left(left.resolve().await),
|
||||
Either::Right(right) => Either::Right(right.resolve().await),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -305,11 +301,11 @@ where
|
|||
B: RenderHtml<Rndr>,
|
||||
Rndr: Renderer,
|
||||
{
|
||||
type AsyncOutput = EitherFuture<A::AsyncOutput, B::AsyncOutput>;
|
||||
type AsyncOutput = Either<A::AsyncOutput, B::AsyncOutput>;
|
||||
|
||||
const MIN_LENGTH: usize = 0;
|
||||
|
||||
fn resolve(self) -> Self::AsyncOutput {
|
||||
async fn resolve(self) -> Self::AsyncOutput {
|
||||
todo!()
|
||||
}
|
||||
|
||||
|
@ -506,13 +502,13 @@ macro_rules! tuples {
|
|||
$($ty: RenderHtml<Rndr>,)*
|
||||
Rndr: Renderer,
|
||||
{
|
||||
type AsyncOutput = [<EitherOf $num Future>]<$($ty::AsyncOutput,)*>;
|
||||
type AsyncOutput = [<EitherOf $num>]<$($ty::AsyncOutput,)*>;
|
||||
|
||||
const MIN_LENGTH: usize = max_usize(&[$($ty ::MIN_LENGTH,)*]);
|
||||
|
||||
fn resolve(self) -> Self::AsyncOutput {
|
||||
async fn resolve(self) -> Self::AsyncOutput {
|
||||
match self {
|
||||
$([<EitherOf $num>]::$ty(this) => [<EitherOf $num Future>]::$ty { inner: this.resolve() },)*
|
||||
$([<EitherOf $num>]::$ty(this) => [<EitherOf $num>]::$ty(this.resolve().await),)*
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -138,16 +138,14 @@ where
|
|||
R: Renderer,
|
||||
E: Into<AnyError> + Send + 'static,
|
||||
{
|
||||
type AsyncOutput = ResultFuture<T::AsyncOutput, E>;
|
||||
type AsyncOutput = Result<T::AsyncOutput, E>;
|
||||
|
||||
const MIN_LENGTH: usize = T::MIN_LENGTH;
|
||||
|
||||
fn resolve(self) -> Self::AsyncOutput {
|
||||
async fn resolve(self) -> Self::AsyncOutput {
|
||||
match self {
|
||||
Ok(view) => ResultFuture::Ok {
|
||||
inner: view.resolve(),
|
||||
},
|
||||
Err(e) => ResultFuture::Err { inner: Some(e) },
|
||||
Ok(view) => Ok(view.resolve().await),
|
||||
Err(e) => Err(e),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -204,37 +202,6 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
pin_project! {
|
||||
#[project = ResultFutureProj]
|
||||
pub enum ResultFuture<T, E> {
|
||||
Ok {
|
||||
#[pin]
|
||||
inner: T
|
||||
},
|
||||
Err { inner: Option<E> }
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, E> Future for ResultFuture<T, E>
|
||||
where
|
||||
T: Future,
|
||||
{
|
||||
type Output = Result<T::Output, E>;
|
||||
|
||||
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
let this = self.project();
|
||||
match this {
|
||||
ResultFutureProj::Err { inner } => Poll::Ready(Err(inner
|
||||
.take()
|
||||
.expect("ResultFuture polled twice"))),
|
||||
ResultFutureProj::Ok { inner } => match inner.poll(cx) {
|
||||
Poll::Ready(value) => Poll::Ready(Ok(value)),
|
||||
Poll::Pending => Poll::Pending,
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
pub trait TryCatchBoundary<Fal, FalFn, Rndr>
|
||||
where
|
||||
|
@ -384,7 +351,7 @@ where
|
|||
|
||||
const MIN_LENGTH: usize = Fal::MIN_LENGTH;
|
||||
|
||||
fn resolve(self) -> Self::AsyncOutput {
|
||||
async fn resolve(self) -> Self::AsyncOutput {
|
||||
todo!()
|
||||
}
|
||||
|
||||
|
|
|
@ -85,16 +85,14 @@ where
|
|||
T: RenderHtml<R>,
|
||||
R: Renderer,
|
||||
{
|
||||
type AsyncOutput = OptionFuture<T::AsyncOutput>;
|
||||
type AsyncOutput = Option<T::AsyncOutput>;
|
||||
|
||||
const MIN_LENGTH: usize = T::MIN_LENGTH;
|
||||
|
||||
fn resolve(self) -> Self::AsyncOutput {
|
||||
async fn resolve(self) -> Self::AsyncOutput {
|
||||
match self {
|
||||
None => OptionFuture::None,
|
||||
Some(value) => OptionFuture::Some {
|
||||
inner: value.resolve(),
|
||||
},
|
||||
None => None,
|
||||
Some(value) => Some(value.resolve().await),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -200,35 +198,6 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
pin_project! {
|
||||
#[project = OptionFutureProj]
|
||||
pub enum OptionFuture<T> {
|
||||
None,
|
||||
Some {
|
||||
#[pin]
|
||||
inner: T
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Future for OptionFuture<T>
|
||||
where
|
||||
T: Future,
|
||||
{
|
||||
type Output = Option<T::Output>;
|
||||
|
||||
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
let this = self.project();
|
||||
match this {
|
||||
OptionFutureProj::None => Poll::Ready(None),
|
||||
OptionFutureProj::Some { inner } => match inner.poll(cx) {
|
||||
Poll::Pending => Poll::Pending,
|
||||
Poll::Ready(value) => Poll::Ready(Some(value)),
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, R> Render<R> for Vec<T>
|
||||
where
|
||||
T: Render<R>,
|
||||
|
@ -364,15 +333,17 @@ where
|
|||
impl<T, R> RenderHtml<R> for Vec<T>
|
||||
where
|
||||
T: RenderHtml<R>,
|
||||
<T::AsyncOutput as Future>::Output: Send,
|
||||
R: Renderer,
|
||||
{
|
||||
type AsyncOutput = JoinAll<T::AsyncOutput>;
|
||||
type AsyncOutput = Vec<T::AsyncOutput>;
|
||||
|
||||
const MIN_LENGTH: usize = 0;
|
||||
|
||||
fn resolve(self) -> Self::AsyncOutput {
|
||||
async fn resolve(self) -> Self::AsyncOutput {
|
||||
futures::future::join_all(self.into_iter().map(T::resolve))
|
||||
.await
|
||||
.into_iter()
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn html_len(&self) -> usize {
|
||||
|
|
|
@ -8,6 +8,7 @@ use drain_filter_polyfill::VecExt as VecDrainFilterExt;
|
|||
use indexmap::IndexSet;
|
||||
use rustc_hash::FxHasher;
|
||||
use std::{
|
||||
future::Future,
|
||||
hash::{BuildHasherDefault, Hash},
|
||||
marker::PhantomData,
|
||||
};
|
||||
|
@ -143,19 +144,25 @@ where
|
|||
impl<T, I, K, KF, VF, V, Rndr> RenderHtml<Rndr>
|
||||
for Keyed<T, I, K, KF, VF, V, Rndr>
|
||||
where
|
||||
I: IntoIterator<Item = T>,
|
||||
I: IntoIterator<Item = T> + Send,
|
||||
K: Eq + Hash + 'static,
|
||||
KF: Fn(&T) -> K,
|
||||
KF: Fn(&T) -> K + Send,
|
||||
V: RenderHtml<Rndr>,
|
||||
VF: Fn(T) -> V,
|
||||
VF: Fn(T) -> V + Send,
|
||||
Rndr: Renderer,
|
||||
{
|
||||
type AsyncOutput = std::future::Ready<()>;
|
||||
type AsyncOutput = Vec<V::AsyncOutput>; // TODO
|
||||
|
||||
const MIN_LENGTH: usize = 0;
|
||||
|
||||
fn resolve(self) -> Self::AsyncOutput {
|
||||
todo!()
|
||||
async fn resolve(self) -> Self::AsyncOutput {
|
||||
futures::future::join_all(self.items.into_iter().map(|item| {
|
||||
let view = (self.view_fn)(item);
|
||||
view.resolve()
|
||||
}))
|
||||
.await
|
||||
.into_iter()
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn to_html_with_buf(self, buf: &mut String, position: &mut Position) {
|
||||
|
|
|
@ -68,13 +68,13 @@ impl std::error::Error for NeverError {}
|
|||
/// whole view piece by piece.
|
||||
pub trait RenderHtml<R: Renderer>
|
||||
where
|
||||
Self: Render<R>,
|
||||
Self: Render<R> + Send,
|
||||
{
|
||||
type AsyncOutput: Future + Send; //RenderHtml<R> + Send;
|
||||
type AsyncOutput: RenderHtml<R>;
|
||||
|
||||
const MIN_LENGTH: usize;
|
||||
|
||||
fn resolve(self) -> Self::AsyncOutput;
|
||||
fn resolve(self) -> impl Future<Output = Self::AsyncOutput> + Send;
|
||||
|
||||
/// An estimated length for this view, when rendered to HTML.
|
||||
///
|
||||
|
|
|
@ -76,12 +76,12 @@ macro_rules! render_primitive {
|
|||
where
|
||||
R: Renderer,
|
||||
{
|
||||
type AsyncOutput = Ready<Self>;
|
||||
type AsyncOutput = Self;
|
||||
|
||||
const MIN_LENGTH: usize = 0;
|
||||
|
||||
fn resolve(self) -> Self::AsyncOutput {
|
||||
ready(self)
|
||||
async fn resolve(self) -> Self::AsyncOutput {
|
||||
self
|
||||
}
|
||||
|
||||
fn to_html_with_buf(self, buf: &mut String, position: &mut Position) {
|
||||
|
|
|
@ -161,12 +161,12 @@ where
|
|||
|
||||
R::Text: Mountable<R>,
|
||||
{
|
||||
type AsyncOutput = Ready<Self>;
|
||||
type AsyncOutput = Self;
|
||||
|
||||
const MIN_LENGTH: usize = V.len();
|
||||
|
||||
fn resolve(self) -> Self::AsyncOutput {
|
||||
ready(self)
|
||||
fn resolve(self) -> futures::future::Ready<Self::AsyncOutput> {
|
||||
futures::future::ready(self)
|
||||
}
|
||||
|
||||
fn to_html_with_buf(self, buf: &mut String, position: &mut Position) {
|
||||
|
|
|
@ -51,12 +51,12 @@ impl<'a, R> RenderHtml<R> for &'a str
|
|||
where
|
||||
R: Renderer,
|
||||
{
|
||||
type AsyncOutput = Ready<Self>;
|
||||
type AsyncOutput = Self;
|
||||
|
||||
const MIN_LENGTH: usize = 0;
|
||||
|
||||
fn resolve(self) -> Self::AsyncOutput {
|
||||
ready(self)
|
||||
async fn resolve(self) -> Self::AsyncOutput {
|
||||
self
|
||||
}
|
||||
|
||||
fn html_len(&self) -> usize {
|
||||
|
@ -185,10 +185,10 @@ where
|
|||
R: Renderer,
|
||||
{
|
||||
const MIN_LENGTH: usize = 0;
|
||||
type AsyncOutput = Ready<Self>;
|
||||
type AsyncOutput = Self;
|
||||
|
||||
fn resolve(self) -> Self::AsyncOutput {
|
||||
ready(self)
|
||||
async fn resolve(self) -> Self::AsyncOutput {
|
||||
self
|
||||
}
|
||||
|
||||
fn html_len(&self) -> usize {
|
||||
|
@ -291,12 +291,12 @@ impl<R> RenderHtml<R> for Rc<str>
|
|||
where
|
||||
R: Renderer,
|
||||
{
|
||||
type AsyncOutput = Ready<Self>;
|
||||
type AsyncOutput = Self;
|
||||
|
||||
const MIN_LENGTH: usize = 0;
|
||||
|
||||
fn resolve(self) -> Self::AsyncOutput {
|
||||
ready(self)
|
||||
async fn resolve(self) -> Self::AsyncOutput {
|
||||
self
|
||||
}
|
||||
|
||||
fn html_len(&self) -> usize {
|
||||
|
@ -397,12 +397,12 @@ impl<R> RenderHtml<R> for Arc<str>
|
|||
where
|
||||
R: Renderer,
|
||||
{
|
||||
type AsyncOutput = Ready<Self>;
|
||||
type AsyncOutput = Self;
|
||||
|
||||
const MIN_LENGTH: usize = 0;
|
||||
|
||||
fn resolve(self) -> Self::AsyncOutput {
|
||||
ready(self)
|
||||
async fn resolve(self) -> Self::AsyncOutput {
|
||||
self
|
||||
}
|
||||
|
||||
fn html_len(&self) -> usize {
|
||||
|
@ -503,12 +503,12 @@ impl<'a, R> RenderHtml<R> for Cow<'a, str>
|
|||
where
|
||||
R: Renderer,
|
||||
{
|
||||
type AsyncOutput = Ready<Self>;
|
||||
type AsyncOutput = Self;
|
||||
|
||||
const MIN_LENGTH: usize = 0;
|
||||
|
||||
fn resolve(self) -> Self::AsyncOutput {
|
||||
ready(self)
|
||||
async fn resolve(self) -> Self::AsyncOutput {
|
||||
self
|
||||
}
|
||||
|
||||
fn html_len(&self) -> usize {
|
||||
|
|
|
@ -86,7 +86,7 @@ where
|
|||
self.view.hydrate::<FROM_SERVER>(cursor, position)
|
||||
}
|
||||
|
||||
fn resolve(self) -> Self::AsyncOutput {
|
||||
async fn resolve(self) -> Self::AsyncOutput {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -41,7 +41,7 @@ impl<R> RenderHtml<R> for ()
|
|||
where
|
||||
R: Renderer,
|
||||
{
|
||||
type AsyncOutput = Ready<()>;
|
||||
type AsyncOutput = ();
|
||||
|
||||
const MIN_LENGTH: usize = 0;
|
||||
|
||||
|
@ -54,9 +54,7 @@ where
|
|||
) -> Self::State {
|
||||
}
|
||||
|
||||
fn resolve(self) -> Self::AsyncOutput {
|
||||
ready(())
|
||||
}
|
||||
async fn resolve(self) -> Self::AsyncOutput {}
|
||||
}
|
||||
|
||||
impl<Rndr> AddAnyAttr<Rndr> for ()
|
||||
|
@ -140,7 +138,7 @@ where
|
|||
A: RenderHtml<R>,
|
||||
R: Renderer,
|
||||
{
|
||||
type AsyncOutput = A::AsyncOutput;
|
||||
type AsyncOutput = (A::AsyncOutput,);
|
||||
|
||||
const MIN_LENGTH: usize = A::MIN_LENGTH;
|
||||
|
||||
|
@ -170,8 +168,8 @@ where
|
|||
self.0.hydrate::<FROM_SERVER>(cursor, position)
|
||||
}
|
||||
|
||||
fn resolve(self) -> Self::AsyncOutput {
|
||||
self.0.resolve()
|
||||
async fn resolve(self) -> Self::AsyncOutput {
|
||||
(self.0.resolve().await,)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -220,7 +218,7 @@ where
|
|||
}
|
||||
|
||||
macro_rules! impl_view_for_tuples {
|
||||
($joiner:ident => $first:ident, $($ty:ident),* $(,)?) => {
|
||||
($first:ident, $($ty:ident),* $(,)?) => {
|
||||
impl<$first, $($ty),*, Rndr> Render<Rndr> for ($first, $($ty,)*)
|
||||
where
|
||||
$first: Render<Rndr>,
|
||||
|
@ -274,7 +272,7 @@ macro_rules! impl_view_for_tuples {
|
|||
$($ty: RenderHtml<Rndr>),*,
|
||||
Rndr: Renderer,
|
||||
{
|
||||
type AsyncOutput = $joiner<$first::AsyncOutput, $($ty::AsyncOutput,)*>;
|
||||
type AsyncOutput = ($first::AsyncOutput, $($ty::AsyncOutput,)*);
|
||||
|
||||
const MIN_LENGTH: usize = $first::MIN_LENGTH $(+ $ty::MIN_LENGTH)*;
|
||||
|
||||
|
@ -317,13 +315,13 @@ macro_rules! impl_view_for_tuples {
|
|||
}
|
||||
}
|
||||
|
||||
fn resolve(self) -> Self::AsyncOutput {
|
||||
async fn resolve(self) -> Self::AsyncOutput {
|
||||
#[allow(non_snake_case)]
|
||||
let ($first, $($ty,)*) = self;
|
||||
$joiner::from((
|
||||
futures::join!(
|
||||
$first.resolve(),
|
||||
$($ty.resolve()),*
|
||||
))
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -421,86 +419,46 @@ macro_rules! impl_view_for_tuples {
|
|||
)
|
||||
}
|
||||
}
|
||||
|
||||
paste::paste! {
|
||||
pin_project! {
|
||||
pub struct $joiner<$first, $($ty,)*> {
|
||||
#[pin]
|
||||
[<$first:lower>]: $first,
|
||||
$(
|
||||
#[pin]
|
||||
pub [<$ty:lower>]: $ty,
|
||||
)*
|
||||
}
|
||||
}
|
||||
|
||||
impl<$first, $($ty,)*> From<($first, $($ty,)*)> for $joiner<$first, $($ty,)*> {
|
||||
fn from(value: ($first, $($ty,)*)) -> Self {
|
||||
#[allow(non_snake_case)]
|
||||
let ($first, $($ty,)*) = value;
|
||||
paste::paste! {
|
||||
$joiner {
|
||||
[<$first:lower>]: $first,
|
||||
$([<$ty:lower>]: $ty,)*
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<$first, $($ty,)*> Future for $joiner<$first, $($ty,)*>
|
||||
where $first: Future, $($ty: Future,)*
|
||||
{
|
||||
type Output = ($first::Output, $($ty::Output,)*);
|
||||
|
||||
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
let this = self.project();
|
||||
match (this.[<$first:lower>].poll(cx), $(this.[<$ty:lower>].poll(cx),)*) {
|
||||
(Poll::Ready($first), $(Poll::Ready($ty),)*) => Poll::Ready(($first, $($ty,)*)),
|
||||
_ => Poll::Pending
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
impl_view_for_tuples!(Join2 => A, B);
|
||||
impl_view_for_tuples!(Join3 => A, B, C);
|
||||
impl_view_for_tuples!(Join4 => A, B, C, D);
|
||||
impl_view_for_tuples!(Join5 => A, B, C, D, E);
|
||||
impl_view_for_tuples!(Join6 => A, B, C, D, E, F);
|
||||
impl_view_for_tuples!(Join7 => A, B, C, D, E, F, G);
|
||||
impl_view_for_tuples!(Join8 => A, B, C, D, E, F, G, H);
|
||||
impl_view_for_tuples!(Join9 => A, B, C, D, E, F, G, H, I);
|
||||
impl_view_for_tuples!(Join10 => A, B, C, D, E, F, G, H, I, J);
|
||||
impl_view_for_tuples!(Join11 => A, B, C, D, E, F, G, H, I, J, K);
|
||||
impl_view_for_tuples!(Join12 => A, B, C, D, E, F, G, H, I, J, K, L);
|
||||
impl_view_for_tuples!(Join13 => A, B, C, D, E, F, G, H, I, J, K, L, M);
|
||||
impl_view_for_tuples!(Join14 => A, B, C, D, E, F, G, H, I, J, K, L, M, N);
|
||||
impl_view_for_tuples!(Join15 => A, B, C, D, E, F, G, H, I, J, K, L, M, N, O);
|
||||
impl_view_for_tuples!(Join16 => A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P);
|
||||
impl_view_for_tuples!(Join17 => A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q);
|
||||
impl_view_for_tuples!(Join18 => A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R);
|
||||
impl_view_for_tuples!(Join19 => A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S);
|
||||
impl_view_for_tuples!(Join20 =>
|
||||
impl_view_for_tuples!(A, B);
|
||||
impl_view_for_tuples!(A, B, C);
|
||||
impl_view_for_tuples!(A, B, C, D);
|
||||
impl_view_for_tuples!(A, B, C, D, E);
|
||||
impl_view_for_tuples!(A, B, C, D, E, F);
|
||||
impl_view_for_tuples!(A, B, C, D, E, F, G);
|
||||
impl_view_for_tuples!(A, B, C, D, E, F, G, H);
|
||||
impl_view_for_tuples!(A, B, C, D, E, F, G, H, I);
|
||||
impl_view_for_tuples!(A, B, C, D, E, F, G, H, I, J);
|
||||
impl_view_for_tuples!(A, B, C, D, E, F, G, H, I, J, K);
|
||||
impl_view_for_tuples!(A, B, C, D, E, F, G, H, I, J, K, L);
|
||||
impl_view_for_tuples!(A, B, C, D, E, F, G, H, I, J, K, L, M);
|
||||
impl_view_for_tuples!(A, B, C, D, E, F, G, H, I, J, K, L, M, N);
|
||||
impl_view_for_tuples!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O);
|
||||
impl_view_for_tuples!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P);
|
||||
impl_view_for_tuples!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q);
|
||||
impl_view_for_tuples!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R);
|
||||
impl_view_for_tuples!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S);
|
||||
impl_view_for_tuples!(
|
||||
A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T
|
||||
);
|
||||
impl_view_for_tuples!(Join21 =>
|
||||
impl_view_for_tuples!(
|
||||
A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U
|
||||
);
|
||||
impl_view_for_tuples!(Join22 =>
|
||||
impl_view_for_tuples!(
|
||||
A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V
|
||||
);
|
||||
impl_view_for_tuples!(Join23 =>
|
||||
impl_view_for_tuples!(
|
||||
A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W
|
||||
);
|
||||
impl_view_for_tuples!(Join24 =>
|
||||
impl_view_for_tuples!(
|
||||
A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X
|
||||
);
|
||||
impl_view_for_tuples!(Join25 =>
|
||||
impl_view_for_tuples!(
|
||||
A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y
|
||||
);
|
||||
impl_view_for_tuples!(Join26 =>
|
||||
impl_view_for_tuples!(
|
||||
A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y,
|
||||
Z
|
||||
);
|
||||
|
|
Loading…
Reference in a new issue