1use super::{
2 add_attr::AddAnyAttr, MarkBranch, Mountable, Position, PositionState,
3 Render, RenderHtml,
4};
5use crate::{
6 html::attribute::{
7 any_attribute::AnyAttribute, Attribute, NamedAttributeKey,
8 NextAttribute,
9 },
10 hydration::Cursor,
11 ssr::StreamBuilder,
12};
13use either_of::*;
14use futures::future::join;
15
16impl<A, B> Render for Either<A, B>
17where
18 A: Render,
19 B: Render,
20{
21 type State = Either<A::State, B::State>;
22
23 fn build(self) -> Self::State {
24 match self {
25 Either::Left(left) => Either::Left(left.build()),
26 Either::Right(right) => Either::Right(right.build()),
27 }
28 }
29
30 fn rebuild(self, state: &mut Self::State) {
31 match (self, &mut *state) {
32 (Either::Left(new), Either::Left(old)) => {
33 new.rebuild(old);
34 }
35 (Either::Right(new), Either::Right(old)) => {
36 new.rebuild(old);
37 }
38 (Either::Right(new), Either::Left(old)) => {
39 let mut new_state = new.build();
40 old.insert_before_this(&mut new_state);
41 old.unmount();
42 *state = Either::Right(new_state);
43 }
44 (Either::Left(new), Either::Right(old)) => {
45 let mut new_state = new.build();
46 old.insert_before_this(&mut new_state);
47 old.unmount();
48 *state = Either::Left(new_state);
49 }
50 }
51 }
52}
53
54impl<A, B> Mountable for Either<A, B>
55where
56 A: Mountable,
57 B: Mountable,
58{
59 fn unmount(&mut self) {
60 match self {
61 Either::Left(left) => left.unmount(),
62 Either::Right(right) => right.unmount(),
63 }
64 }
65
66 fn mount(
67 &mut self,
68 parent: &crate::renderer::types::Element,
69 marker: Option<&crate::renderer::types::Node>,
70 ) {
71 match self {
72 Either::Left(left) => left.mount(parent, marker),
73 Either::Right(right) => right.mount(parent, marker),
74 }
75 }
76
77 fn insert_before_this(&self, child: &mut dyn Mountable) -> bool {
78 match &self {
79 Either::Left(left) => left.insert_before_this(child),
80 Either::Right(right) => right.insert_before_this(child),
81 }
82 }
83
84 fn elements(&self) -> Vec<crate::renderer::types::Element> {
85 match &self {
86 Either::Left(left) => left.elements(),
87 Either::Right(right) => right.elements(),
88 }
89 }
90}
91
92impl<A, B> AddAnyAttr for Either<A, B>
93where
94 A: RenderHtml,
95 B: RenderHtml,
96{
97 type Output<SomeNewAttr: Attribute> = Either<
98 <A as AddAnyAttr>::Output<SomeNewAttr>,
99 <B as AddAnyAttr>::Output<SomeNewAttr>,
100 >;
101
102 fn add_any_attr<NewAttr: Attribute>(
103 self,
104 attr: NewAttr,
105 ) -> Self::Output<NewAttr>
106 where
107 Self::Output<NewAttr>: RenderHtml,
108 {
109 match self {
110 Either::Left(i) => Either::Left(i.add_any_attr(attr)),
111 Either::Right(i) => Either::Right(i.add_any_attr(attr)),
112 }
113 }
114}
115
116const fn max_usize(vals: &[usize]) -> usize {
117 let mut max = 0;
118 let len = vals.len();
119 let mut i = 0;
120 while i < len {
121 if vals[i] > max {
122 max = vals[i];
123 }
124 i += 1;
125 }
126 max
127}
128
129#[cfg(not(erase_components))]
130impl<A, B> NextAttribute for Either<A, B>
131where
132 B: NextAttribute,
133 A: NextAttribute,
134{
135 type Output<NewAttr: Attribute> = Either<
136 <A as NextAttribute>::Output<NewAttr>,
137 <B as NextAttribute>::Output<NewAttr>,
138 >;
139
140 fn add_any_attr<NewAttr: Attribute>(
141 self,
142 new_attr: NewAttr,
143 ) -> Self::Output<NewAttr> {
144 match self {
145 Either::Left(left) => Either::Left(left.add_any_attr(new_attr)),
146 Either::Right(right) => Either::Right(right.add_any_attr(new_attr)),
147 }
148 }
149}
150
151#[cfg(erase_components)]
152impl<A, B> NextAttribute for Either<A, B>
153where
154 B: crate::html::attribute::any_attribute::IntoAnyAttribute,
155 A: crate::html::attribute::any_attribute::IntoAnyAttribute,
156{
157 type Output<NewAttr: Attribute> = Vec<AnyAttribute>;
158
159 fn add_any_attr<NewAttr: Attribute>(
160 self,
161 new_attr: NewAttr,
162 ) -> Self::Output<NewAttr> {
163 use crate::html::attribute::any_attribute::IntoAnyAttribute;
164
165 vec![
166 match self {
167 Either::Left(left) => left.into_any_attr(),
168 Either::Right(right) => right.into_any_attr(),
169 },
170 new_attr.into_any_attr(),
171 ]
172 }
173}
174
175impl<A, B> Attribute for Either<A, B>
176where
177 B: Attribute,
178 A: Attribute,
179{
180 const MIN_LENGTH: usize = max_usize(&[A::MIN_LENGTH, B::MIN_LENGTH]);
181
182 type AsyncOutput = Either<A::AsyncOutput, B::AsyncOutput>;
183 type State = Either<A::State, B::State>;
184 type Cloneable = Either<A::Cloneable, B::Cloneable>;
185 type CloneableOwned = Either<A::CloneableOwned, B::CloneableOwned>;
186
187 fn html_len(&self) -> usize {
188 match self {
189 Either::Left(left) => left.html_len(),
190 Either::Right(right) => right.html_len(),
191 }
192 }
193
194 fn to_html(
195 self,
196 buf: &mut String,
197 class: &mut String,
198 style: &mut String,
199 inner_html: &mut String,
200 ) {
201 match self {
202 Either::Left(left) => left.to_html(buf, class, style, inner_html),
203 Either::Right(right) => {
204 right.to_html(buf, class, style, inner_html)
205 }
206 }
207 }
208
209 fn hydrate<const FROM_SERVER: bool>(
210 self,
211 el: &crate::renderer::types::Element,
212 ) -> Self::State {
213 match self {
214 Either::Left(left) => Either::Left(left.hydrate::<FROM_SERVER>(el)),
215 Either::Right(right) => {
216 Either::Right(right.hydrate::<FROM_SERVER>(el))
217 }
218 }
219 }
220
221 fn build(self, el: &crate::renderer::types::Element) -> Self::State {
222 match self {
223 Either::Left(left) => Either::Left(left.build(el)),
224 Either::Right(right) => Either::Right(right.build(el)),
225 }
226 }
227
228 fn rebuild(self, state: &mut Self::State) {
229 match self {
230 Either::Left(left) => {
231 if let Some(state) = state.as_left_mut() {
232 left.rebuild(state)
233 }
234 }
235 Either::Right(right) => {
236 if let Some(state) = state.as_right_mut() {
237 right.rebuild(state)
238 }
239 }
240 }
241 }
242
243 fn into_cloneable(self) -> Self::Cloneable {
244 match self {
245 Either::Left(left) => Either::Left(left.into_cloneable()),
246 Either::Right(right) => Either::Right(right.into_cloneable()),
247 }
248 }
249
250 fn into_cloneable_owned(self) -> Self::CloneableOwned {
251 match self {
252 Either::Left(left) => Either::Left(left.into_cloneable_owned()),
253 Either::Right(right) => Either::Right(right.into_cloneable_owned()),
254 }
255 }
256
257 fn dry_resolve(&mut self) {
258 match self {
259 Either::Left(left) => left.dry_resolve(),
260 Either::Right(right) => right.dry_resolve(),
261 }
262 }
263
264 async fn resolve(self) -> Self::AsyncOutput {
265 match self {
266 Either::Left(left) => Either::Left(left.resolve().await),
267 Either::Right(right) => Either::Right(right.resolve().await),
268 }
269 }
270
271 fn keys(&self) -> Vec<NamedAttributeKey> {
272 match self {
273 Either::Left(left) => left.keys(),
274 Either::Right(right) => right.keys(),
275 }
276 }
277}
278
279impl<A, B> RenderHtml for Either<A, B>
280where
281 A: RenderHtml,
282 B: RenderHtml,
283{
284 type AsyncOutput = Either<A::AsyncOutput, B::AsyncOutput>;
285 type Owned = Either<A::Owned, B::Owned>;
286
287 fn dry_resolve(&mut self) {
288 match self {
289 Either::Left(left) => left.dry_resolve(),
290 Either::Right(right) => right.dry_resolve(),
291 }
292 }
293
294 async fn resolve(self) -> Self::AsyncOutput {
295 match self {
296 Either::Left(left) => Either::Left(left.resolve().await),
297 Either::Right(right) => Either::Right(right.resolve().await),
298 }
299 }
300
301 const MIN_LENGTH: usize = max_usize(&[A::MIN_LENGTH, B::MIN_LENGTH]);
302
303 #[inline(always)]
304 fn html_len(&self) -> usize {
305 match self {
306 Either::Left(i) => i.html_len(),
307 Either::Right(i) => i.html_len(),
308 }
309 }
310
311 fn to_html_with_buf(
312 self,
313 buf: &mut String,
314 position: &mut Position,
315 escape: bool,
316 mark_branches: bool,
317 extra_attrs: Vec<AnyAttribute>,
318 ) {
319 match self {
320 Either::Left(left) => {
321 if mark_branches && escape {
322 buf.open_branch("0");
323 }
324 left.to_html_with_buf(
325 buf,
326 position,
327 escape,
328 mark_branches,
329 extra_attrs,
330 );
331 if mark_branches && escape {
332 buf.close_branch("0");
333 if *position == Position::NextChildAfterText {
334 *position = Position::NextChild;
335 }
336 }
337 }
338 Either::Right(right) => {
339 if mark_branches && escape {
340 buf.open_branch("1");
341 }
342 right.to_html_with_buf(
343 buf,
344 position,
345 escape,
346 mark_branches,
347 extra_attrs,
348 );
349 if mark_branches && escape {
350 buf.close_branch("1");
351 if *position == Position::NextChildAfterText {
352 *position = Position::NextChild;
353 }
354 }
355 }
356 }
357 }
358
359 fn to_html_async_with_buf<const OUT_OF_ORDER: bool>(
360 self,
361 buf: &mut StreamBuilder,
362 position: &mut Position,
363 escape: bool,
364 mark_branches: bool,
365 extra_attrs: Vec<AnyAttribute>,
366 ) where
367 Self: Sized,
368 {
369 match self {
370 Either::Left(left) => {
371 if mark_branches && escape {
372 buf.open_branch("0");
373 }
374 left.to_html_async_with_buf::<OUT_OF_ORDER>(
375 buf,
376 position,
377 escape,
378 mark_branches,
379 extra_attrs,
380 );
381 if mark_branches && escape {
382 buf.close_branch("0");
383 if *position == Position::NextChildAfterText {
384 *position = Position::NextChild;
385 }
386 }
387 }
388 Either::Right(right) => {
389 if mark_branches && escape {
390 buf.open_branch("1");
391 }
392 right.to_html_async_with_buf::<OUT_OF_ORDER>(
393 buf,
394 position,
395 escape,
396 mark_branches,
397 extra_attrs,
398 );
399 if mark_branches && escape {
400 buf.close_branch("1");
401 if *position == Position::NextChildAfterText {
402 *position = Position::NextChild;
403 }
404 }
405 }
406 }
407 }
408
409 fn hydrate<const FROM_SERVER: bool>(
410 self,
411 cursor: &Cursor,
412 position: &PositionState,
413 ) -> Self::State {
414 if cfg!(feature = "mark_branches") {
415 cursor.advance_to_placeholder(position);
416 }
417 let state = match self {
418 Either::Left(left) => {
419 Either::Left(left.hydrate::<FROM_SERVER>(cursor, position))
420 }
421 Either::Right(right) => {
422 Either::Right(right.hydrate::<FROM_SERVER>(cursor, position))
423 }
424 };
425 if cfg!(feature = "mark_branches") {
426 cursor.advance_to_placeholder(position);
427 }
428 state
429 }
430
431 async fn hydrate_async(
432 self,
433 cursor: &Cursor,
434 position: &PositionState,
435 ) -> Self::State {
436 if cfg!(feature = "mark_branches") {
437 cursor.advance_to_placeholder(position);
438 }
439 let state = match self {
440 Either::Left(left) => {
441 Either::Left(left.hydrate_async(cursor, position).await)
442 }
443 Either::Right(right) => {
444 Either::Right(right.hydrate_async(cursor, position).await)
445 }
446 };
447 if cfg!(feature = "mark_branches") {
448 cursor.advance_to_placeholder(position);
449 }
450 state
451 }
452
453 fn into_owned(self) -> Self::Owned {
454 match self {
455 Either::Left(left) => Either::Left(left.into_owned()),
456 Either::Right(right) => Either::Right(right.into_owned()),
457 }
458 }
459}
460
461pub struct EitherKeepAlive<A, B> {
463 pub a: Option<A>,
465 pub b: Option<B>,
467 pub show_b: bool,
469}
470
471pub struct EitherKeepAliveState<A, B> {
473 a: Option<A>,
474 b: Option<B>,
475 showing_b: bool,
476}
477
478impl<A, B> Render for EitherKeepAlive<A, B>
479where
480 A: Render,
481 B: Render,
482{
483 type State = EitherKeepAliveState<A::State, B::State>;
484
485 fn build(self) -> Self::State {
486 let showing_b = self.show_b;
487 let a = self.a.map(Render::build);
488 let b = self.b.map(Render::build);
489 EitherKeepAliveState { a, b, showing_b }
490 }
491
492 fn rebuild(self, state: &mut Self::State) {
493 match (self.a, &mut state.a) {
495 (Some(new), Some(old)) => new.rebuild(old),
496 (Some(new), None) => state.a = Some(new.build()),
497 _ => {}
498 }
499
500 match (self.b, &mut state.b) {
502 (Some(new), Some(old)) => new.rebuild(old),
503 (Some(new), None) => state.b = Some(new.build()),
504 _ => {}
505 }
506
507 match (self.show_b, state.showing_b) {
508 (true, false) => match (&mut state.a, &mut state.b) {
510 (Some(a), Some(b)) => {
511 a.insert_before_this(b);
512 a.unmount();
513 }
514 _ => unreachable!(),
515 },
516 (false, true) => match (&mut state.a, &mut state.b) {
518 (Some(a), Some(b)) => {
519 b.insert_before_this(a);
520 b.unmount();
521 }
522 _ => unreachable!(),
523 },
524 _ => {}
525 }
526 state.showing_b = self.show_b;
527 }
528}
529
530impl<A, B> AddAnyAttr for EitherKeepAlive<A, B>
531where
532 A: RenderHtml,
533 B: RenderHtml,
534{
535 type Output<SomeNewAttr: Attribute> = EitherKeepAlive<
536 <A as AddAnyAttr>::Output<SomeNewAttr::Cloneable>,
537 <B as AddAnyAttr>::Output<SomeNewAttr::Cloneable>,
538 >;
539
540 fn add_any_attr<NewAttr: Attribute>(
541 self,
542 attr: NewAttr,
543 ) -> Self::Output<NewAttr>
544 where
545 Self::Output<NewAttr>: RenderHtml,
546 {
547 let EitherKeepAlive { a, b, show_b } = self;
548 let attr = attr.into_cloneable();
549 EitherKeepAlive {
550 a: a.map(|a| a.add_any_attr(attr.clone())),
551 b: b.map(|b| b.add_any_attr(attr.clone())),
552 show_b,
553 }
554 }
555}
556
557impl<A, B> RenderHtml for EitherKeepAlive<A, B>
558where
559 A: RenderHtml,
560 B: RenderHtml,
561{
562 type AsyncOutput = EitherKeepAlive<A::AsyncOutput, B::AsyncOutput>;
563 type Owned = EitherKeepAlive<A::Owned, B::Owned>;
564
565 const MIN_LENGTH: usize = 0;
566
567 fn dry_resolve(&mut self) {
568 if let Some(inner) = &mut self.a {
569 inner.dry_resolve();
570 }
571 if let Some(inner) = &mut self.b {
572 inner.dry_resolve();
573 }
574 }
575
576 async fn resolve(self) -> Self::AsyncOutput {
577 let EitherKeepAlive { a, b, show_b } = self;
578 let (a, b) = join(
579 async move {
580 match a {
581 Some(a) => Some(a.resolve().await),
582 None => None,
583 }
584 },
585 async move {
586 match b {
587 Some(b) => Some(b.resolve().await),
588 None => None,
589 }
590 },
591 )
592 .await;
593 EitherKeepAlive { a, b, show_b }
594 }
595
596 fn to_html_with_buf(
597 self,
598 buf: &mut String,
599 position: &mut Position,
600 escape: bool,
601 mark_branches: bool,
602 extra_attrs: Vec<AnyAttribute>,
603 ) {
604 if self.show_b {
605 self.b
606 .expect("rendering B to HTML without filling it")
607 .to_html_with_buf(
608 buf,
609 position,
610 escape,
611 mark_branches,
612 extra_attrs,
613 );
614 } else {
615 self.a
616 .expect("rendering A to HTML without filling it")
617 .to_html_with_buf(
618 buf,
619 position,
620 escape,
621 mark_branches,
622 extra_attrs,
623 );
624 }
625 }
626
627 fn to_html_async_with_buf<const OUT_OF_ORDER: bool>(
628 self,
629 buf: &mut StreamBuilder,
630 position: &mut Position,
631 escape: bool,
632 mark_branches: bool,
633 extra_attrs: Vec<AnyAttribute>,
634 ) where
635 Self: Sized,
636 {
637 if self.show_b {
638 self.b
639 .expect("rendering B to HTML without filling it")
640 .to_html_async_with_buf::<OUT_OF_ORDER>(
641 buf,
642 position,
643 escape,
644 mark_branches,
645 extra_attrs,
646 );
647 } else {
648 self.a
649 .expect("rendering A to HTML without filling it")
650 .to_html_async_with_buf::<OUT_OF_ORDER>(
651 buf,
652 position,
653 escape,
654 mark_branches,
655 extra_attrs,
656 );
657 }
658 }
659
660 fn hydrate<const FROM_SERVER: bool>(
661 self,
662 cursor: &Cursor,
663 position: &PositionState,
664 ) -> Self::State {
665 let showing_b = self.show_b;
666 let a = self.a.map(|a| {
667 if showing_b {
668 a.build()
669 } else {
670 a.hydrate::<FROM_SERVER>(cursor, position)
671 }
672 });
673 let b = self.b.map(|b| {
674 if showing_b {
675 b.hydrate::<FROM_SERVER>(cursor, position)
676 } else {
677 b.build()
678 }
679 });
680
681 EitherKeepAliveState { showing_b, a, b }
682 }
683
684 async fn hydrate_async(
685 self,
686 cursor: &Cursor,
687 position: &PositionState,
688 ) -> Self::State {
689 let showing_b = self.show_b;
690 let a = if let Some(a) = self.a {
691 Some(if showing_b {
692 a.build()
693 } else {
694 a.hydrate_async(cursor, position).await
695 })
696 } else {
697 None
698 };
699 let b = if let Some(b) = self.b {
700 Some(if showing_b {
701 b.hydrate_async(cursor, position).await
702 } else {
703 b.build()
704 })
705 } else {
706 None
707 };
708
709 EitherKeepAliveState { showing_b, a, b }
710 }
711
712 fn into_owned(self) -> Self::Owned {
713 EitherKeepAlive {
714 a: self.a.map(|a| a.into_owned()),
715 b: self.b.map(|b| b.into_owned()),
716 show_b: self.show_b,
717 }
718 }
719}
720
721impl<A, B> Mountable for EitherKeepAliveState<A, B>
722where
723 A: Mountable,
724 B: Mountable,
725{
726 fn unmount(&mut self) {
727 if self.showing_b {
728 self.b.as_mut().expect("B was not present").unmount();
729 } else {
730 self.a.as_mut().expect("A was not present").unmount();
731 }
732 }
733
734 fn mount(
735 &mut self,
736 parent: &crate::renderer::types::Element,
737 marker: Option<&crate::renderer::types::Node>,
738 ) {
739 if self.showing_b {
740 self.b
741 .as_mut()
742 .expect("B was not present")
743 .mount(parent, marker);
744 } else {
745 self.a
746 .as_mut()
747 .expect("A was not present")
748 .mount(parent, marker);
749 }
750 }
751
752 fn insert_before_this(&self, child: &mut dyn Mountable) -> bool {
753 if self.showing_b {
754 self.b
755 .as_ref()
756 .expect("B was not present")
757 .insert_before_this(child)
758 } else {
759 self.a
760 .as_ref()
761 .expect("A was not present")
762 .insert_before_this(child)
763 }
764 }
765
766 fn elements(&self) -> Vec<crate::renderer::types::Element> {
767 if self.showing_b {
768 self.b
769 .as_ref()
770 .map(|inner| inner.elements())
771 .unwrap_or_default()
772 } else {
773 self.a
774 .as_ref()
775 .map(|inner| inner.elements())
776 .unwrap_or_default()
777 }
778 }
779}
780
781macro_rules! tuples {
782 ($num:literal => $($ty:ident),*) => {
783 paste::paste! {
784 #[doc = concat!("Retained view state for ", stringify!([<EitherOf $num>]), ".")]
785 pub struct [<EitherOf $num State>]<$($ty,)*>
786 where
787 $($ty: Render,)*
788
789 {
790 pub state: [<EitherOf $num>]<$($ty::State,)*>,
792 }
793
794 impl<$($ty,)*> Mountable for [<EitherOf $num State>]<$($ty,)*>
795 where
796 $($ty: Render,)*
797
798 {
799 fn unmount(&mut self) {
800 match &mut self.state {
801 $([<EitherOf $num>]::$ty(this) => [<EitherOf $num>]::$ty(this.unmount()),)*
802 };
803 }
804
805 fn mount(
806 &mut self,
807 parent: &crate::renderer::types::Element,
808 marker: Option<&crate::renderer::types::Node>,
809 ) {
810 match &mut self.state {
811 $([<EitherOf $num>]::$ty(this) => [<EitherOf $num>]::$ty(this.mount(parent, marker)),)*
812 };
813 }
814
815 fn insert_before_this(&self,
816 child: &mut dyn Mountable,
817 ) -> bool {
818 match &self.state {
819 $([<EitherOf $num>]::$ty(this) =>this.insert_before_this(child),)*
820 }
821 }
822
823 fn elements(&self) -> Vec<crate::renderer::types::Element> {
824 match &self.state {
825 $([<EitherOf $num>]::$ty(this) => this.elements(),)*
826 }
827 }
828 }
829
830 impl<$($ty,)*> Render for [<EitherOf $num>]<$($ty,)*>
831 where
832 $($ty: Render,)*
833
834 {
835 type State = [<EitherOf $num State>]<$($ty,)*>;
836
837
838 fn build(self) -> Self::State {
839 let state = match self {
840 $([<EitherOf $num>]::$ty(this) => [<EitherOf $num>]::$ty(this.build()),)*
841 };
842 Self::State { state }
843 }
844
845 fn rebuild(self, state: &mut Self::State) {
846 let new_state = match (self, &mut state.state) {
847 $(([<EitherOf $num>]::$ty(new), [<EitherOf $num>]::$ty(old)) => { return new.rebuild(old); },)*
849 $(([<EitherOf $num>]::$ty(new), _) => {
851 let mut new = new.build();
852 state.insert_before_this(&mut new);
853 [<EitherOf $num>]::$ty(new)
854 },)*
855 };
856
857 match &mut state.state {
859 $([<EitherOf $num>]::$ty(this) => this.unmount(),)*
860 };
861
862 state.state = new_state;
864 }
865 }
866
867 impl<$($ty,)*> AddAnyAttr for [<EitherOf $num>]<$($ty,)*>
868 where
869 $($ty: RenderHtml,)*
870
871 {
872 type Output<SomeNewAttr: Attribute> = [<EitherOf $num>]<
873 $(<$ty as AddAnyAttr>::Output<SomeNewAttr>,)*
874 >;
875
876 fn add_any_attr<NewAttr: Attribute>(
877 self,
878 attr: NewAttr,
879 ) -> Self::Output<NewAttr>
880 where
881 Self::Output<NewAttr>: RenderHtml,
882 {
883 match self {
884 $([<EitherOf $num>]::$ty(this) => [<EitherOf $num>]::$ty(this.add_any_attr(attr)),)*
885 }
886 }
887 }
888
889 impl<$($ty,)*> RenderHtml for [<EitherOf $num>]<$($ty,)*>
890 where
891 $($ty: RenderHtml,)*
892
893 {
894 type AsyncOutput = [<EitherOf $num>]<$($ty::AsyncOutput,)*>;
895 type Owned = [<EitherOf $num>]<$($ty::Owned,)*>;
896
897 const MIN_LENGTH: usize = max_usize(&[$($ty ::MIN_LENGTH,)*]);
898
899
900 fn dry_resolve(&mut self) {
901 match self {
902 $([<EitherOf $num>]::$ty(this) => {
903 this.dry_resolve();
904 })*
905 }
906 }
907
908 async fn resolve(self) -> Self::AsyncOutput {
909 match self {
910 $([<EitherOf $num>]::$ty(this) => [<EitherOf $num>]::$ty(this.resolve().await),)*
911 }
912 }
913
914 #[inline(always)]
915 fn html_len(&self) -> usize {
916 match self {
917 $([<EitherOf $num>]::$ty(i) => i.html_len(),)*
918 }
919 }
920
921 fn to_html_with_buf(
922 self,
923 buf: &mut String,
924 position: &mut Position,
925 escape: bool,
926 mark_branches: bool,
927 extra_attrs: Vec<AnyAttribute>
928 ) {
929 match self {
930 $([<EitherOf $num>]::$ty(this) => {
931 if mark_branches && escape {
932 buf.open_branch(stringify!($ty));
933 }
934 this.to_html_with_buf(buf, position, escape, mark_branches, extra_attrs);
935 if mark_branches && escape {
936 buf.close_branch(stringify!($ty));
937 if *position == Position::NextChildAfterText {
938 *position = Position::NextChild;
939 }
940 }
941 })*
942 }
943 }
944
945 fn to_html_async_with_buf<const OUT_OF_ORDER: bool>(
946 self,
947 buf: &mut StreamBuilder,
948 position: &mut Position,
949 escape: bool,
950 mark_branches: bool,
951 extra_attrs: Vec<AnyAttribute>
952 ) where
953 Self: Sized,
954 {
955 match self {
956 $([<EitherOf $num>]::$ty(this) => {
957 if mark_branches && escape {
958 buf.open_branch(stringify!($ty));
959 }
960 this.to_html_async_with_buf::<OUT_OF_ORDER>(buf, position, escape, mark_branches, extra_attrs);
961 if mark_branches && escape {
962 buf.close_branch(stringify!($ty));
963 if *position == Position::NextChildAfterText {
964 *position = Position::NextChild;
965 }
966 }
967 })*
968 }
969 }
970
971 fn hydrate<const FROM_SERVER: bool>(
972 self,
973 cursor: &Cursor,
974 position: &PositionState,
975 ) -> Self::State {
976 if cfg!(feature = "mark_branches") {
977 cursor.advance_to_placeholder(position);
978 }
979 let state = match self {
980 $([<EitherOf $num>]::$ty(this) => {
981 [<EitherOf $num>]::$ty(this.hydrate::<FROM_SERVER>(cursor, position))
982 })*
983 };
984 if cfg!(feature = "mark_branches") {
985 cursor.advance_to_placeholder(position);
986 }
987
988 Self::State { state }
989 }
990
991 async fn hydrate_async(
992 self,
993 cursor: &Cursor,
994 position: &PositionState,
995 ) -> Self::State {
996 if cfg!(feature = "mark_branches") {
997 cursor.advance_to_placeholder(position);
998 }
999 let state = match self {
1000 $([<EitherOf $num>]::$ty(this) => {
1001 [<EitherOf $num>]::$ty(this.hydrate_async(cursor, position).await)
1002 })*
1003 };
1004 if cfg!(feature = "mark_branches") {
1005 cursor.advance_to_placeholder(position);
1006 }
1007
1008 Self::State { state }
1009 }
1010
1011 fn into_owned(self) -> Self::Owned {
1012 match self {
1013 $([<EitherOf $num>]::$ty(this) => {
1014 [<EitherOf $num>]::$ty(this.into_owned())
1015 })*
1016 }
1017 }
1018 }
1019 }
1020 }
1021}
1022
1023tuples!(3 => A, B, C);
1024tuples!(4 => A, B, C, D);
1025tuples!(5 => A, B, C, D, E);
1026tuples!(6 => A, B, C, D, E, F);
1027tuples!(7 => A, B, C, D, E, F, G);
1028tuples!(8 => A, B, C, D, E, F, G, H);
1029tuples!(9 => A, B, C, D, E, F, G, H, I);
1030tuples!(10 => A, B, C, D, E, F, G, H, I, J);
1031tuples!(11 => A, B, C, D, E, F, G, H, I, J, K);
1032tuples!(12 => A, B, C, D, E, F, G, H, I, J, K, L);
1033tuples!(13 => A, B, C, D, E, F, G, H, I, J, K, L, M);
1034tuples!(14 => A, B, C, D, E, F, G, H, I, J, K, L, M, N);
1035tuples!(15 => A, B, C, D, E, F, G, H, I, J, K, L, M, N, O);
1036tuples!(16 => A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P);