Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin' into 3181
Browse files Browse the repository at this point in the history
  • Loading branch information
gbj committed Nov 4, 2024
2 parents 99c1482 + d9f52da commit 2d432f5
Showing 1 changed file with 144 additions and 0 deletions.
144 changes: 144 additions & 0 deletions tachys/src/view/iterators.rs
Original file line number Diff line number Diff line change
Expand Up @@ -336,3 +336,147 @@ where
VecState { states, marker }
}
}

impl<T, const N: usize> Render for [T; N]
where
T: Render,
{
type State = ArrayState<T::State, N>;

fn build(self) -> Self::State {
Self::State {
states: self.map(T::build),
}
}

fn rebuild(self, state: &mut Self::State) {
let Self::State { states } = state;
let old = states;
// this is an unkeyed diff
self.into_iter()
.zip(old.iter_mut())
.for_each(|(new, old)| T::rebuild(new, old));
}
}

/// Retained view state for a `Vec<_>`.
pub struct ArrayState<T, const N: usize>
where
T: Mountable,
{
states: [T; N],
}

impl<T, const N: usize> Mountable for ArrayState<T, N>
where
T: Mountable,
{
fn unmount(&mut self) {
self.states.iter_mut().for_each(Mountable::unmount);
}

fn mount(
&mut self,
parent: &crate::renderer::types::Element,
marker: Option<&crate::renderer::types::Node>,
) {
for state in self.states.iter_mut() {
state.mount(parent, marker);
}
}

fn insert_before_this(&self, child: &mut dyn Mountable) -> bool {
if let Some(first) = self.states.first() {
first.insert_before_this(child)
} else {
false
}
}
}
impl<T, const N: usize> AddAnyAttr for [T; N]
where
T: AddAnyAttr,
{
type Output<SomeNewAttr: Attribute> =
[<T as AddAnyAttr>::Output<SomeNewAttr::Cloneable>; N];

fn add_any_attr<NewAttr: Attribute>(
self,
attr: NewAttr,
) -> Self::Output<NewAttr>
where
Self::Output<NewAttr>: RenderHtml,
{
let attr = attr.into_cloneable();
self.map(|n| n.add_any_attr(attr.clone()))
}
}

impl<T, const N: usize> RenderHtml for [T; N]
where
T: RenderHtml,
{
type AsyncOutput = [T::AsyncOutput; N];

const MIN_LENGTH: usize = 0;

fn dry_resolve(&mut self) {
for inner in self.iter_mut() {
inner.dry_resolve();
}
}

async fn resolve(self) -> Self::AsyncOutput {
futures::future::join_all(self.into_iter().map(T::resolve))
.await
.into_iter()
.collect::<Vec<_>>()
.try_into()
.unwrap_or_else(|_| unreachable!())
}

fn html_len(&self) -> usize {
self.iter().map(RenderHtml::html_len).sum::<usize>()
}

fn to_html_with_buf(
self,
buf: &mut String,
position: &mut Position,
escape: bool,
mark_branches: bool,
) {
for child in self.into_iter() {
child.to_html_with_buf(buf, position, escape, mark_branches);
}
}

fn to_html_async_with_buf<const OUT_OF_ORDER: bool>(
self,
buf: &mut StreamBuilder,
position: &mut Position,
escape: bool,
mark_branches: bool,
) where
Self: Sized,
{
for child in self.into_iter() {
child.to_html_async_with_buf::<OUT_OF_ORDER>(
buf,
position,
escape,
mark_branches,
);
}
}

fn hydrate<const FROM_SERVER: bool>(
self,
cursor: &Cursor,
position: &PositionState,
) -> Self::State {
let states =
self.map(|child| child.hydrate::<FROM_SERVER>(cursor, position));
ArrayState { states }
}
}

0 comments on commit 2d432f5

Please sign in to comment.