Skip to content

Commit db8874f

Browse files
committed
example: minimal-csr
1 parent 2ada5b2 commit db8874f

File tree

3 files changed

+188
-0
lines changed

3 files changed

+188
-0
lines changed

Cargo.lock

Lines changed: 4 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

examples/minimal-csr/Cargo.toml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
[package]
2+
name = "minimal-csr"
3+
version = "0.1.0"
4+
edition = "2021"
5+
6+
[dependencies]

examples/minimal-csr/src/lib.rs

Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
use std::pin::Pin;
2+
3+
#[cfg(remove)]
4+
use ui_handle_maybe::UiHandleMaybeUnmounted;
5+
6+
pub trait RendererWithContext {
7+
type RenderContext;
8+
}
9+
10+
pub trait UiHandle<R: ?Sized> {
11+
type Maybe: UiHandleMaybeMounted<R, UiHandle = Self> + Default;
12+
13+
fn into_ui_handle_maybe(self) -> Self::Maybe;
14+
15+
fn check_and_move_cursor_after_self(&self, render_context: &mut R::RenderContext)
16+
where
17+
R: RendererWithContext;
18+
}
19+
20+
pub trait UiHandleWithContext {}
21+
22+
pub trait ReactiveState {}
23+
24+
pub trait UiHandleMaybeMounted<R: ?Sized>: UiHandle<R, Maybe = Self> {
25+
type UiHandle: UiHandle<R, Maybe = Self>;
26+
// fn is_mounted(&self) -> bool;
27+
28+
fn unmount_if_mounted(&mut self, renderer: &mut R);
29+
30+
fn mount_with_if_unmounted<E>(
31+
&mut self,
32+
el: E,
33+
mount: impl FnOnce(E) -> Self::UiHandle,
34+
update: impl FnOnce(E, &mut Self::UiHandle),
35+
);
36+
}
37+
38+
pub trait RenderHtml {}
39+
40+
pub trait HtmlRenderContext {
41+
type HtmlRenderer: RenderHtml;
42+
43+
fn renderer_mut(&mut self) -> &mut Self::HtmlRenderer;
44+
}
45+
46+
pub trait CsrElement {
47+
type UiHandle<R: ?Sized + RenderHtml>: UiHandle<R>;
48+
type NonReactiveState: Default;
49+
type ReactiveState: ReactiveState + Default;
50+
51+
fn render_init<Ctx: ?Sized + HtmlRenderContext>(
52+
self,
53+
render_context: &mut Ctx,
54+
non_reactive_state: Pin<&mut Self::NonReactiveState>,
55+
reactive_state: Pin<&mut Self::ReactiveState>,
56+
) -> Self::UiHandle<Ctx::HtmlRenderer>;
57+
58+
fn render_update<Ctx: ?Sized + HtmlRenderContext>(
59+
self,
60+
render_context: &mut Ctx,
61+
ui_handle: &mut Self::UiHandle<Ctx::HtmlRenderer>,
62+
non_reactive_state: Pin<&mut Self::NonReactiveState>,
63+
reactive_state: Pin<&mut Self::ReactiveState>,
64+
);
65+
}
66+
67+
#[cfg(remove)]
68+
mod ui_handle_maybe {
69+
use super::UiHandle;
70+
71+
enum Repr<UH> {
72+
BeforeCreated,
73+
MaybeUnmounted { ui_handle: UH, unmounted: bool },
74+
}
75+
76+
impl<UH> Repr<UH> {
77+
fn mounted_ui_handle(&self) -> Option<&UH> {
78+
match self {
79+
Repr::MaybeUnmounted {
80+
ui_handle,
81+
unmounted: false,
82+
} => Some(ui_handle),
83+
_ => None,
84+
}
85+
}
86+
}
87+
88+
pub struct UiHandleMaybeUnmounted<UH> {
89+
repr: Repr<UH>,
90+
}
91+
92+
impl<UH> UiHandleMaybeUnmounted<UH> {
93+
const BEFORE_CREATED: Self = UiHandleMaybeUnmounted {
94+
repr: Repr::BeforeCreated,
95+
};
96+
fn new_mounted(ui_handle: UH) -> Self {
97+
Self {
98+
repr: Repr::MaybeUnmounted {
99+
ui_handle,
100+
unmounted: false,
101+
},
102+
}
103+
}
104+
105+
fn unmount_if_mounted<R: ?Sized>(&mut self, renderer: &mut R)
106+
where
107+
UH: UiHandle<R>,
108+
{
109+
todo!()
110+
}
111+
}
112+
113+
impl<UH: UiHandle<R>, R: ?Sized> UiHandle<R> for UiHandleMaybeUnmounted<UH> {
114+
fn check_and_move_cursor_after_self(&self, render_context: &mut R::RenderContext)
115+
where
116+
R: super::RendererWithContext,
117+
{
118+
if let Some(ui_handle) = self.repr.mounted_ui_handle() {
119+
ui_handle.check_and_move_cursor_after_self(render_context);
120+
}
121+
}
122+
}
123+
}
124+
125+
pub mod option {
126+
use super::{CsrElement, HtmlRenderContext, RenderHtml, UiHandle, UiHandleMaybeMounted};
127+
128+
impl<E: CsrElement> CsrElement for Option<E> {
129+
type UiHandle<R: ?Sized + RenderHtml> = <E::UiHandle<R> as UiHandle<R>>::Maybe;
130+
type NonReactiveState = E::NonReactiveState;
131+
type ReactiveState = E::ReactiveState;
132+
133+
fn render_init<Ctx: ?Sized + super::HtmlRenderContext>(
134+
self,
135+
render_context: &mut Ctx,
136+
non_reactive_state: std::pin::Pin<&mut Self::NonReactiveState>,
137+
reactive_state: std::pin::Pin<&mut Self::ReactiveState>,
138+
) -> Self::UiHandle<Ctx::HtmlRenderer> {
139+
match self {
140+
Some(el) => {
141+
let ui_handle =
142+
el.render_init(render_context, non_reactive_state, reactive_state);
143+
144+
ui_handle.into_ui_handle_maybe()
145+
}
146+
None => Default::default(),
147+
}
148+
}
149+
150+
fn render_update<Ctx: ?Sized + HtmlRenderContext>(
151+
self,
152+
render_context: &mut Ctx,
153+
ui_handle: &mut Self::UiHandle<Ctx::HtmlRenderer>,
154+
non_reactive_state: std::pin::Pin<&mut Self::NonReactiveState>,
155+
reactive_state: std::pin::Pin<&mut Self::ReactiveState>,
156+
) {
157+
match self {
158+
Some(el) => ui_handle.mount_with_if_unmounted(
159+
(el, render_context, non_reactive_state, reactive_state),
160+
|(el, render_context, non_reactive_state, reactive_state)| {
161+
let ui_handle =
162+
el.render_init(render_context, non_reactive_state, reactive_state);
163+
ui_handle
164+
},
165+
|(el, render_context, non_reactive_state, reactive_state), ui_handle| {
166+
el.render_update(
167+
render_context,
168+
ui_handle,
169+
non_reactive_state,
170+
reactive_state,
171+
)
172+
},
173+
),
174+
None => ui_handle.unmount_if_mounted(render_context.renderer_mut()),
175+
}
176+
}
177+
}
178+
}

0 commit comments

Comments
 (0)