Skip to content

Commit

Permalink
feat: implement Attribute for Either<A, B> (#3556)
Browse files Browse the repository at this point in the history
  • Loading branch information
alexisfontaine authored Feb 7, 2025
1 parent 9d3a743 commit 88b1b2d
Showing 1 changed file with 121 additions and 1 deletion.
122 changes: 121 additions & 1 deletion tachys/src/view/either.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ use super::{
Render, RenderHtml,
};
use crate::{
html::attribute::Attribute, hydration::Cursor, ssr::StreamBuilder,
html::attribute::{Attribute, NextAttribute},
hydration::Cursor,
ssr::StreamBuilder,
};
use either_of::*;
use futures::future::join;
Expand Down Expand Up @@ -114,6 +116,124 @@ const fn max_usize(vals: &[usize]) -> usize {
max
}

impl<A, B> NextAttribute for Either<A, B>
where
B: NextAttribute,
A: NextAttribute,
{
type Output<NewAttr: Attribute> = Either<
<A as NextAttribute>::Output<NewAttr>,
<B as NextAttribute>::Output<NewAttr>,
>;

fn add_any_attr<NewAttr: Attribute>(
self,
new_attr: NewAttr,
) -> Self::Output<NewAttr> {
match self {
Either::Left(left) => Either::Left(left.add_any_attr(new_attr)),
Either::Right(right) => Either::Right(right.add_any_attr(new_attr)),
}
}
}

impl<A, B> Attribute for Either<A, B>
where
B: Attribute,
A: Attribute,
{
const MIN_LENGTH: usize = max_usize(&[A::MIN_LENGTH, B::MIN_LENGTH]);

type AsyncOutput = (Either<A::AsyncOutput, B::AsyncOutput>,);
type State = Either<A::State, B::State>;
type Cloneable = (Either<A::Cloneable, B::Cloneable>,);
type CloneableOwned = (Either<A::CloneableOwned, B::CloneableOwned>,);

fn html_len(&self) -> usize {
match self {
Either::Left(left) => left.html_len(),
Either::Right(right) => right.html_len(),
}
}

fn to_html(
self,
buf: &mut String,
class: &mut String,
style: &mut String,
inner_html: &mut String,
) {
match self {
Either::Left(left) => left.to_html(buf, class, style, inner_html),
Either::Right(right) => {
right.to_html(buf, class, style, inner_html)
}
}
}

fn hydrate<const FROM_SERVER: bool>(
self,
el: &crate::renderer::types::Element,
) -> Self::State {
match self {
Either::Left(left) => Either::Left(left.hydrate::<FROM_SERVER>(el)),
Either::Right(right) => {
Either::Right(right.hydrate::<FROM_SERVER>(el))
}
}
}

fn build(self, el: &crate::renderer::types::Element) -> Self::State {
match self {
Either::Left(left) => Either::Left(left.build(el)),
Either::Right(right) => Either::Right(right.build(el)),
}
}

fn rebuild(self, state: &mut Self::State) {
match self {
Either::Left(left) => {
if let Some(state) = state.as_left_mut() {
left.rebuild(state)
}
}
Either::Right(right) => {
if let Some(state) = state.as_right_mut() {
right.rebuild(state)
}
}
}
}

fn into_cloneable(self) -> Self::Cloneable {
(match self {
Either::Left(left) => Either::Left(left.into_cloneable()),
Either::Right(right) => Either::Right(right.into_cloneable()),
},)
}

fn into_cloneable_owned(self) -> Self::CloneableOwned {
(match self {
Either::Left(left) => Either::Left(left.into_cloneable_owned()),
Either::Right(right) => Either::Right(right.into_cloneable_owned()),
},)
}

fn dry_resolve(&mut self) {
match self {
Either::Left(left) => left.dry_resolve(),
Either::Right(right) => right.dry_resolve(),
}
}

async fn resolve(self) -> Self::AsyncOutput {
(match self {
Either::Left(left) => Either::Left(left.resolve().await),
Either::Right(right) => Either::Right(right.resolve().await),
},)
}
}

impl<A, B> RenderHtml for Either<A, B>
where
A: RenderHtml,
Expand Down

0 comments on commit 88b1b2d

Please sign in to comment.