From a0a3ebb856cd89a143aa0b234fd73d0806eb498a Mon Sep 17 00:00:00 2001 From: Daan Vanoverloop Date: Fri, 9 Sep 2022 20:19:18 +0200 Subject: [PATCH] Lifetime subtyping and variance??? --- web/dist/index.html | 6 +- web/src/components/event.rs | 151 +++++++++++++++++++++++++++--------- 2 files changed, 118 insertions(+), 39 deletions(-) diff --git a/web/dist/index.html b/web/dist/index.html index 42c435a..f5c0a58 100644 --- a/web/dist/index.html +++ b/web/dist/index.html @@ -6,7 +6,7 @@ LAN Party - - + + - \ No newline at end of file + \ No newline at end of file diff --git a/web/src/components/event.rs b/web/src/components/event.rs index ee5c52f..dfaeb30 100644 --- a/web/src/components/event.rs +++ b/web/src/components/event.rs @@ -1,4 +1,4 @@ -use std::{marker::PhantomData, str::FromStr}; +use std::{cell::RefCell, marker::PhantomData, str::FromStr}; use crate::components::Block; use lan_party_core::event::{ @@ -7,11 +7,11 @@ use lan_party_core::event::{ }; use log::debug; use paste::paste; -use sycamore::prelude::*; +use sycamore::{builder::prelude::*, component::Prop, prelude::*}; macro_rules! editable { ($type:ty => $editor:ty) => { - impl<'a, G: Html> Editable<'a, G> for $type { + impl<'s: 'a, 'a, G: Html> Editable<'s, 'a, G> for $type { type Editor = $editor; } }; @@ -48,7 +48,7 @@ macro_rules! edit_struct { paste! { pub struct [<$struct Edit>]; - impl<'a, G: Html> Editor<'a, G, $struct> for [<$struct Edit>] { + impl<'s: 'a, 'a, G: Html> Editor<'s, 'a, G, $struct> for [<$struct Edit>] { fn edit(cx: Scope<'a>, props: EditProps<'a, $struct>) -> View { let state = props.state; link_fields!(cx, $($prop,)* => state as $struct); @@ -90,7 +90,7 @@ macro_rules! edit_enum { paste! { pub struct [<$enum Edit>]; - impl<'a, G: Html> Editor<'a, G, $enum> for [<$enum Edit>] { + impl<'s: 'a, 'a, G: Html> Editor<'s, 'a, G, $enum> for [<$enum Edit>] { fn edit(cx: Scope<'a>, props: EditProps<'a, $enum>) -> View { let state = props.state; @@ -129,40 +129,40 @@ impl<'a, T> From<&'a Signal> for EditProps<'a, T> { } } -pub trait IntoEdit<'a, G: Html> { - fn edit(self, cx: Scope<'a>) -> View; +pub trait IntoEdit<'s: 'a, 'a, G: Html> { + fn edit(self, cx: BoundedScope<'a, 's>) -> View; } -impl<'a, G: Html, T: Editable<'a, G>> IntoEdit<'a, G> for &'a Signal +impl<'s: 'a, 'a, G: Html, T: Editable<'s, 'a, G> + 'a> IntoEdit<'s, 'a, G> for &'a Signal where EditProps<'a, T>: From<&'a Signal>, { - fn edit(self, cx: Scope<'a>) -> View { + fn edit(self, cx: BoundedScope<'a, 's>) -> View { T::edit(cx, self.into()) } } -pub trait Edit<'a, G: Html>: Sized { - fn edit(cx: Scope<'a>, props: EditProps<'a, Self>) -> View; +pub trait Edit<'s: 'a, 'a, G: Html>: Sized { + fn edit(cx: BoundedScope<'a, 's>, props: EditProps<'a, Self>) -> View; } -impl<'a, G, E, Type> Edit<'a, G> for Type +impl<'s: 'a, 'a, G, E, Type> Edit<'s, 'a, G> for Type where G: Html, - E: Editor<'a, G, Type>, - Type: Editable<'a, G, Editor = E>, + E: Editor<'s, 'a, G, Type>, + Type: Editable<'s, 'a, G, Editor = E> + 'a, { - fn edit(cx: Scope<'a>, props: EditProps<'a, Self>) -> View { + fn edit(cx: BoundedScope<'a, 's>, props: EditProps<'a, Self>) -> View { E::edit(cx, props) } } -pub trait Editor<'a, G: Html, Type>: Sized { - fn edit(cx: Scope<'a>, props: EditProps<'a, Type>) -> View; +pub trait Editor<'s: 'a, 'a, G: Html, Type: 'a>: Sized { + fn edit(cx: BoundedScope<'a, 's>, props: EditProps<'a, Type>) -> View; } -pub trait Editable<'a, G: Html>: Sized { - type Editor: Editor<'a, G, Self>; +pub trait Editable<'s: 'a, 'a, G: Html>: Sized + 'a { + type Editor: Editor<'s, 'a, G, Self>; } edit_struct!(EventSpec => ("Name", name), ("Description", description), ("Event type", event_type)); @@ -179,7 +179,7 @@ edit_struct!(FreeForAllGameSpec => ); pub struct StringEdit; -impl<'a, G: Html> Editor<'a, G, String> for StringEdit { +impl<'s: 'a, 'a, G: Html> Editor<'s, 'a, G, String> for StringEdit { fn edit(cx: Scope<'a>, props: EditProps<'a, String>) -> View { view! { cx, input(bind:value=props.state) @@ -191,9 +191,9 @@ editable!(String => StringEdit); pub struct StubEdit; -impl<'a, G: Html, T> Editor<'a, G, T> for StubEdit +impl<'s: 'a, 'a, G: Html, T> Editor<'s, 'a, G, T> for StubEdit where - T: Editable<'a, G, Editor = StubEdit>, + T: Editable<'s, 'a, G, Editor = StubEdit>, { fn edit(cx: Scope<'a>, _props: EditProps<'a, T>) -> View { view! { cx, @@ -204,9 +204,9 @@ where pub struct InputEdit; -impl<'a, G: Html, T> Editor<'a, G, T> for InputEdit +impl<'s: 'a, 'a, G: Html, T> Editor<'s, 'a, G, T> for InputEdit where - T: Editable<'a, G, Editor = InputEdit> + FromStr + ToString + Default, + T: Editable<'s, 'a, G, Editor = InputEdit> + FromStr + ToString + Default, { fn edit(cx: Scope<'a>, props: EditProps<'a, T>) -> View { let value = create_signal(cx, props.state.get_untracked().to_string()); @@ -236,7 +236,7 @@ editable!(f32 => InputEdit); pub struct BoolEdit; -impl<'a, G: Html> Editor<'a, G, bool> for BoolEdit { +impl<'s: 'a, 'a, G: Html> Editor<'s, 'a, G, bool> for BoolEdit { fn edit(cx: Scope<'a>, props: EditProps<'a, bool>) -> View { view! { cx, input(type="checkbox", bind:checked=props.state) @@ -248,14 +248,14 @@ editable!(bool => BoolEdit); pub struct VecEdit; -impl<'a, G, T, I> Editor<'a, G, I> for VecEdit +impl<'s: 'a, 'a, G, T, I> Editor<'s, 'a, G, I> for VecEdit where G: Html, - T: Editable<'a, G> + Clone + PartialEq + 'a, - I: IntoIterator + FromIterator + Clone, + T: Editable<'s, 'a, G> + Clone + PartialEq + 'a, + I: IntoIterator + FromIterator + Clone + 'a, { - fn edit(cx: Scope<'a>, props: EditProps<'a, I>) -> View { - let vec = create_signal( + fn edit(cx: BoundedScope<'a, 's>, props: EditProps<'a, I>) -> View { + let vec: &'a Signal>> = create_signal( cx, props .state @@ -273,7 +273,6 @@ where create_effect(cx, || { props.state.set( vec.get() - .as_ref() .iter() .cloned() .map(|x| x.get().as_ref().clone()) @@ -281,26 +280,106 @@ where ) }); + let test = Indexed( + cx, + IndexedProps::builder() + .iterable(vec) + .view(|cx: BoundedScope<'_, '_>, x: &'a Signal| { + //view! { cx, (T::edit(cx, EditProps { state: x })) } + T::edit(cx, EditProps { state: x }) + }) + .build(), + ); + test + /* + //view! { cx, "Vec" } view! { cx, Indexed( iterable=vec, - view=|cx: BoundedScope<'_, 'a>, x| { - let signal = create_ref(cx, x); + view=|cx: BoundedScope<'_, 'a>, x: &'a Signal| { view! { cx, - (T::edit(cx, x.into())) + //(T::edit(cx, EditProps { state: x })) + (something_with_signal(cx, EditProps { state: x })) } }, ) } */ + + /* + view! { cx, + (View::new_fragment((vec.get().try_borrow().unwrap().clone().into_iter().map(|s: &'a Signal| { + view! { cx, (T::edit(cx, s.into())) } + })).collect())) + } + */ } } -impl<'a, G, T> Editable<'a, G> for Vec +/* +#[component] +pub fn VecTest< + 'a, + G: Html, + T: 'a + PartialEq + Clone + Editable<'a, G, Editor = E>, + E: Editor<'a, G, T>, +>( + cx: Scope<'a>, + props: EditProps<'a, Vec>, +) -> View { + /* + let signals: &'a Signal>> = create_signal( + cx, + vec![ + create_signal(cx, String::new()), + create_signal(cx, String::new()), + ], + ); + */ + + let signals = create_signal( + cx, + props + .state + .get() + .iter() + .cloned() + .map(|s| create_signal(cx, s)) + .collect::>(), + ); + + view! { cx, + Indexed( + iterable=signals, + view=|cx: BoundedScope<'_, 'a>, signal: &'a Signal| { + view! { cx, + //(something_with_signal(cx, SignalWrapper(signal))) + //(E::edit(cx, EditProps { state: signal })) + //(T::edit(cx, EditProps { state: signal })) + //(signal.edit(cx)) + } + }, + ) + } +} +*/ + +pub struct SignalWrapper<'a, T>(&'a Signal); + +#[component] +pub fn something_with_signal<'a, G: Html, T: 'a>( + cx: Scope<'a>, + signal: EditProps<'a, T>, +) -> View { + drop(signal); + view! { cx, "Something" } +} + +impl<'s: 'a, 'a, G, T> Editable<'s, 'a, G> for Vec where G: Html, - T: Editable<'a, G> + Clone + PartialEq + 'a, + T: Editable<'s, 'a, G> + Clone + PartialEq + 'a, { type Editor = VecEdit; }